diff options
-rw-r--r-- | client/components/activities/activities.js | 4 | ||||
-rw-r--r-- | client/components/boards/boardHeader.jade | 2 | ||||
-rw-r--r-- | client/components/boards/boardHeader.js | 2 | ||||
-rw-r--r-- | client/components/cards/cardDetails.jade | 15 | ||||
-rw-r--r-- | client/components/cards/cardDetails.js | 15 | ||||
-rw-r--r-- | client/components/sidebar/sidebar.js | 2 | ||||
-rw-r--r-- | client/components/sidebar/sidebar.styl | 61 | ||||
-rw-r--r-- | client/components/sidebar/sidebarCustomFields.jade | 44 | ||||
-rw-r--r-- | client/components/sidebar/sidebarCustomFields.js | 36 | ||||
-rw-r--r-- | i18n/en.i18n.json | 17 | ||||
-rw-r--r-- | models/boards.js | 4 | ||||
-rw-r--r-- | models/customFields.js | 21 | ||||
-rw-r--r-- | server/publications/boards.js | 1 |
13 files changed, 157 insertions, 67 deletions
diff --git a/client/components/activities/activities.js b/client/components/activities/activities.js index 81645a51..95699961 100644 --- a/client/components/activities/activities.js +++ b/client/components/activities/activities.js @@ -92,8 +92,8 @@ BlazeComponent.extendComponent({ }, customField() { - const customField = this.currentData().customFieldId; - return customField; + const customField = this.currentData().customField(); + return customField.name; }, events() { diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade index 67acdc9e..9d16b10a 100644 --- a/client/components/boards/boardHeader.jade +++ b/client/components/boards/boardHeader.jade @@ -103,7 +103,7 @@ template(name="boardHeaderBar") template(name="boardMenuPopup") ul.pop-over-list - li: a.js-custom-fields {{_ 'custom-fields'}} + li: a.js-configure-custom-fields {{_ 'configure-custom-fields'}} li: a.js-open-archives {{_ 'archived-items'}} if currentUser.isBoardAdmin li: a.js-change-board-color {{_ 'board-change-color'}} diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index 8983c722..61cdb149 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -1,6 +1,6 @@ Template.boardMenuPopup.events({ 'click .js-rename-board': Popup.open('boardChangeTitle'), - 'click .js-custom-fields'() { + 'click .js-configure-custom-fields'() { Sidebar.setView('customFields'); Popup.close(); }, diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index 09e0532c..ccb3ae97 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -107,6 +107,7 @@ template(name="cardDetailsActionsPopup") li: a.js-members {{_ 'card-edit-members'}} li: a.js-labels {{_ 'card-edit-labels'}} li: a.js-attachments {{_ 'card-edit-attachments'}} + li: a.js-custom-fields {{_ 'card-edit-custom-fields'}} li: a.js-start-date {{_ 'editCardStartDatePopup-title'}} li: a.js-due-date {{_ 'editCardDueDatePopup-title'}} hr @@ -143,6 +144,20 @@ template(name="cardMembersPopup") if isCardMember i.fa.fa-check +template(name="cardCustomFieldsPopup") + ul.pop-over-list + each board.customFields + li.item(class="") + a.name.js-select-field(href="#") + span.full-name + = name + if isCardMember + i.fa.fa-check + hr + a.quiet-button.full.js-configure-custom-fields + i.fa.fa-cog + span {{_ 'configure-custom-fields'}} + template(name="cardMorePopup") p.quiet span.clearfix diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 7c6c3ce7..f972424f 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -154,6 +154,7 @@ Template.cardDetailsActionsPopup.events({ 'click .js-members': Popup.open('cardMembers'), 'click .js-labels': Popup.open('cardLabels'), 'click .js-attachments': Popup.open('cardAttachments'), + 'click .js-custom-fields': Popup.open('cardCustomFields'), 'click .js-start-date': Popup.open('editCardStartDate'), 'click .js-due-date': Popup.open('editCardDueDate'), 'click .js-move-card': Popup.open('moveCard'), @@ -196,6 +197,20 @@ Template.editCardTitleForm.events({ }, }); +Template.cardCustomFieldsPopup.events({ + 'click .js-select-field'(evt) { + const card = Cards.findOne(Session.get('currentCard')); + const customFieldId = this.customFieldId; + card.toggleCustomField(customFieldId); + evt.preventDefault(); + }, + 'click .js-configure-custom-fields'(evt) { + EscapeActions.executeUpTo('detailsPane'); + Sidebar.setView('customFields'); + evt.preventDefault(); + } +}); + Template.moveCardPopup.events({ 'click .js-select-list' () { // XXX We should *not* get the currentCard from the global state, but diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js index 59a2b42c..0ff73215 100644 --- a/client/components/sidebar/sidebar.js +++ b/client/components/sidebar/sidebar.js @@ -5,7 +5,7 @@ const defaultView = 'home'; const viewTitles = { filter: 'filter-cards', multiselection: 'multi-selection', - customFields: 'custom-fields', + customFields: 'configure-custom-fields', archives: 'archives', }; diff --git a/client/components/sidebar/sidebar.styl b/client/components/sidebar/sidebar.styl index 8f2f493e..740186b5 100644 --- a/client/components/sidebar/sidebar.styl +++ b/client/components/sidebar/sidebar.styl @@ -45,28 +45,45 @@ display: flex flex-direction: column - li > a - display: flex - height: 30px - margin: 0 - padding: 4px - border-radius: 3px - align-items: center - - &:hover - &, i, .quiet - color white - - .member, .card-label - margin-right: 7px - margin-top: 5px - - .sidebar-list-item-description - flex: 1 - overflow: ellipsis - - .fa.fa-check - margin: 0 4px + li + & > a + display: flex + height: 30px + margin: 0 + padding: 4px + border-radius: 3px + align-items: center + + &:hover + &, i, .quiet + color white + + .member, .card-label + margin-right: 7px + margin-top: 5px + + .minicard-edit-button + float: right + padding: 8px + border-radius: 3px + + .sidebar-list-item-description + flex: 1 + overflow: ellipsis + + .fa.fa-check + margin: 0 4px + + .minicard + padding: 6px 8px 4px + + .minicard-edit-button + float: right + padding: 4px + border-radius: 3px + + &:hover + background: #dbdbdb .sidebar-btn display: block diff --git a/client/components/sidebar/sidebarCustomFields.jade b/client/components/sidebar/sidebarCustomFields.jade index 33688441..e17bb75d 100644 --- a/client/components/sidebar/sidebarCustomFields.jade +++ b/client/components/sidebar/sidebarCustomFields.jade @@ -1,31 +1,49 @@ template(name="customFieldsSidebar") ul.sidebar-list - each customsFields + each customFields li - a.name - span.sidebar-list-item-description - {{_ 'some name'}} + div.minicard-wrapper.js-minicard + div.minicard + a.fa.fa-pencil.js-edit-custom-field.minicard-edit-button + div.minicard-title + | {{ name }} ({{ type }}) + if currentUser.isBoardMember hr a.sidebar-btn.js-open-create-custom-field i.fa.fa-plus - span {{_ 'Create Custom Field'}} + span {{_ 'createCustomField'}} template(name="createCustomFieldPopup") form label | {{_ 'name'}} - input.js-field-name(type="text" name="field-name" autofocus) + unless _id + input.js-field-name(type="text" name="field-name" autofocus) + else + input.js-field-name(type="text" name="field-name" value=name) + label | {{_ 'type'}} - select.js-field-type(name="field-type") - option(value="string") String - option(value="number") Number - option(value="checkbox") Checkbox - option(value="date") Date - option(value="DropdownList") Dropdown List + select.js-field-type(name="field-type" disabled="{{#if _id}}disabled{{/if}}") + each types + if selected + option(value=type selected="selected") {{name}} + else + option(value=type) {{name}} a.flex.js-field-show-on-card .materialCheckBox(class="{{#if showOnCard}}is-checked{{/if}}") span {{_ 'show-field-on-card'}} - input.primary.wide(type="submit" value="{{_ 'save'}}")
\ No newline at end of file + button.primary.wide.left(type="submit") + | {{_ 'save'}} + if _id + button.negate.wide.right.js-delete-custom-field + | {{_ 'delete'}} + +template(name="editCustomFieldPopup") + | {{> createCustomFieldPopup}} + +template(name="deleteCustomFieldPopup") + p {{_ "custom-field-delete-pop"}} + button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
\ No newline at end of file diff --git a/client/components/sidebar/sidebarCustomFields.js b/client/components/sidebar/sidebarCustomFields.js index da03f484..6ddd466e 100644 --- a/client/components/sidebar/sidebarCustomFields.js +++ b/client/components/sidebar/sidebarCustomFields.js @@ -9,21 +9,22 @@ BlazeComponent.extendComponent({ events() { return [{ 'click .js-open-create-custom-field': Popup.open('createCustomField'), - 'click .js-edit-custom-field'() { - // todo - }, - 'click .js-delete-custom-field': Popup.afterConfirm('customFieldDelete', function() { - const customFieldId = this._id; - CustomFields.remove(customFieldId); - Popup.close(); - }), + 'click .js-edit-custom-field': Popup.open('editCustomField'), }]; }, }).register('customFieldsSidebar'); Template.createCustomFieldPopup.helpers({ - + types() { + var currentType = this.type; + return ['text', 'number', 'checkbox', 'date', 'dropdown']. + map(type => {return { + type: type, + name: TAPi18n.__('custom-field-' + type), + selected: type == currentType, + }}); + }, }); Template.createCustomFieldPopup.events({ @@ -41,7 +42,7 @@ Template.createCustomFieldPopup.events({ const name = tpl.find('.js-field-name').value.trim(); const type = tpl.find('.js-field-type').value.trim(); const showOnCard = tpl.find('.js-field-show-on-card.is-checked') != null; - //console.log("Create",name,type,showOnCard); + //console.log('Create',name,type,showOnCard); CustomFields.insert({ boardId: Session.get('currentBoard'), @@ -52,4 +53,17 @@ Template.createCustomFieldPopup.events({ Popup.back(); }, -});
\ No newline at end of file + 'click .js-delete-custom-field': Popup.afterConfirm('deleteCustomField', function() { + const customFieldId = this._id; + CustomFields.remove(customFieldId); + Popup.close(); + }), +}); + +/*Template.deleteCustomFieldPopup.events({ + 'submit'(evt) { + const customFieldId = this._id; + CustomFields.remove(customFieldId); + Popup.close(); + } +});*/
\ No newline at end of file diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index d7b9a48b..1039d3c6 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -103,6 +103,7 @@ "card-due": "Due", "card-due-on": "Due on", "card-edit-attachments": "Edit attachments", + "card-edit-custom-fields": "Edit custom fields", "card-edit-labels": "Edit labels", "card-edit-members": "Edit members", "card-labels-title": "Change the labels for the card.", @@ -110,6 +111,7 @@ "card-start": "Start", "card-start-on": "Starts on", "cardAttachmentsPopup-title": "Attach From", + "cardCustomFieldsPopup-title": "Edit custom fields", "cardDeletePopup-title": "Delete Card?", "cardDetailsActionsPopup-title": "Card Actions", "cardLabelsPopup-title": "Labels", @@ -153,16 +155,22 @@ "create": "Create", "createBoardPopup-title": "Create Board", "chooseBoardSourcePopup-title": "Import board", + "configure-custom-fields": "Configure Custom Fields", "createLabelPopup-title": "Create Label", - "createCustomField": "Create Custom Field", - "createCustomFieldPopup-title": "Create Custom Field", + "createCustomField": "Create Field", + "createCustomFieldPopup-title": "Create Field", "current": "current", - "custom-fields": "Custom Fields", - "customFieldDeletePopup-title": "Delete Card?", + "custom-field-delete-pop": "There is no undo. This will remove this custom field from all cards and destroy its history.", + "custom-field-checkbox": "Checkbox", + "custom-field-date": "Date", + "custom-field-dropdown": "Dropdown List", + "custom-field-number": "Number", + "custom-field-text": "Text", "date": "Date", "decline": "Decline", "default-avatar": "Default avatar", "delete": "Delete", + "deleteCustomFieldPopup-title": "Delete Custom Field?", "deleteLabelPopup-title": "Delete Label?", "description": "Description", "disambiguateMultiLabelPopup-title": "Disambiguate Label Action", @@ -175,6 +183,7 @@ "edit-profile": "Edit Profile", "editCardStartDatePopup-title": "Change start date", "editCardDueDatePopup-title": "Change due date", + "editCustomFieldPopup-title": "Edit Field", "editLabelPopup-title": "Change Label", "editNotificationPopup-title": "Edit Notification", "editProfilePopup-title": "Edit Profile", diff --git a/models/boards.js b/models/boards.js index 8a7844e2..98c0e46d 100644 --- a/models/boards.js +++ b/models/boards.js @@ -235,6 +235,10 @@ Boards.helpers({ return `board-color-${this.color}`; }, + customFields() { + return CustomFields.find({ boardId: this._id }, { sort: { name: 1 } }); + }, + // XXX currently mutations return no value so we have an issue when using addLabel in import // XXX waiting on https://github.com/mquandalle/meteor-collection-mutations/issues/1 to remove... pushLabel(name, color) { diff --git a/models/customFields.js b/models/customFields.js index 75ee55e8..5e76db35 100644 --- a/models/customFields.js +++ b/models/customFields.js @@ -25,7 +25,7 @@ CustomFields.allow({ remove(userId, doc) { return allowIsBoardMember(userId, Boards.findOne(doc.boardId)); }, - fetch: ['boardId'], + fetch: ['userId', 'boardId'], }); // not sure if we need this? @@ -41,21 +41,18 @@ function customFieldCreation(userId, doc){ } if (Meteor.isServer) { - // Comments are often fetched within a card, so we create an index to make these - // queries more efficient. - Meteor.startup(() => { - CardComments._collection._ensureIndex({ cardId: 1, createdAt: -1 }); - }); + /*Meteor.startup(() => { + CustomFields._collection._ensureIndex({ boardId: 1}); + });*/ CustomFields.after.insert((userId, doc) => { customFieldCreation(userId, doc); }); CustomFields.after.remove((userId, doc) => { - const activity = Activities.findOne({ customFieldId: doc._id }); - if (activity) { - Activities.remove(activity._id); - } + Activities.remove({ + customFieldId: doc._id, + }); }); } @@ -70,7 +67,7 @@ if (Meteor.isServer) { }); }); - JsonRoutes.add('GET', '/api/boards/:boardId/comments/:customFieldId', function (req, res, next) { + JsonRoutes.add('GET', '/api/boards/:boardId/custom-fields/:customFieldId', function (req, res, next) { Authentication.checkUserId( req.userId); const paramBoardId = req.params.boardId; const paramCustomFieldId = req.params.customFieldId; @@ -90,7 +87,7 @@ if (Meteor.isServer) { boardId: paramBoardId, }); - const customField = CustomFields.findOne({_id: id, cardId:paramCardId, boardId: paramBoardId }); + const customField = CustomFields.findOne({_id: id, boardId: paramBoardId }); customFieldCreation(req.body.authorId, customField); JsonRoutes.sendResult(res, { diff --git a/server/publications/boards.js b/server/publications/boards.js index f482f619..7cadf0c6 100644 --- a/server/publications/boards.js +++ b/server/publications/boards.js @@ -74,6 +74,7 @@ Meteor.publishRelations('board', function(boardId) { }, { limit: 1 }), function(boardId, board) { this.cursor(Lists.find({ boardId })); this.cursor(Integrations.find({ boardId })); + this.cursor(CustomFields.find({ boardId }, { sort: { name: 1 } })); // Cards and cards comments // XXX Originally we were publishing the card documents as a child of the |