Compare commits

...
12 Commits
Author SHA1 Message Date
Lauri Ojansivu b33f44e23f v3.87 2020-04-01 00:12:35 +03:00
Lauri Ojansivu a65e39563b Update translations. 2020-04-01 00:04:18 +03:00
Lauri Ojansivu 703efa5216 Update ChangeLog. 2020-04-01 00:01:15 +03:00
Lauri Ojansivu 6b902bdb36 Improvements on card details visualization.
Thanks to helioguardabaxo and xet7 !

Closes #2974
2020-03-31 23:56:37 +03:00
Lauri Ojansivu d599fc12ff Update ChangeLog. 2020-03-31 23:36:47 +03:00
Lauri Ojansivu e7d2343593 Move "Rules" from "Board View" to "Board Settings".
Thanks to helioguardabaxo and xet7 !

Closes #2973
2020-03-31 23:32:32 +03:00
Lauri Ojansivu c8ec5d5f62 Update ChangeLog. 2020-03-31 23:20:07 +03:00
Lauri Ojansivu 033d671047 Fix richer editor submit did not clear edit area.
Thanks to xet7 !
2020-03-31 23:17:58 +03:00
Lauri Ojansivu 6ef3f8a1c8 Update ChangeLog. 2020-03-31 17:05:02 +03:00
Lauri Ojansivu 3546d7aa02 Fix Browser always reload the whole page when I change one of the card color.
Fixed by making label colors and text again editable.
Regression from [Wekan v3.86 2)](https://github.com/wekan/wekan/commit/b9099a8b7ea6f63c79bdcbb871cb993b2cb7e325).

Thanks to javen9881 and xet7 !

Closes #2971
2020-03-31 16:56:32 +03:00
Lauri Ojansivu 29d62440a5 Update ChangeLog. 2020-03-25 13:41:33 +02:00
Lauri Ojansivu 5bd0459cc2 Hide duplicate "Hide system messages" at Change Settings/Member Settings, because it's also on card slider.
Thanks to notohiro and xet7 !

Closes #2837
2020-03-25 13:35:54 +02:00
21 changed files with 77 additions and 304 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v3.86.0",
"version": "v3.87.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v3.86.0",
"version": "v3.87.0",
"description": "Open-Source kanban",
"private": true,
"scripts": {
+24
View File
@@ -1,3 +1,27 @@
# v3.87 2020-04-01 Wekan release
This release makes the following UI changes:
- [Move "Rules" from "Board View" to "Board Settings"](https://github.com/wekan/wekan/issues/2973).
Thanks to helioguardabaxo and xet7.
- [Improvements on card details visualization](https://github.com/wekan/wekan/issues/2974).
Thanks to helioguardabaxo and xet7.
- [Hide duplicate "Hide system messages" at Change Settings/Member Settings, because it's also on card
slider](https://github.com/wekan/wekan/issues/2837).
Thanks to notohiro and xet7.
and fixes the following bugs:
- [Fix Browser always reload the whole page when I change one of the card
color](https://github.com/wekan/wekan/commit/3546d7aa02bc65cf1183cb493adeb543ba51945d).
Fixed by making label colors and text again editable.
Regression from [Wekan v3.86 2)](https://github.com/wekan/wekan/commit/b9099a8b7ea6f63c79bdcbb871cb993b2cb7e325).
Thanks to javen9881 and xet7.
- [Fix richer editor submit did not clear edit area](https://github.com/wekan/wekan/commit/033d6710470b2ecd7a0ec0b2f0741ff459e68b32).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v3.86 2020-03-24 Wekan release
This release fixes the following bugs:
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v3.86.0"
appVersion: "v3.87.0"
files:
userUploads:
- README.md
-7
View File
@@ -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');
-14
View File
@@ -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
-4
View File
@@ -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({
+1 -1
View File
@@ -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' }}
+7 -4
View File
@@ -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
+1 -6
View File
@@ -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
+19 -47
View File
@@ -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();
}
},
});
+4
View File
@@ -267,6 +267,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
+4
View File
@@ -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();
+6 -6
View File
@@ -98,12 +98,12 @@ template(name="changeLanguagePopup")
template(name="changeSettingsPopup")
ul.pop-over-list
li
a.js-toggle-system-messages
i.fa.fa-comments-o
| {{_ 'hide-system-messages'}}
if hiddenSystemMessages
i.fa.fa-check
//li
// a.js-toggle-system-messages
// i.fa.fa-comments-o
// | {{_ 'hide-system-messages'}}
// if hiddenSystemMessages
// i.fa.fa-check
li
a.js-toggle-desktop-drag-handles
i.fa.fa-arrows
-204
View File
@@ -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;
};
}
})();
+1 -1
View File
@@ -182,7 +182,7 @@
"changeLanguagePopup-title": "Alterar Idioma",
"changePasswordPopup-title": "Alterar Senha",
"changePermissionsPopup-title": "Alterar Permissões",
"changeSettingsPopup-title": "Altera configurações",
"changeSettingsPopup-title": "Alterar configurações",
"subtasks": "Subtarefas",
"checklists": "Listas de verificação",
"click-to-star": "Marcar quadro como favorito.",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v3.86.0",
"version": "v3.87.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v3.86.0",
"version": "v3.87.0",
"description": "Open-Source kanban",
"private": true,
"scripts": {
+2 -2
View File
@@ -1524,7 +1524,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
<ul class="toc-list-h1">
<li>
<a href="#wekan-rest-api" class="toc-h1 toc-link" data-title="Wekan REST API v3.86">Wekan REST API v3.86</a>
<a href="#wekan-rest-api" class="toc-h1 toc-link" data-title="Wekan REST API v3.87">Wekan REST API v3.87</a>
</li>
@@ -2017,7 +2017,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
<div class="page-wrapper">
<div class="dark-box"></div>
<div class="content">
<h1 id="wekan-rest-api">Wekan REST API v3.86</h1>
<h1 id="wekan-rest-api">Wekan REST API v3.87</h1>
<blockquote>
<p>Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.</p>
</blockquote>
+1 -1
View File
@@ -1,7 +1,7 @@
swagger: '2.0'
info:
title: Wekan REST API
version: v3.86
version: v3.87
description: |
The REST API allows you to control and extend Wekan with ease.
+2 -2
View File
@@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
appTitle = (defaultText = "Wekan"),
# The name of the app as it is displayed to the user.
appVersion = 386,
appVersion = 387,
# Increment this for every release.
appMarketingVersion = (defaultText = "3.86.0~2020-03-24"),
appMarketingVersion = (defaultText = "3.87.0~2020-04-01"),
# Human-readable presentation of the app version.
minUpgradableAppVersion = 0,