summaryrefslogtreecommitdiffstats
path: root/client/components
diff options
context:
space:
mode:
Diffstat (limited to 'client/components')
-rw-r--r--client/components/boards/boardHeader.jade19
-rw-r--r--client/components/boards/boardHeader.js50
-rw-r--r--client/components/cards/checklists.jade4
-rw-r--r--client/components/cards/checklists.js24
-rw-r--r--client/components/cards/checklists.styl3
-rw-r--r--client/components/import/import.jade4
-rw-r--r--client/components/import/import.js48
-rw-r--r--client/components/import/trelloMembersMapper.js14
-rw-r--r--client/components/import/wekanMembersMapper.js24
9 files changed, 164 insertions, 26 deletions
diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade
index e61aea35..d33ee11b 100644
--- a/client/components/boards/boardHeader.jade
+++ b/client/components/boards/boardHeader.jade
@@ -112,6 +112,7 @@ template(name="boardMenuPopup")
ul.pop-over-list
li: a(href="{{exportUrl}}", download="{{exportFilename}}") {{_ 'export-board'}}
li: a.js-archive-board {{_ 'archive-board'}}
+ li: a.js-outgoing-webhooks {{_ 'outgoing-webhooks'}}
template(name="boardVisibilityList")
ul.pop-over-list
@@ -191,8 +192,14 @@ template(name="createBoard")
input.primary.wide(type="submit" value="{{_ 'create'}}")
span.quiet
| {{_ 'or'}}
- a(href="{{pathFor 'import'}}") {{_ 'import-board'}}
+ a.js-import-board {{_ 'import-board'}}
+template(name="chooseBoardSource")
+ ul.pop-over-list
+ li
+ a(href="{{pathFor 'import/trello'}}") {{_ 'from-trello'}}
+ li
+ a(href="{{pathFor 'import/wekan'}}") {{_ 'from-wekan'}}
template(name="boardChangeTitlePopup")
form
@@ -207,3 +214,13 @@ template(name="boardChangeTitlePopup")
template(name="archiveBoardPopup")
p {{_ 'close-board-pop'}}
button.js-confirm.negate.full(type="submit") {{_ 'archive'}}
+
+template(name="outgoingWebhooksPopup")
+ form
+ label
+ | URL
+ if integration.enabled
+ input.js-outgoing-webhooks-url(type="text" value=integration.url autofocus)
+ else
+ input.js-outgoing-webhooks-url(type="text" autofocus)
+ input.primary.wide(type="submit" value="{{_ 'save'}}")
diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js
index 06defbfa..dafbfd30 100644
--- a/client/components/boards/boardHeader.js
+++ b/client/components/boards/boardHeader.js
@@ -13,6 +13,7 @@ Template.boardMenuPopup.events({
// confirm that the board was successfully archived.
FlowRouter.go('home');
}),
+ 'click .js-outgoing-webhooks': Popup.open('outgoingWebhooks'),
});
Template.boardMenuPopup.helpers({
@@ -174,10 +175,17 @@ const CreateBoard = BlazeComponent.extendComponent({
'click .js-change-visibility': this.toggleVisibilityMenu,
'click .js-import': Popup.open('boardImportBoard'),
submit: this.onSubmit,
+ 'click .js-import-board': Popup.open('chooseBoardSource'),
}];
},
}).register('createBoardPopup');
+BlazeComponent.extendComponent({
+ template() {
+ return 'chooseBoardSource';
+ },
+}).register('chooseBoardSourcePopup');
+
(class HeaderBarCreateBoard extends CreateBoard {
onSubmit(evt) {
super.onSubmit(evt);
@@ -227,3 +235,45 @@ BlazeComponent.extendComponent({
}];
},
}).register('boardChangeWatchPopup');
+
+BlazeComponent.extendComponent({
+ integration() {
+ const boardId = Session.get('currentBoard');
+ return Integrations.findOne({ boardId: `${boardId}` });
+ },
+
+ events() {
+ return [{
+ 'submit'(evt) {
+ evt.preventDefault();
+ const url = this.find('.js-outgoing-webhooks-url').value.trim();
+ const boardId = Session.get('currentBoard');
+ const integration = this.integration();
+ if (integration) {
+ if (url) {
+ Integrations.update(integration._id, {
+ $set: {
+ enabled: true,
+ url: `${url}`,
+ },
+ });
+ } else {
+ Integrations.update(integration._id, {
+ $set: {
+ enabled: false,
+ },
+ });
+ }
+ } else if (url) {
+ Integrations.insert({
+ enabled: true,
+ type: 'outgoing-webhooks',
+ url: `${url}`,
+ boardId: `${boardId}`,
+ });
+ }
+ Popup.close();
+ },
+ }];
+ },
+}).register('outgoingWebhooksPopup');
diff --git a/client/components/cards/checklists.jade b/client/components/cards/checklists.jade
index a0d89351..d04a9b60 100644
--- a/client/components/cards/checklists.jade
+++ b/client/components/cards/checklists.jade
@@ -4,7 +4,7 @@ template(name="checklists")
each checklist in currentCard.checklists
+checklistDetail(checklist = checklist)
if canModifyCard
- +inlinedForm(classNames="js-add-checklist" cardId = cardId)
+ +inlinedForm(autoclose=false classNames="js-add-checklist" cardId = cardId)
+addChecklistItemForm
else
a.js-open-inlined-form
@@ -53,7 +53,7 @@ template(name="checklistItems")
else
+itemDetail(item = item checklist = checklist)
if canModifyCard
- +inlinedForm(classNames="js-add-checklist-item" checklist = checklist)
+ +inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist)
+addChecklistItemForm
else
a.add-checklist-item.js-open-inlined-form
diff --git a/client/components/cards/checklists.js b/client/components/cards/checklists.js
index b8f5e443..24a78035 100644
--- a/client/components/cards/checklists.js
+++ b/client/components/cards/checklists.js
@@ -4,10 +4,18 @@ BlazeComponent.extendComponent({
const textarea = this.find('textarea.js-add-checklist-item');
const title = textarea.value.trim();
const cardId = this.currentData().cardId;
- Checklists.insert({
- cardId,
- title,
- });
+
+ if (title) {
+ Checklists.insert({
+ cardId,
+ title,
+ });
+ setTimeout(() => {
+ this.$('.add-checklist-item').last().click();
+ }, 100);
+ }
+ textarea.value = '';
+ textarea.focus();
},
addChecklistItem(event) {
@@ -15,7 +23,13 @@ BlazeComponent.extendComponent({
const textarea = this.find('textarea.js-add-checklist-item');
const title = textarea.value.trim();
const checklist = this.currentData().checklist;
- checklist.addItem(title);
+
+ if (title) {
+ checklist.addItem(title);
+ }
+ // We keep the form opened, empty it.
+ textarea.value = '';
+ textarea.focus();
},
editChecklist(event) {
diff --git a/client/components/cards/checklists.styl b/client/components/cards/checklists.styl
index 885d7528..1156c577 100644
--- a/client/components/cards/checklists.styl
+++ b/client/components/cards/checklists.styl
@@ -46,6 +46,8 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
font-size: 1.1em
margin-top: 3px
display: flex
+ &:hover
+ background-color: darken(white, 8%)
.check-box
margin-top: 5px
@@ -54,6 +56,7 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
border-right: 2px solid #3cb500
.item-title
+ flex-grow: 1
padding-left: 10px;
&.is-checked
color: #8c8c8c
diff --git a/client/components/import/import.jade b/client/components/import/import.jade
index d4def7d8..d1b3489a 100644
--- a/client/components/import/import.jade
+++ b/client/components/import/import.jade
@@ -2,7 +2,7 @@ template(name="importHeaderBar")
h1
a.back-btn(href="{{pathFor 'home'}}")
i.fa.fa-chevron-left
- | {{_ 'import-board-title'}}
+ | {{_ title}}
template(name="import")
.wrapper
@@ -12,7 +12,7 @@ template(name="import")
template(name="importTextarea")
form
- p: label(for='import-textarea') {{_ 'import-board-trello-instruction'}}
+ p: label(for='import-textarea') {{_ instruction}}
textarea.js-import-json(placeholder="{{_ 'import-json-placeholder'}}" autofocus)
| {{jsonText}}
input.primary.wide(type="submit" value="{{_ 'import'}}")
diff --git a/client/components/import/import.js b/client/components/import/import.js
index 11a5308a..d72a02dd 100644
--- a/client/components/import/import.js
+++ b/client/components/import/import.js
@@ -1,3 +1,12 @@
+import trelloMembersMapper from './trelloMembersMapper';
+import wekanMembersMapper from './wekanMembersMapper';
+
+BlazeComponent.extendComponent({
+ title() {
+ return `import-board-title-${Session.get('importSource')}`;
+ },
+}).register('importHeaderBar');
+
BlazeComponent.extendComponent({
onCreated() {
this.error = new ReactiveVar('');
@@ -5,6 +14,7 @@ BlazeComponent.extendComponent({
this._currentStepIndex = new ReactiveVar(0);
this.importedData = new ReactiveVar();
this.membersToMap = new ReactiveVar([]);
+ this.importSource = Session.get('importSource');
},
currentTemplate() {
@@ -27,7 +37,10 @@ BlazeComponent.extendComponent({
const dataObject = JSON.parse(dataJson);
this.setError('');
this.importedData.set(dataObject);
- this._prepareAdditionalData(dataObject);
+ const membersToMap = this._prepareAdditionalData(dataObject);
+ // store members data and mapping in Session
+ // (we go deep and 2-way, so storing in data context is not a viable option)
+ this.membersToMap.set(membersToMap);
this.nextStep();
} catch (e) {
this.setError('error-json-malformed');
@@ -51,7 +64,10 @@ BlazeComponent.extendComponent({
additionalData.membersMapping = mappingById;
}
this.membersToMap.set([]);
- Meteor.call('importTrelloBoard', this.importedData.get(), additionalData,
+ Meteor.call('importBoard',
+ this.importedData.get(),
+ additionalData,
+ this.importSource,
(err, res) => {
if (err) {
this.setError(err.error);
@@ -63,20 +79,16 @@ BlazeComponent.extendComponent({
},
_prepareAdditionalData(dataObject) {
- // we will work on the list itself (an ordered array of objects) when a
- // mapping is done, we add a 'wekan' field to the object representing the
- // imported member
- const membersToMap = dataObject.members;
- // auto-map based on username
- membersToMap.forEach((importedMember) => {
- const wekanUser = Users.findOne({ username: importedMember.username });
- if (wekanUser) {
- importedMember.wekanId = wekanUser._id;
- }
- });
- // store members data and mapping in Session
- // (we go deep and 2-way, so storing in data context is not a viable option)
- this.membersToMap.set(membersToMap);
+ const importSource = Session.get('importSource');
+ let membersToMap;
+ switch (importSource) {
+ case 'trello':
+ membersToMap = trelloMembersMapper.getMembersToMap(dataObject);
+ break;
+ case 'wekan':
+ membersToMap = wekanMembersMapper.getMembersToMap(dataObject);
+ break;
+ }
return membersToMap;
},
@@ -90,6 +102,10 @@ BlazeComponent.extendComponent({
return 'importTextarea';
},
+ instruction() {
+ return `import-board-instruction-${Session.get('importSource')}`;
+ },
+
events() {
return [{
submit(evt) {
diff --git a/client/components/import/trelloMembersMapper.js b/client/components/import/trelloMembersMapper.js
new file mode 100644
index 00000000..0f353bf1
--- /dev/null
+++ b/client/components/import/trelloMembersMapper.js
@@ -0,0 +1,14 @@
+export function getMembersToMap(data) {
+ // we will work on the list itself (an ordered array of objects) when a
+ // mapping is done, we add a 'wekan' field to the object representing the
+ // imported member
+ const membersToMap = data.members;
+ // auto-map based on username
+ membersToMap.forEach((importedMember) => {
+ const wekanUser = Users.findOne({ username: importedMember.username });
+ if (wekanUser) {
+ importedMember.wekanId = wekanUser._id;
+ }
+ });
+ return membersToMap;
+}
diff --git a/client/components/import/wekanMembersMapper.js b/client/components/import/wekanMembersMapper.js
new file mode 100644
index 00000000..f4c110f7
--- /dev/null
+++ b/client/components/import/wekanMembersMapper.js
@@ -0,0 +1,24 @@
+export function getMembersToMap(data) {
+ // we will work on the list itself (an ordered array of objects) when a
+ // mapping is done, we add a 'wekan' field to the object representing the
+ // imported member
+ const membersToMap = data.members;
+ const users = data.users;
+ // auto-map based on username
+ membersToMap.forEach((importedMember) => {
+ importedMember.id = importedMember.userId;
+ delete importedMember.userId;
+ const user = users.filter((user) => {
+ return user._id === importedMember.id;
+ })[0];
+ if (user.profile && user.profile.fullname) {
+ importedMember.fullName = user.profile.fullname;
+ }
+ importedMember.username = user.username;
+ const wekanUser = Users.findOne({ username: importedMember.username });
+ if (wekanUser) {
+ importedMember.wekanId = wekanUser._id;
+ }
+ });
+ return membersToMap;
+}