summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/components/activities/comments.js7
-rw-r--r--client/components/boards/boardHeader.jade14
-rw-r--r--client/components/boards/boardHeader.js4
-rw-r--r--client/components/cards/attachments.jade2
-rw-r--r--client/components/cards/cardDetails.jade11
-rw-r--r--client/components/cards/minicard.styl2
-rw-r--r--client/components/main/editor.jade7
-rwxr-xr-xclient/components/main/editor.js66
-rw-r--r--client/components/sidebar/sidebar.jade4
-rw-r--r--client/components/sidebar/sidebar.js4
-rw-r--r--client/lib/popup.js204
11 files changed, 37 insertions, 288 deletions
diff --git a/client/components/activities/comments.js b/client/components/activities/comments.js
index e885459e..50ca019b 100644
--- a/client/components/activities/comments.js
+++ b/client/components/activities/comments.js
@@ -33,13 +33,6 @@ BlazeComponent.extendComponent({
cardId,
});
resetCommentInput(input);
- // With Richer editor is in use, and comment is submitted,
- // clear comment form with JQuery. Id #summernote is defined
- // at client/components/main/editor.jade where it previously was
- // id=id, now it is id="summernote".
- if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR === 'true') {
- $('#summernote').summernote('code', '');
- }
Tracker.flush();
autosize.update(input);
input.trigger('submitted');
diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade
index 53a74f76..4c0edac4 100644
--- a/client/components/boards/boardHeader.jade
+++ b/client/components/boards/boardHeader.jade
@@ -193,20 +193,6 @@ template(name="boardChangeViewPopup")
| {{_ 'board-view-cal'}}
if $eq Utils.boardView "board-view-cal"
i.fa.fa-check
- if currentUser.isAdmin
- hr
- li
- with "board-view-rules"
- a.js-open-rules-view(title="{{_ 'rules'}}")
- i.fa.fa-magic
- | {{_ 'rules'}}
- else if currentUser.isBoardAdmin
- hr
- li
- with "board-view-rules"
- a.js-open-rules-view(title="{{_ 'rules'}}")
- i.fa.fa-magic
- | {{_ 'rules'}}
template(name="createBoard")
form
diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js
index 9040ed83..dc553134 100644
--- a/client/components/boards/boardHeader.js
+++ b/client/components/boards/boardHeader.js
@@ -191,10 +191,6 @@ Template.boardChangeViewPopup.events({
Utils.setBoardView('board-view-cal');
Popup.close();
},
- 'click .js-open-rules-view'() {
- Modal.openWide('rulesMain');
- Popup.close();
- },
});
const CreateBoard = BlazeComponent.extendComponent({
diff --git a/client/components/cards/attachments.jade b/client/components/cards/attachments.jade
index b695ea41..61454fa7 100644
--- a/client/components/cards/attachments.jade
+++ b/client/components/cards/attachments.jade
@@ -55,5 +55,5 @@ template(name="attachmentsGalery")
unless currentUser.isWorker
//li.attachment-item.add-attachment
a.js-add-attachment
- i.fa.fa-paperclip
+ i.fa.fa-plus
| {{_ 'add-attachment' }}
diff --git a/client/components/cards/cardDetails.jade b/client/components/cards/cardDetails.jade
index 615ae1d5..257ca0a8 100644
--- a/client/components/cards/cardDetails.jade
+++ b/client/components/cards/cardDetails.jade
@@ -203,6 +203,7 @@ template(name="cardDetails")
if canModifyCard
unless currentUser.isWorker
if currentBoard.allowsDescriptionTitle
+ hr
h3
i.fa.fa-align-left
card-details-item-title {{_ 'description'}}
@@ -229,6 +230,7 @@ template(name="cardDetails")
a.js-close-inlined-form {{_ 'discard'}}
else if getDescription
if currentBoard.allowsDescriptionTitle
+ hr
h3.card-details-item-title {{_ 'description'}}
if currentBoard.allowsDescriptionText
+viewer
@@ -237,15 +239,16 @@ template(name="cardDetails")
.card-checklist-attachmentGalerys
.card-checklist-attachmentGalery.card-checklists
if currentBoard.allowsChecklists
+ hr
+checklists(cardId = _id)
if currentBoard.allowsSubtasks
hr
+subtasks(cardId = _id)
if currentBoard.allowsAttachments
- //- hr
- //- h3
- //- i.fa.fa-paperclip
- //- | {{_ 'attachments'}}
+ hr
+ h3
+ i.fa.fa-paperclip
+ | {{_ 'attachments'}}
.card-checklist-attachmentGalery.card-attachmentGalery
+attachmentsGalery
diff --git a/client/components/cards/minicard.styl b/client/components/cards/minicard.styl
index 8607e118..7d72a588 100644
--- a/client/components/cards/minicard.styl
+++ b/client/components/cards/minicard.styl
@@ -79,7 +79,7 @@
border-radius: top 2px
.minicard-labels
- float: right
+ float: none
display: flex
flex-wrap: wrap
diff --git a/client/components/main/editor.jade b/client/components/main/editor.jade
index 5c5454ee..dbd61715 100644
--- a/client/components/main/editor.jade
+++ b/client/components/main/editor.jade
@@ -1,13 +1,8 @@
template(name="editor")
- // With Richer editor is in use, and comment is submitted,
- // clear comment form with JQuery Comment at
- // client/components/activities/comments.js . Id #summernote is defined
- // here at client/components/main/editor.jade where it previously was
- // id=id, now it is id="summernote".
textarea.editor(
dir="auto"
class="{{class}}"
- id="summernote"
+ id=id
autofocus=autofocus
placeholder="{{_ 'comment-placeholder'}}")
+Template.contentBlock
diff --git a/client/components/main/editor.js b/client/components/main/editor.js
index 3f09d284..081c6521 100755
--- a/client/components/main/editor.js
+++ b/client/components/main/editor.js
@@ -30,7 +30,7 @@ Template.editor.onRendered(() => {
autosize($textarea);
$textarea.escapeableTextComplete(mentions);
};
- if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR === 'true') {
+ if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR !== false) {
const isSmall = Utils.isMiniScreen();
const toolbar = isSmall
? [
@@ -108,45 +108,17 @@ Template.editor.onRendered(() => {
}
return undefined;
};
- // Prevent @member mentions on Add Comment input field
- // from closing card, part 1.
- let popupShown = false;
inputs.each(function(idx, input) {
mSummernotes[idx] = $(input).summernote({
placeholder,
- // Prevent @member mentions on Add Comment input field
- // from closing card, part 2.
- onKeydown(e) {
- if (popupShown) {
- e.preventDefault();
- }
- },
- onKeyup(e) {
- if (popupShown) {
- e.preventDefault();
- }
- },
callbacks: {
- // Prevent @member mentions on Add Comment input field
- // from closing card, part 3.
- onKeydown(e) {
- if (popupShown) {
- e.preventDefault();
- }
- },
- onKeyup(e) {
- if (popupShown) {
- e.preventDefault();
- }
- },
onInit(object) {
const originalInput = this;
- $(originalInput).on('input', function() {
+ $(originalInput).on('submitted', function() {
// when comment is submitted, the original textarea will be set to '', so shall we
if (!this.value) {
const sn = getSummernote(this);
- sn && sn.summernote('reset');
- object && object.editingArea.find('.note-placeholder').show();
+ sn && sn.summernote('code', '');
}
});
const jEditor = object && object.editable;
@@ -163,6 +135,7 @@ Template.editor.onRendered(() => {
});
}
},
+
onImageUpload(files) {
const $summernote = getSummernote(this);
if (files && files.length > 0) {
@@ -249,7 +222,7 @@ Template.editor.onRendered(() => {
// == Fix End ==
const original = someNote.summernote('code');
const cleaned = cleanPastedHTML(original); //this is where to call whatever clean function you want. I have mine in a different file, called CleanPastedHTML.
- someNote.summernote('reset'); //clear original
+ someNote.summernote('code', ''); //clear original
someNote.summernote('pasteHTML', cleaned); //this sets the displayed content editor to the cleaned pasted code.
};
setTimeout(function() {
@@ -316,15 +289,15 @@ Blaze.Template.registerHelper(
let currentMention;
while ((currentMention = mentionRegex.exec(content)) !== null) {
- const [fullMention, username] = currentMention;
+ const [fullMention, quoteduser, simple] = currentMention;
+ const username = quoteduser || simple;
const knowedUser = _.findWhere(knowedUsers, { username });
if (!knowedUser) {
continue;
}
const linkValue = [' ', at, knowedUser.username];
- //let linkClass = 'atMention js-open-member';
- let linkClass = 'atMention';
+ let linkClass = 'atMention js-open-member';
if (knowedUser.userId === Meteor.userId()) {
linkClass += ' me';
}
@@ -357,25 +330,24 @@ Template.viewer.events({
// the corresponding text). Clicking a link shouldn't fire these actions, stop
// we stop these event at the viewer component level.
'click a'(event, templateInstance) {
- event.stopPropagation();
-
- // XXX We hijack the build-in browser action because we currently don't have
- // `_blank` attributes in viewer links, and the transformer function is
- // handled by a third party package that we can't configure easily. Fix that
- // by using directly `_blank` attribute in the rendered HTML.
- event.preventDefault();
-
+ let prevent = true;
const userId = event.currentTarget.dataset.userid;
if (userId) {
- // Prevent @member mentions on Add Comment input field
- // from closing card, part 4.
- PopupNoClose.open('member').call({ userId }, event, templateInstance);
- event.preventDefault();
+ Popup.open('member').call({ userId }, event, templateInstance);
} else {
const href = event.currentTarget.href;
if (href) {
window.open(href, '_blank');
}
}
+ if (prevent) {
+ event.stopPropagation();
+
+ // XXX We hijack the build-in browser action because we currently don't have
+ // `_blank` attributes in viewer links, and the transformer function is
+ // handled by a third party package that we can't configure easily. Fix that
+ // by using directly `_blank` attribute in the rendered HTML.
+ event.preventDefault();
+ }
},
});
diff --git a/client/components/sidebar/sidebar.jade b/client/components/sidebar/sidebar.jade
index f0b0e4be..901fe99f 100644
--- a/client/components/sidebar/sidebar.jade
+++ b/client/components/sidebar/sidebar.jade
@@ -268,6 +268,10 @@ template(name="outgoingWebhooksPopup")
template(name="boardMenuPopup")
ul.pop-over-list
li
+ a.js-open-rules-view(title="{{_ 'rules'}}")
+ i.fa.fa-magic
+ | {{_ 'rules'}}
+ li
a.js-custom-fields
i.fa.fa-list-alt
| {{_ 'custom-fields'}}
diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js
index 8e640564..baf57114 100644
--- a/client/components/sidebar/sidebar.js
+++ b/client/components/sidebar/sidebar.js
@@ -182,6 +182,10 @@ Template.memberPopup.helpers({
Template.boardMenuPopup.events({
'click .js-rename-board': Popup.open('boardChangeTitle'),
+ 'click .js-open-rules-view'() {
+ Modal.openWide('rulesMain');
+ Popup.close();
+ },
'click .js-custom-fields'() {
Sidebar.setView('customFields');
Popup.close();
diff --git a/client/lib/popup.js b/client/lib/popup.js
index 8a55c2df..8095fbd2 100644
--- a/client/lib/popup.js
+++ b/client/lib/popup.js
@@ -206,207 +206,3 @@ escapeActions.forEach(actionName => {
},
);
});
-
-// Prevent @member mentions on Add Comment input field
-// from closing card, part 5.
-// This duplicate below of above popup function is needed, because at
-// wekan/components/main/editor.js at bottom is popping up visible
-// @member mention, and it seems to trigger closing also card popup,
-// so in below closing popup is disabled.
-window.PopupNoClose = new (class {
- constructor() {
- // The template we use to render popups
- this.template = Template.popup;
-
- // We only want to display one popup at a time and we keep the view object
- // in this `Popup.current` variable. If there is no popup currently opened
- // the value is `null`.
- this.current = null;
-
- // It's possible to open a sub-popup B from a popup A. In that case we keep
- // the data of popup A so we can return back to it. Every time we open a new
- // popup the stack grows, every time we go back the stack decrease, and if
- // we close the popup the stack is reseted to the empty stack [].
- this._stack = [];
-
- // We invalidate this internal dependency every time the top of the stack
- // has changed and we want to re-render a popup with the new top-stack data.
- this._dep = new Tracker.Dependency();
- }
-
- /// This function returns a callback that can be used in an event map:
- /// Template.tplName.events({
- /// 'click .elementClass': Popup.open("popupName"),
- /// });
- /// The popup inherit the data context of its parent.
- open(name) {
- const self = this;
- const popupName = `${name}Popup`;
- function clickFromPopup(evt) {
- return $(evt.target).closest('.js-pop-over').length !== 0;
- }
- return function(evt) {
- // If a popup is already opened, clicking again on the opener element
- // should close it -- and interrupt the current `open` function.
- /*
- if (self.isOpen()) {
- const previousOpenerElement = self._getTopStack().openerElement;
- if (previousOpenerElement === evt.currentTarget) {
- self.close();
- return;
- } else {
- $(previousOpenerElement).removeClass('is-active');
- }
- }
- */
- // We determine the `openerElement` (the DOM element that is being clicked
- // and the one we take in reference to position the popup) from the event
- // if the popup has no parent, or from the parent `openerElement` if it
- // has one. This allows us to position a sub-popup exactly at the same
- // position than its parent.
- let openerElement;
- if (clickFromPopup(evt)) {
- openerElement = self._getTopStack().openerElement;
- } else {
- self._stack = [];
- openerElement = evt.currentTarget;
- }
- $(openerElement).addClass('is-active');
- evt.preventDefault();
-
- // We push our popup data to the stack. The top of the stack is always
- // used as the data source for our current popup.
- self._stack.push({
- popupName,
- openerElement,
- hasPopupParent: clickFromPopup(evt),
- title: self._getTitle(popupName),
- depth: self._stack.length,
- offset: self._getOffset(openerElement),
- dataContext: (this && this.currentData && this.currentData()) || this,
- });
-
- // If there are no popup currently opened we use the Blaze API to render
- // one into the DOM. We use a reactive function as the data parameter that
- // return the complete along with its top element and depends on our
- // internal dependency that is being invalidated every time the top
- // element of the stack has changed and we want to update the popup.
- //
- // Otherwise if there is already a popup open we just need to invalidate
- // our internal dependency, and since we just changed the top element of
- // our internal stack, the popup will be updated with the new data.
- if (!self.isOpen()) {
- self.current = Blaze.renderWithData(
- self.template,
- () => {
- self._dep.depend();
- return { ...self._getTopStack(), stack: self._stack };
- },
- document.body,
- );
- } else {
- self._dep.changed();
- }
- };
- }
-
- /// This function returns a callback that can be used in an event map:
- /// Template.tplName.events({
- /// 'click .elementClass': Popup.afterConfirm("popupName", function() {
- /// // What to do after the user has confirmed the action
- /// }),
- /// });
- afterConfirm(name, action) {
- const self = this;
-
- return function(evt, tpl) {
- const context = (this.currentData && this.currentData()) || this;
- context.__afterConfirmAction = action;
- self.open(name).call(context, evt, tpl);
- };
- }
-
- /// The public reactive state of the popup.
- isOpen() {
- this._dep.changed();
- return Boolean(this.current);
- }
-
- /// In case the popup was opened from a parent popup we can get back to it
- /// with this `Popup.back()` function. You can go back several steps at once
- /// by providing a number to this function, e.g. `Popup.back(2)`. In this case
- /// intermediate popup won't even be rendered on the DOM. If the number of
- /// steps back is greater than the popup stack size, the popup will be closed.
- back(n = 1) {
- if (this._stack.length > n) {
- _.times(n, () => this._stack.pop());
- this._dep.changed();
- }
- // else {
- // this.close();
- //}
- }
-
- /// Close the current opened popup.
- /*
- close() {
- if (this.isOpen()) {
- Blaze.remove(this.current);
- this.current = null;
-
- const openerElement = this._getTopStack().openerElement;
- $(openerElement).removeClass('is-active');
-
- this._stack = [];
- }
- }
- */
-
- getOpenerComponent() {
- const { openerElement } = Template.parentData(4);
- return BlazeComponent.getComponentForElement(openerElement);
- }
-
- // An utility fonction that returns the top element of the internal stack
- _getTopStack() {
- return this._stack[this._stack.length - 1];
- }
-
- // We automatically calculate the popup offset from the reference element
- // position and dimensions. We also reactively use the window dimensions to
- // ensure that the popup is always visible on the screen.
- _getOffset(element) {
- const $element = $(element);
- return () => {
- Utils.windowResizeDep.depend();
-
- if (Utils.isMiniScreen()) return { left: 0, top: 0 };
-
- const offset = $element.offset();
- const popupWidth = 300 + 15;
- return {
- left: Math.min(offset.left, $(window).width() - popupWidth),
- top: offset.top + $element.outerHeight(),
- };
- };
- }
-
- // We get the title from the translation files. Instead of returning the
- // result, we return a function that compute the result and since `TAPi18n.__`
- // is a reactive data source, the title will be changed reactively.
- _getTitle(popupName) {
- return () => {
- const translationKey = `${popupName}-title`;
-
- // XXX There is no public API to check if there is an available
- // translation for a given key. So we try to translate the key and if the
- // translation output equals the key input we deduce that no translation
- // was available and returns `false`. There is a (small) risk a false
- // positives.
- const title = TAPi18n.__(translationKey);
- // when popup showed as full of small screen, we need a default header to clearly see [X] button
- const defaultTitle = Utils.isMiniScreen() ? '' : false;
- return title !== translationKey ? title : defaultTitle;
- };
- }
-})();