Customize of some card's functions

This commit is contained in:
dollybean 2020-02-04 02:28:45 -08:00
parent 85d47c4ff2
commit 0b00a8095c
21 changed files with 582 additions and 254 deletions

View file

@ -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:

View file

@ -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

View file

@ -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({

View file

@ -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'}}
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'}}
.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.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'}}
.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.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
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
.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 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
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
.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
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
hr
+checklists(cardId = _id)
.card-checklist-attachmentGalerys
.card-checklist-attachmentGalery.card-checklists
+checklists(cardId = _id)
if currentBoard.allowsSubtasks
hr
+subtasks(cardId = _id)
if currentBoard.allowsSubtasks
hr
+subtasks(cardId = _id)
hr
h3
i.fa.fa-paperclip
| {{_ 'attachments'}}
+attachmentsGalery
//- 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

View file

@ -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';

View file

@ -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

View file

@ -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

View file

@ -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({

View file

@ -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

View file

@ -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('');

View file

@ -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"
}

View file

@ -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"
}

View file

@ -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 <body> start",
"add-custom-html-before-body-end": "Add Custom HTML before </body> 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"

View file

@ -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 } };
},

2
package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v3.73.0",
"version": "v3.71.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v3.73.0",
"version": "v3.71.0",
"description": "Open-Source kanban",
"private": true,
"scripts": {

File diff suppressed because one or more lines are too long

View file

@ -1,7 +1,7 @@
swagger: '2.0'
info:
title: Wekan REST API
version: v3.73
version: v3.71
description: |
The REST API allows you to control and extend Wekan with ease.

View file

@ -2,7 +2,10 @@
REM NOTE: You can try this to install Meteor on Windows, it works:
REM https://github.com/zodern/windows-meteor-installer/
<<<<<<< HEAD
=======
>>>>>>> ac37e360b69b799c12f03e1c158cfc0367d26e55
REM Installing Meteor with Chocolatey does not currently work.
REM NOTE: THIS .BAT DOES NOT WORK !!

View file

@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
appTitle = (defaultText = "Wekan"),
# The name of the app as it is displayed to the user.
appVersion = 375,
appVersion = 374,
# Increment this for every release.
appMarketingVersion = (defaultText = "3.73.0~2020-01-29"),
appMarketingVersion = (defaultText = "3.72.0~2020-01-19"),
# Human-readable presentation of the app version.
minUpgradableAppVersion = 0,

View file

@ -42,65 +42,35 @@ RulesHelper = {
performAction(activity, action) {
const card = Cards.findOne({ _id: activity.cardId });
const boardId = activity.boardId;
if (
action.actionType === 'moveCardToTop' ||
action.actionType === 'moveCardToBottom'
) {
let list;
if (action.actionType === 'moveCardToTop') {
let listId;
if (action.listName === '*') {
let list;
if (action.listTitle === '*') {
listId = card.listId;
list = card.list();
if (boardId !== action.boardId) {
list = Lists.findOne({ title: list.title, boardId: action.boardId });
}
} else {
list = Lists.findOne({
title: action.listName,
boardId: action.boardId,
});
}
if (list === undefined) {
listId = '';
} else {
list = Lists.findOne({ title: action.listTitle, boardId });
listId = list._id;
}
let swimlane;
let swimlaneId;
if (action.swimlaneName === '*') {
swimlane = Swimlanes.findOne(card.swimlaneId);
if (boardId !== action.boardId) {
swimlane = Swimlanes.findOne({
title: swimlane.title,
boardId: action.boardId,
});
}
const minOrder = _.min(
list.cardsUnfiltered(card.swimlaneId).map(c => c.sort),
);
card.move(boardId, card.swimlaneId, listId, minOrder - 1);
}
if (action.actionType === 'moveCardToBottom') {
let listId;
let list;
if (action.listTitle === '*') {
listId = card.listId;
list = card.list();
} else {
swimlane = Swimlanes.findOne({
title: action.swimlaneName,
boardId: action.boardId,
});
}
if (swimlane === undefined) {
swimlaneId = Swimlanes.findOne({
title: 'Default',
boardId: action.boardId,
})._id;
} else {
swimlaneId = swimlane._id;
}
if (action.actionType === 'moveCardToTop') {
const minOrder = _.min(
list.cardsUnfiltered(swimlaneId).map(c => c.sort),
);
card.move(action.boardId, swimlaneId, listId, minOrder - 1);
} else {
const maxOrder = _.max(
list.cardsUnfiltered(swimlaneId).map(c => c.sort),
);
card.move(action.boardId, swimlaneId, listId, maxOrder + 1);
list = Lists.findOne({ title: action.listTitle, boardId });
listId = list._id;
}
const maxOrder = _.max(
list.cardsUnfiltered(card.swimlaneId).map(c => c.sort),
);
card.move(boardId, card.swimlaneId, listId, maxOrder + 1);
}
if (action.actionType === 'sendEmail') {
const to = action.emailTo;