From 0b00a8095ce34c753e5edac86d4b62e8aaa1b1e0 Mon Sep 17 00:00:00 2001 From: dollybean Date: Tue, 4 Feb 2020 02:28:45 -0800 Subject: Customize of some card's functions --- CHANGELOG.md | 4 +- Stackerfile.yml | 2 +- client/components/boards/boardHeader.js | 1 + client/components/cards/cardDetails.jade | 243 ++++++++++++---------- client/components/cards/cardDetails.js | 87 ++++++++ client/components/main/editor.js | 4 + client/components/rules/actions/boardActions.jade | 37 ++-- client/components/rules/actions/boardActions.js | 30 +-- client/components/sidebar/sidebar.jade | 29 +++ client/components/sidebar/sidebar.js | 125 +++++++++++ i18n/en.i18n.json | 9 +- i18n/it.i18n.json | 20 +- i18n/ja.i18n.json | 42 ++-- models/boards.js | 117 +++++++++++ package-lock.json | 2 +- package.json | 2 +- public/api/wekan.html | 9 +- public/api/wekan.yml | 2 +- rebuild-wekan.bat | 3 + sandstorm-pkgdef.capnp | 4 +- server/rulesHelper.js | 74 ++----- 21 files changed, 587 insertions(+), 259 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ef0d452..ee0e5683 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,9 @@ -# v3.73 2020-01-29 Wekan release +# Upcoming Wekan release This release adds the following new features: - [Login to Wekan with Nextcloud](https://github.com/wekan/wekan/pull/2897). Thanks to bogie. -- [Add rule action to move cards to other boards](https://github.com/wekan/wekan/pull/2899). - Thanks to peterverraedt. and fixes the following bugs: diff --git a/Stackerfile.yml b/Stackerfile.yml index 19fb5c81..7162e4fc 100644 --- a/Stackerfile.yml +++ b/Stackerfile.yml @@ -1,5 +1,5 @@ appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928 -appVersion: "v3.73.0" +appVersion: "v3.72.0" files: userUploads: - README.md diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index eea43bd3..8dea0f85 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -30,6 +30,7 @@ Template.boardMenuPopup.events({ 'click .js-outgoing-webhooks': Popup.open('outgoingWebhooks'), 'click .js-import-board': Popup.open('chooseBoardSource'), 'click .js-subtask-settings': Popup.open('boardSubtaskSettings'), + 'click .js-Date-settings': Popup.open('boardDateSettings') }); Template.boardMenuPopup.helpers({ diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade index de4e102a..aec95486 100644 --- a/client/components/cards/cardDetails.jade +++ b/client/components/cards/cardDetails.jade @@ -8,10 +8,13 @@ template(name="cardDetails") a.fa.fa-times-thin.close-card-details.js-close-card-details if currentUser.isBoardMember a.fa.fa-navicon.card-details-menu.js-open-card-details-menu + input.inline-input(type="text" id="cardURL_copy" value="{{ absoluteUrl }}" autofocus="autofocus") + a.fa.fa-link.card-copy-button.js-copy-link if isMiniScreen a.fa.fa-times-thin.close-card-details-mobile-web.js-close-card-details if currentUser.isBoardMember a.fa.fa-navicon.card-details-menu-mobile-web.js-open-card-details-menu + a.fa.fa-link.card-copy-mobile-button h2.card-details-title.js-card-title( class="{{#if canModifyCard}}js-open-inlined-form is-editable{{/if}}") +viewer @@ -36,49 +39,41 @@ template(name="cardDetails") p.warning {{_ 'card-archived'}} .card-details-items - .card-details-item.card-details-item-received - h3 - i.fa.fa-sign-out - card-details-item-title {{_ 'card-received'}} - if getReceived - +cardReceivedDate - else - if canModifyCard - unless currentUser.isWorker - a.js-received-date {{_ 'add'}} - - .card-details-item.card-details-item-start - h3 - i.fa.fa-hourglass-start - card-details-item-title {{_ 'card-start'}} - if getStart - +cardStartDate - else - if canModifyCard - unless currentUser.isWorker - a.js-start-date {{_ 'add'}} - - .card-details-item.card-details-item-due - h3 - i.fa.fa-sign-in - card-details-item-title {{_ 'card-due'}} - if getDue - +cardDueDate - else - if canModifyCard - unless currentUser.isWorker - a.js-due-date {{_ 'add'}} - - .card-details-item.card-details-item-end - h3 - i.fa.fa-hourglass-end - card-details-item-title {{_ 'card-end'}} - if getEnd - +cardEndDate - else - if canModifyCard - unless currentUser.isWorker - a.js-end-date {{_ 'add'}} + if currentBoard.allowsReceivedDate + .card-details-item.card-details-item-received + h3 + i.fa.fa-sign-out + card-details-item-title {{_ 'card-received'}} + if getReceived + +cardReceivedDate + else + if canModifyCard + unless currentUser.isWorker + a.js-received-date {{_ 'add'}} + + if currentBoard.allowsStartDate + .card-details-item.card-details-item-start + h3 + i.fa.fa-hourglass-start + card-details-item-title {{_ 'card-start'}} + if getStart + +cardStartDate + else + if canModifyCard + unless currentUser.isWorker + a.js-start-date {{_ 'add'}} + + if currentBoard.allowsEndDate + .card-details-item.card-details-item-end + h3 + i.fa.fa-hourglass-end + card-details-item-title {{_ 'card-end'}} + if getEnd + +cardEndDate + else + if canModifyCard + unless currentUser.isWorker + a.js-end-date {{_ 'add'}} .card-details-items .card-details-item.card-details-item-members @@ -92,22 +87,34 @@ template(name="cardDetails") unless currentUser.isWorker a.member.add-member.card-details-item-add-button.js-add-members(title="{{_ 'card-members-title'}}") i.fa.fa-plus - - .card-details-item.card-details-item-assignees - h3 - i.fa.fa-user - card-details-item-title {{_ 'assignee'}} - each getAssignees - +userAvatarAssignee(userId=this cardId=../_id) - | {{! XXX Hack to hide syntaxic coloration /// }} - if canModifyCard - a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}") - i.fa.fa-plus - if currentUser.isWorker - unless assigneeSelected + if currentBoard.allowsDueDate + .card-details-item.card-details-item-due + h3 + i.fa.fa-sign-in + card-details-item-title {{_ 'card-due'}} + if getDue + +cardDueDate + else + if canModifyCard + unless currentUser.isWorker + a.card-label.add-label.js-due-date + i.fa.fa-plus + + if assigngeeSelected + .card-details-item.card-details-item-assignees + h3 + i.fa.fa-user + card-details-item-title {{_ 'assignee'}} + each getAssignees + +userAvatarAssignee(userId=this cardId=../_id) + | {{! XXX Hack to hide syntaxic coloration /// }} + if canModifyCard a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}") i.fa.fa-plus - + if currentUser.isWorker + unless assigneeSelected + a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}") + i.fa.fa-plus .card-details-item.card-details-item-labels h3 @@ -143,9 +150,9 @@ template(name="cardDetails") //- XXX We should use "editable" to avoid repetiting ourselves if canModifyCard unless currentUser.isWorker - h3 - i.fa.fa-align-left - card-details-item-title {{_ 'description'}} + //h3 + //- i.fa.fa-align-left + //- card-details-item-title {{_ 'description'}} +inlinedCardDescription(classNames="card-description js-card-description") +editor(autofocus=true) | {{getUnsavedValue 'cardDescription' _id getDescription}} @@ -153,16 +160,16 @@ template(name="cardDetails") button.primary(type="submit") {{_ 'save'}} a.fa.fa-times-thin.js-close-inlined-form else - a.js-open-inlined-form + a.description-item.add-description.js-open-inlined-form if getDescription +viewer = getDescription else - | {{_ 'edit'}} + | {{_ 'addmore-detail'}} if (hasUnsavedValue 'cardDescription' _id) p.quiet | {{_ 'unsaved-description'}} - a.js-open-inlined-form {{_ 'view-it'}} + a.description-item.add-description.js-open-inlined-form {{_ 'view-it'}} = ' - ' a.js-close-inlined-form {{_ 'discard'}} else if getDescription @@ -171,57 +178,59 @@ template(name="cardDetails") = getDescription .card-details-items - .card-details-item.card-details-item-name - h3 - i.fa.fa-shopping-cart - card-details-item-title {{_ 'requested-by'}} - if canModifyCard - unless currentUser.isWorker - +inlinedForm(classNames="js-card-details-requester") - +editCardRequesterForm - else - a.js-open-inlined-form - if getRequestedBy - +viewer - = getRequestedBy - else - | {{_ 'add'}} - else if getRequestedBy - +viewer - = getRequestedBy - - .card-details-item.card-details-item-name - h3 - i.fa.fa-user-plus - card-details-item-title {{_ 'assigned-by'}} - if canModifyCard - unless currentUser.isWorker - +inlinedForm(classNames="js-card-details-assigner") - +editCardAssignerForm - else - a.js-open-inlined-form - if getAssignedBy - +viewer - = getAssignedBy - else - | {{_ 'add'}} - else if getRequestedBy - +viewer - = getAssignedBy - - hr - +checklists(cardId = _id) - - if currentBoard.allowsSubtasks - hr - +subtasks(cardId = _id) - - hr - h3 - i.fa.fa-paperclip - | {{_ 'attachments'}} + if requestBySelected + .card-details-item.card-details-item-name + h3 + i.fa.fa-shopping-cart + card-details-item-title {{_ 'requested-by'}} + if canModifyCard + unless currentUser.isWorker + +inlinedForm(classNames="js-card-details-requester") + +editCardRequesterForm + else + a.js-open-inlined-form + if getRequestedBy + +viewer + = getRequestedBy + else + | {{_ 'add'}} + else if getRequestedBy + +viewer + = getRequestedBy - +attachmentsGalery + if assigneeBySelected + .card-details-item.card-details-item-name + h3 + i.fa.fa-user-plus + card-details-item-title {{_ 'assigned-by'}} + if canModifyCard + unless currentUser.isWorker + +inlinedForm(classNames="js-card-details-assigner") + +editCardAssignerForm + else + a.js-open-inlined-form + if getAssignedBy + +viewer + = getAssignedBy + else + | {{_ 'add'}} + else if getRequestedBy + +viewer + = getAssignedBy + + .card-checklist-attachmentGalerys + .card-checklist-attachmentGalery.card-checklists + +checklists(cardId = _id) + if currentBoard.allowsSubtasks + hr + +subtasks(cardId = _id) + + //- hr + //- h3 + //- i.fa.fa-paperclip + //- | {{_ 'attachments'}} + .card-checklist-attachmentGalery.card-attachmentGalery + +attachmentsGalery hr unless currentUser.isNoComments @@ -239,7 +248,13 @@ template(name="cardDetails") label.toggle-label(for="toggleButton") if currentUser.isBoardMember unless currentUser.isNoComments - +commentForm + if canModifyCard + +inlinedForm(autoclose=false classNames="js-new-comment-form") + +commentForm + else + +userAvatar(userId=currentUser._id) + a.comment-item.add-comment.js-open-inlined-form + | {{_ 'Write Comment'}} unless currentUser.isNoComments if isLoaded.get if isLinkedCard diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js index 07dcac44..231cbb10 100644 --- a/client/components/cards/cardDetails.js +++ b/client/components/cards/cardDetails.js @@ -279,6 +279,29 @@ BlazeComponent.extendComponent({ 'click .js-close-card-details'() { Utils.goBoardId(this.data().boardId); }, + 'click .js-copy-link'() { + StringToCopyElement = document.getElementById('cardURL_copy'); + StringToCopyElement.select(); + if (document.execCommand('copy')) { + StringToCopyElement.blur(); + } else { + document.getElementById('cardURL_copy').selectionStart = 0; + document.getElementById('cardURL_copy').selectionEnd = 999; + document.execCommand('copy'); + if (window.getSelection) { + if (window.getSelection().empty) { + // Chrome + window.getSelection().empty(); + } else if (window.getSelection().removeAllRanges) { + // Firefox + window.getSelection().removeAllRanges(); + } + } else if (document.selection) { + // IE? + document.selection.empty(); + } + } + }, 'click .js-open-card-details-menu': Popup.open('cardDetailsActions'), 'submit .js-card-description'(event) { event.preventDefault(); @@ -371,6 +394,54 @@ Template.cardDetails.helpers({ }); }, + receivedSelected() { + if (this.getReceived().length === 0) { + return false; + } else { + return true; + } + }, + + startSelected() { + if (this.getstart().length === 0) { + return false; + } else { + return true; + } + }, + + endSelected() { + if (this.getEnd().length === 0) { + return false; + } else { + return true; + } + }, + + dueSelected() { + if (this.getDue().length === 0) { + return false; + } else { + return true; + } + }, + + memberSelected() { + if (this.getMembers().length === 0) { + return false; + } else { + return true; + } + }, + + labelSelected() { + if (this.getLabels().length === 0) { + return false; + } else { + return true; + } + }, + assigneeSelected() { if (this.getAssignees().length === 0) { return false; @@ -379,6 +450,22 @@ Template.cardDetails.helpers({ } }, + requestBySelected() { + if (this.getRequestBy().length === 0) { + return false; + } else { + return true; + } + }, + + assigneeBySelected() { + if (this.getAssigneeBy().length === 0) { + return false; + } else { + return true; + } + }, + memberType() { const user = Users.findOne(this.userId); return user && user.isBoardAdmin() ? 'admin' : 'normal'; diff --git a/client/components/main/editor.js b/client/components/main/editor.js index 39c03aa9..6c5b72b7 100755 --- a/client/components/main/editor.js +++ b/client/components/main/editor.js @@ -120,6 +120,10 @@ Template.editor.onRendered(() => { autosize($textarea); $textarea.escapeableTextComplete(mentions); }; +<<<<<<< HEAD +======= + +>>>>>>> ac37e360b69b799c12f03e1c158cfc0367d26e55 if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR !== false) { const isSmall = Utils.isMiniScreen(); const toolbar = isSmall diff --git a/client/components/rules/actions/boardActions.jade b/client/components/rules/actions/boardActions.jade index fda15062..6034184c 100644 --- a/client/components/rules/actions/boardActions.jade +++ b/client/components/rules/actions/boardActions.jade @@ -1,42 +1,29 @@ template(name="boardActions") div.trigger-item div.trigger-content - div.trigger-text + div.trigger-text | {{_'r-move-card-to'}} div.trigger-dropdown select(id="move-gen-action") option(value="top") {{_'r-top-of'}} option(value="bottom") {{_'r-bottom-of'}} - div.trigger-text + div.trigger-text | {{_'r-its-list'}} div.trigger-button.js-add-gen-move-action.js-goto-rules i.fa.fa-plus div.trigger-item div.trigger-content - div.trigger-text + div.trigger-text | {{_'r-move-card-to'}} div.trigger-dropdown select(id="move-spec-action") option(value="top") {{_'r-top-of'}} option(value="bottom") {{_'r-bottom-of'}} - div.trigger-text - | {{_'r-the-board'}} - div.trigger-dropdown - select(id="board-id") - each boards - if $eq _id currentBoard._id - option(value="{{_id}}" selected) {{_ 'current'}} - else - option(value="{{_id}}") {{title}} - div.trigger-text - | {{_'r-in-list'}} + div.trigger-text + | {{_'r-list'}} div.trigger-dropdown input(id="listName",type=text,placeholder="{{_'r-name'}}") - div.trigger-text - | {{_'r-in-swimlane'}} - div.trigger-dropdown - input(id="swimlaneName",type=text,placeholder="{{_'r-name'}}") div.trigger-button.js-add-spec-move-action.js-goto-rules i.fa.fa-plus @@ -46,14 +33,14 @@ template(name="boardActions") select(id="arch-action") option(value="archive") {{_'r-archive'}} option(value="unarchive") {{_'r-unarchive'}} - div.trigger-text + div.trigger-text | {{_'r-card'}} div.trigger-button.js-add-arch-action.js-goto-rules i.fa.fa-plus div.trigger-item div.trigger-content - div.trigger-text + div.trigger-text | {{_'r-add-swimlane'}} div.trigger-dropdown input(id="swimlane-name",type=text,placeholder="{{_'r-name'}}") @@ -62,15 +49,15 @@ template(name="boardActions") div.trigger-item div.trigger-content - div.trigger-text + div.trigger-text | {{_'r-create-card'}} div.trigger-dropdown input(id="card-name",type=text,placeholder="{{_'r-name'}}") - div.trigger-text + div.trigger-text | {{_'r-in-list'}} div.trigger-dropdown input(id="list-name",type=text,placeholder="{{_'r-name'}}") - div.trigger-text + div.trigger-text | {{_'r-in-swimlane'}} div.trigger-dropdown input(id="swimlane-name2",type=text,placeholder="{{_'r-name'}}") @@ -78,8 +65,8 @@ template(name="boardActions") i.fa.fa-plus - - + + diff --git a/client/components/rules/actions/boardActions.js b/client/components/rules/actions/boardActions.js index c2f2375a..8568d2bf 100644 --- a/client/components/rules/actions/boardActions.js +++ b/client/components/rules/actions/boardActions.js @@ -1,22 +1,6 @@ BlazeComponent.extendComponent({ onCreated() {}, - boards() { - const boards = Boards.find( - { - archived: false, - 'members.userId': Meteor.userId(), - _id: { - $ne: Meteor.user().getTemplatesBoardId(), - }, - }, - { - sort: ['title'], - }, - ); - return boards; - }, - events() { return [ { @@ -68,18 +52,15 @@ BlazeComponent.extendComponent({ const ruleName = this.data().ruleName.get(); const trigger = this.data().triggerVar.get(); const actionSelected = this.find('#move-spec-action').value; - const swimlaneName = this.find('#swimlaneName').value; - const listName = this.find('#listName').value; + const listTitle = this.find('#listName').value; const boardId = Session.get('currentBoard'); - const destBoardId = this.find('#board-id').value; const desc = Utils.getTriggerActionDesc(event, this); if (actionSelected === 'top') { const triggerId = Triggers.insert(trigger); const actionId = Actions.insert({ actionType: 'moveCardToTop', - listName, - swimlaneName, - boardId: destBoardId, + listTitle, + boardId, desc, }); Rules.insert({ @@ -93,9 +74,8 @@ BlazeComponent.extendComponent({ const triggerId = Triggers.insert(trigger); const actionId = Actions.insert({ actionType: 'moveCardToBottom', - listName, - swimlaneName, - boardId: destBoardId, + listTitle, + boardId, desc, }); Rules.insert({ diff --git a/client/components/sidebar/sidebar.jade b/client/components/sidebar/sidebar.jade index 8e84cd61..fc5ff3a6 100644 --- a/client/components/sidebar/sidebar.jade +++ b/client/components/sidebar/sidebar.jade @@ -72,6 +72,25 @@ template(name="boardChangeColorPopup") if isSelected i.fa.fa-check +template(name="boardDateSettingsPopup") + form.board-Date-settings + div.check-div + a.flex.js-field-has-receiveddate(class="{{#if allowsReceivedDate}}is-checked{{/if}}") + .materialCheckBox(class="{{#if allowsReceivedDate}}is-checked{{/if}}") + span {{_ 'show-receiveddate-field'}} + div.check-div + a.flex.js-field-has-startdate(class="{{#if allowsStartDate}}is-checked{{/if}}") + .materialCheckBox(class="{{#if allowsStartDate}}is-checked{{/if}}") + span {{_ 'show-startdate-field'}} + div.check-div + a.flex.js-field-has-enddate(class="{{#if allowsEndDate}}is-checked{{/if}}") + .materialCheckBox(class="{{#if allowsEndDate}}is-checked{{/if}}") + span {{_ 'show-enddate-field'}} + div.check-div + a.flex.js-field-has-duedate(class="{{#if allowsDueDate}}is-checked{{/if}}") + .materialCheckBox(class="{{#if allowsDueDate}}is-checked{{/if}}") + span {{_ 'show-duedate-field'}} + template(name="boardSubtaskSettingsPopup") form.board-subtask-settings h3 {{_ 'show-parent-in-minicard'}} @@ -201,6 +220,10 @@ template(name="boardMenuPopup") a.js-subtask-settings i.fa.fa-sitemap | {{_ 'subtask-settings'}} + li + a.js-Date-settings + i.fa.fa-calendar + | {{_ 'Date-settings'}} unless currentBoard.isTemplatesBoard hr ul.pop-over-list @@ -238,6 +261,12 @@ template(name="boardMenuPopup") a.js-subtask-settings i.fa.fa-sitemap | {{_ 'subtask-settings'}} + hr + ul.pop-over-list + li + a.js-Date-settings + i.fa.fa-calendar + | {{_ 'Date-settings'}} template(name="labelsWidget") .board-widget.board-widget-labels diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js index e8f38b8c..d909a8ae 100644 --- a/client/components/sidebar/sidebar.js +++ b/client/components/sidebar/sidebar.js @@ -208,6 +208,7 @@ Template.boardMenuPopup.events({ 'click .js-outgoing-webhooks': Popup.open('outgoingWebhooks'), 'click .js-import-board': Popup.open('chooseBoardSource'), 'click .js-subtask-settings': Popup.open('boardSubtaskSettings'), + 'click .js-Date-settings': Popup.open('boardDateSettings') }); Template.boardMenuPopup.helpers({ @@ -585,6 +586,130 @@ BlazeComponent.extendComponent({ }, }).register('boardSubtaskSettingsPopup'); +BlazeComponent.extendComponent({ + onCreated(){ + this.currentBoard = Boards.findOne(Session.get('currentBoard')); + }, + + allowsReceivedDate(){ + return this.currentBoard.allowsReceivedDate; + }, + + allowsStartDate(){ + return this.currentBoard.allowsStartDate; + }, + + allowsEndDate(){ + return this.currentBoard.allowsEndDate; + }, + + allowsDueDate(){ + return this.currentBoard.allowsDueDate; + }, + + isBoardSelected(){ + return this.currentBoard.dateSettingsDefaultBoardID + }, + + isNullBoardSelected() { + return ( + this.currentBoard.dateSettingsDefaultBoardId === null || + this.currentBoard.dateSettingsDefaultBoardId === undefined + ); + }, + + boards() { + return Boards.find( + { + archived: false, + 'members.userId': Meteor.userId(), + }, + { + sort: ['title'], + }, + ); + }, + + lists() { + return Lists.find( + { + boardId: this.currentBoard._id, + archived: false, + }, + { + sort: ['title'], + }, + ); + }, + + hasLists() { + return this.lists().count() > 0; + }, + + isListSelected() { + return this.currentBoard.dateSettingsDefaultBoardId === this.currentData()._id; + }, + + events() { + return [ + { + 'click .js-field-has-receiveddate'(evt) { + evt.preventDefault(); + this.currentBoard.allowsReceivedDate = !this.currentBoard.allowsReceivedDate; + this.currentBoard.setAllowsReceivedDate(this.currentBoard.allowsReceivedDate); + $(`.js-field-has-receiveddate ${MCB}`).toggleClass( + CKCLS, + this.currentBoard.allowsReceivedDate, + ); + $('.js-field-has-receiveddate').toggleClass( + CKCLS, + this.currentBoard.allowsReceivedDate, + ); + }, + 'click .js-field-has-startdate'(evt) { + evt.preventDefault(); + this.currentBoard.allowsStartDate = !this.currentBoard.allowsStartDate; + this.currentBoard.setAllowsStartDate(this.currentBoard.allowsStartDate); + $(`.js-field-has-startdate ${MCB}`).toggleClass( + CKCLS, + this.currentBoard.allowsStartDate, + ); + $('.js-field-has-startdate').toggleClass( + CKCLS, + this.currentBoard.allowsStartDate, + ); + }, + 'click .js-field-has-enddate'(evt) { + evt.preventDefault(); + this.currentBoard.allowsEndDate = !this.currentBoard.allowsEndDate; + this.currentBoard.setAllowsEndDate(this.currentBoard.allowsEndDate); + $(`.js-field-has-enddate ${MCB}`).toggleClass( + CKCLS, + this.currentBoard.allowsEndDate, + ); + $('.js-field-has-enddate').toggleClass( + CKCLS, + this.currentBoard.allowsEndDate, + ); + }, + 'click .js-field-has-duedate'(evt) { + evt.preventDefault(); + this.currentBoard.allowsDueDate = !this.currentBoard.allowsDueDate; + this.currentBoard.setAllowsDueDate(this.currentBoard.allowsDueDate); + $(`.js-field-has-duedate ${MCB}`).toggleClass( + CKCLS, + this.currentBoard.allowsDueDate, + ); + $('.js-field-has-duedate').toggleClass( + CKCLS, + this.currentBoard.allowsDueDate, + ); + }, + }, + ]; + }, +}).register('boardDateSettingsPopup'); + BlazeComponent.extendComponent({ onCreated() { this.error = new ReactiveVar(''); diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 64fada1a..0892c953 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -583,8 +583,14 @@ "default": "Default", "queue": "Queue", "subtask-settings": "Subtasks Settings", + "Date-settings": "Dates Settings", "boardSubtaskSettingsPopup-title": "Board Subtasks Settings", + "boardDateSettingsPopup-title": "Board Dates Settings", "show-subtasks-field": "Cards can have subtasks", + "show-receiveddate-field": "Cards can have Received Date", + "show-startdate-field": "Cards can have Start Date", + "show-enddate-field": "Cards can have End Date", + "show-duedate-field": "Cards can have Due Date", "deposit-subtasks-board": "Deposit subtasks to this board:", "deposit-subtasks-list": "Landing list for subtasks deposited here:", "show-parent-in-minicard": "Show parent in minicard:", @@ -756,5 +762,6 @@ "hide-minicard-label-text": "Hide minicard label text", "show-desktop-drag-handles": "Show desktop drag handles", "assignee": "Assignee", - "cardAssigneesPopup-title": "Assignee" + "cardAssigneesPopup-title": "Assignee", + "addmore-detail": "Add a more detailed description" } diff --git a/i18n/it.i18n.json b/i18n/it.i18n.json index fc7efefd..f9b64bac 100644 --- a/i18n/it.i18n.json +++ b/i18n/it.i18n.json @@ -137,7 +137,7 @@ "board-view": "Visualizza bacheca", "board-view-cal": "Calendario", "board-view-swimlanes": "Diagramma Swimlane", - "board-view-collapse": "Collassa", + "board-view-collapse": "Collapse", "board-view-lists": "Liste", "bucket-example": "Per esempio come \"una lista di cose da fare\"", "cancel": "Cancella", @@ -223,7 +223,7 @@ "comment-only-desc": "Puoi commentare solo le schede.", "no-comments": "Non ci sono commenti.", "no-comments-desc": "Impossibile visualizzare commenti o attività.", - "worker": "Lavoratore", + "worker": "Worker", "worker-desc": "Può solo spostare schede, assegnarsi una scheda e commentare.", "computer": "Computer", "confirm-subtask-delete-dialog": "Sei sicuro di voler eliminare il sotto-compito?", @@ -309,7 +309,7 @@ "list-sort-by": "Ordina la lista per:", "list-label-modifiedAt": "Orario ultimo accesso", "list-label-title": "Nome della lista", - "list-label-sort": "Il tuo ordine manuale", + "list-label-sort": "Your Manual Order", "list-label-short-modifiedAt": "(L)", "list-label-short-title": "(N)", "list-label-short-sort": "(M)", @@ -527,11 +527,11 @@ "webhook-title": "Nome Webhook", "webhook-token": "Token (facoltativo per l'autenticazione)", "outgoing-webhooks": "Server esterni", - "bidirectional-webhooks": "Webhook a due vie", + "bidirectional-webhooks": "Two-Way Webhooks", "outgoingWebhooksPopup-title": "Server esterni", "boardCardTitlePopup-title": "Filtro per Titolo Scheda", "disable-webhook": "Disattiva questo Webhook", - "global-webhook": "Webhook globali", + "global-webhook": "Global Webhooks", "new-outgoing-webhook": "Nuovo webhook in uscita", "no-name": "(Sconosciuto)", "Node_version": "Versione di Node", @@ -707,7 +707,7 @@ "r-df-due-at": "scadenza", "r-df-end-at": "fine", "r-df-received-at": "ricevuta", - "r-to-current-datetime": "a data/ora corrente", + "r-to-current-datetime": "to current date/time", "r-remove-value-from": "Rimuovi valore da", "ldap": "LDAP", "oauth2": "Oauth2", @@ -750,8 +750,8 @@ "act-atUserComment": "You were mentioned in [__board__] __list__/__card__", "delete-user-confirm-popup": "Sei sicuro di voler cancellare questo profilo? Non sarà possibile ripristinarlo.", "accounts-allowUserDelete": "Permetti agli utenti di cancellare il loro profilo", - "hide-minicard-label-text": "Nascondi etichetta minicard", - "show-desktop-drag-handles": "Mostra maniglie di trascinamento del desktop", - "assignee": "Assegnatario", - "cardAssigneesPopup-title": "Assegnatario" + "hide-minicard-label-text": "Hide minicard label text", + "show-desktop-drag-handles": "Show desktop drag handles", + "assignee": "Assignee", + "cardAssigneesPopup-title": "Assignee" } diff --git a/i18n/ja.i18n.json b/i18n/ja.i18n.json index 22a0917f..a64e5eb7 100644 --- a/i18n/ja.i18n.json +++ b/i18n/ja.i18n.json @@ -90,9 +90,9 @@ "addMemberPopup-title": "メンバー", "admin": "管理", "admin-desc": "カードの閲覧と編集、メンバーの削除、ボードの設定変更が可能", - "admin-announcement": "アナウンス", - "admin-announcement-active": "システム全体アナウンスを有効化", - "admin-announcement-title": "管理者からのアナウンス", + "admin-announcement": "Announcement", + "admin-announcement-active": "Active System-Wide Announcement", + "admin-announcement-title": "Announcement from Administrator", "all-boards": "全てのボード", "and-n-other-card": "And __count__ other card", "and-n-other-card_plural": "And __count__ other cards", @@ -109,7 +109,7 @@ "archived-items": "アーカイブ", "archived-boards": "アーカイブ済みボード", "restore-board": "ボードをリストア", - "no-archived-boards": "アーカイブ済みボードはありません。", + "no-archived-boards": "No Boards in Archive.", "archives": "アーカイブ", "template": "テンプレート", "templates": "テンプレート", @@ -142,7 +142,7 @@ "bucket-example": "例:バケットリスト", "cancel": "キャンセル", "card-archived": "This card is moved to Archive.", - "board-archived": "このボードをアーカイブしました。", + "board-archived": "This board is moved to Archive.", "card-comments-title": "%s 件のコメントがあります。", "card-delete-notice": "削除は取り消しできません。このカードに関係するすべてのアクションがなくなります。", "card-delete-pop": "すべての内容がアクティビティから削除されます。この削除は元に戻すことができません。", @@ -516,7 +516,7 @@ "smtp-password": "パスワード", "smtp-tls": "TLSサポート", "send-from": "送信元", - "send-smtp-test": "テストメールを自分に送信", + "send-smtp-test": "Send a test email to yourself", "invitation-code": "招待コード", "email-invite-register-subject": "__inviter__さんがあなたを招待しています", "email-invite-register-text": "Dear __user__,\n\n__inviter__ invites you to kanban board for collaborations.\n\nPlease follow the link below:\n__url__\n\nAnd your invitation code is: __icode__\n\nThanks.", @@ -535,7 +535,7 @@ "new-outgoing-webhook": "発信Webフックの作成", "no-name": "(Unknown)", "Node_version": "Nodeバージョン", - "Meteor_version": "Meteor バージョン", + "Meteor_version": "Meteor version", "MongoDB_version": "MongoDB version", "MongoDB_storage_engine": "MongoDB storage engine", "MongoDB_Oplog_enabled": "MongoDB Oplog enabled", @@ -559,7 +559,7 @@ "no": "いいえ", "accounts": "アカウント", "accounts-allowEmailChange": "メールアドレスの変更を許可", - "accounts-allowUserNameChange": "ユーザー名の変更を許可", + "accounts-allowUserNameChange": "Allow Username Change", "createdAt": "Created at", "verified": "Verified", "active": "Active", @@ -579,11 +579,11 @@ "delete-board-confirm-popup": "すべてのリスト、カード、ラベル、アクティビティは削除され、ボードの内容を元に戻すことができません。", "boardDeletePopup-title": "ボードを削除しますか?", "delete-board": "ボードを削除", - "default-subtasks-board": "__board__ ボードのサブタスク", + "default-subtasks-board": "Subtasks for __board__ board", "default": "Default", "queue": "Queue", - "subtask-settings": "サブタスク設定", - "boardSubtaskSettingsPopup-title": "ボードのサブタスク設定", + "subtask-settings": "Subtasks Settings", + "boardSubtaskSettingsPopup-title": "Board Subtasks Settings", "show-subtasks-field": "Cards can have subtasks", "deposit-subtasks-board": "Deposit subtasks to this board:", "deposit-subtasks-list": "Landing list for subtasks deposited here:", @@ -596,11 +596,11 @@ "parent-card": "Parent card", "source-board": "Source board", "no-parent": "Don't show parent", - "activity-added-label": "ラベル '%s' を %s に追加しました", - "activity-removed-label": "ラベル '%s' を %s から削除しました", + "activity-added-label": "added label '%s' to %s", + "activity-removed-label": "removed label '%s' from %s", "activity-delete-attach": "deleted an attachment from %s", - "activity-added-label-card": "ラベル '%s' を追加しました", - "activity-removed-label-card": "ラベル '%s' を削除しました", + "activity-added-label-card": "added label '%s'", + "activity-removed-label-card": "removed label '%s'", "activity-delete-attach-card": "deleted an attachment", "activity-set-customfield": "set custom field '%s' to '%s' in %s", "activity-unset-customfield": "unset custom field '%s' in %s", @@ -650,7 +650,7 @@ "r-card": "card", "r-add": "追加", "r-remove": "Remove", - "r-label": "ラベル", + "r-label": "label", "r-member": "member", "r-remove-all": "Remove all members from the card", "r-set-color": "Set color to", @@ -677,7 +677,7 @@ "r-d-archive": "Move card to Archive", "r-d-unarchive": "Restore card from Archive", "r-d-add-label": "Add label", - "r-d-remove-label": "ラベルの削除", + "r-d-remove-label": "Remove label", "r-create-card": "Create new card", "r-in-list": "リスト:", "r-in-swimlane": "in swimlane", @@ -714,15 +714,15 @@ "cas": "CAS", "authentication-method": "認証方式", "authentication-type": "認証タイプ", - "custom-product-name": "カスタム製品名", + "custom-product-name": "Custom Product Name", "layout": "レイアウト", "hide-logo": "ロゴを隠す", "add-custom-html-after-body-start": "Add Custom HTML after start", "add-custom-html-before-body-end": "Add Custom HTML before end", "error-undefined": "Something went wrong", "error-ldap-login": "An error occurred while trying to login", - "display-authentication-method": "認証方式を表示", - "default-authentication-method": "デフォルトの認証方式", + "display-authentication-method": "Display Authentication Method", + "default-authentication-method": "Default Authentication Method", "duplicate-board": "ボードの複製", "people-number": "The number of people is:", "swimlaneDeletePopup-title": "スイムレーンを削除しますか?", @@ -750,7 +750,7 @@ "act-atUserComment": "You were mentioned in [__board__] __list__/__card__", "delete-user-confirm-popup": "Are you sure you want to delete this account? There is no undo.", "accounts-allowUserDelete": "ユーザー自身のアカウント削除を許可", - "hide-minicard-label-text": "ミニカードのラベル名を隠す", + "hide-minicard-label-text": "Hide minicard label text", "show-desktop-drag-handles": "Show desktop drag handles", "assignee": "Assignee", "cardAssigneesPopup-title": "Assignee" diff --git a/models/boards.js b/models/boards.js index 4e193dc7..121272ec 100644 --- a/models/boards.js +++ b/models/boards.js @@ -278,6 +278,7 @@ Boards.attachSchema( optional: true, defaultValue: null, }, + subtasksDefaultListId: { /** * The default List ID assigned to subtasks. @@ -286,6 +287,19 @@ Boards.attachSchema( optional: true, defaultValue: null, }, + + dateSettingsDefaultBoardId: { + type: String, + optional: true, + defaultValue: null, + }, + + dateSettingsDefaultListId: { + type: String, + optional: true, + defaultValue: null, + }, + allowsSubtasks: { /** * Does the board allows subtasks? @@ -293,6 +307,39 @@ Boards.attachSchema( type: Boolean, defaultValue: true, }, + + allowsReceivedDate: { + /** + * Does the board allows received date? + */ + type: Boolean, + defaultValue: true, + }, + + allowsStartDate: { + /** + * Does the board allows start date? + */ + type: Boolean, + defaultValue: true, + }, + + allowsEndDate: { + /** + * Does the board allows end date? + */ + type: Boolean, + defaultValue: true, + }, + + allowsDueDate: { + /** + * Does the board allows due date? + */ + type: Boolean, + defaultValue: true, + }, + presentParentTask: { /** * Controls how to present the parent task: @@ -710,6 +757,39 @@ Boards.helpers({ return Boards.findOne(this.getDefaultSubtasksBoardId()); }, +//Date Settings option such as received date, start date and so on. + getDefaultDateSettingsBoardId() { + if ( + this.dateSettingsDefaultBoardId === null || + this.dateSettingsDefaultBoardId === undefined + ) { + this.dateSettingsDefaultBoardId = Boards.insert({ + title: `^${this.title}^`, + permission: this.permission, + members: this.members, + color: this.color, + description: TAPi18n.__('default-dates-board', { + board: this.title, + }), + }); + + Swimlanes.insert({ + title: TAPi18n.__('default'), + boardId: this.dateSettingsDefaultBoardId, + }); + Boards.update(this._id, { + $set: { + dateSettingsDefaultBoardId: this.dateSettingsDefaultBoardId, + }, + }); + } + return this.dateSettingsDefaultBoardId; + }, + + getDefaultDateSettingsBoard() { + return Boards.findOne(this.getDefaultDateSettingsBoardId()); + }, + getDefaultSubtasksListId() { if ( this.subtasksDefaultListId === null || @@ -728,6 +808,24 @@ Boards.helpers({ return Lists.findOne(this.getDefaultSubtasksListId()); }, + getDefaultDateSettingsListId() { + if ( + this.dateSettingsDefaultListId === null || + this.dateSettingsDefaultListId === undefined + ) { + this.dateSettingsDefaultListId = Lists.insert({ + title: TAPi18n.__('queue'), + boardId: this._id, + }); + this.setDateSettingsDefaultListId(this.dateSettingsDefaultListId); + } + return this.dateSettingsDefaultListId; + }, + + getDefaultDateSettingsList() { + return Lists.findOne(this.getDefaultDateSettingsListId()); + }, + getDefaultSwimline() { let result = Swimlanes.findOne({ boardId: this._id }); if (result === undefined) { @@ -925,6 +1023,25 @@ Boards.mutations({ return { $set: { allowsSubtasks } }; }, + setAllowsReceivedDate(allowsReceivedDate) { + return { $set: { allowsReceivedDate } }; + }, + + + setAllowsStartDate(allowsStartDate) { + return { $set: { allowsStartDate } }; + }, + + + setAllowsEndDate(allowsEndDate) { + return { $set: { allowsEndDate } }; + }, + + + setAllowsDueDate(allowsDueDate) { + return { $set: { allowsDueDate } }; + }, + setSubtasksDefaultBoardId(subtasksDefaultBoardId) { return { $set: { subtasksDefaultBoardId } }; }, diff --git a/package-lock.json b/package-lock.json index 3509389c..6af17fd9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "wekan", - "version": "v3.73.0", + "version": "v3.71.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 3c31c0e9..c29d5224 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wekan", - "version": "v3.73.0", + "version": "v3.71.0", "description": "Open-Source kanban", "private": true, "scripts": { diff --git a/public/api/wekan.html b/public/api/wekan.html index 18154fa5..7d3c180a 100644 --- a/public/api/wekan.html +++ b/public/api/wekan.html @@ -1457,6 +1457,7 @@ Darkula color scheme from the JetBrains family of IDEs .php .xml { opacity: 0.5; } +<<<<<<< HEAD +======= + + +>>>>>>> ac37e360b69b799c12f03e1c158cfc0367d26e55 @@ -1524,7 +1529,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc