diff options
author | Lauri Ojansivu <x@xet7.org> | 2019-01-25 19:05:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-25 19:05:09 +0200 |
commit | ba15526516e1754385d2d6404d64ae9cead3ce95 (patch) | |
tree | 29834be1c70610ea3373e03c64891a6b35569fd1 | |
parent | 542cc75dc4a4bf392cac72345ab013cf59c67ad3 (diff) | |
parent | 6c3dbc3c6f52a42ddbeeaec9bbfcc82c1c839f7d (diff) | |
download | wekan-ba15526516e1754385d2d6404d64ae9cead3ce95.tar.gz wekan-ba15526516e1754385d2d6404d64ae9cead3ce95.tar.bz2 wekan-ba15526516e1754385d2d6404d64ae9cead3ce95.zip |
Merge pull request #2126 from bentiss/color-swimlanes
Color for swimlanes
-rw-r--r-- | client/components/boards/boardBody.js | 31 | ||||
-rw-r--r-- | client/components/cards/cardDetails.jade | 12 | ||||
-rw-r--r-- | client/components/cards/cardDetails.js | 4 | ||||
-rw-r--r-- | client/components/cards/cardDetails.styl | 26 | ||||
-rw-r--r-- | client/components/cards/minicard.js | 4 | ||||
-rw-r--r-- | client/components/lists/list.styl | 1 | ||||
-rw-r--r-- | client/components/rules/actions/cardActions.jade | 37 | ||||
-rw-r--r-- | client/components/rules/actions/cardActions.js | 50 | ||||
-rw-r--r-- | client/components/rules/rules.styl | 9 | ||||
-rw-r--r-- | client/components/swimlanes/swimlaneHeader.jade | 23 | ||||
-rw-r--r-- | client/components/swimlanes/swimlaneHeader.js | 74 | ||||
-rw-r--r-- | client/components/swimlanes/swimlanes.jade | 48 | ||||
-rw-r--r-- | client/components/swimlanes/swimlanes.js | 42 | ||||
-rw-r--r-- | client/components/swimlanes/swimlanes.styl | 103 | ||||
-rw-r--r-- | i18n/en.i18n.json | 5 | ||||
-rw-r--r-- | models/boards.js | 27 | ||||
-rw-r--r-- | models/cards.js | 19 | ||||
-rw-r--r-- | models/lists.js | 2 | ||||
-rw-r--r-- | models/swimlanes.js | 34 |
19 files changed, 402 insertions, 149 deletions
diff --git a/client/components/boards/boardBody.js b/client/components/boards/boardBody.js index ccbd0f23..ae5b67fd 100644 --- a/client/components/boards/boardBody.js +++ b/client/components/boards/boardBody.js @@ -35,6 +35,37 @@ BlazeComponent.extendComponent({ this._isDragging = false; // Used to set the overlay this.mouseHasEnterCardDetails = false; + + // fix swimlanes sort field if there are null values + const currentBoardData = Boards.findOne(Session.get('currentBoard')); + const nullSortSwimlanes = currentBoardData.nullSortSwimlanes(); + if (nullSortSwimlanes.count() > 0) { + const swimlanes = currentBoardData.swimlanes(); + let count = 0; + swimlanes.forEach((s) => { + Swimlanes.update(s._id, { + $set: { + sort: count, + }, + }); + count += 1; + }); + } + + // fix lists sort field if there are null values + const nullSortLists = currentBoardData.nullSortLists(); + if (nullSortLists.count() > 0) { + const lists = currentBoardData.lists(); + let count = 0; + lists.forEach((l) => { + Lists.update(l._id, { + $set: { + sort: count, + }, + }); + count += 1; + }); + } }, onRendered() { const boardComponent = this; diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index c1e771cb..25316d04 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -234,7 +234,7 @@ template(name="cardDetailsActionsPopup") li: a.js-due-date {{_ 'editCardDueDatePopup-title'}} li: a.js-end-date {{_ 'editCardEndDatePopup-title'}} li: a.js-spent-time {{_ 'editCardSpentTimePopup-title'}} - li: a.js-set-card-color {{_ 'setCardColor-title'}} + li: a.js-set-card-color {{_ 'setCardColorPopup-title'}} hr ul.pop-over-list li: a.js-move-card-to-top {{_ 'moveCardToTop-title'}} @@ -337,14 +337,12 @@ template(name="cardMorePopup") a.js-delete(title="{{_ 'card-delete-notice'}}") {{_ 'delete'}} template(name="setCardColorPopup") - p.quiet - span.clearfix - label {{_ "select-color"}} form.edit-label .palette-colors: each colors - span.card-label.palette-color.js-palette-color(class="card-details-{{color}}") - if(isSelected color) - i.fa.fa-check + unless $eq color 'white' + span.card-label.palette-color.js-palette-color(class="card-details-{{color}}") + if(isSelected color) + i.fa.fa-check button.primary.confirm.js-submit {{_ 'save'}} button.js-remove-color.negate.wide.right {{_ 'unset-color'}} diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index cc04b830..79a686a7 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -27,7 +27,6 @@ BlazeComponent.extendComponent({ onCreated() { this.currentBoard = Boards.findOne(Session.get('currentBoard')); this.isLoaded = new ReactiveVar(false); - this.currentColor = new ReactiveVar(this.data().color); const boardBody = this.parentComponent().parentComponent(); //in Miniview parent is Board, not BoardBody. if (boardBody !== null) { @@ -601,6 +600,9 @@ BlazeComponent.extendComponent({ }, isSelected(color) { + if (this.currentColor.get() === null) { + return color === 'white'; + } return this.currentColor.get() === color; }, diff --git a/client/components/cards/cardDetails.styl b/client/components/cards/cardDetails.styl index 5a486d84..bf50c071 100644 --- a/client/components/cards/cardDetails.styl +++ b/client/components/cards/cardDetails.styl @@ -144,16 +144,20 @@ input[type="submit"].attachment-add-link-submit card-details-color(background, color...) background: background !important if color - color: color //overwrite text for better visibility + color: color !important //overwrite text for better visibility + +.card-details-white + card-details-color(unset, #000) //Black text for better visibility + border: 1px solid #eee .card-details-green card-details-color(#3cb500, #ffffff) //White text for better visibility .card-details-yellow - card-details-color(#fad900) + card-details-color(#fad900, #000) //Black text for better visibility .card-details-orange - card-details-color(#ff9f19) + card-details-color(#ff9f19, #000) //Black text for better visibility .card-details-red card-details-color(#eb4646, #ffffff) //White text for better visibility @@ -165,7 +169,7 @@ card-details-color(background, color...) card-details-color(#0079bf, #ffffff) //White text for better visibility .card-details-pink - card-details-color(#ff78cb) + card-details-color(#ff78cb, #000) //Black text for better visibility .card-details-sky card-details-color(#00c2e0, #ffffff) //White text for better visibility @@ -174,19 +178,19 @@ card-details-color(background, color...) card-details-color(#4d4d4d, #ffffff) //White text for better visibility .card-details-lime - card-details-color(#51e898) + card-details-color(#51e898, #000) //Black text for better visibility .card-details-silver - card-details-color(#c0c0c0) + card-details-color(#c0c0c0, #000) //Black text for better visibility .card-details-peachpuff - card-details-color(#ffdab9) + card-details-color(#ffdab9, #000) //Black text for better visibility .card-details-crimson card-details-color(#dc143c, #ffffff) //White text for better visibility .card-details-plum - card-details-color(#dda0dd) + card-details-color(#dda0dd, #000) //Black text for better visibility .card-details-darkgreen card-details-color(#006400, #ffffff) //White text for better visibility @@ -198,7 +202,7 @@ card-details-color(background, color...) card-details-color(#ff00ff, #ffffff) //White text for better visibility .card-details-gold - card-details-color(#ffd700) + card-details-color(#ffd700, #000) //Black text for better visibility .card-details-navy card-details-color(#000080, #ffffff) //White text for better visibility @@ -210,10 +214,10 @@ card-details-color(background, color...) card-details-color(#8b4513, #ffffff) //White text for better visibility .card-details-paleturquoise - card-details-color(#afeeee) + card-details-color(#afeeee, #000) //Black text for better visibility .card-details-mistyrose - card-details-color(#ffe4e1) + card-details-color(#ffe4e1, #000) //Black text for better visibility .card-details-indigo card-details-color(#4b0082, #ffffff) //White text for better visibility diff --git a/client/components/cards/minicard.js b/client/components/cards/minicard.js index e468ec56..da7f9e01 100644 --- a/client/components/cards/minicard.js +++ b/client/components/cards/minicard.js @@ -3,10 +3,6 @@ // }); BlazeComponent.extendComponent({ - onCreated() { - this.currentColor = new ReactiveVar(this.data().color); - }, - template() { return 'minicard'; }, diff --git a/client/components/lists/list.styl b/client/components/lists/list.styl index 72cb19f4..ec835961 100644 --- a/client/components/lists/list.styl +++ b/client/components/lists/list.styl @@ -10,7 +10,6 @@ // transparent, because that won't work during a list drag. background: darken(white, 13%) border-left: 1px solid darken(white, 20%) - border-bottom: 1px solid #CCC padding: 0 float: left diff --git a/client/components/rules/actions/cardActions.jade b/client/components/rules/actions/cardActions.jade index dd92d8fe..1fee5231 100644 --- a/client/components/rules/actions/cardActions.jade +++ b/client/components/rules/actions/cardActions.jade @@ -39,32 +39,15 @@ template(name="cardActions") div.trigger-content div.trigger-text | {{{_'r-set-color'}}} - div.trigger-dropdown - select(id="color-action") - option(value="white") {{{_'color-white'}}} - option(value="green") {{{_'color-green'}}} - option(value="yellow") {{{_'color-yellow'}}} - option(value="orange") {{{_'color-orange'}}} - option(value="red") {{{_'color-red'}}} - option(value="purple") {{{_'color-purple'}}} - option(value="blue") {{{_'color-blue'}}} - option(value="sky") {{{_'color-sky'}}} - option(value="lime") {{{_'color-lime'}}} - option(value="pink") {{{_'color-pink'}}} - option(value="black") {{{_'color-black'}}} - option(value="silver") {{{_'color-silver'}}} - option(value="peachpuff") {{{_'color-peachpuff'}}} - option(value="crimson") {{{_'color-crimson'}}} - option(value="plum") {{{_'color-plum'}}} - option(value="darkgreen") {{{_'color-darkgreen'}}} - option(value="slateblue") {{{_'color-slateblue'}}} - option(value="magenta") {{{_'color-magenta'}}} - option(value="gold") {{{_'color-gold'}}} - option(value="navy") {{{_'color-navy'}}} - option(value="gray") {{{_'color-gray'}}} - option(value="saddlebrown") {{{_'color-saddlebrown'}}} - option(value="paleturquoise") {{{_'color-paleturquoise'}}} - option(value="mistyrose") {{{_'color-mistyrose'}}} - option(value="indigo") {{{_'color-indigo'}}} + button.trigger-button.trigger-button-color.card-details-green.js-show-color-palette(id="color-action") + | {{{_'color-green'}}} div.trigger-button.js-set-color-action.js-goto-rules i.fa.fa-plus + +template(name="setCardActionsColorPopup") + form.edit-label + .palette-colors: each colors + span.card-label.palette-color.js-palette-color(class="card-details-{{color}}") + if(isSelected color) + i.fa.fa-check + button.primary.confirm.js-submit {{_ 'save'}} diff --git a/client/components/rules/actions/cardActions.js b/client/components/rules/actions/cardActions.js index b66556b4..6c858358 100644 --- a/client/components/rules/actions/cardActions.js +++ b/client/components/rules/actions/cardActions.js @@ -1,3 +1,8 @@ +let cardColors; +Meteor.startup(() => { + cardColors = Cards.simpleSchema()._schema.color.allowedValues; +}); + BlazeComponent.extendComponent({ onCreated() { this.subscribe('allRules'); @@ -112,10 +117,22 @@ BlazeComponent.extendComponent({ boardId, }); }, + 'click .js-show-color-palette'(event){ + const funct = Popup.open('setCardActionsColor'); + const colorButton = this.find('#color-action'); + if (colorButton.value === '') { + colorButton.value = 'green'; + } + funct.call(this, event); + }, 'click .js-set-color-action' (event) { const ruleName = this.data().ruleName.get(); const trigger = this.data().triggerVar.get(); - const selectedColor = this.find('#color-action').value; + const colorButton = this.find('#color-action'); + if (colorButton.value === '') { + colorButton.value = 'green'; + } + const selectedColor = colorButton.value; const boardId = Session.get('currentBoard'); const desc = Utils.getTriggerActionDesc(event, this); const triggerId = Triggers.insert(trigger); @@ -136,3 +153,34 @@ BlazeComponent.extendComponent({ }, }).register('cardActions'); + +BlazeComponent.extendComponent({ + onCreated() { + this.currentAction = this.currentData(); + this.colorButton = Popup.getOpenerComponent().find('#color-action'); + this.currentColor = new ReactiveVar(this.colorButton.value); + }, + + colors() { + return cardColors.map((color) => ({ color, name: '' })); + }, + + isSelected(color) { + return this.currentColor.get() === color; + }, + + events() { + return [{ + 'click .js-palette-color'() { + this.currentColor.set(this.currentData().color); + }, + 'click .js-submit' () { + this.colorButton.classList.remove(`card-details-${ this.colorButton.value }`); + this.colorButton.value = this.currentColor.get(); + this.colorButton.innerText = `${TAPi18n.__(`color-${ this.currentColor.get() }`)}`; + this.colorButton.classList.add(`card-details-${ this.colorButton.value }`); + Popup.close(); + }, + }]; + }, +}).register('setCardActionsColorPopup'); diff --git a/client/components/rules/rules.styl b/client/components/rules/rules.styl index 27463d12..05302f7f 100644 --- a/client/components/rules/rules.styl +++ b/client/components/rules/rules.styl @@ -174,6 +174,15 @@ top:30px .trigger-button.trigger-button-person right:-40px + .trigger-button.trigger-button-color + top: unset + position: unset + transform: unset + font-size: 16px + width:auto + padding-left: 10px + padding-right: 10px + height:40px .trigger-item.trigger-item-mail height:300px diff --git a/client/components/swimlanes/swimlaneHeader.jade b/client/components/swimlanes/swimlaneHeader.jade index 483de06f..33eb5731 100644 --- a/client/components/swimlanes/swimlaneHeader.jade +++ b/client/components/swimlanes/swimlaneHeader.jade @@ -1,5 +1,5 @@ template(name="swimlaneHeader") - .swimlane-header-wrap.js-swimlane-header + .swimlane-header-wrap.js-swimlane-header(class='{{#if colorClass}}swimlane-{{colorClass}}{{/if}}') +inlinedForm +editSwimlaneTitleForm else @@ -8,6 +8,7 @@ template(name="swimlaneHeader") = title .swimlane-header-menu unless currentUser.isCommentOnly + a.fa.fa-plus.js-open-add-swimlane-menu.swimlane-header-plus-icon a.fa.fa-navicon.js-open-swimlane-menu template(name="editSwimlaneTitleForm") @@ -20,4 +21,24 @@ template(name="editSwimlaneTitleForm") template(name="swimlaneActionPopup") unless currentUser.isCommentOnly ul.pop-over-list + li: a.js-set-swimlane-color {{_ 'select-color'}} + hr + ul.pop-over-list li: a.js-close-swimlane {{_ 'archive-swimlane'}} + +template(name="swimlaneAddPopup") + unless currentUser.isCommentOnly + form + input.swimlane-name-input.full-line(type="text" placeholder="{{_ 'add-swimlane'}}" + autocomplete="off" autofocus) + .edit-controls.clearfix + button.primary.confirm(type="submit") {{_ 'add'}} + +template(name="setSwimlaneColorPopup") + form.edit-label + .palette-colors: each colors + span.card-label.palette-color.js-palette-color(class="card-details-{{color}}") + if(isSelected color) + i.fa.fa-check + button.primary.confirm.js-submit {{_ 'save'}} + button.js-remove-color.negate.wide.right {{_ 'unset-color'}} diff --git a/client/components/swimlanes/swimlaneHeader.js b/client/components/swimlanes/swimlaneHeader.js index 50635f86..1004cb25 100644 --- a/client/components/swimlanes/swimlaneHeader.js +++ b/client/components/swimlanes/swimlaneHeader.js @@ -1,3 +1,10 @@ +const { calculateIndexData } = Utils; + +let swimlaneColors; +Meteor.startup(() => { + swimlaneColors = Swimlanes.simpleSchema()._schema.color.allowedValues; +}); + BlazeComponent.extendComponent({ editTitle(evt) { evt.preventDefault(); @@ -11,15 +18,82 @@ BlazeComponent.extendComponent({ events() { return [{ 'click .js-open-swimlane-menu': Popup.open('swimlaneAction'), + 'click .js-open-add-swimlane-menu': Popup.open('swimlaneAdd'), submit: this.editTitle, }]; }, }).register('swimlaneHeader'); Template.swimlaneActionPopup.events({ + 'click .js-set-swimlane-color': Popup.open('setSwimlaneColor'), 'click .js-close-swimlane' (evt) { evt.preventDefault(); this.archive(); Popup.close(); }, }); + +BlazeComponent.extendComponent({ + onCreated() { + this.currentSwimlane = this.currentData(); + }, + + events() { + return [{ + submit(evt) { + evt.preventDefault(); + const currentBoard = Boards.findOne(Session.get('currentBoard')); + const nextSwimlane = currentBoard.nextSwimlane(this.currentSwimlane); + const titleInput = this.find('.swimlane-name-input'); + const title = titleInput.value.trim(); + const sortValue = calculateIndexData(this.currentSwimlane, nextSwimlane, 1); + + if (title) { + Swimlanes.insert({ + title, + boardId: Session.get('currentBoard'), + sort: sortValue.base, + }); + + titleInput.value = ''; + titleInput.focus(); + } + // XXX ideally, we should move the popup to the newly + // created swimlane so a user can add more than one swimlane + // with a minimum of interactions + Popup.close(); + }, + }]; + }, +}).register('swimlaneAddPopup'); + +BlazeComponent.extendComponent({ + onCreated() { + this.currentSwimlane = this.currentData(); + this.currentColor = new ReactiveVar(this.currentSwimlane.color); + }, + + colors() { + return swimlaneColors.map((color) => ({ color, name: '' })); + }, + + isSelected(color) { + return this.currentColor.get() === color; + }, + + events() { + return [{ + 'click .js-palette-color'() { + this.currentColor.set(this.currentData().color); + }, + 'click .js-submit' () { + this.currentSwimlane.setColor(this.currentColor.get()); + Popup.close(); + }, + 'click .js-remove-color'() { + this.currentSwimlane.setColor(null); + Popup.close(); + }, + }]; + }, +}).register('setSwimlaneColorPopup'); diff --git a/client/components/swimlanes/swimlanes.jade b/client/components/swimlanes/swimlanes.jade index 76f54c66..cd864a7c 100644 --- a/client/components/swimlanes/swimlanes.jade +++ b/client/components/swimlanes/swimlanes.jade @@ -1,21 +1,22 @@ template(name="swimlane") .swimlane.js-lists.js-swimlane +swimlaneHeader - if isMiniScreen - if currentList - +list(currentList) + .swimlane.list-group.js-lists + if isMiniScreen + if currentList + +list(currentList) + else + each currentBoard.lists + +miniList(this) + if currentUser.isBoardMember + +addListForm else each currentBoard.lists - +miniList(this) + +list(this) + if currentCardIsInThisList _id ../_id + +cardDetails(currentCard) if currentUser.isBoardMember +addListForm - else - each currentBoard.lists - +list(this) - if currentCardIsInThisList _id ../_id - +cardDetails(currentCard) - if currentUser.isBoardMember - +addListAndSwimlaneForm template(name="listsGroup") .swimlane.list-group.js-lists @@ -35,31 +36,6 @@ template(name="listsGroup") if currentUser.isBoardMember +addListForm -template(name="addListAndSwimlaneForm") - .list.list-composer.js-list-composer - .list-header - +inlinedForm(autoclose=false) - input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}" - autocomplete="off" autofocus) - .edit-controls.clearfix - button.primary.confirm(type="submit") {{_ 'save'}} - a.fa.fa-times-thin.js-close-inlined-form - else - a.open-list-composer.js-open-inlined-form - i.fa.fa-plus - | {{_ 'add-list'}} - .list-header - +inlinedForm(autoclose=false) - input.swimlane-name-input.full-line(type="text" placeholder="{{_ 'add-swimlane'}}" - autocomplete="off" autofocus) - .edit-controls.clearfix - button.primary.confirm(type="submit") {{_ 'save'}} - a.fa.fa-times-thin.js-close-inlined-form - else - a.open-list-composer.js-open-inlined-form - i.fa.fa-plus - | {{_ 'add-swimlane'}} - template(name="addListForm") .list.list-composer.js-list-composer .list-header diff --git a/client/components/swimlanes/swimlanes.js b/client/components/swimlanes/swimlanes.js index 865895a9..71317714 100644 --- a/client/components/swimlanes/swimlanes.js +++ b/client/components/swimlanes/swimlanes.js @@ -175,48 +175,6 @@ BlazeComponent.extendComponent({ }, }).register('addListForm'); -BlazeComponent.extendComponent({ - // Proxy - open() { - this.childComponents('inlinedForm')[0].open(); - }, - - events() { - return [{ - submit(evt) { - evt.preventDefault(); - let titleInput = this.find('.list-name-input'); - if (titleInput) { - const title = titleInput.value.trim(); - if (title) { - Lists.insert({ - title, - boardId: Session.get('currentBoard'), - sort: $('.list').length, - }); - - titleInput.value = ''; - titleInput.focus(); - } - } else { - titleInput = this.find('.swimlane-name-input'); - const title = titleInput.value.trim(); - if (title) { - Swimlanes.insert({ - title, - boardId: Session.get('currentBoard'), - sort: $('.swimlane').length, - }); - - titleInput.value = ''; - titleInput.focus(); - } - } - }, - }]; - }, -}).register('addListAndSwimlaneForm'); - Template.swimlane.helpers({ canSeeAddList() { return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly(); diff --git a/client/components/swimlanes/swimlanes.styl b/client/components/swimlanes/swimlanes.styl index abcc90d4..e4e2cd3b 100644 --- a/client/components/swimlanes/swimlanes.styl +++ b/client/components/swimlanes/swimlanes.styl @@ -5,7 +5,7 @@ // transparent, because that won't work during a swimlane drag. background: darken(white, 13%) display: flex - flex-direction: row + flex-direction: column overflow: 0; max-height: 100% @@ -27,20 +27,15 @@ .swimlane-header-wrap display: flex; flex-direction: row; - flex: 0 0 50px; - padding-bottom: 30px; - border-bottom: 1px solid #CCC + flex: 0 0 24px; + background-color: #ccc; .swimlane-header - -ms-writing-mode: tb-rl; - writing-mode: vertical-rl; - transform: rotate(180deg); font-size: 14px; - line-height: 50px; - margin-top: 50px; + padding: 5px 5px font-weight: bold; min-height: 9px; - width: 50px; + width: 100%; overflow: hidden; -o-text-overflow: ellipsis; text-overflow: ellipsis; @@ -49,7 +44,93 @@ .swimlane-header-menu position: absolute - padding: 20px 20px + padding: 5px 5px + + .swimlane-header-plus-icon + margin-left: 5px + margin-right: 10px .list-group + flex-direction: row height: 100% + +swimlane-color(background, color...) + background: background !important + if color + color: color !important //overwrite text for better visibility + +.swimlane-white + swimlane-color(#ffffff, #4d4d4d) //Black text for better visibility + border: 1px solid #eee + +.swimlane-green + swimlane-color(#3cb500, #ffffff) //White text for better visibility + +.swimlane-yellow + swimlane-color(#fad900, #4d4d4d) //Black text for better visibility + +.swimlane-orange + swimlane-color(#ff9f19, #4d4d4d) //Black text for better visibility + +.swimlane-red + swimlane-color(#eb4646, #ffffff) //White text for better visibility + +.swimlane-purple + swimlane-color(#a632db, #ffffff) //White text for better visibility + +.swimlane-blue + swimlane-color(#0079bf, #ffffff) //White text for better visibility + +.swimlane-pink + swimlane-color(#ff78cb, #4d4d4d) //Black text for better visibility + +.swimlane-sky + swimlane-color(#00c2e0, #ffffff) //White text for better visibility + +.swimlane-black + swimlane-color(#4d4d4d, #ffffff) //White text for better visibility + +.swimlane-lime + swimlane-color(#51e898, #4d4d4d) //Black text for better visibility + +.swimlane-silver + swimlane-color(unset, #4d4d4d) //Black text for better visibility + +.swimlane-peachpuff + swimlane-color(#ffdab9, #4d4d4d) //Black text for better visibility + +.swimlane-crimson + swimlane-color(#dc143c, #ffffff) //White text for better visibility + +.swimlane-plum + swimlane-color(#dda0dd, #4d4d4d) //Black text for better visibility + +.swimlane-darkgreen + swimlane-color(#006400, #ffffff) //White text for better visibility + +.swimlane-slateblue + swimlane-color(#6a5acd, #ffffff) //White text for better visibility + +.swimlane-magenta + swimlane-color(#ff00ff, #ffffff) //White text for better visibility + +.swimlane-gold + swimlane-color(#ffd700, #4d4d4d) //Black text for better visibility + +.swimlane-navy + swimlane-color(#000080, #ffffff) //White text for better visibility + +.swimlane-gray + swimlane-color(#808080, #ffffff) //White text for better visibility + +.swimlane-saddlebrown + swimlane-color(#8b4513, #ffffff) //White text for better visibility + +.swimlane-paleturquoise + swimlane-color(#afeeee, #4d4d4d) //Black text for better visibility + +.swimlane-mistyrose + swimlane-color(#ffe4e1, #4d4d4d) //Black text for better visibility + +.swimlane-indigo + swimlane-color(#4b0082, #ffffff) //White text for better visibility diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 7097af7d..409946bb 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -337,6 +337,7 @@ "list-select-cards": "Select all cards in this list", "listActionPopup-title": "List Actions", "swimlaneActionPopup-title": "Swimlane Actions", + "swimlaneAddPopup-title": "Add a Swimlane below", "listImportCardPopup-title": "Import a Trello card", "listMorePopup-title": "More", "link-list": "Link to this list", @@ -517,7 +518,9 @@ "card-end-on": "Ends on", "editCardReceivedDatePopup-title": "Change received date", "editCardEndDatePopup-title": "Change end date", - "setCardColor-title": "Set color", + "setCardColorPopup-title": "Set color", + "setCardActionsColorPopup-title": "Choose a color", + "setSwimlaneColorPopup-title": "Choose a color", "assigned-by": "Assigned By", "requested-by": "Requested By", "board-delete-notice": "Deleting is permanent. You will lose all lists, cards and actions associated with this board.", diff --git a/models/boards.js b/models/boards.js index 99480ca7..b0f5cecb 100644 --- a/models/boards.js +++ b/models/boards.js @@ -347,10 +347,37 @@ Boards.helpers({ return Lists.find({ boardId: this._id, archived: false }, { sort: { sort: 1 } }); }, + nullSortLists() { + return Lists.find({ + boardId: this._id, + archived: false, + sort: { $eq: null }, + }); + }, + swimlanes() { return Swimlanes.find({ boardId: this._id, archived: false }, { sort: { sort: 1 } }); }, + nextSwimlane(swimlane) { + return Swimlanes.findOne({ + boardId: this._id, + archived: false, + sort: { $gte: swimlane.sort }, + _id: { $ne: swimlane._id }, + }, { + sort: { sort: 1 }, + }); + }, + + nullSortSwimlanes() { + return Swimlanes.find({ + boardId: this._id, + archived: false, + sort: { $eq: null }, + }); + }, + hasOvertimeCards(){ const card = Cards.findOne({isOvertime: true, boardId: this._id, archived: false} ); return card !== undefined; diff --git a/models/cards.js b/models/cards.js index c5d9bf05..ff19a9a0 100644 --- a/models/cards.js +++ b/models/cards.js @@ -69,7 +69,7 @@ Cards.attachSchema(new SimpleSchema({ type: String, optional: true, allowedValues: [ - 'green', 'yellow', 'orange', 'red', 'purple', + 'white', 'green', 'yellow', 'orange', 'red', 'purple', 'blue', 'sky', 'lime', 'pink', 'black', 'silver', 'peachpuff', 'crimson', 'plum', 'darkgreen', 'slateblue', 'magenta', 'gold', 'navy', 'gray', @@ -1526,6 +1526,10 @@ if (Meteor.isServer) { Authentication.checkUserId(req.userId); const paramBoardId = req.params.boardId; const paramListId = req.params.listId; + const currentCards = Cards.find({ + listId: paramListId, + archived: false, + }, { sort: ['sort'] }); const check = Users.findOne({ _id: req.body.authorId, }); @@ -1538,7 +1542,7 @@ if (Meteor.isServer) { description: req.body.description, userId: req.body.authorId, swimlaneId: req.body.swimlaneId, - sort: 0, + sort: currentCards.count(), members, }); JsonRoutes.sendResult(res, { @@ -1571,13 +1575,16 @@ if (Meteor.isServer) { * * @description Edit a card * - * The color has to be chosen between `green`, `yellow`, `orange`, `red`, - * `purple`, `blue`, `sky`, `lime`, `pink`, `black`, `silver`, `peachpuff`, - * `crimson`, `plum`, `darkgreen`, `slateblue`, `magenta`, `gold`, `navy`, - * `gray`, `saddlebrown`, `paleturquoise`, `mistyrose`, `indigo`: + * The color has to be chosen between `white`, `green`, `yellow`, `orange`, + * `red`, `purple`, `blue`, `sky`, `lime`, `pink`, `black`, `silver`, + * `peachpuff`, `crimson`, `plum`, `darkgreen`, `slateblue`, `magenta`, + * `gold`, `navy`, `gray`, `saddlebrown`, `paleturquoise`, `mistyrose`, + * `indigo`: * * <img src="/card-colors.png" width="40%" alt="Wekan card colors" /> * + * Note: setting the color to white has the same effect than removing it. + * * @param {string} boardId the board ID of the card * @param {string} list the list ID of the card * @param {string} cardId the ID of the card diff --git a/models/lists.js b/models/lists.js index 0e1ba801..39ff130a 100644 --- a/models/lists.js +++ b/models/lists.js @@ -314,9 +314,11 @@ if (Meteor.isServer) { try { Authentication.checkUserId( req.userId); const paramBoardId = req.params.boardId; + const board = Boards.findOne(paramBoardId); const id = Lists.insert({ title: req.body.title, boardId: paramBoardId, + sort: board.lists().count(), }); JsonRoutes.sendResult(res, { code: 200, diff --git a/models/swimlanes.js b/models/swimlanes.js index fa5245da..e2c3925c 100644 --- a/models/swimlanes.js +++ b/models/swimlanes.js @@ -49,6 +49,21 @@ Swimlanes.attachSchema(new SimpleSchema({ // XXX We should probably provide a default optional: true, }, + color: { + /** + * the color of the swimlane + */ + type: String, + optional: true, + // silver is the default, so it is left out + allowedValues: [ + 'white', 'green', 'yellow', 'orange', 'red', 'purple', + 'blue', 'sky', 'lime', 'pink', 'black', + 'peachpuff', 'crimson', 'plum', 'darkgreen', + 'slateblue', 'magenta', 'gold', 'navy', 'gray', + 'saddlebrown', 'paleturquoise', 'mistyrose', 'indigo', + ], + }, updatedAt: { /** * when was the swimlane last edited @@ -93,6 +108,12 @@ Swimlanes.helpers({ board() { return Boards.findOne(this.boardId); }, + + colorClass() { + if (this.color) + return this.color; + return ''; + }, }); Swimlanes.mutations({ @@ -107,6 +128,17 @@ Swimlanes.mutations({ restore() { return { $set: { archived: false } }; }, + + setColor(newColor) { + if (newColor === 'silver') { + newColor = null; + } + return { + $set: { + color: newColor, + }, + }; + }, }); Swimlanes.hookOptions.after.update = { fetchPrevious: false }; @@ -224,9 +256,11 @@ if (Meteor.isServer) { try { Authentication.checkUserId( req.userId); const paramBoardId = req.params.boardId; + const board = Boards.findOne(paramBoardId); const id = Swimlanes.insert({ title: req.body.title, boardId: paramBoardId, + sort: board.swimlanes().count(), }); JsonRoutes.sendResult(res, { code: 200, |