mirror of
https://github.com/wekan/wekan.git
synced 2026-01-31 05:35:16 +01:00
Merge branch 'devel' into minicard-editor
Conflicts: client/components/lists/listBody.js
This commit is contained in:
commit
2b134ff7a9
54 changed files with 1027 additions and 310 deletions
|
|
@ -14,53 +14,62 @@ template(name="boardActivities")
|
|||
p.activity-desc
|
||||
+memberName(user=user)
|
||||
|
||||
if($eq activityType 'createBoard')
|
||||
| {{_ 'activity-created' boardLabel}}.
|
||||
|
||||
if($eq activityType 'createList')
|
||||
| {{_ 'activity-added' list.title boardLabel}}.
|
||||
|
||||
if($eq activityType 'archivedList')
|
||||
| {{_ 'activity-archived' list.title}}.
|
||||
|
||||
if($eq activityType 'createCard')
|
||||
| {{{_ 'activity-added' cardLink boardLabel}}}.
|
||||
|
||||
if($eq activityType 'archivedCard')
|
||||
| {{{_ 'activity-archived' cardLink}}}.
|
||||
|
||||
if($eq activityType 'restoredCard')
|
||||
| {{{_ 'activity-sent' cardLink boardLabel}}}.
|
||||
|
||||
if($eq activityType 'moveCard')
|
||||
| {{{_ 'activity-moved' cardLink oldList.title list.title}}}.
|
||||
if($eq activityType 'addAttachment')
|
||||
| {{{_ 'activity-attached' attachmentLink cardLink}}}.
|
||||
|
||||
if($eq activityType 'addBoardMember')
|
||||
| {{{_ 'activity-added' memberLink boardLabel}}}.
|
||||
|
||||
if($eq activityType 'removeBoardMember')
|
||||
| {{{_ 'activity-excluded' memberLink boardLabel}}}.
|
||||
|
||||
if($eq activityType 'joinMember')
|
||||
if($eq currentUser._id member._id)
|
||||
| {{{_ 'activity-joined' cardLink}}}.
|
||||
else
|
||||
| {{{_ 'activity-added' memberLink cardLink}}}.
|
||||
|
||||
if($eq activityType 'unjoinMember')
|
||||
if($eq currentUser._id member._id)
|
||||
| {{{_ 'activity-unjoined' cardLink}}}.
|
||||
else
|
||||
| {{{_ 'activity-removed' memberLink cardLink}}}.
|
||||
|
||||
if($eq activityType 'addComment')
|
||||
| {{{_ 'activity-on' cardLink}}}
|
||||
a.activity-comment(href="{{ card.absoluteUrl }}")
|
||||
+viewer
|
||||
= comment.text
|
||||
|
||||
if($eq activityType 'addAttachment')
|
||||
| {{{_ 'activity-attached' attachmentLink cardLink}}}.
|
||||
if($eq activityType 'archivedCard')
|
||||
| {{{_ 'activity-archived' cardLink}}}.
|
||||
|
||||
if($eq activityType 'archivedList')
|
||||
| {{_ 'activity-archived' list.title}}.
|
||||
|
||||
if($eq activityType 'createBoard')
|
||||
| {{_ 'activity-created' boardLabel}}.
|
||||
|
||||
if($eq activityType 'createCard')
|
||||
| {{{_ 'activity-added' cardLink boardLabel}}}.
|
||||
|
||||
if($eq activityType 'createList')
|
||||
| {{_ 'activity-added' list.title boardLabel}}.
|
||||
|
||||
if($eq activityType 'importBoard')
|
||||
| {{{_ 'activity-imported-board' boardLabel sourceLink}}}.
|
||||
|
||||
if($eq activityType 'importCard')
|
||||
| {{{_ 'activity-imported' cardLink boardLabel sourceLink}}}.
|
||||
|
||||
if($eq activityType 'importList')
|
||||
| {{{_ 'activity-imported' listLabel boardLabel sourceLink}}}.
|
||||
|
||||
if($eq activityType 'joinMember')
|
||||
if($eq currentUser._id member._id)
|
||||
| {{{_ 'activity-joined' cardLink}}}.
|
||||
else
|
||||
| {{{_ 'activity-added' memberLink cardLink}}}.
|
||||
|
||||
if($eq activityType 'moveCard')
|
||||
| {{{_ 'activity-moved' cardLink oldList.title list.title}}}.
|
||||
|
||||
if($eq activityType 'removeBoardMember')
|
||||
| {{{_ 'activity-excluded' memberLink boardLabel}}}.
|
||||
|
||||
if($eq activityType 'restoredCard')
|
||||
| {{{_ 'activity-sent' cardLink boardLabel}}}.
|
||||
|
||||
if($eq activityType 'unjoinMember')
|
||||
if($eq currentUser._id member._id)
|
||||
| {{{_ 'activity-unjoined' cardLink}}}.
|
||||
else
|
||||
| {{{_ 'activity-removed' memberLink cardLink}}}.
|
||||
|
||||
span.activity-meta {{ moment createdAt }}
|
||||
|
||||
|
|
@ -72,6 +81,8 @@ template(name="cardActivities")
|
|||
+memberName(user=user)
|
||||
if($eq activityType 'createCard')
|
||||
| {{_ 'activity-added' cardLabel list.title}}.
|
||||
if($eq activityType 'importCard')
|
||||
| {{{_ 'activity-imported' cardLabel list.title sourceLink}}}.
|
||||
if($eq activityType 'joinMember')
|
||||
if($eq currentUser._id member._id)
|
||||
| {{_ 'activity-joined' cardLabel}}.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ BlazeComponent.extendComponent({
|
|||
// XXX Should we use ReactiveNumber?
|
||||
this.page = new ReactiveVar(1);
|
||||
this.loadNextPageLocked = false;
|
||||
const sidebar = this.componentParent(); // XXX for some reason not working
|
||||
const sidebar = this.parentComponent(); // XXX for some reason not working
|
||||
sidebar.callFirstWith(null, 'resetNextPeak');
|
||||
this.autorun(() => {
|
||||
const mode = this.data().mode;
|
||||
|
|
@ -55,11 +55,29 @@ BlazeComponent.extendComponent({
|
|||
cardLink() {
|
||||
const card = this.currentData().card();
|
||||
return card && Blaze.toHTML(HTML.A({
|
||||
href: card.absoluteUrl(),
|
||||
href: FlowRouter.path(card.absoluteUrl()),
|
||||
'class': 'action-card',
|
||||
}, card.title));
|
||||
},
|
||||
|
||||
listLabel() {
|
||||
return this.currentData().list().title;
|
||||
},
|
||||
|
||||
sourceLink() {
|
||||
const source = this.currentData().source;
|
||||
if(source) {
|
||||
if(source.url) {
|
||||
return Blaze.toHTML(HTML.A({
|
||||
href: source.url,
|
||||
}, source.system));
|
||||
} else {
|
||||
return source.system;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
memberLink() {
|
||||
return Blaze.toHTMLWithData(Template.memberName, {
|
||||
user: this.currentData().member(),
|
||||
|
|
@ -69,7 +87,7 @@ BlazeComponent.extendComponent({
|
|||
attachmentLink() {
|
||||
const attachment = this.currentData().attachment();
|
||||
return attachment && Blaze.toHTML(HTML.A({
|
||||
href: attachment.url({ download: true }),
|
||||
href: FlowRouter.path(attachment.url({ download: true })),
|
||||
target: '_blank',
|
||||
}, attachment.name()));
|
||||
},
|
||||
|
|
@ -83,9 +101,9 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
'submit .js-edit-comment'(evt) {
|
||||
evt.preventDefault();
|
||||
const commentText = this.currentComponent().getValue();
|
||||
const commentText = this.currentComponent().getValue().trim();
|
||||
const commentId = Template.parentData().commentId;
|
||||
if ($.trim(commentText)) {
|
||||
if (commentText) {
|
||||
CardComments.update(commentId, {
|
||||
$set: {
|
||||
text: commentText,
|
||||
|
|
|
|||
|
|
@ -24,11 +24,12 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
'submit .js-new-comment-form'(evt) {
|
||||
const input = this.getInput();
|
||||
if ($.trim(input.val())) {
|
||||
const text = input.val().trim();
|
||||
if (text) {
|
||||
CardComments.insert({
|
||||
text,
|
||||
boardId: this.currentData().boardId,
|
||||
cardId: this.currentData()._id,
|
||||
text: input.val(),
|
||||
});
|
||||
resetCommentInput(input);
|
||||
Tracker.flush();
|
||||
|
|
@ -72,8 +73,9 @@ EscapeActions.register('inlinedForm',
|
|||
docId: Session.get('currentCard'),
|
||||
};
|
||||
const commentInput = $('.js-new-comment-input');
|
||||
if ($.trim(commentInput.val())) {
|
||||
UnsavedEdits.set(draftKey, commentInput.val());
|
||||
const draft = commentInput.val().trim();
|
||||
if (draft) {
|
||||
UnsavedEdits.set(draftKey, draft);
|
||||
} else {
|
||||
UnsavedEdits.reset(draftKey);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
|
||||
openNewListForm() {
|
||||
this.componentChildren('addListForm')[0].open();
|
||||
this.childComponents('addListForm')[0].open();
|
||||
},
|
||||
|
||||
// XXX Flow components allow us to avoid creating these two setter methods by
|
||||
|
|
@ -179,22 +179,24 @@ BlazeComponent.extendComponent({
|
|||
|
||||
// Proxy
|
||||
open() {
|
||||
this.componentChildren('inlinedForm')[0].open();
|
||||
this.childComponents('inlinedForm')[0].open();
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
submit(evt) {
|
||||
evt.preventDefault();
|
||||
const title = this.find('.list-name-input');
|
||||
if ($.trim(title.value)) {
|
||||
const titleInput = this.find('.list-name-input');
|
||||
const title = titleInput.value.trim();
|
||||
if (title) {
|
||||
Lists.insert({
|
||||
title: title.value,
|
||||
title,
|
||||
boardId: Session.get('currentBoard'),
|
||||
sort: $('.list').length,
|
||||
});
|
||||
|
||||
title.value = '';
|
||||
titleInput.value = '';
|
||||
titleInput.focus();
|
||||
}
|
||||
},
|
||||
}];
|
||||
|
|
|
|||
|
|
@ -107,6 +107,9 @@ template(name="createBoardPopup")
|
|||
| {{{_ 'board-private-info'}}}
|
||||
a.js-change-visibility {{_ 'change'}}.
|
||||
input.primary.wide(type="submit" value="{{_ 'create'}}")
|
||||
span.quiet
|
||||
| {{_ 'or'}}
|
||||
a.js-import {{_ 'import-board'}}
|
||||
|
||||
|
||||
template(name="boardChangeTitlePopup")
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ BlazeComponent.extendComponent({
|
|||
this.setVisibility(this.currentData());
|
||||
},
|
||||
'click .js-change-visibility': this.toggleVisibilityMenu,
|
||||
'click .js-import': Popup.open('boardImportBoard'),
|
||||
submit: this.onSubmit,
|
||||
}];
|
||||
},
|
||||
|
|
|
|||
2
client/components/boards/boardHeader.styl
Normal file
2
client/components/boards/boardHeader.styl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
a.js-import
|
||||
text-decoration underline
|
||||
|
|
@ -15,7 +15,7 @@ template(name="attachmentsGalery")
|
|||
.attachment-thumbnail
|
||||
if isUploaded
|
||||
if isImage
|
||||
img.attachment-thumbnail-img(src=url)
|
||||
img.attachment-thumbnail-img(src="{{pathFor url}}")
|
||||
else
|
||||
span.attachment-thumbnail-ext= extension
|
||||
else
|
||||
|
|
|
|||
|
|
@ -13,19 +13,19 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
|
||||
reachNextPeak() {
|
||||
const activitiesComponent = this.componentChildren('activities')[0];
|
||||
const activitiesComponent = this.childrenComponents('activities')[0];
|
||||
activitiesComponent.loadNextPage();
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
this.isLoaded = new ReactiveVar(false);
|
||||
this.componentParent().showOverlay.set(true);
|
||||
this.componentParent().mouseHasEnterCardDetails = false;
|
||||
this.parentComponent().showOverlay.set(true);
|
||||
this.parentComponent().mouseHasEnterCardDetails = false;
|
||||
},
|
||||
|
||||
scrollParentContainer() {
|
||||
const cardPanelWidth = 510;
|
||||
const bodyBoardComponent = this.componentParent();
|
||||
const bodyBoardComponent = this.parentComponent();
|
||||
|
||||
const $cardContainer = bodyBoardComponent.$('.js-lists');
|
||||
const $cardView = this.$(this.firstNode());
|
||||
|
|
@ -52,7 +52,7 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
|
||||
onDestroyed() {
|
||||
this.componentParent().showOverlay.set(false);
|
||||
this.parentComponent().showOverlay.set(false);
|
||||
},
|
||||
|
||||
events() {
|
||||
|
|
@ -62,7 +62,8 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
};
|
||||
|
||||
return [_.extend(events, {
|
||||
return [{
|
||||
...events,
|
||||
'click .js-close-card-details'() {
|
||||
Utils.goBoardId(this.data().boardId);
|
||||
},
|
||||
|
|
@ -74,8 +75,8 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
'submit .js-card-details-title'(evt) {
|
||||
evt.preventDefault();
|
||||
const title = this.currentComponent().getValue();
|
||||
if ($.trim(title)) {
|
||||
const title = this.currentComponent().getValue().trim();
|
||||
if (title) {
|
||||
this.data().setTitle(title);
|
||||
}
|
||||
},
|
||||
|
|
@ -83,10 +84,10 @@ BlazeComponent.extendComponent({
|
|||
'click .js-add-members': Popup.open('cardMembers'),
|
||||
'click .js-add-labels': Popup.open('cardLabels'),
|
||||
'mouseenter .js-card-details'() {
|
||||
this.componentParent().showOverlay.set(true);
|
||||
this.componentParent().mouseHasEnterCardDetails = true;
|
||||
this.parentComponent().showOverlay.set(true);
|
||||
this.parentComponent().mouseHasEnterCardDetails = true;
|
||||
},
|
||||
})];
|
||||
}];
|
||||
},
|
||||
}).register('cardDetails');
|
||||
|
||||
|
|
@ -105,7 +106,7 @@ BlazeComponent.extendComponent({
|
|||
|
||||
close(isReset = false) {
|
||||
if (this.isOpen.get() && !isReset) {
|
||||
const draft = $.trim(this.getValue());
|
||||
const draft = this.getValue().trim();
|
||||
if (draft !== Cards.findOne(Session.get('currentCard')).description) {
|
||||
UnsavedEdits.set(this._getUnsavedEditKey(), this.getValue());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ template(name="editLabelPopup")
|
|||
form.edit-label
|
||||
+formLabel
|
||||
button.primary.wide.left(type="submit") {{_ 'save'}}
|
||||
span.right
|
||||
button.js-delete-label.negate.wide.right {{_ 'delete'}}
|
||||
|
||||
template(name="deleteLabelPopup")
|
||||
p {{_ "label-delete-pop"}}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
|
||||
labels() {
|
||||
return _.map(labelColors, (color) => {
|
||||
return labelColors.map((color) => {
|
||||
return { color, name: '' };
|
||||
});
|
||||
},
|
||||
|
|
@ -69,12 +69,12 @@ Template.formLabel.events({
|
|||
Template.createLabelPopup.events({
|
||||
// Create the new label
|
||||
'submit .create-label'(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const board = Boards.findOne(Session.get('currentBoard'));
|
||||
const name = tpl.$('#labelName').val().trim();
|
||||
const color = Blaze.getData(tpl.find('.fa-check')).color;
|
||||
board.addLabel(name, color);
|
||||
Popup.back();
|
||||
evt.preventDefault();
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ template(name="minicard")
|
|||
.minicard
|
||||
if cover
|
||||
.minicard-cover
|
||||
img(src=cover.url)
|
||||
img(src="{{pathFor cover.url}}")
|
||||
if labels
|
||||
.minicard-labels
|
||||
each labels
|
||||
|
|
|
|||
7
client/components/import/import.jade
Normal file
7
client/components/import/import.jade
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
template(name="importPopup")
|
||||
if error.get
|
||||
.warning {{_ error.get}}
|
||||
form
|
||||
p: label(for='import-textarea') {{_ getLabel}}
|
||||
textarea#import-textarea.js-import-json(placeholder="{{_ 'import-json-placeholder'}}" autofocus)
|
||||
input.primary.wide(type="submit" value="{{_ 'import'}}")
|
||||
90
client/components/import/import.js
Normal file
90
client/components/import/import.js
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/// Abstract root for all import popup screens.
|
||||
/// Descendants must define:
|
||||
/// - getMethodName(): return the Meteor method to call for import, passing json
|
||||
/// data decoded as object and additional data (see below);
|
||||
/// - getAdditionalData(): return object containing additional data passed to
|
||||
/// Meteor method (like list ID and position for a card import);
|
||||
/// - getLabel(): i18n key for the text displayed in the popup, usually to
|
||||
/// explain how to get the data out of the source system.
|
||||
const ImportPopup = BlazeComponent.extendComponent({
|
||||
template() {
|
||||
return 'importPopup';
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'submit': (evt) => {
|
||||
evt.preventDefault();
|
||||
const dataJson = $(evt.currentTarget).find('.js-import-json').val();
|
||||
let dataObject;
|
||||
try {
|
||||
dataObject = JSON.parse(dataJson);
|
||||
} catch (e) {
|
||||
this.setError('error-json-malformed');
|
||||
return;
|
||||
}
|
||||
Meteor.call(this.getMethodName(), dataObject, this.getAdditionalData(),
|
||||
(error, response) => {
|
||||
if (error) {
|
||||
this.setError(error.error);
|
||||
} else {
|
||||
Filter.addException(response);
|
||||
this.onFinish(response);
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
}];
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
this.error = new ReactiveVar('');
|
||||
},
|
||||
|
||||
setError(error) {
|
||||
this.error.set(error);
|
||||
},
|
||||
|
||||
onFinish() {
|
||||
Popup.close();
|
||||
},
|
||||
});
|
||||
|
||||
ImportPopup.extendComponent({
|
||||
getAdditionalData() {
|
||||
const listId = this.data()._id;
|
||||
const selector = `#js-list-${this.currentData()._id} .js-minicard:first`;
|
||||
const firstCardDom = $(selector).get(0);
|
||||
const sortIndex = Utils.calculateIndex(null, firstCardDom).base;
|
||||
const result = {listId, sortIndex};
|
||||
return result;
|
||||
},
|
||||
|
||||
getMethodName() {
|
||||
return 'importTrelloCard';
|
||||
},
|
||||
|
||||
getLabel() {
|
||||
return 'import-card-trello-instruction';
|
||||
},
|
||||
}).register('listImportCardPopup');
|
||||
|
||||
ImportPopup.extendComponent({
|
||||
getAdditionalData() {
|
||||
const result = {};
|
||||
return result;
|
||||
},
|
||||
|
||||
getMethodName() {
|
||||
return 'importTrelloBoard';
|
||||
},
|
||||
|
||||
getLabel() {
|
||||
return 'import-board-trello-instruction';
|
||||
},
|
||||
|
||||
onFinish(response) {
|
||||
Utils.goBoardId(response);
|
||||
},
|
||||
}).register('boardImportBoardPopup');
|
||||
|
||||
|
|
@ -7,7 +7,7 @@ BlazeComponent.extendComponent({
|
|||
|
||||
// Proxy
|
||||
openForm(options) {
|
||||
this.componentChildren('listBody')[0].openForm(options);
|
||||
this.childrenComponents('listBody')[0].openForm(options);
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
|
|
@ -25,7 +25,7 @@ BlazeComponent.extendComponent({
|
|||
if (!Meteor.user() || !Meteor.user().isBoardMember())
|
||||
return;
|
||||
|
||||
const boardComponent = this.componentParent();
|
||||
const boardComponent = this.parentComponent();
|
||||
const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
|
||||
const $cards = this.$('.js-minicards');
|
||||
$cards.sortable({
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ BlazeComponent.extendComponent({
|
|||
options = options || {};
|
||||
options.position = options.position || 'top';
|
||||
|
||||
const forms = this.componentChildren('inlinedForm');
|
||||
let form = _.find(forms, (component) => {
|
||||
const forms = this.childrenComponents('inlinedForm');
|
||||
let form = forms.find((component) => {
|
||||
return component.data().position === options.position;
|
||||
});
|
||||
if (!form && forms.length > 0) {
|
||||
|
|
@ -26,8 +26,8 @@ BlazeComponent.extendComponent({
|
|||
const firstCardDom = this.find('.js-minicard:first');
|
||||
const lastCardDom = this.find('.js-minicard:last');
|
||||
const textarea = $(evt.currentTarget).find('textarea');
|
||||
let title = textarea.val();
|
||||
const position = Blaze.getData(evt.currentTarget).position;
|
||||
const position = this.currentData().position;
|
||||
let title = textarea.val().trim();
|
||||
let sortIndex;
|
||||
if (position === 'top') {
|
||||
sortIndex = Utils.calculateIndex(null, firstCardDom).base;
|
||||
|
|
@ -62,7 +62,7 @@ BlazeComponent.extendComponent({
|
|||
}
|
||||
});
|
||||
|
||||
if ($.trim(title)) {
|
||||
if (title) {
|
||||
const _id = Cards.insert({
|
||||
title,
|
||||
listId: this.data()._id,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ template(name="listActionPopup")
|
|||
li: a.js-archive-cards {{_ 'list-archive-cards'}}
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-import-card {{_ 'import-card'}}
|
||||
li: a.js-close-list {{_ 'archive-list'}}
|
||||
|
||||
template(name="listMoveCardsPopup")
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ BlazeComponent.extendComponent({
|
|||
|
||||
editTitle(evt) {
|
||||
evt.preventDefault();
|
||||
const newTitle = this.componentChildren('inlinedForm')[0].getValue();
|
||||
const newTitle = this.childrenComponents('inlinedForm')[0].getValue().trim();
|
||||
const list = this.currentData();
|
||||
if ($.trim(newTitle)) {
|
||||
list.rename(newTitle);
|
||||
if (newTitle) {
|
||||
list.rename(newTitle.trim());
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -33,6 +33,7 @@ Template.listActionPopup.events({
|
|||
MultiSelection.add(cardIds);
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-import-card': Popup.open('listImportCard'),
|
||||
'click .js-move-cards': Popup.open('listMoveCards'),
|
||||
'click .js-archive-cards': Popup.afterConfirm('listArchiveCards', function() {
|
||||
this.allCards().forEach((card) => {
|
||||
|
|
@ -40,6 +41,7 @@ Template.listActionPopup.events({
|
|||
});
|
||||
Popup.close();
|
||||
}),
|
||||
|
||||
'click .js-close-list'(evt) {
|
||||
evt.preventDefault();
|
||||
this.archive();
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
let dropdownMenuIsOpened = false;
|
||||
|
||||
Template.editor.onRendered(() => {
|
||||
const $textarea = this.$('textarea');
|
||||
|
||||
autosize($textarea);
|
||||
|
||||
$textarea.textcomplete([
|
||||
$textarea.escapeableTextComplete([
|
||||
// Emojies
|
||||
{
|
||||
match: /\B:([\-+\w]*)$/,
|
||||
search(term, callback) {
|
||||
callback($.map(Emoji.values, (emoji) => {
|
||||
return emoji.indexOf(term) === 0 ? emoji : null;
|
||||
callback(Emoji.values.map((emoji) => {
|
||||
return emoji.includes(term) ? emoji : null;
|
||||
}));
|
||||
},
|
||||
template(value) {
|
||||
|
|
@ -30,9 +28,9 @@ Template.editor.onRendered(() => {
|
|||
match: /\B@(\w*)$/,
|
||||
search(term, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
callback($.map(currentBoard.members, (member) => {
|
||||
callback(currentBoard.members.map((member) => {
|
||||
const username = Users.findOne(member.userId).username;
|
||||
return username.indexOf(term) === 0 ? username : null;
|
||||
return username.includes(term) ? username : null;
|
||||
}));
|
||||
},
|
||||
template(value) {
|
||||
|
|
@ -44,30 +42,8 @@ Template.editor.onRendered(() => {
|
|||
index: 1,
|
||||
},
|
||||
]);
|
||||
|
||||
// Since commit d474017 jquery-textComplete automatically closes a potential
|
||||
// opened dropdown menu when the user press Escape. This behavior conflicts
|
||||
// with our EscapeActions system, but it's too complicated and hacky to
|
||||
// monkey-pach textComplete to disable it -- I tried. Instead we listen to
|
||||
// 'open' and 'hide' events, and create a ghost escapeAction when the dropdown
|
||||
// is opened (and rely on textComplete to execute the actual action).
|
||||
$textarea.on({
|
||||
'textComplete:show'() {
|
||||
dropdownMenuIsOpened = true;
|
||||
},
|
||||
'textComplete:hide'() {
|
||||
Tracker.afterFlush(() => {
|
||||
dropdownMenuIsOpened = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
EscapeActions.register('textcomplete',
|
||||
() => {},
|
||||
() => dropdownMenuIsOpened
|
||||
);
|
||||
|
||||
// XXX I believe we should compute a HTML rendered field on the server that
|
||||
// would handle markdown, emojies and user mentions. We can simply have two
|
||||
// fields, one source, and one compiled version (in HTML) and send only the
|
||||
|
|
@ -78,7 +54,7 @@ const at = HTML.CharRef({html: '@', str: '@'});
|
|||
Blaze.Template.registerHelper('mentions', new Template('mentions', function() {
|
||||
const view = this;
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const knowedUsers = _.map(currentBoard.members, (member) => {
|
||||
const knowedUsers = currentBoard.members.map((member) => {
|
||||
member.username = Users.findOne(member.userId).username;
|
||||
return member;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ template(name="header")
|
|||
the list of all boards.
|
||||
if isSandstorm
|
||||
.wekan-logo
|
||||
img(src="/wekan-logo-header.png" alt="Wekan")
|
||||
img(src="{{pathFor '/wekan-logo-header.png'}}" alt="Wekan")
|
||||
else
|
||||
a.wekan-logo(href="{{pathFor 'home'}}" title="{{_ 'header-logo-title'}}")
|
||||
img(src="/wekan-logo-header.png" alt="Wekan")
|
||||
img(src="{{pathFor '/wekan-logo-header.png'}}" alt="Wekan")
|
||||
|
||||
template(name="headerTitle")
|
||||
h1 {{_ 'my-boards'}}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,16 @@ head
|
|||
title Wekan
|
||||
meta(name="viewport"
|
||||
content="maximum-scale=1.0,width=device-width,initial-scale=1.0,user-scalable=0")
|
||||
//- XXX We should use pathFor in the following `href` to support the case
|
||||
where the application is deployed with a path prefix, but it seems to be
|
||||
difficult to do that cleanly with Blaze -- at least without adding extra
|
||||
packages.
|
||||
link(rel="shortcut icon" href="/wekan-favicon.png")
|
||||
|
||||
template(name="userFormsLayout")
|
||||
section.auth-layout
|
||||
h1.at-form-landing-logo
|
||||
img(src="/wekan-logo.png" alt="Wekan")
|
||||
img(src="{{pathFor '/wekan-logo.png'}}" alt="Wekan")
|
||||
+Template.dynamic(template=content)
|
||||
|
||||
template(name="defaultLayout")
|
||||
|
|
|
|||
|
|
@ -17,9 +17,11 @@ $popupWidth = 300px
|
|||
margin: 4px -10px
|
||||
width: $popupWidth
|
||||
|
||||
p,
|
||||
textarea,
|
||||
input[type="text"],
|
||||
input[type="email"],
|
||||
input[type="password"]
|
||||
input[type="password"],
|
||||
input[type="file"]
|
||||
margin: 4px 0 12px
|
||||
width: 100%
|
||||
|
|
@ -30,8 +32,6 @@ $popupWidth = 300px
|
|||
|
||||
textarea
|
||||
height: 72px
|
||||
margin: 4px 0 12px
|
||||
width: 100%
|
||||
|
||||
.header
|
||||
height: 36px
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
|
||||
reachNextPeak() {
|
||||
const activitiesComponent = this.componentChildren('activities')[0];
|
||||
const activitiesComponent = this.childrenComponents('activities')[0];
|
||||
activitiesComponent.loadNextPage();
|
||||
},
|
||||
|
||||
|
|
@ -95,10 +95,10 @@ BlazeComponent.extendComponent({
|
|||
events() {
|
||||
// XXX Hacky, we need some kind of `super`
|
||||
const mixinEvents = this.getMixin(Mixins.InfiniteScrolling).events();
|
||||
return mixinEvents.concat([{
|
||||
return [...mixinEvents, {
|
||||
'click .js-toggle-sidebar': this.toggle,
|
||||
'click .js-back-home': this.setView,
|
||||
}]);
|
||||
}];
|
||||
},
|
||||
}).register('sidebar');
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ template(name="filterSidebar")
|
|||
if name
|
||||
= name
|
||||
else
|
||||
span.quiet {{_ "label-default" color}}
|
||||
span.quiet {{_ "label-default" (_ (concat "color-" color))}}
|
||||
if Filter.labelIds.isSelected _id
|
||||
i.fa.fa-check
|
||||
hr
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
template(name="userAvatar")
|
||||
a.member.js-member(title="{{userData.profile.fullname}} ({{userData.username}})")
|
||||
if userData.profile.avatarUrl
|
||||
img.avatar.avatar-image(src=userData.profile.avatarUrl)
|
||||
if userData.getAvatarUrl
|
||||
img.avatar.avatar-image(src=userData.getAvatarUrl)
|
||||
else
|
||||
+userAvatarInitials(userId=userData._id)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ Template.memberMenuPopup.events({
|
|||
Template.editProfilePopup.events({
|
||||
submit(evt, tpl) {
|
||||
evt.preventDefault();
|
||||
const fullname = $.trim(tpl.find('.js-profile-fullname').value);
|
||||
const username = $.trim(tpl.find('.js-profile-username').value);
|
||||
const initials = $.trim(tpl.find('.js-profile-initials').value);
|
||||
const fullname = tpl.find('.js-profile-fullname').value.trim();
|
||||
const username = tpl.find('.js-profile-username').value.trim();
|
||||
const initials = tpl.find('.js-profile-initials').value.trim();
|
||||
Users.update(Meteor.userId(), {$set: {
|
||||
'profile.fullname': fullname,
|
||||
'profile.initials': initials,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue