mirror of
https://github.com/wekan/wekan.git
synced 2025-04-22 04:57:07 -04:00
Merge pull request #4297 from mfilser/checklist_action_menu_and_move_checklist
Added "move checklist" and created a "Checklist Action Menu"
This commit is contained in:
commit
cd6b4529be
6 changed files with 304 additions and 12 deletions
|
@ -31,7 +31,7 @@ template(name="checklistDetail")
|
|||
.checklist-title
|
||||
span
|
||||
if canModifyCard
|
||||
a.js-delete-checklist.toggle-delete-checklist-dialog {{_ "delete"}}...
|
||||
a.fa.fa-navicon.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}")
|
||||
|
||||
if canModifyCard
|
||||
h2.title.js-open-inlined-form.is-editable
|
||||
|
@ -133,3 +133,41 @@ template(name="boardsSwimlanesAndLists")
|
|||
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-done {{_ 'done'}}
|
||||
|
||||
template(name="checklistActionsPopup")
|
||||
ul.pop-over-list
|
||||
li
|
||||
a.js-delete-checklist.delete-checklist
|
||||
i.fa.fa-trash
|
||||
| {{_ "delete"}} ...
|
||||
a.js-move-checklist.move-checklist
|
||||
i.fa.fa-arrow-right
|
||||
| {{_ "moveChecklist"}} ...
|
||||
|
||||
template(name="moveChecklistPopup")
|
||||
unless currentUser.isWorker
|
||||
label {{_ 'boards'}}:
|
||||
select.js-select-boards(autofocus)
|
||||
each boards
|
||||
if $eq _id currentBoard._id
|
||||
option(value="{{_id}}" selected) {{_ 'current'}}
|
||||
else
|
||||
option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionBoardId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'swimlanes'}}:
|
||||
select.js-select-swimlanes
|
||||
each swimlanes
|
||||
option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'lists'}}:
|
||||
select.js-select-lists
|
||||
each lists
|
||||
option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionListId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'cards'}}:
|
||||
select.js-select-cards
|
||||
each cards
|
||||
option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionCardId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-done {{_ 'done'}}
|
||||
|
|
|
@ -190,13 +190,7 @@ BlazeComponent.extendComponent({
|
|||
return [
|
||||
{
|
||||
...events,
|
||||
'click .toggle-delete-checklist-dialog' : Popup.afterConfirm('checklistDelete', function () {
|
||||
Popup.close();
|
||||
const checklist = this.checklist;
|
||||
if (checklist && checklist._id) {
|
||||
Checklists.remove(checklist._id);
|
||||
}
|
||||
}),
|
||||
'click .js-open-checklist-details-menu': Popup.open('checklistActions'),
|
||||
'submit .js-add-checklist': this.addChecklist,
|
||||
'submit .js-edit-checklist-title': this.editChecklist,
|
||||
'submit .js-add-checklist-item': this.addChecklistItem,
|
||||
|
@ -293,6 +287,23 @@ BlazeComponent.extendComponent({
|
|||
}
|
||||
}).register('addChecklistItemForm');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-delete-checklist' : Popup.afterConfirm('checklistDelete', function () {
|
||||
Popup.back(2);
|
||||
const checklist = this.checklist;
|
||||
if (checklist && checklist._id) {
|
||||
Checklists.remove(checklist._id);
|
||||
}
|
||||
}),
|
||||
'click .js-move-checklist' : Popup.open('moveChecklist'),
|
||||
}
|
||||
]
|
||||
}
|
||||
}).register('checklistActionsPopup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
autosize(this.$('textarea.js-edit-checklist-item'));
|
||||
|
@ -352,3 +363,155 @@ BlazeComponent.extendComponent({
|
|||
];
|
||||
},
|
||||
}).register('checklistItemDetail');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
const boardId = Utils.getCurrentBoardId();
|
||||
subManager.subscribe('board', boardId, false);
|
||||
// subManager.subscribe('swimlane', swimlaneId, false);
|
||||
// subManager.subscribe('list', listId, false);
|
||||
// subManager.subscribe('card', cardId, false);
|
||||
this.selectedBoardId = new ReactiveVar(boardId);
|
||||
this.selectedSwimlaneId = new ReactiveVar('');
|
||||
this.selectedListId = new ReactiveVar('');
|
||||
this.selectedCardId = new ReactiveVar('');
|
||||
this.setMoveChecklistDialogOption(boardId);
|
||||
},
|
||||
|
||||
/** set the last confirmed dialog field values
|
||||
* @param boardId the current board id
|
||||
*/
|
||||
setMoveChecklistDialogOption(boardId) {
|
||||
this.moveChecklistDialogOption = {
|
||||
'boardId' : "",
|
||||
'swimlaneId' : "",
|
||||
'listId' : "",
|
||||
'cardId': "",
|
||||
}
|
||||
|
||||
let currentOptions = Meteor.user().getMoveChecklistDialogOptions();
|
||||
if (currentOptions && boardId && currentOptions[boardId]) {
|
||||
this.moveChecklistDialogOption = currentOptions[boardId];
|
||||
}
|
||||
const board = Boards.findOne(boardId);
|
||||
try {
|
||||
const swimlaneId = board.swimlanes().fetch()[0]._id;
|
||||
this.selectedSwimlaneId.set(swimlaneId);
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
const listId = board.lists().fetch()[0];
|
||||
this.selectedListId.set(listId);
|
||||
} catch (e) {}
|
||||
|
||||
const cardId = Utils.getCurrentCardId();
|
||||
this.selectedCardId.set(cardId);
|
||||
},
|
||||
|
||||
/** returns if the board id was the last confirmed one
|
||||
* @param boardId check this board id
|
||||
* @return if the board id was the last confirmed one
|
||||
*/
|
||||
isMoveChecklistDialogOptionBoardId(boardId) {
|
||||
let ret = this.moveChecklistDialogOption.boardId == boardId;
|
||||
return ret;
|
||||
},
|
||||
|
||||
/** returns if the swimlane id was the last confirmed one
|
||||
* @param swimlaneId check this swimlane id
|
||||
* @return if the swimlane id was the last confirmed one
|
||||
*/
|
||||
isMoveChecklistDialogOptionSwimlaneId(swimlaneId) {
|
||||
let ret = this.moveChecklistDialogOption.swimlaneId == swimlaneId;
|
||||
return ret;
|
||||
},
|
||||
|
||||
/** returns if the list id was the last confirmed one
|
||||
* @param listId check this list id
|
||||
* @return if the list id was the last confirmed one
|
||||
*/
|
||||
isMoveChecklistDialogOptionListId(listId) {
|
||||
let ret = this.moveChecklistDialogOption.listId == listId;
|
||||
return ret;
|
||||
},
|
||||
|
||||
/** returns if the card id was the last confirmed one
|
||||
* @param cardId check this card id
|
||||
* @return if the card id was the last confirmed one
|
||||
*/
|
||||
isMoveChecklistDialogOptionCardId(cardId) {
|
||||
let ret = this.moveChecklistDialogOption.cardId == cardId;
|
||||
return ret;
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: { $ne: Meteor.user().getTemplatesBoardId() },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
swimlanes() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
return board.swimlanes();
|
||||
},
|
||||
|
||||
lists() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
return board.lists();
|
||||
},
|
||||
|
||||
cards() {
|
||||
const list = Lists.findOne(this.selectedListId.get());
|
||||
const ret = list.cards(this.selectedSwimlaneId.get());
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-done'() {
|
||||
const boardSelect = this.$('.js-select-boards')[0];
|
||||
const boardId = boardSelect.options[boardSelect.selectedIndex].value;
|
||||
|
||||
const listSelect = this.$('.js-select-lists')[0];
|
||||
const listId = listSelect.options[listSelect.selectedIndex].value;
|
||||
|
||||
const swimlaneSelect = this.$('.js-select-swimlanes')[0];
|
||||
const swimlaneId = swimlaneSelect.options[swimlaneSelect.selectedIndex].value;
|
||||
|
||||
const cardSelect = this.$('.js-select-cards')[0];
|
||||
const cardId = cardSelect.options[cardSelect.selectedIndex].value;
|
||||
|
||||
const options = {
|
||||
'boardId' : boardId,
|
||||
'swimlaneId' : swimlaneId,
|
||||
'listId' : listId,
|
||||
'cardId': cardId,
|
||||
}
|
||||
Meteor.user().setMoveChecklistDialogOption(boardId, options);
|
||||
this.data().checklist.move(cardId);
|
||||
Popup.back(2);
|
||||
},
|
||||
'change .js-select-boards'(event) {
|
||||
const boardId = $(event.currentTarget).val();
|
||||
subManager.subscribe('board', boardId, false);
|
||||
this.setMoveChecklistDialogOption(boardId);
|
||||
this.selectedBoardId.set(boardId);
|
||||
},
|
||||
'change .js-select-swimlanes'(event) {
|
||||
this.selectedSwimlaneId.set($(event.currentTarget).val());
|
||||
},
|
||||
'change .js-select-lists'(event) {
|
||||
this.selectedListId.set($(event.currentTarget).val());
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('moveChecklistPopup');
|
||||
|
|
|
@ -39,9 +39,6 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
|||
&.is-finished
|
||||
color: #3cb500
|
||||
|
||||
.js-delete-checklist
|
||||
@extends .delete-text
|
||||
|
||||
span.fa.checklist-handle
|
||||
padding-right: 20px
|
||||
padding-top: 3px
|
||||
|
@ -142,3 +139,7 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
|||
background: #dbdbdb
|
||||
color: #222
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.2)
|
||||
|
||||
.checklist-details-menu
|
||||
float: right
|
||||
padding: 6px 10px 6px 10px
|
||||
|
|
|
@ -1138,5 +1138,8 @@
|
|||
"custom-legal-notice-link-url": "Custom legal notice page URL",
|
||||
"acceptance_of_our_legalNotice": "By continuing, you accept our",
|
||||
"legalNotice": "legal notice",
|
||||
"copied": "Copied!"
|
||||
"copied": "Copied!",
|
||||
"checklistActionsPopup-title": "Checklist Actions",
|
||||
"moveChecklist": "Move Checklist",
|
||||
"moveChecklistPopup-title": "Move Checklist"
|
||||
}
|
||||
|
|
|
@ -147,6 +147,37 @@ Checklists.mutations({
|
|||
setTitle(title) {
|
||||
return { $set: { title } };
|
||||
},
|
||||
/** move the checklist to another card
|
||||
* @param newCardId move the checklist to this cardId
|
||||
*/
|
||||
move(newCardId) {
|
||||
// update every activity
|
||||
Activities.find(
|
||||
{checklistId: this._id}
|
||||
).forEach(activity => {
|
||||
Activities.update(activity._id, {
|
||||
$set: {
|
||||
cardId: newCardId,
|
||||
},
|
||||
});
|
||||
});
|
||||
// update every checklist-item
|
||||
ChecklistItems.find(
|
||||
{checklistId: this._id}
|
||||
).forEach(checklistItem => {
|
||||
ChecklistItems.update(checklistItem._id, {
|
||||
$set: {
|
||||
cardId: newCardId,
|
||||
},
|
||||
});
|
||||
});
|
||||
// update the checklist itself
|
||||
return {
|
||||
$set: {
|
||||
cardId: newCardId,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
if (Meteor.isServer) {
|
||||
|
|
|
@ -252,6 +252,38 @@ Users.attachSchema(
|
|||
*/
|
||||
type: String,
|
||||
},
|
||||
'profile.moveChecklistDialog' : {
|
||||
/**
|
||||
* move and copy card dialog
|
||||
*/
|
||||
type: Object,
|
||||
optional: true,
|
||||
blackbox: true,
|
||||
},
|
||||
'profile.moveChecklistDialog.$.boardId': {
|
||||
/**
|
||||
* last selected board id
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
'profile.moveChecklistDialog.$.swimlaneId': {
|
||||
/**
|
||||
* last selected swimlane id
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
'profile.moveChecklistDialog.$.listId': {
|
||||
/**
|
||||
* last selected list id
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
'profile.moveChecklistDialog.$.cardId': {
|
||||
/**
|
||||
* last selected card id
|
||||
*/
|
||||
type: String,
|
||||
},
|
||||
'profile.notifications': {
|
||||
/**
|
||||
* enabled notifications for the user
|
||||
|
@ -653,6 +685,17 @@ Users.helpers({
|
|||
return _ret;
|
||||
},
|
||||
|
||||
/** returns all confirmed move checklist dialog field values
|
||||
* <li> the board, swimlane, list and card id is stored for each board
|
||||
*/
|
||||
getMoveChecklistDialogOptions() {
|
||||
let _ret = {}
|
||||
if (this.profile && this.profile.moveChecklistDialog) {
|
||||
_ret = this.profile.moveChecklistDialog;
|
||||
}
|
||||
return _ret;
|
||||
},
|
||||
|
||||
hasTag(tag) {
|
||||
const { tags = [] } = this.profile || {};
|
||||
return _.contains(tags, tag);
|
||||
|
@ -781,6 +824,19 @@ Users.mutations({
|
|||
},
|
||||
};
|
||||
},
|
||||
/** set the confirmed board id/swimlane id/list id/card id of a board
|
||||
* @param boardId the current board id
|
||||
* @param options an object with the confirmed field values
|
||||
*/
|
||||
setMoveChecklistDialogOption(boardId, options) {
|
||||
let currentOptions = this.getMoveChecklistDialogOptions();
|
||||
currentOptions[boardId] = options;
|
||||
return {
|
||||
$set: {
|
||||
'profile.moveChecklistDialog': currentOptions,
|
||||
},
|
||||
};
|
||||
},
|
||||
toggleBoardStar(boardId) {
|
||||
const queryKind = this.hasStarred(boardId) ? '$pull' : '$addToSet';
|
||||
return {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue