Skip to content

Commit

Permalink
Merge pull request #9 from feugy/january-fixes
Browse files Browse the repository at this point in the history
January fixes
  • Loading branch information
feugy authored Feb 16, 2018
2 parents 655a5b7 + fe85d35 commit 23ff8c1
Show file tree
Hide file tree
Showing 21 changed files with 96 additions and 45 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ To publish a new one:

1. change version in `package.json`
2. push to github all changes, using PRs
3. Create a github release, tag must be `package.json` version prefixed with `v`. Set title and description, then publish it.
3. Create a github release, tag must be `package.json` version prefixed with `v`. Set title and description, then _save it as draft_.
4. set GH_TOKEN has environment variable
4. run `npm run release`
5. run `npm run release`
6. go back to github, and publish your release

## Bugs

Expand Down
19 changes: 13 additions & 6 deletions app/src/controller/card.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ Registration = require '../model/registration'
Invoice = require '../model/invoice'
RegisterController = require './register'
SearchDancerController = require './search_dancer'
{currentSeason} = require '../util/common'

# Displays and edits a a dancer card, that is a bunch of dancers, their registrations and their classes
# New registration may be added, and the corresponding directive will be consequently used.
module.exports = class CardController

# Controller dependencies
@$inject: ['$scope', '$rootScope', 'cardList', 'dialog', '$q', '$state', '$filter', '$stateParams']
@$inject: ['$scope', '$rootScope', 'cardList', 'conf', 'dialog', '$q', '$state', '$filter', '$stateParams']

# Route declaration
@declaration:
Expand Down Expand Up @@ -47,6 +48,9 @@ module.exports = class CardController
# Angular's promise factory
q: null

# Configuration service
conf: null

# displayed card
card: null

Expand Down Expand Up @@ -92,17 +96,19 @@ module.exports = class CardController
# @param scope [Object] Controller's own scope, for change detection
# @param rootscope [Object] Angular global scope for digest triggering
# @param cardList [CardListService] service responsible for card list
# @param conf [Object] configuration service
# @param dialog [Object] Angular dialog service
# @param q [Object] Angular's promise factory
# @param state [Object] Angular state provider
# @param filter [Function] Angular's filter factory
# @param stateParams [Object] invokation route parameters
constructor: (@scope, @rootScope, @cardList, @dialog, @q, @state, @filter, stateParams) ->
constructor: (@scope, @rootScope, @cardList, @conf, @dialog, @q, @state, @filter, stateParams) ->
# initialize global change status
@dancers = []
@addresses = []
@required = {}
@invoices = []
@allInvoices = []
@_modalOpened = false
@_previous = {}
@_removable = []
Expand Down Expand Up @@ -474,14 +480,14 @@ module.exports = class CardController
#
# @param registration [Registration] for which invoice is edited
# @param teacher [Number] index of the selected teacher
editInvoice: (registration, teacher) =>
editInvoice: (teacher, registration = null) =>
# save pending modifications
@save true, (err) =>
return console.error err if err?
# new invoice date
date = registration.created or registration.payments[0]?.receipt or moment()
date = registration?.created or registration?.payments[0]?.receipt or moment()
# search for unsent invoices related to that card, and create a new one if needed
makeInvoice @dancers, date, registration.season, teacher, (err, invoice) =>
makeInvoice @dancers, date, registration?.season or currentSeason(), teacher, (err, invoice) =>
# there could be an error if invoice already exists, and invoice will be populated.
return @state.go 'list.invoice', {invoice} if invoice?
# or just an error
Expand Down Expand Up @@ -553,7 +559,8 @@ module.exports = class CardController
@required.regs = ([] for registration in @card.registrations)
@required.regClasses = ('' for registration in @card.registrations)
@invoices = (for registration in @card.registrations
invoices.filter(({season, sent}) -> season is registration.season).sort (a, b) -> a.sent.diff b.sent)
invoices.filter(({season, sent}) -> season is registration.season).sort (a, b) -> a.sent?.diff b.sent)
@allInvoices = invoices.sort (a, b) -> a.sent?.diff b.sent

# get dance classes
async.map @dancers, (dancer, next) ->
Expand Down
6 changes: 6 additions & 0 deletions app/src/controller/expanded_list.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ module.exports = class ExpandedListController extends ListController
attr: (dancer, done) ->
dancer.getLastRegistration (err, registration) -> done err, registration?.due() or 0
},
{
name: 'period'
title: 'lbl.period'
attr: (dancer, done) ->
dancer.getLastRegistration (err, registration) -> done err, registration?.period or 'year'
},
{
name: 'age'
title: 'lbl.age'
Expand Down
2 changes: 1 addition & 1 deletion app/src/controller/lessons.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ module.exports = class LessonsController
# @return [String] formated name
formatDancer: =>
return "" unless @selectedDancer?
"#{@selectedDancer.firstname} #{@selectedDancer.lastname}"
"#{@selectedDancer.firstname or ''} #{@selectedDancer.lastname or ''}".trim()

# Displays date and hour of a given lesson
#
Expand Down
6 changes: 6 additions & 0 deletions app/src/controller/list_layout.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ module.exports = class ListLayoutController extends ListController
title: 'lbl.due'
attr: (dancer, done) ->
dancer.getLastRegistration (err, registration) -> done err, registration?.due() or 0
},
{
name: 'period'
title: 'lbl.period'
attr: (dancer, done) ->
dancer.getLastRegistration (err, registration) -> done err, registration?.period or 'year'
}

@constructor.colSpec.invoice.push {name: 'teacher', title: 'lbl.teacherColumn', attr: (invoice) => @conf.teachers[invoice.selectedTeacher]?.owner},
Expand Down
2 changes: 1 addition & 1 deletion app/src/controller/search_dancer.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ module.exports = class SearchController
# @return formated name
formatDancer: =>
return "" unless @dancer?
"#{@dancer.firstname} #{@dancer.lastname}"
"#{@dancer.firstname or ''} #{@dancer.lastname or ''}".trim()

# Search within existing dancers a match on lastname
#
Expand Down
7 changes: 6 additions & 1 deletion app/src/directive/list.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class ListDirective
html.push "<th #{if name? then "data-attr='#{name}'" else ''}>"

if title
html.push @filter('i18n')(title)
html.push "<span title=\"#{@filter('i18n')(title)}\">#{@filter('i18n')(title)}</span>"
else if selectable
html.push '<input type="checkbox"/>'
html.push '</th>'
Expand Down Expand Up @@ -170,6 +170,11 @@ class ListDirective
html.push '><i class="glyphicon glyphicon-'
html.push if value then 'ok' else 'exclamation-sign'
html.push '"/>'
when 'period'
html.push '><i class="glyphicon glyphicon-'
html.push if value is 'class' then 'stop' else if value is 'quarter' then 'th-large' else 'th'
html.push '" title="' + @filter('i18n')("periods.#{value}")
html.push '"/>'
when 'sent', 'invoiced', 'isCredit'
if value then html.push '><i class="glyphicon glyphicon-ok"/>' else '/>'
else
Expand Down
1 change: 1 addition & 0 deletions app/src/directive/registration.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class RegistrationDirective
# @param element [DOM] directive root element
# @param dialog [Object] Angular's dialog service
# @param filter [Function] Angular's filters factory
# @param conf [Object] configuration service
# @param rootScope [Object] Angular root scope
constructor: (@scope, @element, @dialog, @filter, @conf, rootScope) ->
@_updateRendering()
Expand Down
6 changes: 3 additions & 3 deletions app/src/labels/common.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module.exports =
exportEmails: 'Copier les emails'
ignore: 'Ne rien modifier'
invoice: 'Factures'
invoiceWithoutRegistration: 'Factures hors inscriptions'
import: 'Importer des données'
lessons: 'Cours particuliers'
markAsSent: 'Archiver'
Expand Down Expand Up @@ -79,8 +80,7 @@ module.exports =
card: 'Fiche danseurs'
cellphone: 'Portable'
certificates: 'Nb. certificats'
certified: 'Cert.'
certifiedLong: 'Certificat médical'
certified: 'Certificat médical'
charged: 'Réglement de'
choose: '---'
city: 'Ville'
Expand All @@ -96,7 +96,7 @@ module.exports =
details: 'Détails'
designation: 'Désignation'
discount: 'Remise'
due: 'Rgt.'
due: 'Réglement'
dumpPath: 'Fichier de sauvegarde'
dutyFreeTotal: 'Total HT'
duration: 'Durée'
Expand Down
7 changes: 6 additions & 1 deletion app/src/model/invoice.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ module.exports = class Invoice extends Persisted
.map ([y, m, ref]) -> +ref
.sort (a, b) -> a - b
last = refs[refs.length-1] or 0
# search wholes in sequence
for c, i in refs when i > 0
if c - refs[i-1] isnt 1
last = refs[i-1]
break
done null, "#{year}-#{_.padStart month, 2, '0'}-#{_.padStart last + 1, 3, '0'}"

# invoice reference
Expand Down Expand Up @@ -159,7 +164,7 @@ module.exports = class Invoice extends Persisted
# @option done err [Error] an error object or null if no error occured
setCustomers: (dancers, done) =>
return done null unless dancers? && dancers.length
@customer.name = ("#{dancer.title} #{dancer.firstname} #{dancer.lastname}" for dancer in dancers).join '\n'
@customer.name = ("#{dancer.title or ''} #{dancer.firstname or ''} #{dancer.lastname or ''}".trim() for dancer in dancers).join '\n'
dancers[0].getAddress (err, address) =>
return done err if err?
Object.assign @customer, address.toJSON() if address?
Expand Down
1 change: 1 addition & 0 deletions app/src/model/tools/initializer.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ plannings = [{
{kind:'Danse sportive', color:'color7', level:'solo team 2', start:'Thu 19:00', end:'Thu 20:00', teacher:'Anthony', hall:'Gratte-ciel 2', _id:'eb1ac8ec29b1'}
{kind:'Danse sportive', color:'color7', level:'compétiteurs latine', start:'Tue 20:00', end:'Tue 22:00', teacher:'Anthony', hall:'Croix-Luizet', _id:'6983f6d5acaf'}
{kind:'Danse sportive', color:'color7', level:'compétiteurs standard', start:'Thu 20:30', end:'Thu 22:00', teacher:'Anthony', hall:'Gratte-ciel 1', _id:'4be87d67ff85'}
{kind:'Danse sportive', color:'color7', level:'entrainement enfants', start:'Wed 18:30', end:'Wed 20:00', teacher:'Anthony', hall:'Croix-Luizet', _id:'5929fd8d55f3'}

{kind:'Salsa/Bachata', color:'color8', level:'niveau 1', start:'Thu 20:00', end:'Thu 21:00', teacher:'Anthony', hall:'Gratte-ciel 2', _id:'fa8d7b7c8578'}
{kind:'Salsa/Bachata', color:'color8', level:'niveau 2', start:'Thu 21:00', end:'Thu 22:00', teacher:'Anthony', hall:'Gratte-ciel 2', _id:'a56e2966dac9'}
Expand Down
14 changes: 0 additions & 14 deletions app/src/model/tools/persisted.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,6 @@ module.exports = class Persisted extends Base
# @option done models [Array<Object>] an array (that may be empty) of matching raw values
@findAllRaw: (done) -> persistance.find @name, {}, done

# **static**
# Find a list of models from the storage provider that match given conditions
# Condition is an object, whose fields are path within the dancer, with their expected values.
# (interpreted in the same order)
# In path, dots are supported, and allow diving in sub object or sub array.
# An expected value may be a function, that will take as arguments the given value and it's model,
# and must returns a boolean.
#
# @param conditions [Object] keys define path, values are expected values
# @param done [Function] completion callback, invoked with arguments:
# @option done err [Error] an error object or null if no error occured
# @option done models [Array<Persisted>] an array (that may be empty) of matching models
@findWhere: (conditions, done) ->

# **static**
# Find a list of models from the storage provider that match given conditions
# Condition is an object, whose fields are path within the instance, with their expected values.
Expand Down
3 changes: 3 additions & 0 deletions app/src/style/controller/card.styl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
border-top 2px solid headingColor
margin 10px 0

> .invoice-without-registration
float right

> article
.tab-pane > article
position relative
Expand Down
9 changes: 5 additions & 4 deletions app/src/style/main_layout.styl
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ body
cursor pointer
text-overflow ellipsis
overflow hidden
white-space nowrap

.glyphicon
margin-right 0.5em
Expand Down Expand Up @@ -158,11 +159,11 @@ body

// tables MUST have fixed width columns
.table.dancers
for width, i in 30 35 15 20
for width, i in 30 34 12 12 12
td:nth-child({i+1})
width unit(width, '%')
th:nth-child({i+1})
width unit((width - 2), '%')
width unit((width - 1), '%')

.table.invoices
for width, i in 18 26 44 12
Expand Down Expand Up @@ -219,8 +220,8 @@ body

// tables MUST have fixed width columns
&.dancers
// title, firstname, lastname, certificate, payement, age, birth, known-by, phone, mobile, email, address
for col, i in 4em 7% 10% 4em 4em 3em 10% 10% 9em 9em 10%
// title, firstname, lastname, certificate, payement, due, age, birth, known-by, phone, mobile, email, address
for col, i in 4em 7% 10% 4em 4em 4em 3em 10% 10% 9em 9em 10%
td:nth-child({i+1})
th:nth-child({i+1})
width col
Expand Down
9 changes: 8 additions & 1 deletion app/src/style/themes/dark.styl
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,16 @@ for color, i in colors
.card
padding-top 0

> article
border-top none

> .invoice-without-registration
float none
top inherit
right 0

> article:first-child
margin-top 0
border-top none
display flex
flex-direction column
align-items flex-end
Expand Down
18 changes: 16 additions & 2 deletions app/template/card.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,22 @@ <h2>{{::'ttl.knownBy'|i18n}}</h2>
<span data-ng-class="ctrl.knownByOther ? 'selected' : ''" class="known-by-other"><input type="text" data-ng-model="ctrl.knownByOther" data-ng-change="ctrl.setKnownBy()"/><label>{{::'lbl.other'|i18n}}</label></span>
</div>
</article>
<!-- invoice without active registration -->
<article data-ng-if="!ctrl.card.registrations.length">
<span class="btn-group invoice-without-registration hidable">
<span class="btn-group" data-uib-dropdown>
<a href="" class="btn glyphed dropdown-toggle" uib-dropdown-toggle><i class="glyphicon glyphicon-euro"/>{{::'btn.invoiceWithoutRegistration'|i18n}}<span class="caret"></span></a>
<ul class="dropdown-menu right">
<!-- don't order by teachers, or $index will be the wrong one ! -->
<li data-ng-repeat="teacher in ctrl.conf.teachers"><a href="" data-ng-click="ctrl.editInvoice($index)">{{::'btn.editInvoice'|i18n:{args:teacher} }}</a></li>
<li class="divider"></li>
<li data-ng-repeat="invoice in ctrl.allInvoices"><a href="" data-ng-click="ctrl.displayInvoice(invoice)">{{ctrl.conf.teachers[invoice.selectedTeacher].owner}} - {{invoice.ref}} - {{invoice.total}}{{'lbl.currency'|i18n}}</a></li>
</ul>
</span>
</span>
</article>
<!-- registrations -->
<uib-tabset class="registration-tabs">
<uib-tabset class="registration-tabs" data-ng-if="ctrl.card.registrations.length">
<uib-tab data-ng-repeat="registration in ctrl.card.registrations"
data-heading="{{::registration.season}}"
classes="{{ctrl.required.regClasses[$index]}}">
Expand All @@ -51,7 +65,7 @@ <h2>{{::'ttl.knownBy'|i18n}}</h2>
data-invoices="ctrl.invoices[$index]"
data-on-remove="ctrl.removeRegistration(model)"
data-on-print-settlement="ctrl.printSettlement(registration, selectedTeacher)"
data-on-edit-invoice="ctrl.editInvoice(registration, teacher)"
data-on-edit-invoice="ctrl.editInvoice(teacher, registration)"
data-on-display-invoice="ctrl.displayInvoice(invoice)"
data-required-fields="ctrl.required.regs[$index]"
data-on-change="ctrl._onChange('registrations['+$index+'].'+$field)"/>
Expand Down
4 changes: 2 additions & 2 deletions app/template/dancer.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ <h4>{{::'ttl.dancer'|i18n}}</h4>
data-set-null
data-ng-class="ctrl.isRequired('firstname')"
data-ng-model="ctrl.src.firstname"
data-uib-typeahead="choice.firstname as choice.firstname+' '+choice.lastname for choice in ctrl.findByAttr('firstname', $viewValue) | limitTo:20"
data-uib-typeahead="choice.firstname as ((choice.firstname || '')+' '+(choice.lastname || '')).trim() for choice in ctrl.findByAttr('firstname', $viewValue) | limitTo:20"
data-typeahead-min-length="3"
data-typeahead-on-select="ctrl.onLoad({evt:$event, model:$item})"
data-ng-change="ctrl.onChange({$field:'firstname'})"
Expand All @@ -30,7 +30,7 @@ <h4>{{::'ttl.dancer'|i18n}}</h4>
data-set-null
data-ng-class="ctrl.isRequired('lastname')"
data-ng-model="ctrl.src.lastname"
data-uib-typeahead="choice.lastname as choice.firstname+' '+choice.lastname for choice in ctrl.findByAttr('lastname', $viewValue) | limitTo:20"
data-uib-typeahead="choice.lastname as ((choice.firstname || '')+' '+(choice.lastname || '')).trim() for choice in ctrl.findByAttr('lastname', $viewValue) | limitTo:20"
data-typeahead-min-length="3"
data-typeahead-on-select="ctrl.onLoad({evt:$event, model:$item})"
data-ng-change="ctrl.onChange({$field:'lastname'})"
Expand Down
2 changes: 1 addition & 1 deletion app/template/lessons.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ <h2>{{::'ttl.editLesson'|i18n}}</h2>
data-set-null
data-ng-class="ctrl.required.includes('dancer') && 'invalid'"
data-ng-model="ctrl.selectedDancer"
data-uib-typeahead="choice.firstname+' '+choice.lastname for choice in ctrl.search($viewValue) | limitTo:20"
data-uib-typeahead="((choice.firstname || '')+' '+(choice.lastname || '')).trim() for choice in ctrl.search($viewValue) | limitTo:20"
data-typeahead-min-length="3"
data-typeahead-on-select="ctrl.affectDancer($item)"/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/template/search_dancer.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ <h3>{{::'ttl.searchDancer'|i18n}}</h3>
<label>{{::'lbl.lastname'|i18n:{sep:true} }}</label><input
type="text"
data-ng-model="ctrl.dancer"
data-uib-typeahead="choice.firstname+' '+choice.lastname for choice in ctrl.search($viewValue) | limitTo:20"
data-uib-typeahead="((choice.firstname || '')+' '+(choice.lastname || '')).trim() for choice in ctrl.search($viewValue) | limitTo:20"
data-typeahead-min-length="3"
data-typeahead-input-formatter="ctrl.formatDancer()"
data-typeahead-on-select="ctrl.dancer = $item"/>
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dancerm",
"version": "4.4.0",
"version": "4.5.0",
"author": "Feugy <[email protected]>",
"description": "DanceRM is a very simple Customer Relationship software specialized for dance schools",
"repository": {
Expand Down Expand Up @@ -46,7 +46,7 @@
"coffee-script": "1.12.6",
"coveralls": "2.13.1",
"download": "6.2.5",
"electron": "1.8.2-beta.2",
"electron": "1.8.2",
"electron-builder": "19.46.9",
"electron-mocha": "5.0.0",
"electron-test-utils": "1.0.0",
Expand Down
Loading

0 comments on commit 23ff8c1

Please sign in to comment.