summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md16
-rw-r--r--Stackerfile.yml2
-rw-r--r--client/components/activities/activities.jade9
-rw-r--r--client/components/activities/activities.js8
-rw-r--r--client/components/cards/cardDetails.js8
-rw-r--r--client/components/lists/list.js6
-rw-r--r--client/components/settings/settingBody.js2
-rw-r--r--client/components/sidebar/sidebarCustomFields.js16
-rw-r--r--i18n/hu.i18n.json42
-rw-r--r--i18n/oc.i18n.json10
-rw-r--r--i18n/sv.i18n.json160
-rw-r--r--models/boards.js6
-rw-r--r--models/cards.js104
-rw-r--r--models/customFields.js71
-rw-r--r--models/export.js2
-rw-r--r--package.json2
-rw-r--r--sandstorm-pkgdef.capnp4
-rw-r--r--server/lib/utils.js6
-rw-r--r--server/migrations.js13
-rw-r--r--server/publications/boards.js5
-rw-r--r--server/rulesHelper.js2
21 files changed, 335 insertions, 159 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dca4f793..ac1624d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+# v2.49 2019-03-21 Wekan release
+
+This release fixes the following bugs:
+
+- [The invitation code doesn't exist - case-sensitive eMail](https://github.com/wekan/wekan/issues/1384). Thanks to neurolabs.
+- [Don't swallow email errors](https://github.com/wekan/wekan/pull/2272). Thanks to justinr1234.
+- [Migrate customFields model](https://github.com/wekan/wekan/pull/2264].
+ Modifies the customFields model to keep an array of boardIds where the customField can be used.
+ Adds name matching for labels when copying/moving cards between boards.
+ This way, customFields are not lost when copying/moving a card. Particularly useful when templates have customFields or labels with specific names (not tested for templates yet).
+ Thanks to andresmanelli.
+- [Fix dissapearing subtasks](https://github.com/wekan/wekan/pull/2265). Thanks to andresmanelli.
+- [Cards disappear when rearranged on template board](https://github.com/wekan/wekan/issues/2266). Thanks to andresmanelli.
+
+Thanks to above GitHub users for their contributions and translators for their translations.
+
# v2.48 2019-03-15 Wekan release
This release fixes the following bugs, thanks to GitHub user xet7:
diff --git a/Stackerfile.yml b/Stackerfile.yml
index 46037269..49ac8a7c 100644
--- a/Stackerfile.yml
+++ b/Stackerfile.yml
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
-appVersion: "v2.48.0"
+appVersion: "v2.49.0"
files:
userUploads:
- README.md
diff --git a/client/components/activities/activities.jade b/client/components/activities/activities.jade
index 949400f6..54066da8 100644
--- a/client/components/activities/activities.jade
+++ b/client/components/activities/activities.jade
@@ -99,6 +99,9 @@ template(name="boardActivities")
else
| {{{_ 'activity-added' memberLink cardLink}}}.
+ if($eq activityType 'moveCardBoard')
+ | {{{_ 'activity-moved' cardLink oldBoardName boardName}}}.
+
if($eq activityType 'moveCard')
| {{{_ 'activity-moved' cardLink oldList.title list.title}}}.
@@ -135,7 +138,7 @@ template(name="cardActivities")
p.activity-desc
+memberName(user=user)
if($eq activityType 'createCard')
- | {{_ 'activity-added' cardLabel list.title}}.
+ | {{_ 'activity-added' cardLabel listName}}.
if($eq activityType 'importCard')
| {{{_ 'activity-imported' cardLabel list.title sourceLink}}}.
if($eq activityType 'joinMember')
@@ -176,6 +179,10 @@ template(name="cardActivities")
| {{_ 'activity-sent' cardLabel boardLabel}}.
if($eq activityType 'moveCard')
| {{_ 'activity-moved' cardLabel oldList.title list.title}}.
+
+ if($eq activityType 'moveCardBoard')
+ | {{{_ 'activity-moved' cardLink oldBoardName boardName}}}.
+
if($eq activityType 'addAttachment')
| {{{_ 'activity-attached' attachmentLink cardLabel}}}.
if attachment.isImage
diff --git a/client/components/activities/activities.js b/client/components/activities/activities.js
index 81995221..0476897f 100644
--- a/client/components/activities/activities.js
+++ b/client/components/activities/activities.js
@@ -74,6 +74,8 @@ BlazeComponent.extendComponent({
lastLabel(){
const lastLabelId = this.currentData().labelId;
+ if (!lastLabelId)
+ return null;
const lastLabel = Boards.findOne(Session.get('currentBoard')).getLabelById(lastLabelId);
if(lastLabel.name === undefined || lastLabel.name === ''){
return lastLabel.color;
@@ -84,11 +86,15 @@ BlazeComponent.extendComponent({
lastCustomField(){
const lastCustomField = CustomFields.findOne(this.currentData().customFieldId);
+ if (!lastCustomField)
+ return null;
return lastCustomField.name;
},
lastCustomFieldValue(){
const lastCustomField = CustomFields.findOne(this.currentData().customFieldId);
+ if (!lastCustomField)
+ return null;
const value = this.currentData().value;
if (lastCustomField.settings.dropdownItems && lastCustomField.settings.dropdownItems.length > 0) {
const dropDownValue = _.find(lastCustomField.settings.dropdownItems, (item) => {
@@ -135,6 +141,8 @@ BlazeComponent.extendComponent({
customField() {
const customField = this.currentData().customField();
+ if (!customField)
+ return null;
return customField.name;
},
diff --git a/client/components/cards/cardDetails.js b/client/components/cards/cardDetails.js
index d27fe732..79e9e311 100644
--- a/client/components/cards/cardDetails.js
+++ b/client/components/cards/cardDetails.js
@@ -412,11 +412,13 @@ Template.moveCardPopup.events({
// XXX We should *not* get the currentCard from the global state, but
// instead from a “component” state.
const card = Cards.findOne(Session.get('currentCard'));
+ const bSelect = $('.js-select-boards')[0];
+ const boardId = bSelect.options[bSelect.selectedIndex].value;
const lSelect = $('.js-select-lists')[0];
- const newListId = lSelect.options[lSelect.selectedIndex].value;
+ const listId = lSelect.options[lSelect.selectedIndex].value;
const slSelect = $('.js-select-swimlanes')[0];
- card.swimlaneId = slSelect.options[slSelect.selectedIndex].value;
- card.move(card.swimlaneId, newListId, 0);
+ const swimlaneId = slSelect.options[slSelect.selectedIndex].value;
+ card.move(boardId, swimlaneId, listId, 0);
Popup.close();
},
});
diff --git a/client/components/lists/list.js b/client/components/lists/list.js
index 868be2ce..12932a82 100644
--- a/client/components/lists/list.js
+++ b/client/components/lists/list.js
@@ -70,7 +70,7 @@ BlazeComponent.extendComponent({
const currentBoard = Boards.findOne(Session.get('currentBoard'));
let swimlaneId = '';
const boardView = Meteor.user().profile.boardView;
- if (boardView === 'board-view-swimlanes')
+ if (boardView === 'board-view-swimlanes' || currentBoard.isTemplatesBoard())
swimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0))._id;
else if ((boardView === 'board-view-lists') || (boardView === 'board-view-cal'))
swimlaneId = currentBoard.getDefaultSwimline()._id;
@@ -86,12 +86,12 @@ BlazeComponent.extendComponent({
if (MultiSelection.isActive()) {
Cards.find(MultiSelection.getMongoSelector()).forEach((card, i) => {
- card.move(swimlaneId, listId, sortIndex.base + i * sortIndex.increment);
+ card.move(currentBoard._id, swimlaneId, listId, sortIndex.base + i * sortIndex.increment);
});
} else {
const cardDomElement = ui.item.get(0);
const card = Blaze.getData(cardDomElement);
- card.move(swimlaneId, listId, sortIndex.base);
+ card.move(currentBoard._id, swimlaneId, listId, sortIndex.base);
}
boardComponent.setIsDragging(false);
},
diff --git a/client/components/settings/settingBody.js b/client/components/settings/settingBody.js
index 2f58d551..8279a092 100644
--- a/client/components/settings/settingBody.js
+++ b/client/components/settings/settingBody.js
@@ -90,7 +90,7 @@ BlazeComponent.extendComponent({
},
inviteThroughEmail() {
- const emails = $('#email-to-invite').val().trim().split('\n').join(',').split(',');
+ const emails = $('#email-to-invite').val().toLowerCase().trim().split('\n').join(',').split(',');
const boardsToInvite = [];
$('.js-toggle-board-choose .materialCheckBox.is-checked').each(function () {
boardsToInvite.push($(this).data('id'));
diff --git a/client/components/sidebar/sidebarCustomFields.js b/client/components/sidebar/sidebarCustomFields.js
index ccc8ffb9..28af973b 100644
--- a/client/components/sidebar/sidebarCustomFields.js
+++ b/client/components/sidebar/sidebarCustomFields.js
@@ -2,7 +2,7 @@ BlazeComponent.extendComponent({
customFields() {
return CustomFields.find({
- boardId: Session.get('currentBoard'),
+ boardIds: {$in: [Session.get('currentBoard')]},
});
},
@@ -103,7 +103,6 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
evt.preventDefault();
const data = {
- boardId: Session.get('currentBoard'),
name: this.find('.js-field-name').value.trim(),
type: this.type.get(),
settings: this.getSettings(),
@@ -114,6 +113,7 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
// insert or update
if (!this.data()._id) {
+ data.boardIds = [Session.get('currentBoard')];
CustomFields.insert(data);
} else {
CustomFields.update(this.data()._id, {$set: data});
@@ -122,8 +122,16 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
Popup.back();
},
'click .js-delete-custom-field': Popup.afterConfirm('deleteCustomField', function() {
- const customFieldId = this._id;
- CustomFields.remove(customFieldId);
+ const customField = CustomFields.findOne(this._id);
+ if (customField.boardIds.length > 1) {
+ CustomFields.update(customField._id, {
+ $pull: {
+ boardIds: Session.get('currentBoard'),
+ },
+ });
+ } else {
+ CustomFields.remove(customField._id);
+ }
Popup.close();
}),
}];
diff --git a/i18n/hu.i18n.json b/i18n/hu.i18n.json
index 0f10daf1..cb500412 100644
--- a/i18n/hu.i18n.json
+++ b/i18n/hu.i18n.json
@@ -1,6 +1,6 @@
{
"accept": "Elfogadás",
- "act-activity-notify": "Activity Notification",
+ "act-activity-notify": "Tevékenység értesítés",
"act-addAttachment": "added attachment __attachment__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-deleteAttachment": "deleted attachment __attachment__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addSubtask": "added subtask __subtask__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
@@ -626,7 +626,7 @@
"r-check": "Check",
"r-uncheck": "Uncheck",
"r-item": "item",
- "r-of-checklist": "of checklist",
+ "r-of-checklist": "ellenőrzőlistából",
"r-send-email": "Send an email",
"r-to": "to",
"r-subject": "subject",
@@ -651,32 +651,32 @@
"r-d-remove-all-member": "Remove all member",
"r-d-check-all": "Check all items of a list",
"r-d-uncheck-all": "Uncheck all items of a list",
- "r-d-check-one": "Check item",
+ "r-d-check-one": "Elem ellenőrzése",
"r-d-uncheck-one": "Uncheck item",
- "r-d-check-of-list": "of checklist",
- "r-d-add-checklist": "Add checklist",
- "r-d-remove-checklist": "Remove checklist",
- "r-by": "by",
- "r-add-checklist": "Add checklist",
- "r-with-items": "with items",
+ "r-d-check-of-list": "ellenőrzőlistából",
+ "r-d-add-checklist": "Ellenőrzőlista hozzáadása",
+ "r-d-remove-checklist": "Ellenőrzőlista eltávolítása",
+ "r-by": "által",
+ "r-add-checklist": "Ellenőrzőlista hozzáadása",
+ "r-with-items": "elemekkel",
"r-items-list": "item1,item2,item3",
"r-add-swimlane": "Add swimlane",
"r-swimlane-name": "swimlane name",
"r-board-note": "Note: leave a field empty to match every possible value.",
"r-checklist-note": "Note: checklist's items have to be written as comma separated values.",
- "r-when-a-card-is-moved": "When a card is moved to another list",
+ "r-when-a-card-is-moved": "Amikor egy kártya másik listába kerül",
"ldap": "LDAP",
"oauth2": "OAuth2",
"cas": "CAS",
- "authentication-method": "Authentication method",
- "authentication-type": "Authentication type",
- "custom-product-name": "Custom Product Name",
- "layout": "Layout",
- "hide-logo": "Hide Logo",
- "add-custom-html-after-body-start": "Add Custom HTML after <body> start",
- "add-custom-html-before-body-end": "Add Custom HTML before </body> end",
- "error-undefined": "Something went wrong",
- "error-ldap-login": "An error occurred while trying to login",
- "display-authentication-method": "Display Authentication Method",
- "default-authentication-method": "Default Authentication Method"
+ "authentication-method": "Hitelesítési mód",
+ "authentication-type": "Hitelesítés típusa",
+ "custom-product-name": "Saját terméknév",
+ "layout": "Elrendezés",
+ "hide-logo": "Logo elrejtése",
+ "add-custom-html-after-body-start": "Egyedi HTML hozzáadása <body> után",
+ "add-custom-html-before-body-end": "1",
+ "error-undefined": "Valami hiba történt",
+ "error-ldap-login": "Hiba történt bejelentkezés közben",
+ "display-authentication-method": "Hitelelesítési mód mutatása",
+ "default-authentication-method": "Alapértelmezett hitelesítési mód"
} \ No newline at end of file
diff --git a/i18n/oc.i18n.json b/i18n/oc.i18n.json
index 89f68375..57389d44 100644
--- a/i18n/oc.i18n.json
+++ b/i18n/oc.i18n.json
@@ -76,7 +76,7 @@
"add-label": "Apondre una etiqueta",
"add-list": "Apondre una tièra",
"add-members": "Apondre un participant",
- "added": "Apondut",
+ "added": "Apondut lo",
"addMemberPopup-title": "Participants",
"admin": "Administartor",
"admin-desc": "As lo drech de legir e modificar las cartas, tirar de participants, e modificar las opcions del tablèu.",
@@ -135,8 +135,8 @@
"card-delete-notice": "Un còp tirat, pas de posibilitat de tornar enrè",
"card-delete-pop": "Totes las accions van èsser quitadas del seguit d'activitat e poiretz pas mai utilizar aquesta carta.",
"card-delete-suggest-archive": "Podètz desplaçar una carta dins Archius per la quitar del tablèu e gardar las activitats.",
- "card-due": "esperat",
- "card-due-on": "esperat per",
+ "card-due": "Esperat",
+ "card-due-on": "Esperat lo",
"card-spent": "Temps passat",
"card-edit-attachments": "Cambiar las pèças jonchas",
"card-edit-custom-fields": "Cambiar los camps personalizats",
@@ -326,7 +326,7 @@
"import-user-select": "Pick your existing user you want to use as this member",
"importMapMembersAddPopup-title": "Seleccionar un participant",
"info": "Vesion",
- "initials": "Data inicala",
+ "initials": "Iniciala",
"invalid-date": "Data invalida",
"invalid-time": "Temps invalid",
"invalid-user": "Participant invalid",
@@ -458,7 +458,7 @@
"username": "Username",
"view-it": "View it",
"warn-list-archived": "warning: this card is in an list at Archive",
- "watch": "Agachar",
+ "watch": "Seguit",
"watching": "Agachat",
"watching-info": "You will be notified of any change in this board",
"welcome-board": "Tablèu de benvenguda",
diff --git a/i18n/sv.i18n.json b/i18n/sv.i18n.json
index 34c35927..647c3c10 100644
--- a/i18n/sv.i18n.json
+++ b/i18n/sv.i18n.json
@@ -1,37 +1,37 @@
{
"accept": "Acceptera",
"act-activity-notify": "Aktivitetsnotifikation",
- "act-addAttachment": "added attachment __attachment__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-deleteAttachment": "deleted attachment __attachment__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-addSubtask": "added subtask __subtask__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-addLabel": "Added label __label__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-removeLabel": "Removed label __label__ from card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-addChecklist": "added checklist __checklist__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-addChecklistItem": "added checklist item __checklistItem__ to checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-removeChecklist": "removed checklist __checklist__ from card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-removeChecklistItem": "removed checklist item __checklistItem__ from checklist __checkList__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-checkedItem": "checked __checklistItem__ of checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-uncheckedItem": "unchecked __checklistItem__ of checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-completeChecklist": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-uncompleteChecklist": "uncompleted checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-addComment": "commented on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-createBoard": "created board __board__",
- "act-createCard": "created card __card__ to list __list__ at swimlane __swimlane__ at board __board__",
- "act-createCustomField": "created custom field __customField__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-createList": "added list __list__ to board __board__",
- "act-addBoardMember": "added member __member__ to board __board__",
- "act-archivedBoard": "Board __board__ moved to Archive",
- "act-archivedCard": "Card __card__ at list __list__ at swimlane __swimlane__ at board __board__ moved to Archive",
- "act-archivedList": "List __list__ at swimlane __swimlane__ at board __board__ moved to Archive",
- "act-archivedSwimlane": "Swimlane __swimlane__ at board __board__ moved to Archive",
- "act-importBoard": "imported board __board__",
- "act-importCard": "imported card __card__ to list __list__ at swimlane __swimlane__ at board __board__",
- "act-importList": "imported list __list__ to swimlane __swimlane__ at board __board__",
- "act-joinMember": "added member __member__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
- "act-moveCard": "moved card __card__ from list __oldList__ at swimlane __oldSwimlane__ at board __oldBoard__ to list __list__ at swimlane __swimlane__ at board __board__",
- "act-removeBoardMember": "removed member __member__ from board __board__",
- "act-restoredCard": "restored card __card__ to list __list__ at swimlane __swimlane__ at board __board__",
- "act-unjoinMember": "removed member __member__ from card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+ "act-addAttachment": "la till bifogad fil __attachment__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-deleteAttachment": "raderade bifogad fil __attachment__ från kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-addSubtask": "la till underaktivitet __subtask__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-addLabel": "la till etikett __label__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-removeLabel": "Tog bort etikett __label__ från kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-addChecklist": "la till checklista __checklist__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-addChecklistItem": "la till checklistobjekt __checklistItem__ till checklista __checklist__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-removeChecklist": "tag bort checklista __checklist__ från kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-removeChecklistItem": "tog bort checklistobjekt __checklistItem__ från __checklist__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-checkedItem": "bockade av __checklistItem__ från checklista __checklist__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-uncheckedItem": "avmarkerade __checklistItem__ från checklista __checklist__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-completeChecklist": "slutförde checklista __checklist__ i kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-uncompleteChecklist": "ofullbordade checklista __checklist__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-addComment": "kommenterade på kort __card__: __comment__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-createBoard": "skapade tavla __board__",
+ "act-createCard": "skapade kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-createCustomField": "skapade anpassat fält __customField__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-createList": "la till lista __list__ på tavla __board__",
+ "act-addBoardMember": "la till medlem __member__ på tavla __board__",
+ "act-archivedBoard": "Tavla__board__ flyttad till arkivet",
+ "act-archivedCard": "Kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__ flyttad till arkivet",
+ "act-archivedList": "Lista __list__ i simbana __swimlane__ på tavla __board__ flyttad till arkivet",
+ "act-archivedSwimlane": "Simbana __swimlane__ på tavla __board__ flyttad till arkivet",
+ "act-importBoard": "importerade board __board__",
+ "act-importCard": "importerade kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-importList": "importerade lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-joinMember": "la till medlem __member__ på kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-moveCard": "flyttade kort __card__ från lista __oldList__ i simbana __oldSwimlane__ på tavla __oldBoard__ till lista __list__ i simbana __swimlane__ på tavla __board__",
+ "act-removeBoardMember": "borttagen medlem __member__  från tavla __board__",
+ "act-restoredCard": "återställde kort __card__ till lista __lis__ i simbana __swimlane__ på tavla __board__",
+ "act-unjoinMember": "tog bort medlem __member__ från kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
"act-withBoardTitle": "_tavla_",
"act-withCardTitle": "[__board__] __card__",
"actions": "Åtgärder",
@@ -56,14 +56,14 @@
"activity-unchecked-item": "okryssad %s i checklistan %s av %s",
"activity-checklist-added": "lade kontrollista till %s",
"activity-checklist-removed": "tog bort en checklista från %s",
- "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+ "activity-checklist-completed": "slutförde checklista __checklist__ i kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
"activity-checklist-uncompleted": "inte slutfört checklistan %s av %s",
"activity-checklist-item-added": "lade checklista objekt till '%s' i %s",
"activity-checklist-item-removed": "tog bort en checklista objekt från \"%s\" i %s",
"add": "Lägg till",
"activity-checked-item-card": "kryssad %s i checklistan %s",
"activity-unchecked-item-card": "okryssad %s i checklistan %s",
- "activity-checklist-completed-card": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+ "activity-checklist-completed-card": "slutförde checklista __checklist__ i kort __card__ i lista __list__ i simbana __swimlane__ på tavla __board__",
"activity-checklist-uncompleted-card": "icke slutfört checklistan %s",
"add-attachment": "Lägg till bilaga",
"add-board": "Lägg till anslagstavla",
@@ -93,7 +93,7 @@
"archive-board": "Flytta Anslagstavla till Arkiv",
"archive-card": "Flytta Kort till Arkiv",
"archive-list": "Flytta Lista till Arkiv",
- "archive-swimlane": "Move Swimlane to Archive",
+ "archive-swimlane": "Flytta simbanan till arkivet",
"archive-selection": "Flytta markerade till Arkiv",
"archiveBoardPopup-title": "Flytta Anslagstavla till Arkiv?",
"archived-items": "Arkiv",
@@ -121,7 +121,7 @@
"boardChangeTitlePopup-title": "Byt namn på anslagstavla",
"boardChangeVisibilityPopup-title": "Ändra synlighet",
"boardChangeWatchPopup-title": "Ändra bevaka",
- "boardMenuPopup-title": "Board Settings",
+ "boardMenuPopup-title": "Tavlans inställningar",
"boards": "Anslagstavlor",
"board-view": "Anslagstavelsvy",
"board-view-cal": "Kalender",
@@ -181,7 +181,7 @@
"close-board-pop": "Du kommer att kunna återställa anslagstavlan genom att klicka på knappen \"Arkiv\" från hemrubriken.",
"color-black": "svart",
"color-blue": "blå",
- "color-crimson": "crimson",
+ "color-crimson": "mörkröd",
"color-darkgreen": "mörkgrön",
"color-gold": "guld",
"color-gray": "grå",
@@ -189,22 +189,22 @@
"color-indigo": "indigo",
"color-lime": "lime",
"color-magenta": "magenta",
- "color-mistyrose": "mistyrose",
- "color-navy": "navy",
+ "color-mistyrose": "ljusrosa",
+ "color-navy": "marinblå",
"color-orange": "orange",
- "color-paleturquoise": "paleturquoise",
- "color-peachpuff": "peachpuff",
+ "color-paleturquoise": "turkos",
+ "color-peachpuff": "ersika",
"color-pink": "rosa",
- "color-plum": "plum",
+ "color-plum": "lila",
"color-purple": "lila",
"color-red": "röd",
"color-saddlebrown": "sadelbrun",
"color-silver": "silver",
"color-sky": "himmel",
- "color-slateblue": "slateblue",
+ "color-slateblue": "skifferblå",
"color-white": "vit",
"color-yellow": "gul",
- "unset-color": "Unset",
+ "unset-color": "Urkoppla",
"comment": "Kommentera",
"comment-placeholder": "Skriv kommentar",
"comment-only": "Kommentera endast",
@@ -312,7 +312,7 @@
"import-board-c": "Importera anslagstavla",
"import-board-title-trello": "Importera anslagstavla från Trello",
"import-board-title-wekan": "Importera anslagstavla från tidigare export",
- "import-sandstorm-backup-warning": "Do not delete data you import from original exported board or Trello before checking does this grain close and open again, or do you get Board not found error, that means data loss.",
+ "import-sandstorm-backup-warning": "Ta inte bort data som du importerar från exporterad original-tavla eller Trello innan du kontrollerar att det här spannet stänger och öppnas igen, eller får du felmeddelandet Tavla hittades inte, det vill säga dataförlust.",
"import-sandstorm-warning": "Importerad anslagstavla raderar all befintlig data på anslagstavla och ersätter den med importerat anslagstavla.",
"from-trello": "Från Trello",
"from-wekan": "Från tidigare export",
@@ -323,7 +323,7 @@
"import-map-members": "Kartlägg medlemmar",
"import-members-map": "Din importerade anslagstavla har några medlemmar. Vänligen kartlägg medlemmarna du vill importera till dina användare",
"import-show-user-mapping": "Granska medlemskartläggning",
- "import-user-select": "Pick your existing user you want to use as this member",
+ "import-user-select": "Välj din befintliga användare du vill använda som den här medlemmen",
"importMapMembersAddPopup-title": "Välj medlem",
"info": "Version",
"initials": "Initialer ",
@@ -350,7 +350,7 @@
"set-color-list": "Ange färg",
"listActionPopup-title": "Liståtgärder",
"swimlaneActionPopup-title": "Simbana-åtgärder",
- "swimlaneAddPopup-title": "Add a Swimlane below",
+ "swimlaneAddPopup-title": "Lägg till en simbana nedan",
"listImportCardPopup-title": "Importera ett Trello kort",
"listMorePopup-title": "Mera",
"link-list": "Länk till den här listan",
@@ -377,7 +377,7 @@
"name": "Namn",
"no-archived-cards": "Inga kort i Arkiv.",
"no-archived-lists": "Inga listor i Arkiv.",
- "no-archived-swimlanes": "No swimlanes in Archive.",
+ "no-archived-swimlanes": "Inga simbanor i arkivet.",
"no-results": "Inga reslutat",
"normal": "Normal",
"normal-desc": "Kan se och redigera kort. Kan inte ändra inställningar.",
@@ -465,9 +465,9 @@
"welcome-swimlane": "Milstolpe 1",
"welcome-list1": "Grunderna",
"welcome-list2": "Avancerad",
- "card-templates-swimlane": "Card Templates",
- "list-templates-swimlane": "List Templates",
- "board-templates-swimlane": "Board Templates",
+ "card-templates-swimlane": "Kortmallar",
+ "list-templates-swimlane": "Listmalla",
+ "board-templates-swimlane": "Tavelmallar",
"what-to-do": "Vad vill du göra?",
"wipLimitErrorPopup-title": "Ogiltig WIP-gräns",
"wipLimitErrorPopup-dialog-pt1": "Antalet uppgifter i den här listan är högre än WIP-gränsen du har definierat.",
@@ -493,14 +493,14 @@
"send-smtp-test": "Skicka ett prov e-postmeddelande till dig själv",
"invitation-code": "Inbjudningskod",
"email-invite-register-subject": "__inviter__ skickade dig en inbjudan",
- "email-invite-register-text": "Dear __user__,\n\n__inviter__ invites you to kanban board for collaborations.\n\nPlease follow the link below:\n__url__\n\nAnd your invitation code is: __icode__\n\nThanks.",
- "email-smtp-test-subject": "SMTP Test Email",
+ "email-invite-register-text": "Kära__user__,\n\n__inviter__ bjuder in dig att samarbeta på kanban-tavlan.\n\nFölj länken nedan:\n__url__\n\nDin inbjudningskod är: __icode__\n\nTack!",
+ "email-smtp-test-subject": "SMTP test-email",
"email-smtp-test-text": "Du har skickat ett e-postmeddelande",
"error-invitation-code-not-exist": "Inbjudningskod finns inte",
"error-notAuthorized": "Du är inte behörig att se den här sidan.",
"outgoing-webhooks": "Utgående Webhookar",
"outgoingWebhooksPopup-title": "Utgående Webhookar",
- "boardCardTitlePopup-title": "Card Title Filter",
+ "boardCardTitlePopup-title": "Korttitelfiler",
"new-outgoing-webhook": "Ny utgående webhook",
"no-name": "(Okänd)",
"Node_version": "Nodversion",
@@ -552,25 +552,25 @@
"show-subtasks-field": "Kort kan ha deluppgifter",
"deposit-subtasks-board": "Insättnings deluppgifter på denna anslagstavla:",
"deposit-subtasks-list": "Landningslista för deluppgifter deponerade här:",
- "show-parent-in-minicard": "Show parent in minicard:",
+ "show-parent-in-minicard": "Visa förälder i minikort:",
"prefix-with-full-path": "Prefix med fullständig sökväg",
- "prefix-with-parent": "Prefix with parent",
+ "prefix-with-parent": "Prefix med förälder",
"subtext-with-full-path": "Undertext med fullständig sökväg",
- "subtext-with-parent": "Subtext with parent",
- "change-card-parent": "Change card's parent",
- "parent-card": "Parent card",
+ "subtext-with-parent": "Undertext med förälder",
+ "change-card-parent": "Ändra kortets förälder",
+ "parent-card": "Föräldrakort",
"source-board": "Källa för anslagstavla",
- "no-parent": "Don't show parent",
+ "no-parent": "Visa inte förälder",
"activity-added-label": "lade till etiketten '%s' till %s",
"activity-removed-label": "tog bort etiketten '%s' från %s",
"activity-delete-attach": "raderade en bilaga från %s",
"activity-added-label-card": "lade till etiketten \"%s\"",
"activity-removed-label-card": "tog bort etiketten \"%s\"",
"activity-delete-attach-card": "tog bort en bilaga",
- "activity-set-customfield": "set custom field '%s' to '%s' in %s",
- "activity-unset-customfield": "unset custom field '%s' in %s",
+ "activity-set-customfield": "ställ in anpassat fält '%s' till '%s' i %s",
+ "activity-unset-customfield": "Koppla bort anpassat fält '%s' i %s",
"r-rule": "Regel",
- "r-add-trigger": "Add trigger",
+ "r-add-trigger": "Lägg till utlösare",
"r-add-action": "Lägg till åtgärd",
"r-board-rules": "Regler för anslagstavla",
"r-add-rule": "Lägg till regel",
@@ -601,15 +601,15 @@
"r-when-a-checklist": "När en checklista är",
"r-when-the-checklist": "När checklistan",
"r-completed": "Avslutad",
- "r-made-incomplete": "Made incomplete",
- "r-when-a-item": "When a checklist item is",
- "r-when-the-item": "When the checklist item",
+ "r-made-incomplete": "Gjord ofullständig",
+ "r-when-a-item": "När ett checklistobjekt ä",
+ "r-when-the-item": "När checklistans objekt",
"r-checked": "Kryssad",
"r-unchecked": "Okryssad",
"r-move-card-to": "Flytta kort till",
"r-top-of": "Överst på",
"r-bottom-of": "Nederst av",
- "r-its-list": "its list",
+ "r-its-list": "sin lista",
"r-archive": "Flytta till Arkiv",
"r-unarchive": "Återställ från Arkiv",
"r-card": "kort",
@@ -631,10 +631,10 @@
"r-to": "till",
"r-subject": "änme",
"r-rule-details": "Regeldetaljer",
- "r-d-move-to-top-gen": "Move card to top of its list",
- "r-d-move-to-top-spec": "Move card to top of list",
- "r-d-move-to-bottom-gen": "Move card to bottom of its list",
- "r-d-move-to-bottom-spec": "Move card to bottom of list",
+ "r-d-move-to-top-gen": "Flytta kort till toppen av sin lista",
+ "r-d-move-to-top-spec": "Flytta kort till toppen av listan",
+ "r-d-move-to-bottom-gen": "Flytta kort till botten av sin lista",
+ "r-d-move-to-bottom-spec": "Flytta kort till botten av listan",
"r-d-send-email": "Skicka e-post",
"r-d-send-email-to": "till",
"r-d-send-email-subject": "ämne",
@@ -645,7 +645,7 @@
"r-d-remove-label": "Ta bort etikett",
"r-create-card": "Skapa nytt kort",
"r-in-list": "i listan",
- "r-in-swimlane": "in swimlane",
+ "r-in-swimlane": "i simbana",
"r-d-add-member": "Lägg till medlem",
"r-d-remove-member": "Ta bort medlem",
"r-d-remove-all-member": "Ta bort alla medlemmar",
@@ -658,13 +658,13 @@
"r-d-remove-checklist": "Ta bort checklista",
"r-by": "av",
"r-add-checklist": "Lägg till checklista",
- "r-with-items": "with items",
- "r-items-list": "item1,item2,item3",
- "r-add-swimlane": "Add swimlane",
- "r-swimlane-name": "swimlane name",
- "r-board-note": "Note: leave a field empty to match every possible value.",
- "r-checklist-note": "Note: checklist's items have to be written as comma separated values.",
- "r-when-a-card-is-moved": "When a card is moved to another list",
+ "r-with-items": "med objekt",
+ "r-items-list": "objekt1,objekt2,objekt3",
+ "r-add-swimlane": "Lägg till simbana",
+ "r-swimlane-name": "Simbanans namn",
+ "r-board-note": "Notera: lämna ett fält tomt för att matcha alla möjliga värden.",
+ "r-checklist-note": "Notera: Objekt i en checklista måste skrivas som kommaseparerade objekt",
+ "r-when-a-card-is-moved": "När ett kort flyttas till en annan lista",
"ldap": "LDAP",
"oauth2": "OAuth2",
"cas": "CAS",
@@ -673,8 +673,8 @@
"custom-product-name": "Anpassat produktnamn",
"layout": "Layout",
"hide-logo": "Dölj logotypen",
- "add-custom-html-after-body-start": "Add Custom HTML after <body> start",
- "add-custom-html-before-body-end": "Add Custom HTML before </body> end",
+ "add-custom-html-after-body-start": "Lägg till anpassad HTML efter <body> start",
+ "add-custom-html-before-body-end": "Lägg till anpassad HTML före </body> slut",
"error-undefined": "Något gick fel",
"error-ldap-login": "Ett fel uppstod när du försökte logga in",
"display-authentication-method": "Visa autentiseringsmetod",
diff --git a/models/boards.js b/models/boards.js
index 9a71ede8..36651d54 100644
--- a/models/boards.js
+++ b/models/boards.js
@@ -466,7 +466,7 @@ Boards.helpers({
},
customFields() {
- return CustomFields.find({ boardId: this._id }, { sort: { name: 1 } });
+ return CustomFields.find({ boardIds: {$in: [this._id]} }, { sort: { name: 1 } });
},
// XXX currently mutations return no value so we have an issue when using addLabel in import
@@ -605,9 +605,7 @@ Boards.helpers({
title: TAPi18n.__('queue'),
boardId: this._id,
});
- Boards.update(this._id, {$set: {
- subtasksDefaultListId: this.subtasksDefaultListId,
- }});
+ this.setSubtasksDefaultListId(this.subtasksDefaultListId);
}
return this.subtasksDefaultListId;
},
diff --git a/models/cards.js b/models/cards.js
index c3bae400..2bf83825 100644
--- a/models/cards.js
+++ b/models/cards.js
@@ -289,9 +289,19 @@ Cards.helpers({
const oldId = this._id;
const oldCard = Cards.findOne(oldId);
+ // Copy Custom Fields
+ if (oldBoard._id !== boardId) {
+ CustomFields.find({
+ _id: {$in: oldCard.customFields.map((cf) => { return cf._id; })},
+ }).forEach((cf) => {
+ if (!_.contains(cf.boardIds, boardId))
+ cf.addBoard(boardId);
+ });
+ }
+
delete this._id;
delete this.labelIds;
- this.labelIds= newCardLabels;
+ this.labelIds = newCardLabels;
this.boardId = boardId;
this.swimlaneId = swimlaneId;
this.listId = listId;
@@ -306,7 +316,6 @@ Cards.helpers({
// copy checklists
Checklists.find({cardId: oldId}).forEach((ch) => {
- // REMOVE verify copy with arguments
ch.copy(_id);
});
@@ -314,13 +323,11 @@ Cards.helpers({
Cards.find({parentId: oldId}).forEach((subtask) => {
subtask.parentId = _id;
subtask._id = null;
- // REMOVE verify copy with arguments instead of insert?
Cards.insert(subtask);
});
// copy card comments
CardComments.find({cardId: oldId}).forEach((cmt) => {
- // REMOVE verify copy with arguments
cmt.copy(_id);
});
@@ -476,7 +483,7 @@ Cards.helpers({
// get all definitions
const definitions = CustomFields.find({
- boardId: this.boardId,
+ boardIds: {$in: [this.boardId]},
}).fetch();
// match right definition to each field
@@ -485,6 +492,9 @@ Cards.helpers({
const definition = definitions.find((definition) => {
return definition._id === customField._id;
});
+ if (!definition) {
+ return {};
+ }
//search for "True Value" which is for DropDowns other then the Value (which is the id)
let trueValue = customField.value;
if (definition.settings.dropdownItems && definition.settings.dropdownItems.length > 0) {
@@ -1054,18 +1064,41 @@ Cards.mutations({
};
},
- move(swimlaneId, listId, sortIndex) {
- const list = Lists.findOne(listId);
+ move(boardId, swimlaneId, listId, sort) {
+ // Copy Custom Fields
+ if (this.boardId !== boardId) {
+ CustomFields.find({
+ _id: {$in: this.customFields.map((cf) => { return cf._id; })},
+ }).forEach((cf) => {
+ if (!_.contains(cf.boardIds, boardId))
+ cf.addBoard(boardId);
+ });
+ }
+
+ // Get label names
+ const oldBoard = Boards.findOne(this.boardId);
+ const oldBoardLabels = oldBoard.labels;
+ const oldCardLabels = _.pluck(_.filter(oldBoardLabels, (label) => {
+ return _.contains(this.labelIds, label._id);
+ }), 'name');
+
+ const newBoard = Boards.findOne(boardId);
+ const newBoardLabels = newBoard.labels;
+ const newCardLabelIds = _.pluck(_.filter(newBoardLabels, (label) => {
+ return label.name && _.contains(oldCardLabels, label.name);
+ }), '_id');
+
const mutatedFields = {
+ boardId,
swimlaneId,
listId,
- boardId: list.boardId,
- sort: sortIndex,
+ sort,
+ labelIds: newCardLabelIds,
};
- return {
+ Cards.update(this._id, {
$set: mutatedFields,
- };
+ });
},
addLabel(labelId) {
@@ -1287,8 +1320,47 @@ Cards.mutations({
//FUNCTIONS FOR creation of Activities
-function cardMove(userId, doc, fieldNames, oldListId, oldSwimlaneId) {
- if ((_.contains(fieldNames, 'listId') && doc.listId !== oldListId) ||
+function updateActivities(doc, fieldNames, modifier) {
+ if (_.contains(fieldNames, 'labelIds') && _.contains(fieldNames, 'boardId')) {
+ Activities.find({
+ activityType: 'addedLabel',
+ cardId: doc._id,
+ }).forEach((a) => {
+ const lidx = doc.labelIds.indexOf(a.labelId);
+ if (lidx !== -1 && modifier.$set.labelIds.length > lidx) {
+ Activities.update(a._id, {
+ $set: {
+ labelId: modifier.$set.labelIds[doc.labelIds.indexOf(a.labelId)],
+ boardId: modifier.$set.boardId,
+ },
+ });
+ } else {
+ Activities.remove(a._id);
+ }
+ });
+ } else if (_.contains(fieldNames, 'boardId')) {
+ Activities.remove({
+ activityType: 'addedLabel',
+ cardId: doc._id,
+ });
+ }
+}
+
+function cardMove(userId, doc, fieldNames, oldListId, oldSwimlaneId, oldBoardId) {
+ if (_.contains(fieldNames, 'boardId') && (doc.boardId !== oldBoardId)) {
+ Activities.insert({
+ userId,
+ activityType: 'moveCardBoard',
+ boardName: Boards.findOne(doc.boardId).title,
+ boardId: doc.boardId,
+ oldBoardId,
+ oldBoardName: Boards.findOne(oldBoardId).title,
+ cardId: doc._id,
+ swimlaneName: Swimlanes.findOne(doc.swimlaneId).title,
+ swimlaneId: doc.swimlaneId,
+ oldSwimlaneId,
+ });
+ } else if ((_.contains(fieldNames, 'listId') && doc.listId !== oldListId) ||
(_.contains(fieldNames, 'swimlaneId') && doc.swimlaneId !== oldSwimlaneId)){
Activities.insert({
userId,
@@ -1435,7 +1507,7 @@ function cardCustomFields(userId, doc, fieldNames, modifier) {
// only individual changes are registered
if (dotNotation.length > 1) {
- const customFieldId = doc.customFields[dot_notation[1]]._id;
+ const customFieldId = doc.customFields[dotNotation[1]]._id;
const act = {
userId,
customFieldId,
@@ -1508,12 +1580,14 @@ if (Meteor.isServer) {
Cards.after.update(function(userId, doc, fieldNames) {
const oldListId = this.previous.listId;
const oldSwimlaneId = this.previous.swimlaneId;
- cardMove(userId, doc, fieldNames, oldListId, oldSwimlaneId);
+ const oldBoardId = this.previous.boardId;
+ cardMove(userId, doc, fieldNames, oldListId, oldSwimlaneId, oldBoardId);
});
// Add a new activity if we add or remove a member to the card
Cards.before.update((userId, doc, fieldNames, modifier) => {
cardMembers(userId, doc, fieldNames, modifier);
+ updateActivities(doc, fieldNames, modifier);
});
// Add a new activity if we add or remove a label to the card
diff --git a/models/customFields.js b/models/customFields.js
index b7ad5467..a67ddb7d 100644
--- a/models/customFields.js
+++ b/models/customFields.js
@@ -4,11 +4,11 @@ CustomFields = new Mongo.Collection('customFields');
* A custom field on a card in the board
*/
CustomFields.attachSchema(new SimpleSchema({
- boardId: {
+ boardIds: {
/**
* the ID of the board
*/
- type: String,
+ type: [String],
},
name: {
/**
@@ -72,17 +72,37 @@ CustomFields.attachSchema(new SimpleSchema({
},
}));
+CustomFields.mutations({
+ addBoard(boardId) {
+ if (boardId) {
+ return {
+ $push: {
+ boardIds: boardId,
+ },
+ };
+ } else {
+ return null;
+ }
+ },
+});
+
CustomFields.allow({
insert(userId, doc) {
- return allowIsBoardMember(userId, Boards.findOne(doc.boardId));
+ return allowIsAnyBoardMember(userId, Boards.find({
+ _id: {$in: doc.boardIds},
+ }).fetch());
},
update(userId, doc) {
- return allowIsBoardMember(userId, Boards.findOne(doc.boardId));
+ return allowIsAnyBoardMember(userId, Boards.find({
+ _id: {$in: doc.boardIds},
+ }).fetch());
},
remove(userId, doc) {
- return allowIsBoardMember(userId, Boards.findOne(doc.boardId));
+ return allowIsAnyBoardMember(userId, Boards.find({
+ _id: {$in: doc.boardIds},
+ }).fetch());
},
- fetch: ['userId', 'boardId'],
+ fetch: ['userId', 'boardIds'],
});
// not sure if we need this?
@@ -92,27 +112,48 @@ function customFieldCreation(userId, doc){
Activities.insert({
userId,
activityType: 'createCustomField',
- boardId: doc.boardId,
+ boardId: doc.boardIds[0], // We are creating a customField, it has only one boardId
customFieldId: doc._id,
});
}
if (Meteor.isServer) {
Meteor.startup(() => {
- CustomFields._collection._ensureIndex({ boardId: 1 });
+ CustomFields._collection._ensureIndex({ boardIds: 1 });
});
CustomFields.after.insert((userId, doc) => {
customFieldCreation(userId, doc);
});
- CustomFields.after.remove((userId, doc) => {
+ CustomFields.before.update((userId, doc, fieldNames, modifier) => {
+ if (_.contains(fieldNames, 'boardIds') && modifier.$pull) {
+ Cards.update(
+ {boardId: modifier.$pull.boardIds, 'customFields._id': doc._id},
+ {$pull: {'customFields': {'_id': doc._id}}},
+ {multi: true}
+ );
+ Activities.remove({
+ customFieldId: doc._id,
+ boardId: modifier.$pull.boardIds,
+ });
+ } else if (_.contains(fieldNames, 'boardIds') && modifier.$push) {
+ Activities.insert({
+ userId,
+ activityType: 'createCustomField',
+ boardId: modifier.$push.boardIds,
+ customFieldId: doc._id,
+ });
+ }
+ });
+
+ CustomFields.before.remove((userId, doc) => {
Activities.remove({
customFieldId: doc._id,
});
Cards.update(
- {'boardId': doc.boardId, 'customFields._id': doc._id},
+ {boardId: {$in: doc.boardIds}, 'customFields._id': doc._id},
{$pull: {'customFields': {'_id': doc._id}}},
{multi: true}
);
@@ -135,7 +176,7 @@ if (Meteor.isServer) {
const paramBoardId = req.params.boardId;
JsonRoutes.sendResult(res, {
code: 200,
- data: CustomFields.find({ boardId: paramBoardId }).map(function (cf) {
+ data: CustomFields.find({ boardIds: {$in: [paramBoardId]} }).map(function (cf) {
return {
_id: cf._id,
name: cf.name,
@@ -159,7 +200,7 @@ if (Meteor.isServer) {
const paramCustomFieldId = req.params.customFieldId;
JsonRoutes.sendResult(res, {
code: 200,
- data: CustomFields.findOne({ _id: paramCustomFieldId, boardId: paramBoardId }),
+ data: CustomFields.findOne({ _id: paramCustomFieldId, boardIds: {$in: [paramBoardId]} }),
});
});
@@ -186,10 +227,10 @@ if (Meteor.isServer) {
showOnCard: req.body.showOnCard,
automaticallyOnCard: req.body.automaticallyOnCard,
showLabelOnMiniCard: req.body.showLabelOnMiniCard,
- boardId: paramBoardId,
+ boardIds: {$in: [paramBoardId]},
});
- const customField = CustomFields.findOne({_id: id, boardId: paramBoardId });
+ const customField = CustomFields.findOne({_id: id, boardIds: {$in: [paramBoardId]} });
customFieldCreation(req.body.authorId, customField);
JsonRoutes.sendResult(res, {
@@ -214,7 +255,7 @@ if (Meteor.isServer) {
Authentication.checkUserId( req.userId);
const paramBoardId = req.params.boardId;
const id = req.params.customFieldId;
- CustomFields.remove({ _id: id, boardId: paramBoardId });
+ CustomFields.remove({ _id: id, boardIds: {$in: [paramBoardId]} });
JsonRoutes.sendResult(res, {
code: 200,
data: {
diff --git a/models/export.js b/models/export.js
index 76f2da06..f281b34a 100644
--- a/models/export.js
+++ b/models/export.js
@@ -75,7 +75,7 @@ class Exporter {
result.lists = Lists.find(byBoard, noBoardId).fetch();
result.cards = Cards.find(byBoardNoLinked, noBoardId).fetch();
result.swimlanes = Swimlanes.find(byBoard, noBoardId).fetch();
- result.customFields = CustomFields.find(byBoard, noBoardId).fetch();
+ result.customFields = CustomFields.find({boardIds: {$in: [this.boardId]}}, {fields: {boardId: 0}}).fetch();
result.comments = CardComments.find(byBoard, noBoardId).fetch();
result.activities = Activities.find(byBoard, noBoardId).fetch();
result.rules = Rules.find(byBoard, noBoardId).fetch();
diff --git a/package.json b/package.json
index 72d5e403..4fec5bb7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "wekan",
- "version": "v2.48.0",
+ "version": "v2.49.0",
"description": "Open-Source kanban",
"private": true,
"scripts": {
diff --git a/sandstorm-pkgdef.capnp b/sandstorm-pkgdef.capnp
index f9551eff..6d9798e0 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 = 250,
+ appVersion = 251,
# Increment this for every release.
- appMarketingVersion = (defaultText = "2.48.0~2019-03-15"),
+ appMarketingVersion = (defaultText = "2.49.0~2019-03-21"),
# Human-readable presentation of the app version.
minUpgradableAppVersion = 0,
diff --git a/server/lib/utils.js b/server/lib/utils.js
index ee925847..3b4412fe 100644
--- a/server/lib/utils.js
+++ b/server/lib/utils.js
@@ -6,6 +6,12 @@ allowIsBoardMember = function(userId, board) {
return board && board.hasMember(userId);
};
+allowIsAnyBoardMember = function(userId, boards) {
+ return _.some(boards, (board) => {
+ return board && board.hasMember(userId);
+ });
+};
+
allowIsBoardMemberCommentOnly = function(userId, board) {
return board && board.hasMember(userId) && !board.hasCommentOnly(userId);
};
diff --git a/server/migrations.js b/server/migrations.js
index b8915fe9..09852495 100644
--- a/server/migrations.js
+++ b/server/migrations.js
@@ -525,3 +525,16 @@ Migrations.add('fix-circular-reference_', () => {
}
});
});
+
+Migrations.add('mutate-boardIds-in-customfields', () => {
+ CustomFields.find().forEach((cf) => {
+ CustomFields.update(cf, {
+ $set: {
+ boardIds: [cf.boardId],
+ },
+ $unset: {
+ boardId: '',
+ },
+ }, noValidateMulti);
+ });
+});
diff --git a/server/publications/boards.js b/server/publications/boards.js
index 18c44d2b..144eabb8 100644
--- a/server/publications/boards.js
+++ b/server/publications/boards.js
@@ -78,7 +78,7 @@ Meteor.publishRelations('board', function(boardId) {
this.cursor(Lists.find({ boardId }));
this.cursor(Swimlanes.find({ boardId }));
this.cursor(Integrations.find({ boardId }));
- this.cursor(CustomFields.find({ boardId }, { sort: { name: 1 } }));
+ this.cursor(CustomFields.find({ boardIds: {$in: [boardId]} }, { sort: { name: 1 } }));
// Cards and cards comments
// XXX Originally we were publishing the card documents as a child of the
@@ -116,7 +116,7 @@ Meteor.publishRelations('board', function(boardId) {
const boards = this.join(Boards);
const subCards = this.join(Cards);
- this.cursor(Cards.find({ boardId }), function(cardId, card) {
+ this.cursor(Cards.find({ boardId: {$in: [boardId, board.subtasksDefaultBoardId]}}), function(cardId, card) {
if (card.type === 'cardType-linkedCard') {
const impCardId = card.linkedId;
subCards.push(impCardId);
@@ -141,6 +141,7 @@ Meteor.publishRelations('board', function(boardId) {
checklists.send();
checklistItems.send();
boards.send();
+ parentCards.send();
if (board.members) {
// Board members. This publication also includes former board members that
diff --git a/server/rulesHelper.js b/server/rulesHelper.js
index 163bd41e..453c586d 100644
--- a/server/rulesHelper.js
+++ b/server/rulesHelper.js
@@ -78,6 +78,8 @@ RulesHelper = {
emailMsg,
});
} catch (e) {
+ // eslint-disable-next-line no-console
+ console.error(e);
return;
}
}