mirror of
https://github.com/wekan/wekan.git
synced 2025-12-16 07:20:12 +01:00
Add UI for importing card-as-card and board-as-card
This commit is contained in:
parent
193af893ee
commit
dcc7b2970f
8 changed files with 199 additions and 1 deletions
|
|
@ -225,9 +225,12 @@ textarea
|
||||||
|
|
||||||
.edit-controls,
|
.edit-controls,
|
||||||
.add-controls
|
.add-controls
|
||||||
|
display: flex
|
||||||
|
align-items: baseline
|
||||||
margin-top: 0
|
margin-top: 0
|
||||||
|
|
||||||
button[type=submit]
|
button[type=submit]
|
||||||
|
input[type=button]
|
||||||
float: left
|
float: left
|
||||||
height: 32px
|
height: 32px
|
||||||
margin-top: -2px
|
margin-top: -2px
|
||||||
|
|
|
||||||
|
|
@ -187,3 +187,14 @@
|
||||||
padding: 7px
|
padding: 7px
|
||||||
top: -@padding
|
top: -@padding
|
||||||
right: 17px
|
right: 17px
|
||||||
|
|
||||||
|
.import-board-wrapper
|
||||||
|
display: flex
|
||||||
|
align-items: baseline
|
||||||
|
|
||||||
|
.js-import-board
|
||||||
|
margin-left: 15px
|
||||||
|
|
||||||
|
.search-card-results
|
||||||
|
max-height: 250px
|
||||||
|
overflow: hidden
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,59 @@ template(name="addCardForm")
|
||||||
|
|
||||||
.add-controls.clearfix
|
.add-controls.clearfix
|
||||||
button.primary.confirm(type="submit") {{_ 'add'}}
|
button.primary.confirm(type="submit") {{_ 'add'}}
|
||||||
a.fa.fa-times-thin.js-close-inlined-form
|
span.quiet
|
||||||
|
| {{_ 'or'}}
|
||||||
|
a.js-import {{_ 'import'}}
|
||||||
|
|
||||||
template(name="autocompleteLabelLine")
|
template(name="autocompleteLabelLine")
|
||||||
.minicard-label(class="card-label-{{colorName}}" title=labelName)
|
.minicard-label(class="card-label-{{colorName}}" title=labelName)
|
||||||
span(class="{{#if hasNoName}}quiet{{/if}}")= labelName
|
span(class="{{#if hasNoName}}quiet{{/if}}")= labelName
|
||||||
|
|
||||||
|
template(name="importCardPopup")
|
||||||
|
label {{_ 'boards'}}:
|
||||||
|
.import-board-wrapper
|
||||||
|
select.js-select-boards
|
||||||
|
each boards
|
||||||
|
if $eq _id currentBoard._id
|
||||||
|
option(value="{{_id}}" selected) {{_ 'current'}}
|
||||||
|
else
|
||||||
|
option(value="{{_id}}") {{title}}
|
||||||
|
input.primary.confirm.js-import-board(type="submit" value="{{_ 'add'}}")
|
||||||
|
|
||||||
|
label {{_ 'swimlanes'}}:
|
||||||
|
select.js-select-swimlanes
|
||||||
|
each swimlanes
|
||||||
|
option(value="{{_id}}") {{title}}
|
||||||
|
|
||||||
|
label {{_ 'lists'}}:
|
||||||
|
select.js-select-lists
|
||||||
|
each lists
|
||||||
|
option(value="{{_id}}") {{title}}
|
||||||
|
|
||||||
|
label {{_ 'cards'}}:
|
||||||
|
select.js-select-lists
|
||||||
|
each cards
|
||||||
|
option(value="{{_id}}") {{title}}
|
||||||
|
|
||||||
|
.edit-controls.clearfix
|
||||||
|
input.primary.confirm.js-done(type="submit" value="{{_ 'done'}}")
|
||||||
|
span.quiet
|
||||||
|
| {{_ 'or'}}
|
||||||
|
a.js-search {{_ 'search'}}
|
||||||
|
|
||||||
|
template(name="searchCardPopup")
|
||||||
|
label {{_ 'boards'}}:
|
||||||
|
.import-board-wrapper
|
||||||
|
select.js-select-boards
|
||||||
|
each boards
|
||||||
|
if $eq _id currentBoard._id
|
||||||
|
option(value="{{_id}}" selected) {{_ 'current'}}
|
||||||
|
else
|
||||||
|
option(value="{{_id}}") {{title}}
|
||||||
|
form.js-search-term-form
|
||||||
|
input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus)
|
||||||
|
.list-body.js-perfect-scrollbar.search-card-results
|
||||||
|
.minicards.clearfix.js-minicards
|
||||||
|
each results
|
||||||
|
a.minicard-wrapper.js-minicard
|
||||||
|
+minicard(this)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
const subManager = new SubsManager();
|
||||||
|
|
||||||
BlazeComponent.extendComponent({
|
BlazeComponent.extendComponent({
|
||||||
mixins() {
|
mixins() {
|
||||||
return [Mixins.PerfectScrollbar];
|
return [Mixins.PerfectScrollbar];
|
||||||
|
|
@ -55,6 +57,7 @@ BlazeComponent.extendComponent({
|
||||||
boardId: boardId._id,
|
boardId: boardId._id,
|
||||||
sort: sortIndex,
|
sort: sortIndex,
|
||||||
swimlaneId,
|
swimlaneId,
|
||||||
|
type: 'cardType-card',
|
||||||
});
|
});
|
||||||
// In case the filter is active we need to add the newly inserted card in
|
// In case the filter is active we need to add the newly inserted card in
|
||||||
// the list of exceptions -- cards that are not filtered. Otherwise the
|
// the list of exceptions -- cards that are not filtered. Otherwise the
|
||||||
|
|
@ -197,6 +200,7 @@ BlazeComponent.extendComponent({
|
||||||
events() {
|
events() {
|
||||||
return [{
|
return [{
|
||||||
keydown: this.pressKey,
|
keydown: this.pressKey,
|
||||||
|
'click .js-import': Popup.open('importCard'),
|
||||||
}];
|
}];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -268,3 +272,105 @@ BlazeComponent.extendComponent({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}).register('addCardForm');
|
}).register('addCardForm');
|
||||||
|
|
||||||
|
BlazeComponent.extendComponent({
|
||||||
|
onCreated() {
|
||||||
|
subManager.subscribe('board', Session.get('currentBoard'));
|
||||||
|
this.selectedBoardId = new ReactiveVar(Session.get('currentBoard'));
|
||||||
|
},
|
||||||
|
|
||||||
|
boards() {
|
||||||
|
const boards = Boards.find({
|
||||||
|
archived: false,
|
||||||
|
'members.userId': Meteor.userId(),
|
||||||
|
}, {
|
||||||
|
sort: ['title'],
|
||||||
|
});
|
||||||
|
return boards;
|
||||||
|
},
|
||||||
|
|
||||||
|
swimlanes() {
|
||||||
|
const board = Boards.findOne(this.selectedBoardId.get());
|
||||||
|
return board.swimlanes();
|
||||||
|
},
|
||||||
|
|
||||||
|
lists() {
|
||||||
|
const board = Boards.findOne(this.selectedBoardId.get());
|
||||||
|
return board.lists();
|
||||||
|
},
|
||||||
|
|
||||||
|
cards() {
|
||||||
|
const board = Boards.findOne(this.selectedBoardId.get());
|
||||||
|
return board.cards();
|
||||||
|
},
|
||||||
|
|
||||||
|
events() {
|
||||||
|
return [{
|
||||||
|
'change .js-select-boards'(evt) {
|
||||||
|
this.selectedBoardId.set($(evt.currentTarget).val());
|
||||||
|
subManager.subscribe('board', this.selectedBoardId.get());
|
||||||
|
},
|
||||||
|
'submit .js-done' (evt) {
|
||||||
|
// IMPORT CARD
|
||||||
|
evt.preventDefault();
|
||||||
|
// XXX We should *not* get the currentCard from the global state, but
|
||||||
|
// instead from a “component” state.
|
||||||
|
const card = Cards.findOne(Session.get('currentCard'));
|
||||||
|
const lSelect = $('.js-select-lists')[0];
|
||||||
|
const newListId = lSelect.options[lSelect.selectedIndex].value;
|
||||||
|
const slSelect = $('.js-select-swimlanes')[0];
|
||||||
|
card.swimlaneId = slSelect.options[slSelect.selectedIndex].value;
|
||||||
|
Popup.close();
|
||||||
|
},
|
||||||
|
'submit .js-import-board' (evt) {
|
||||||
|
//IMPORT BOARD
|
||||||
|
evt.preventDefault();
|
||||||
|
Popup.close();
|
||||||
|
},
|
||||||
|
'click .js-search': Popup.open('searchCard'),
|
||||||
|
}];
|
||||||
|
},
|
||||||
|
}).register('importCardPopup');
|
||||||
|
|
||||||
|
BlazeComponent.extendComponent({
|
||||||
|
mixins() {
|
||||||
|
return [Mixins.PerfectScrollbar];
|
||||||
|
},
|
||||||
|
|
||||||
|
onCreated() {
|
||||||
|
subManager.subscribe('board', Session.get('currentBoard'));
|
||||||
|
this.selectedBoardId = new ReactiveVar(Session.get('currentBoard'));
|
||||||
|
this.term = new ReactiveVar('');
|
||||||
|
},
|
||||||
|
|
||||||
|
boards() {
|
||||||
|
const boards = Boards.find({
|
||||||
|
archived: false,
|
||||||
|
'members.userId': Meteor.userId(),
|
||||||
|
}, {
|
||||||
|
sort: ['title'],
|
||||||
|
});
|
||||||
|
return boards;
|
||||||
|
},
|
||||||
|
|
||||||
|
results() {
|
||||||
|
const board = Boards.findOne(this.selectedBoardId.get());
|
||||||
|
return board.searchCards(this.term.get());
|
||||||
|
},
|
||||||
|
|
||||||
|
events() {
|
||||||
|
return [{
|
||||||
|
'change .js-select-boards'(evt) {
|
||||||
|
this.selectedBoardId.set($(evt.currentTarget).val());
|
||||||
|
subManager.subscribe('board', this.selectedBoardId.get());
|
||||||
|
},
|
||||||
|
'submit .js-search-term-form'(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
this.term.set(evt.target.searchTerm.value);
|
||||||
|
},
|
||||||
|
'click .js-minicard'() {
|
||||||
|
// IMPORT CARD
|
||||||
|
},
|
||||||
|
}];
|
||||||
|
},
|
||||||
|
}).register('searchCardPopup');
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,9 @@
|
||||||
"cards": "Cards",
|
"cards": "Cards",
|
||||||
"cards-count": "Cards",
|
"cards-count": "Cards",
|
||||||
"casSignIn" : "Sign In with CAS",
|
"casSignIn" : "Sign In with CAS",
|
||||||
|
"cardType-card": "Card",
|
||||||
|
"cardType-importedCard": "Imported Card",
|
||||||
|
"cardType-importedBoard": "Imported Board",
|
||||||
"change": "Change",
|
"change": "Change",
|
||||||
"change-avatar": "Change Avatar",
|
"change-avatar": "Change Avatar",
|
||||||
"change-password": "Change Password",
|
"change-password": "Change Password",
|
||||||
|
|
@ -171,6 +174,8 @@
|
||||||
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
|
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
|
||||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
|
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
|
||||||
"copy-card-link-to-clipboard": "Copy card link to clipboard",
|
"copy-card-link-to-clipboard": "Copy card link to clipboard",
|
||||||
|
"importCardPopup-title": "Import Card",
|
||||||
|
"searchCardPopup-title": "Search Card",
|
||||||
"copyCardPopup-title": "Copy Card",
|
"copyCardPopup-title": "Copy Card",
|
||||||
"copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards",
|
"copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards",
|
||||||
"copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format",
|
"copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format",
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,10 @@ Boards.helpers({
|
||||||
return this.permission === 'public';
|
return this.permission === 'public';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
cards() {
|
||||||
|
return Cards.find({ boardId: this._id, archived: false }, { sort: { title: 1 } });
|
||||||
|
},
|
||||||
|
|
||||||
lists() {
|
lists() {
|
||||||
return Lists.find({ boardId: this._id, archived: false }, { sort: { sort: 1 } });
|
return Lists.find({ boardId: this._id, archived: false }, { sort: { sort: 1 } });
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,13 @@ Cards.attachSchema(new SimpleSchema({
|
||||||
defaultValue: -1,
|
defaultValue: -1,
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
importedId: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
Cards.allow({
|
Cards.allow({
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,17 @@ Migrations.add('add-profile-view', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Migrations.add('add-card-types', () => {
|
||||||
|
Cards.find().forEach((card) => {
|
||||||
|
Cards.direct.update(
|
||||||
|
{ _id: card._id },
|
||||||
|
{ $set: {
|
||||||
|
type: 'cardType-card',
|
||||||
|
importedId: null } },
|
||||||
|
noValidate
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
Migrations.add('add-custom-fields-to-cards', () => {
|
Migrations.add('add-custom-fields-to-cards', () => {
|
||||||
Cards.update({
|
Cards.update({
|
||||||
customFields: {
|
customFields: {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue