diff options
-rw-r--r-- | CHANGELOG.md | 21 | ||||
-rw-r--r-- | client/components/cards/cardDate.js | 20 | ||||
-rw-r--r-- | client/components/cards/minicard.jade | 2 | ||||
-rw-r--r-- | client/lib/filter.js | 196 | ||||
-rw-r--r-- | i18n/bg.i18n.json | 46 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | sandstorm-pkgdef.capnp | 4 | ||||
-rw-r--r-- | server/migrations.js | 2 |
8 files changed, 159 insertions, 134 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 31410bf2..af018d46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +# v1.05 2018-06-14 Wekan release + +This release adds the following new features: + +* [Markdown support in Custom Fields, and view on minicard](https://github.com/wekan/wekan/pull/1699); +* [Fixes to Advanced Filter, you are now able to filter for Dropdown and Numbers, + also Dropdown are now correctly displayed on minicard](https://github.com/wekan/wekan/pull/1699). + +and fixes the following bugs: + +* [Fix data colour changes on cards](https://github.com/wekan/wekan/pull/1698); +* [Fix for migration error "title is required" and breaking of Standalone and + Sandstorm Wekan](https://github.com/wekan/wekan/commit/8d5cbf1e6c2b6d467fe1c0708cd794fd11b98a2e#commitcomment-29362180); +* [Fix Issue with custom fields shown on card](https://github.com/wekan/wekan/issues/1659); +* [Fix showing public board in list mode](https://github.com/wekan/wekan/issues/1623); +* [Fix for not able to remove Custom Field "Show on Card"](https://github.com/wekan/wekan/pull/1699); +* [Fix minicardReceivedDate typo in 1.04 regression: Socket connection error and boards + not loading](https://github.com/wekan/wekan/issues/1694). + +Thanks to GitHub users feuerball11, Fran-KTA, oec, rjevnikar and xet7 for their contributions. + # v1.04 2018-06-12 Wekan release This release adds the following new features: diff --git a/client/components/cards/cardDate.js b/client/components/cards/cardDate.js index e95c3a23..c3e0524d 100644 --- a/client/components/cards/cardDate.js +++ b/client/components/cards/cardDate.js @@ -279,14 +279,18 @@ class CardDueDate extends CardDate { classes() { let classes = 'due-date' + ' '; - if ((this.now.get().diff(this.date.get(), 'days') >= 2) && + // if endAt exists & is < dueAt, dueAt doesn't need to be flagged + if ((this.data().endAt !== 0) && + (this.data().endAt !== null) && + (this.data().endAt !== '') && + (this.data().endAt !== undefined) && (this.date.get().isBefore(this.data().endAt))) + classes += 'current'; + else if (this.now.get().diff(this.date.get(), 'days') >= 2) classes += 'long-overdue'; - else if ((this.now.get().diff(this.date.get(), 'minute') >= 0) && - (this.date.get().isBefore(this.data().endAt))) + else if (this.now.get().diff(this.date.get(), 'minute') >= 0) classes += 'due'; - else if ((this.now.get().diff(this.date.get(), 'days') >= -1) && - (this.date.get().isBefore(this.data().endAt))) + else if (this.now.get().diff(this.date.get(), 'days') >= -1) classes += 'almost-due'; return classes; } @@ -316,10 +320,10 @@ class CardEndDate extends CardDate { let classes = 'end-date' + ' '; if (this.data.dueAt.diff(this.date.get(), 'days') >= 2) classes += 'long-overdue'; - else if (this.data.dueAt.diff(this.date.get(), 'days') >= 0) + else if (this.data.dueAt.diff(this.date.get(), 'days') > 0) classes += 'due'; - else if (this.data.dueAt.diff(this.date.get(), 'days') >= -2) - classes += 'almost-due'; + else if (this.data.dueAt.diff(this.date.get(), 'days') <= 0) + classes += 'current'; return classes; } diff --git a/client/components/cards/minicard.jade b/client/components/cards/minicard.jade index c912ea70..2a8e95ab 100644 --- a/client/components/cards/minicard.jade +++ b/client/components/cards/minicard.jade @@ -15,7 +15,7 @@ template(name="minicard") unless dueAt unless endAt .date - +miniCardReceivedDate + +minicardReceivedDate if startAt .date +minicardStartDate diff --git a/client/lib/filter.js b/client/lib/filter.js index ea1811de..e3658e1e 100644 --- a/client/lib/filter.js +++ b/client/lib/filter.js @@ -149,11 +149,11 @@ class AdvancedFilter { { const found = CustomFields.findOne({ 'name': field }); if (found.settings.dropdownItems && found.settings.dropdownItems.length > 0) - { + { for (let i = 0; i < found.settings.dropdownItems.length; i++) - { + { if (found.settings.dropdownItems[i].name === value) - { + { return found.settings.dropdownItems[i]._id; } } @@ -179,27 +179,27 @@ class AdvancedFilter { if (commands[i].cmd) { switch (commands[i].cmd) { case '(': - { - level++; - if (start === -1) start = i; - continue; - } + { + level++; + if (start === -1) start = i; + continue; + } case ')': - { - level--; + { + level--; + commands.splice(i, 1); + i--; + continue; + } + default: + { + if (level > 0) { + subcommands.push(commands[i]); commands.splice(i, 1); i--; continue; } - default: - { - if (level > 0) { - subcommands.push(commands[i]); - commands.splice(i, 1); - i--; - continue; - } - } + } } } } @@ -221,86 +221,86 @@ class AdvancedFilter { case '=': case '==': case '===': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} }; - commands.splice(i - 1, 1); - commands.splice(i, 1); + { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} }; + commands.splice(i - 1, 1); + commands.splice(i, 1); //changed = true; - i--; - break; - } + i--; + break; + } case '!=': case '!==': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $not: {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} } }; - commands.splice(i - 1, 1); - commands.splice(i, 1); + { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $not: {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} } }; + commands.splice(i - 1, 1); + commands.splice(i, 1); //changed = true; - i--; - break; - } + i--; + break; + } case '>': case 'gt': case 'Gt': case 'GT': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gt: parseInt(str, 10) } }; - commands.splice(i - 1, 1); - commands.splice(i, 1); + { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gt: parseInt(str, 10) } }; + commands.splice(i - 1, 1); + commands.splice(i, 1); //changed = true; - i--; - break; - } + i--; + break; + } case '>=': case '>==': case 'gte': case 'Gte': case 'GTE': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gte: parseInt(str, 10) } }; - commands.splice(i - 1, 1); - commands.splice(i, 1); + { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gte: parseInt(str, 10) } }; + commands.splice(i - 1, 1); + commands.splice(i, 1); //changed = true; - i--; - break; - } + i--; + break; + } case '<': case 'lt': case 'Lt': case 'LT': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lt: parseInt(str, 10) } }; - commands.splice(i - 1, 1); - commands.splice(i, 1); + { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lt: parseInt(str, 10) } }; + commands.splice(i - 1, 1); + commands.splice(i, 1); //changed = true; - i--; - break; - } + i--; + break; + } case '<=': case '<==': case 'lte': case 'Lte': case 'LTE': - { - const field = commands[i - 1].cmd; - const str = commands[i + 1].cmd; - commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lte: parseInt(str, 10) } }; - commands.splice(i - 1, 1); - commands.splice(i, 1); + { + const field = commands[i - 1].cmd; + const str = commands[i + 1].cmd; + commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lte: parseInt(str, 10) } }; + commands.splice(i - 1, 1); + commands.splice(i, 1); //changed = true; - i--; - break; - } + i--; + break; + } } } @@ -316,44 +316,44 @@ class AdvancedFilter { case 'OR': case '|': case '||': - { - const op1 = commands[i - 1]; - const op2 = commands[i + 1]; - commands[i] = { $or: [op1, op2] }; - commands.splice(i - 1, 1); - commands.splice(i, 1); + { + const op1 = commands[i - 1]; + const op2 = commands[i + 1]; + commands[i] = { $or: [op1, op2] }; + commands.splice(i - 1, 1); + commands.splice(i, 1); //changed = true; - i--; - break; - } + i--; + break; + } case 'and': case 'And': case 'AND': case '&': case '&&': - { - const op1 = commands[i - 1]; - const op2 = commands[i + 1]; - commands[i] = { $and: [op1, op2] }; - commands.splice(i - 1, 1); - commands.splice(i, 1); + { + const op1 = commands[i - 1]; + const op2 = commands[i + 1]; + commands[i] = { $and: [op1, op2] }; + commands.splice(i - 1, 1); + commands.splice(i, 1); //changed = true; - i--; - break; - } + i--; + break; + } case 'not': case 'Not': case 'NOT': case '!': - { - const op1 = commands[i + 1]; - commands[i] = { $not: op1 }; - commands.splice(i + 1, 1); + { + const op1 = commands[i + 1]; + commands[i] = { $not: op1 }; + commands.splice(i + 1, 1); //changed = true; - i--; - break; - } + i--; + break; + } } } diff --git a/i18n/bg.i18n.json b/i18n/bg.i18n.json index 87c914bf..3940e33a 100644 --- a/i18n/bg.i18n.json +++ b/i18n/bg.i18n.json @@ -45,7 +45,7 @@ "activity-checklist-item-added": "добави точка към '%s' в/във %s", "add": "Добави", "add-attachment": "Добави прикачен файл", - "add-board": "Добави дъска", + "add-board": "Добави Табло", "add-card": "Добави карта", "add-swimlane": "Добави коридор", "add-checklist": "Добави списък със задачи", @@ -61,23 +61,23 @@ "admin-announcement": "Съобщение", "admin-announcement-active": "Active System-Wide Announcement", "admin-announcement-title": "Съобщение от администратора", - "all-boards": "Всички дъски", + "all-boards": "Всички табла", "and-n-other-card": "И __count__ друга карта", "and-n-other-card_plural": "И __count__ други карти", "apply": "Приложи", "app-is-offline": "Wekan зарежда, моля изчакайте! Презареждането на страницата може да доведе до загуба на данни. Ако Wekan не се зареди, моля проверете дали сървъра му работи.", "archive": "Премести в Кошчето", "archive-all": "Премести всички в Кошчето", - "archive-board": "Премести Дъската в Кошчето", + "archive-board": "Премести Таблото в Кошчето", "archive-card": "Премести Картата в Кошчето", "archive-list": "Премести Списъка в Кошчето", "archive-swimlane": "Премести Коридора в Кошчето", "archive-selection": "Премести избраните в Кошчето", - "archiveBoardPopup-title": "Сигурни ли сте, че искате да преместите Дъската в Кошчето?", + "archiveBoardPopup-title": "Сигурни ли сте, че искате да преместите Таблото в Кошчето?", "archived-items": "Кошче", - "archived-boards": "Дъски в Кошчето", - "restore-board": "Възстанови Дъската", - "no-archived-boards": "Няма Дъски в Кошчето.", + "archived-boards": "Табла в Кошчето", + "restore-board": "Възстанови Таблото", + "no-archived-boards": "Няма Табла в Кошчето.", "archives": "Кошче", "assign-member": "Възложи на член от екипа", "attached": "прикачен", @@ -85,20 +85,20 @@ "attachment-delete-pop": "Изтриването на прикачен файл е завинаги. Няма как да бъде възстановен.", "attachmentDeletePopup-title": "Желаете ли да изтриете прикачения файл?", "attachments": "Прикачени файлове", - "auto-watch": "Автоматично наблюдаване на дъските, когато са създадени", + "auto-watch": "Автоматично наблюдаване на таблата, когато са създадени", "avatar-too-big": "Аватарът е прекалено голям (максимум 70KB)", "back": "Назад", "board-change-color": "Промени цвета", "board-nb-stars": "%s звезди", - "board-not-found": "Дъската не е намерена", + "board-not-found": "Таблото не е намерено", "board-private-info": "This board will be <strong>private</strong>.", "board-public-info": "This board will be <strong>public</strong>.", "boardChangeColorPopup-title": "Change Board Background", - "boardChangeTitlePopup-title": "Промени името на Дъската", + "boardChangeTitlePopup-title": "Промени името на Таблото", "boardChangeVisibilityPopup-title": "Change Visibility", "boardChangeWatchPopup-title": "Промени наблюдаването", - "boardMenuPopup-title": "Меню на Дъската", - "boards": "Дъски", + "boardMenuPopup-title": "Меню на Таблото", + "boards": "Табла", "board-view": "Board View", "board-view-swimlanes": "Коридори", "board-view-lists": "Списъци", @@ -117,7 +117,7 @@ "card-edit-labels": "Промени етикетите", "card-edit-members": "Промени членовете", "card-labels-title": "Промени етикетите за картата.", - "card-members-title": "Добави или премахни членове на Дъската от тази карта.", + "card-members-title": "Добави или премахни членове на Таблото от тази карта.", "card-start": "Начало", "card-start-on": "Започва на", "cardAttachmentsPopup-title": "Прикачи от", @@ -142,10 +142,10 @@ "changeSettingsPopup-title": "Промяна на настройките", "checklists": "Списъци със задачи", "click-to-star": "Click to star this board.", - "click-to-unstar": "Натиснете, за да премахнете тази дъска от любими.", + "click-to-unstar": "Натиснете, за да премахнете това табло от любими.", "clipboard": "Клипборда или с драг & дроп", "close": "Затвори", - "close-board": "Затвори Дъската", + "close-board": "Затвори Таблото", "close-board-pop": "You will be able to restore the board by clicking the “Recycle Bin” button from the home header.", "color-black": "черно", "color-blue": "синьо", @@ -165,7 +165,7 @@ "confirm-checklist-delete-dialog": "Сигурни ли сте, че искате да изтриете този чеклист?", "copy-card-link-to-clipboard": "Копирай връзката на картата в клипборда", "copyCardPopup-title": "Копирай картата", - "copyChecklistToManyCardsPopup-title": "Копирай шаблона за чеклисти в много карти", + "copyChecklistToManyCardsPopup-title": "Копирай чеклисти в други карти", "copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format", "copyChecklistToManyCardsPopup-format": "[ {\"title\": \"First card title\", \"description\":\"First card description\"}, {\"title\":\"Second card title\",\"description\":\"Second card description\"},{\"title\":\"Last card title\",\"description\":\"Last card description\"} ]", "create": "Create", @@ -244,7 +244,7 @@ "filter-no-member": "без член", "filter-no-custom-fields": "Няма Собствени полета", "filter-on": "Има приложени филтри", - "filter-on-desc": "В момента филтрирате картите в тази дъска. Моля, натиснете тук, за да промените филтъра.", + "filter-on-desc": "В момента филтрирате картите в това табло. Моля, натиснете тук, за да промените филтъра.", "filter-to-selection": "Филтрирай избраните", "advanced-filter-label": "Advanced Filter", "advanced-filter-description": "Advanced Filter allows to write a string containing following operators: == != <= >= && || ( ) A space is used as a separator between the Operators. You can filter for all Custom Fields by typing their names and values. For Example: Field1 == Value1. Note: If fields or values contains spaces, you need to encapsulate them into single quotes. For Example: 'Field 1' == 'Value 1'. Also you can combine multiple conditions. For Example: F1 == V1 || F1 = V2. Normally all operators are interpreted from left to right. You can change the order by placing brackets. For Example: F1 == V1 and ( F2 == V2 || F2 == V3 )", @@ -297,7 +297,7 @@ "listMorePopup-title": "Още", "link-list": "Връзка към този списък", "list-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the list. There is no undo.", - "list-delete-suggest-archive": "Можете да преместите списък в Кошчето, за да го премахнете от Дъската и запазите активността.", + "list-delete-suggest-archive": "Можете да преместите списък в Кошчето, за да го премахнете от Таблото и запазите активността.", "lists": "Списъци", "swimlanes": "Коридори", "log-out": "Изход", @@ -315,7 +315,7 @@ "multi-selection-on": "Множественият избор е приложен", "muted": "Muted", "muted-info": "You will never be notified of any changes in this board", - "my-boards": "Моите дъски", + "my-boards": "Моите табла", "name": "Име", "no-archived-cards": "Няма карти в Кошчето.", "no-archived-lists": "Няма списъци в Кошчето.", @@ -325,7 +325,7 @@ "normal-desc": "Can view and edit cards. Can't change settings.", "not-accepted-yet": "Invitation not accepted yet", "notify-participate": "Получавате информация за всички карти, в които сте отбелязани или сте създали", - "notify-watch": "Получавате информация за всички дъски, списъци и карти, които наблюдавате", + "notify-watch": "Получавате информация за всички табла, списъци и карти, които наблюдавате", "optional": "optional", "or": "or", "page-maybe-private": "This page may be private. You may be able to view it by <a href='%s'>logging in</a>.", @@ -351,7 +351,7 @@ "remove-member-pop": "Remove __name__ (__username__) from __boardTitle__? The member will be removed from all cards on this board. They will receive a notification.", "removeMemberPopup-title": "Remove Member?", "rename": "Rename", - "rename-board": "Промени името на Дъската", + "rename-board": "Промени името на Таблото", "restore": "Възстанови", "save": "Запази", "search": "Търсене", @@ -374,8 +374,8 @@ "sidebar-close": "Close Sidebar", "signupPopup-title": "Create an Account", "star-board-title": "Click to star this board. It will show up at top of your boards list.", - "starred-boards": "Любими дъски", - "starred-boards-description": "Любимите дъски се показват в началото на списъка Ви.", + "starred-boards": "Любими табла", + "starred-boards-description": "Любимите табла се показват в началото на списъка Ви.", "subscribe": "Subscribe", "team": "Team", "this-board": "this board", diff --git a/package.json b/package.json index 1e1db802..4da56a02 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wekan", - "version": "1.04.0", + "version": "1.05.0", "description": "The open-source Trello-like kanban", "private": true, "scripts": { diff --git a/sandstorm-pkgdef.capnp b/sandstorm-pkgdef.capnp index 7953f0f9..3c12205e 100644 --- a/sandstorm-pkgdef.capnp +++ b/sandstorm-pkgdef.capnp @@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = ( appTitle = (defaultText = "Wekan"), # The name of the app as it is displayed to the user. - appVersion = 89, + appVersion = 90, # Increment this for every release. - appMarketingVersion = (defaultText = "1.04.0~2018-06-12"), + appMarketingVersion = (defaultText = "1.05.0~2018-06-14"), # Human-readable presentation of the app version. minUpgradableAppVersion = 0, diff --git a/server/migrations.js b/server/migrations.js index 640eae69..a1a5c65a 100644 --- a/server/migrations.js +++ b/server/migrations.js @@ -140,7 +140,7 @@ Migrations.add('add-sort-checklists', () => { noValidate ); } - checklist.items.find().forEach((item, index) => { + checklist.items.forEach((item, index) => { if (!item.hasOwnProperty('sort')) { Checklists.direct.update( { _id: checklist._id, 'items._id': item._id }, |