diff --git a/client/components/lists/listHeader.jade b/client/components/lists/listHeader.jade index 485058100..a6d7bb5d4 100644 --- a/client/components/lists/listHeader.jade +++ b/client/components/lists/listHeader.jade @@ -165,7 +165,7 @@ template(name="setListWidthPopup") #js-list-width-edit label {{_ 'set-list-width-value'}} p - input.list-width-value(type="number" value="{{ listWidthValue }}" min="100" max="800") + input.list-width-value(type="number" value="{{ listWidthValue }}" min="100") input.list-width-apply(type="submit" value="{{_ 'apply'}}") input.list-width-error diff --git a/client/components/swimlanes/swimlaneHeader.jade b/client/components/swimlanes/swimlaneHeader.jade index 0911ee06b..a92331341 100644 --- a/client/components/swimlanes/swimlaneHeader.jade +++ b/client/components/swimlanes/swimlaneHeader.jade @@ -44,6 +44,9 @@ template(name="swimlaneActionPopup") li: a.js-set-swimlane-color i.fa.fa-paint-brush | {{_ 'select-color'}} + li: a.js-set-swimlane-height + i.fa.fa-arrows-v + | {{_ 'set-swimlane-height'}} unless this.isTemplateContainer hr ul.pop-over-list @@ -82,6 +85,19 @@ template(name="setSwimlaneColorPopup") button.primary.confirm.js-submit {{_ 'save'}} button.js-remove-color.negate.wide.right {{_ 'unset-color'}} +template(name="setSwimlaneHeightPopup") + #js-swimlane-height-edit + label {{_ 'set-swimlane-height-value'}} + p + input.swimlane-height-value(type="number" value="{{ swimlaneHeightValue }}" min="100") + input.swimlane-height-apply(type="submit" value="{{_ 'apply'}}") + input.swimlane-height-error + +template(name="swimlaneHeightErrorPopup") + .swimlane-height-invalid + p {{_ 'swimlane-height-error-message'}} + button.full.js-back-view(type="submit") {{_ 'cancel'}} + template(name="swimlaneDeletePopup") p {{_ "swimlane-delete-pop"}} button.js-confirm.negate.full(type="submit") {{_ 'delete'}} diff --git a/client/components/swimlanes/swimlaneHeader.js b/client/components/swimlanes/swimlaneHeader.js index 5b9398ba3..7803798ff 100644 --- a/client/components/swimlanes/swimlaneHeader.js +++ b/client/components/swimlanes/swimlaneHeader.js @@ -36,6 +36,7 @@ Template.swimlaneFixedHeader.helpers({ Template.swimlaneActionPopup.events({ 'click .js-set-swimlane-color': Popup.open('setSwimlaneColor'), + 'click .js-set-swimlane-height': Popup.open('setSwimlaneHeight'), 'click .js-close-swimlane'(event) { event.preventDefault(); this.archive(); @@ -128,3 +129,45 @@ BlazeComponent.extendComponent({ ]; }, }).register('setSwimlaneColorPopup'); + +BlazeComponent.extendComponent({ + onCreated() { + this.currentSwimlane = this.currentData(); + }, + + applySwimlaneHeight() { + const swimlane = this.currentData(); + const board = swimlane.boardId; + const height = parseInt( + Template.instance() + .$('.swimlane-height-value') + .val(), + 10, + ); + + // FIXME(mark-i-m): where do we put constants? + if (height < 100 || !height) { + Template.instance() + .$('.swimlane-height-error') + .click(); + } else { + Meteor.call('applySwimlaneHeight', board, swimlane._id, height); + Popup.back(); + } + }, + + swimlaneHeightValue() { + const swimlane = this.currentData(); + const board = swimlane.boardId; + return Meteor.user().getSwimlaneHeight(board, swimlane._id); + }, + + events() { + return [ + { + 'click .swimlane-height-apply': this.applySwimlaneHeight, + 'click .swimlane-height-error': Popup.open('swimlaneHeightError'), + }, + ]; + }, +}).register('setSwimlaneHeightPopup'); diff --git a/client/components/swimlanes/swimlanes.css b/client/components/swimlanes/swimlanes.css index 39aa42031..60d3fa0b0 100644 --- a/client/components/swimlanes/swimlanes.css +++ b/client/components/swimlanes/swimlanes.css @@ -116,6 +116,9 @@ left: 87vw; font-size: 24px; } +#js-swimlane-height-edit .swimlane-height-error { + display: none; +} .list-group { height: 100%; } diff --git a/client/components/swimlanes/swimlanes.jade b/client/components/swimlanes/swimlanes.jade index e517da882..02f8e8ec7 100644 --- a/client/components/swimlanes/swimlanes.jade +++ b/client/components/swimlanes/swimlanes.jade @@ -2,7 +2,8 @@ template(name="swimlane") .swimlane +swimlaneHeader unless collapseSwimlane - .swimlane.js-lists.js-swimlane(id="swimlane-{{_id}}") + .swimlane.js-lists.js-swimlane(id="swimlane-{{_id}}" + style="height:{{swimlaneHeight}}px;") if isMiniScreen if currentListIsInThisSwimlane _id +list(currentList) diff --git a/client/components/swimlanes/swimlanes.js b/client/components/swimlanes/swimlanes.js index 2cc3cb21d..cd3eb2806 100644 --- a/client/components/swimlanes/swimlanes.js +++ b/client/components/swimlanes/swimlanes.js @@ -235,6 +235,12 @@ BlazeComponent.extendComponent({ }, ]; }, + + swimlaneHeight() { + const user = Meteor.user(); + const swimlane = Template.currentData(); + return user.getSwimlaneHeight(swimlane.boardId, swimlane._id); + }, }).register('swimlane'); BlazeComponent.extendComponent({ diff --git a/imports/i18n/data/en.i18n.json b/imports/i18n/data/en.i18n.json index f157537d1..42e8f2a3a 100644 --- a/imports/i18n/data/en.i18n.json +++ b/imports/i18n/data/en.i18n.json @@ -87,7 +87,10 @@ "add-card-to-bottom-of-list": "Add Card to Bottom of List", "set-list-width": "Set List Width", "set-list-width-value": "List Width (pixels)", - "list-width-error-message": "List width must be a positive integer between 100 and 800. TODO(mark-i-m): hard-coded constants", + "list-width-error-message": "List width must be a positive integer >=100. TODO(mark-i-m): hard-coded constants", + "set-swimlane-height": "Set Swimlane Height", + "set-swimlane-height-value": "Swimlane Height (pixels)", + "swimlane-height-error-message": "Swimlane height must be a positive integer >=100. TODO(mark-i-m): hard-coded constants", "add-swimlane": "Add Swimlane", "add-subtask": "Add Subtask", "add-checklist": "Add Checklist", diff --git a/models/users.js b/models/users.js index d6487df82..a34f80664 100644 --- a/models/users.js +++ b/models/users.js @@ -791,6 +791,19 @@ Users.helpers({ } }, + getSwimlaneHeights() { + const { swimlaneHeights = {} } = this.profile || {}; + return swimlaneHeights; + }, + getSwimlaneHeight(boardId, listId) { + const swimlaneHeights = this.getSwimlaneHeights(); + if (swimlaneHeights[boardId] && swimlaneHeights[boardId][listId]) { + return swimlaneHeights[boardId][listId]; + } else { + return 270; //TODO(mark-i-m): default? + } + }, + /** returns all confirmed move and copy dialog field values *
  • the board, swimlane and list id is stored for each board */ @@ -1181,6 +1194,19 @@ Users.mutations({ }, }; }, + + setSwimlaneHeight(boardId, swimlaneId, height) { + let currentHeights = this.getSwimlaneHeights(); + if (!currentHeights[boardId]) { + currentHeights[boardId] = {}; + } + currentHeights[boardId][swimlaneId] = height; + return { + $set: { + 'profile.swimlaneHeights': currentHeights, + }, + }; + }, }); Meteor.methods({ @@ -1231,6 +1257,13 @@ Meteor.methods({ const user = Meteor.user(); user.setListWidth(boardId, listId, width); }, + applySwimlaneHeight(boardId, swimlaneId, height) { + check(boardId, String); + check(swimlaneId, String); + check(height, Number); + const user = Meteor.user(); + user.setSwimlaneHeight(boardId, swimlaneId, height); + }, }); if (Meteor.isServer) {