diff options
46 files changed, 358 insertions, 107 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c2896a4..adf022f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,21 @@ +# v0.35 2017-09-02 Wekan release + +This release adds the following new features: + +* [Add more than one Outgoing Webhook](https://github.com/wekan/wekan/pull/1199). + +and fixes the following bugs: + +* [Fix errors caused by checklist items activities](https://github.com/wekan/wekan/pull/1200). + +Thanks to GitHub users andresmanelli, GhassenRjab and nztqa for contributions. + # v0.34 2017-08-30 Wekan release This release adds the following new features: -* [Import Trello and Wekan board times of creation of activities](https://github.com/wekan/wekan/pull/1187). +* [Import Trello and Wekan board times of creation of activities](https://github.com/wekan/wekan/pull/1187); +* Newest Wekan is available at Sandstorm App Market. Known issues: diff --git a/client/components/boards/boardHeader.jade b/client/components/boards/boardHeader.jade index 3d98322d..9539fc79 100644 --- a/client/components/boards/boardHeader.jade +++ b/client/components/boards/boardHeader.jade @@ -227,11 +227,21 @@ template(name="archiveBoardPopup") button.js-confirm.negate.full(type="submit") {{_ 'archive'}} template(name="outgoingWebhooksPopup") - form + each integrations + form.integration-form + if title + h4 {{title}} + else + h4 {{_ 'no-name'}} + label + | URL + input.js-outgoing-webhooks-url(type="text" name="url" value=url) + input(type="hidden" value=_id name="id") + input.primary.wide(type="submit" value="{{_ 'save'}}") + form.integration-form + h4 + | {{_ 'new-integration'}} label | URL - if integration.enabled - input.js-outgoing-webhooks-url(type="text" value=integration.url autofocus) - else - input.js-outgoing-webhooks-url(type="text" autofocus) + input.js-outgoing-webhooks-url(type="text" name="url" autofocus) input.primary.wide(type="submit" value="{{_ 'save'}}") diff --git a/client/components/boards/boardHeader.js b/client/components/boards/boardHeader.js index 2ee21905..b7807ca9 100644 --- a/client/components/boards/boardHeader.js +++ b/client/components/boards/boardHeader.js @@ -241,39 +241,44 @@ BlazeComponent.extendComponent({ }).register('boardChangeWatchPopup'); BlazeComponent.extendComponent({ - integration() { + integrations() { const boardId = Session.get('currentBoard'); - return Integrations.findOne({ boardId: `${boardId}` }); + return Integrations.find({ boardId: `${boardId}` }).fetch(); + }, + + integration(id) { + const boardId = Session.get('currentBoard'); + return Integrations.findOne({ _id: id, boardId: `${boardId}` }); }, events() { return [{ 'submit'(evt) { evt.preventDefault(); - const url = this.find('.js-outgoing-webhooks-url').value.trim(); + const url = evt.target.url.value; const boardId = Session.get('currentBoard'); - const integration = this.integration(); - if (integration) { + let id = null; + let integration = null; + if (evt.target.id) { + id = evt.target.id.value; + integration = this.integration(id); if (url) { Integrations.update(integration._id, { $set: { - enabled: true, url: `${url}`, }, }); } else { - Integrations.update(integration._id, { - $set: { - enabled: false, - }, - }); + Integrations.remove(integration._id); } } else if (url) { Integrations.insert({ + userId: Meteor.userId(), enabled: true, type: 'outgoing-webhooks', url: `${url}`, boardId: `${boardId}`, + activities: ['all'], }); } Popup.close(); diff --git a/client/components/boards/boardHeader.styl b/client/components/boards/boardHeader.styl new file mode 100644 index 00000000..0abdb5bd --- /dev/null +++ b/client/components/boards/boardHeader.styl @@ -0,0 +1,3 @@ +.integration-form + padding: 5px + border-bottom: 1px solid #ccc diff --git a/docker-compose.yml b/docker-compose.yml index 22ccb71c..ae0e5b90 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ version: '2' services: wekandb: - image: mongo:3.2.15 + image: mongo:3.2.16 container_name: wekan-db restart: always command: mongod --smallfiles --oplogSize 128 diff --git a/i18n/ar.i18n.json b/i18n/ar.i18n.json index 866aee30..7639f1c6 100644 --- a/i18n/ar.i18n.json +++ b/i18n/ar.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/br.i18n.json b/i18n/br.i18n.json index 3bdda564..80b62f3a 100644 --- a/i18n/br.i18n.json +++ b/i18n/br.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/ca.i18n.json b/i18n/ca.i18n.json index 94b5e14b..efdb2b2e 100644 --- a/i18n/ca.i18n.json +++ b/i18n/ca.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/cs.i18n.json b/i18n/cs.i18n.json index c235c80e..4022b5bd 100644 --- a/i18n/cs.i18n.json +++ b/i18n/cs.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/de.i18n.json b/i18n/de.i18n.json index f3070ee2..08fb8711 100644 --- a/i18n/de.i18n.json +++ b/i18n/de.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "Sie sind nicht berechtigt diese Seite zu sehen.", "outgoing-webhooks": "Ausgehende Webhooks", "outgoingWebhooksPopup-title": "Ausgehende Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan-Version", "Node_version": "Node-Version", "OS_Arch": "Betriebssystem-Architektur", diff --git a/i18n/en-GB.i18n.json b/i18n/en-GB.i18n.json index fd46b568..2eca7bc1 100644 --- a/i18n/en-GB.i18n.json +++ b/i18n/en-GB.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorised to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index b2ea9354..ebf4722b 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/eo.i18n.json b/i18n/eo.i18n.json index 266fea82..5a2a837d 100644 --- a/i18n/eo.i18n.json +++ b/i18n/eo.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/es.i18n.json b/i18n/es.i18n.json index 3ed18a2d..86bfc1f4 100644 --- a/i18n/es.i18n.json +++ b/i18n/es.i18n.json @@ -142,9 +142,9 @@ "comment": "Comentario", "comment-placeholder": "Escribir Comentario", "comment-only": "Sólo comentario", - "comment-only-desc": "Can comment on cards only.", + "comment-only-desc": "Solo se puede comentar en tarjetas.", "computer": "Ordenador", - "copy-card-link-to-clipboard": "Copy card link to clipboard", + "copy-card-link-to-clipboard": "Copiar enlace a la tarjeta al portapapeles", "create": "Crear", "createBoardPopup-title": "Crear tablero", "chooseBoardSourcePopup-title": "Importar tablero", @@ -192,7 +192,7 @@ "error-user-notAllowSelf": "No puedes invitarte a ti mismo", "error-user-notCreated": "This user is not created", "error-username-taken": "Este nombre de usuario ya está en uso", - "error-email-taken": "Email has already been taken", + "error-email-taken": "Esta direccion de Email ya está en uso", "export-board": "Export board", "filter": "Filter", "filter-cards": "Fichas de filtro", @@ -208,22 +208,22 @@ "headerBarCreateBoardPopup-title": "Crear tablero", "home": "Inicio", "import": "Importar", - "import-board": "import board", + "import-board": "importar tablero", "import-board-c": "Importar tablero", "import-board-title-trello": "Importar tablero desde Trello", - "import-board-title-wekan": "Import board from Wekan", - "import-sandstorm-warning": "Imported board will delete all existing data on board and replace it with imported board.", + "import-board-title-wekan": "Importar tablero desde Wekan", + "import-sandstorm-warning": "El tablero importado va a borrar todos los datos existentes en este tablero y reemplazarlos con los datos del tablero importado.", "from-trello": "Desde Trello", "from-wekan": "Desde Wekan", "import-board-instruction-trello": "In your Trello board, go to 'Menu', then 'More', 'Print and Export', 'Export JSON', and copy the resulting text", - "import-board-instruction-wekan": "In your Wekan board, go to 'Menu', then 'Export board', and copy the text in the downloaded file.", + "import-board-instruction-wekan": "En tu tablero Wekan, ve a 'Menu', luego 'Exportar tablero', y copia el texto en el archivo descargado.", "import-json-placeholder": "Paste your valid JSON data here", "import-map-members": "Mapa de miembros", "import-members-map": "Your imported board has some members. Please map the members you want to import to Wekan users", "import-show-user-mapping": "Review members mapping", "import-user-select": "Pick the Wekan user you want to use as this member", "importMapMembersAddPopup-title": "Seleccionar un miembro de Wekan", - "info": "Version", + "info": "Versión", "initials": "Iniciales", "invalid-date": "Fecha no Válida", "joined": "se ha unido", @@ -368,6 +368,8 @@ "error-notAuthorized": "No estás autorizado a ver esta página.", "outgoing-webhooks": "Webhooks salientes", "outgoingWebhooksPopup-title": "Webhooks salientes", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/eu.i18n.json b/i18n/eu.i18n.json index a13558e8..51e83d90 100644 --- a/i18n/eu.i18n.json +++ b/i18n/eu.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "Ez duzu orri hau ikusteko baimenik.", "outgoing-webhooks": "Irteerako Webhook-ak", "outgoingWebhooksPopup-title": "Irteerako Webhook-ak", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan bertsioa", "Node_version": "Nodo bertsioa", "OS_Arch": "SE Arkitektura", diff --git a/i18n/fa.i18n.json b/i18n/fa.i18n.json index 0662de40..738cf1ce 100644 --- a/i18n/fa.i18n.json +++ b/i18n/fa.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/fi.i18n.json b/i18n/fi.i18n.json index 7658edb4..9b83ad6c 100644 --- a/i18n/fi.i18n.json +++ b/i18n/fi.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "Sinulla ei ole oikeutta tarkastella tätä sivua.", "outgoing-webhooks": "Lähtevät Webkoukut", "outgoingWebhooksPopup-title": "Lähtevät Webkoukut", + "new-integration": "Uusi integraatio", + "no-name": "(Tuntematon)", "Wekan_version": "Wekan versio", "Node_version": "Node versio", "OS_Arch": "Käyttöjärjestelmän arkkitehtuuri", diff --git a/i18n/fr.i18n.json b/i18n/fr.i18n.json index 48b9ee66..1d5162af 100644 --- a/i18n/fr.i18n.json +++ b/i18n/fr.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "Vous n'êtes pas autorisé à accéder à cette page.", "outgoing-webhooks": "Webhooks sortants", "outgoingWebhooksPopup-title": "Webhooks sortants", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Version de Wekan", "Node_version": "Version de Node", "OS_Arch": "OS Architecture", diff --git a/i18n/gl.i18n.json b/i18n/gl.i18n.json index 1910045b..573d0c4e 100644 --- a/i18n/gl.i18n.json +++ b/i18n/gl.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/he.i18n.json b/i18n/he.i18n.json index e14ade13..923a9381 100644 --- a/i18n/he.i18n.json +++ b/i18n/he.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "אין לך הרשאה לצפות בעמוד זה.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "גרסת wekan", "Node_version": "גרסת Node", "OS_Arch": "ארכיטקטורת מערכת הפעלה", diff --git a/i18n/hu.i18n.json b/i18n/hu.i18n.json index 71cfd544..105cea3d 100644 --- a/i18n/hu.i18n.json +++ b/i18n/hu.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/id.i18n.json b/i18n/id.i18n.json index c9c370e3..cb92f92d 100644 --- a/i18n/id.i18n.json +++ b/i18n/id.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/it.i18n.json b/i18n/it.i18n.json index 5c40ba09..11b0e025 100644 --- a/i18n/it.i18n.json +++ b/i18n/it.i18n.json @@ -144,7 +144,7 @@ "comment-only": "Solo commenti", "comment-only-desc": "Puoi commentare solo le schede.", "computer": "Computer", - "copy-card-link-to-clipboard": "Copy card link to clipboard", + "copy-card-link-to-clipboard": "Copia link della scheda sulla clipboard", "create": "Crea", "createBoardPopup-title": "Crea bacheca", "chooseBoardSourcePopup-title": "Importa bacheca", @@ -192,7 +192,7 @@ "error-user-notAllowSelf": "Non puoi invitare te stesso", "error-user-notCreated": "L'utente non è stato creato", "error-username-taken": "Questo username è già utilizzato", - "error-email-taken": "Email has already been taken", + "error-email-taken": "L'email è già stata presa", "export-board": "Esporta bacheca", "filter": "Filtra", "filter-cards": "Filtra schede", @@ -223,7 +223,7 @@ "import-show-user-mapping": "Rivedi la mappatura dei membri", "import-user-select": "Scegli l'utente Wekan che vuoi utilizzare come questo membro", "importMapMembersAddPopup-title": "Seleziona i membri di Wekan", - "info": "Version", + "info": "Versione", "initials": "Iniziali", "invalid-date": "Data non valida", "joined": "si è unito a", @@ -368,7 +368,9 @@ "error-notAuthorized": "Non sei autorizzato ad accedere a questa pagina.", "outgoing-webhooks": "Server esterni", "outgoingWebhooksPopup-title": "Server esterni", - "Wekan_version": "Wekan version", + "new-integration": "New integration", + "no-name": "(Unknown)", + "Wekan_version": "Versione di Wekan", "Node_version": "Node version", "OS_Arch": "OS Arch", "OS_Cpus": "OS CPU Count", @@ -379,11 +381,11 @@ "OS_Totalmem": "OS Total Memory", "OS_Type": "OS Type", "OS_Uptime": "OS Uptime", - "hours": "hours", - "minutes": "minutes", - "seconds": "seconds", - "yes": "Yes", + "hours": "ore", + "minutes": "minuti", + "seconds": "secondi", + "yes": "Sì", "no": "No", - "accounts": "Accounts", - "accounts-allowEmailChange": "Allow Email Change" + "accounts": "Profili", + "accounts-allowEmailChange": "Permetti modifica dell'email" }
\ No newline at end of file diff --git a/i18n/ja.i18n.json b/i18n/ja.i18n.json index 270d6081..5a4eb370 100644 --- a/i18n/ja.i18n.json +++ b/i18n/ja.i18n.json @@ -144,7 +144,7 @@ "comment-only": "コメントのみ", "comment-only-desc": "カードにのみコメント可能", "computer": "コンピューター", - "copy-card-link-to-clipboard": "Copy card link to clipboard", + "copy-card-link-to-clipboard": "カードへのリンクをクリップボードにコピー", "create": "作成", "createBoardPopup-title": "ボードの作成", "chooseBoardSourcePopup-title": "ボードをインポート", @@ -368,6 +368,8 @@ "error-notAuthorized": "このページを参照する権限がありません。", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekanバージョン", "Node_version": "Nodeバージョン", "OS_Arch": "OSアーキテクチャ", diff --git a/i18n/ko.i18n.json b/i18n/ko.i18n.json index 32064ab2..880db0a6 100644 --- a/i18n/ko.i18n.json +++ b/i18n/ko.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "이 페이지를 볼 수있는 권한이 없습니다.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/nb.i18n.json b/i18n/nb.i18n.json index 86a87a52..a98e05bf 100644 --- a/i18n/nb.i18n.json +++ b/i18n/nb.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/nl.i18n.json b/i18n/nl.i18n.json index 37623dea..bd2457b5 100644 --- a/i18n/nl.i18n.json +++ b/i18n/nl.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "Je bent niet toegestaan om deze pagina te bekijken.", "outgoing-webhooks": "Uitgaande Webhooks", "outgoingWebhooksPopup-title": "Uitgaande Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan versie", "Node_version": "Node versie", "OS_Arch": "OS Arch", diff --git a/i18n/pl.i18n.json b/i18n/pl.i18n.json index 1e2162b9..71d8e574 100644 --- a/i18n/pl.i18n.json +++ b/i18n/pl.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/pt-BR.i18n.json b/i18n/pt-BR.i18n.json index df689d9b..ed1127ac 100644 --- a/i18n/pt-BR.i18n.json +++ b/i18n/pt-BR.i18n.json @@ -144,7 +144,7 @@ "comment-only": "Somente comentários", "comment-only-desc": "Pode comentar apenas em cartões.", "computer": "Computador", - "copy-card-link-to-clipboard": "Copy card link to clipboard", + "copy-card-link-to-clipboard": "Copiar link do cartão para a área de transferência", "create": "Criar", "createBoardPopup-title": "Criar Quadro", "chooseBoardSourcePopup-title": "Importar quadro", @@ -366,8 +366,10 @@ "email-invite-register-text": "Caro __user__,\n\n__inviter__ convidou você para colaborar no Wekan.\n\nPor favor, vá no link abaixo:\n__url__\n\nE seu código de convite é: __icode__\n\nObrigado.", "error-invitation-code-not-exist": "O código do convite não existe", "error-notAuthorized": "Você não está autorizado à ver esta página.", - "outgoing-webhooks": "Outgoing Webhooks", - "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "outgoing-webhooks": "Webhook de saída", + "outgoingWebhooksPopup-title": "Webhook de saída", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Versão do Wekan", "Node_version": "Versão do Node", "OS_Arch": "Arquitetura do SO", @@ -375,7 +377,7 @@ "OS_Freemem": "Memória Disponível do SO", "OS_Loadavg": "Carga Média do SO", "OS_Platform": "Plataforma do SO", - "OS_Release": "OS Release", + "OS_Release": "Versão do SO", "OS_Totalmem": "Memória Total do SO", "OS_Type": "Tipo do SO", "OS_Uptime": "Disponibilidade do SO", diff --git a/i18n/ro.i18n.json b/i18n/ro.i18n.json index 5833bc80..3b99c244 100644 --- a/i18n/ro.i18n.json +++ b/i18n/ro.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/ru.i18n.json b/i18n/ru.i18n.json index 704d01e0..2b9acac2 100644 --- a/i18n/ru.i18n.json +++ b/i18n/ru.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "У вас нет доступа на просмотр этой страницы.", "outgoing-webhooks": "Исходящие Веб-хуки", "outgoingWebhooksPopup-title": "Исходящие Веб-хуки", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Версия Wekan", "Node_version": "Версия NodeJS", "OS_Arch": "Архитектура", diff --git a/i18n/sr.i18n.json b/i18n/sr.i18n.json index fdcd855c..075317f0 100644 --- a/i18n/sr.i18n.json +++ b/i18n/sr.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/sv.i18n.json b/i18n/sv.i18n.json index 82ffb201..987afdae 100644 --- a/i18n/sv.i18n.json +++ b/i18n/sv.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/ta.i18n.json b/i18n/ta.i18n.json index b2f15d20..74bb83fd 100644 --- a/i18n/ta.i18n.json +++ b/i18n/ta.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/th.i18n.json b/i18n/th.i18n.json index e150b483..f1699a0a 100644 --- a/i18n/th.i18n.json +++ b/i18n/th.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/tr.i18n.json b/i18n/tr.i18n.json index ddefaf91..62276996 100644 --- a/i18n/tr.i18n.json +++ b/i18n/tr.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "Bu sayfayı görmek için yetkiniz yok.", "outgoing-webhooks": "Dışarı giden bağlantılar", "outgoingWebhooksPopup-title": "Dışarı giden bağlantılar", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan sürümü", "Node_version": "Node sürümü", "OS_Arch": "OS Arch", diff --git a/i18n/uk.i18n.json b/i18n/uk.i18n.json index 2e19530a..483922ce 100644 --- a/i18n/uk.i18n.json +++ b/i18n/uk.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/vi.i18n.json b/i18n/vi.i18n.json index 96799670..d59122fe 100644 --- a/i18n/vi.i18n.json +++ b/i18n/vi.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "You are not authorized to view this page.", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/zh-CN.i18n.json b/i18n/zh-CN.i18n.json index 00b47f41..c20ba8cf 100644 --- a/i18n/zh-CN.i18n.json +++ b/i18n/zh-CN.i18n.json @@ -368,6 +368,8 @@ "error-notAuthorized": "您无权查看此页面。", "outgoing-webhooks": "Outgoing Webhooks", "outgoingWebhooksPopup-title": "Outgoing Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", "Wekan_version": "Wekan version", "Node_version": "Node version", "OS_Arch": "OS Arch", diff --git a/i18n/zh-TW.i18n.json b/i18n/zh-TW.i18n.json index d3279be5..b87b2741 100644 --- a/i18n/zh-TW.i18n.json +++ b/i18n/zh-TW.i18n.json @@ -37,7 +37,7 @@ "activity-sent": "寄送 %s 至 %s", "activity-unjoined": "解除關聯 %s", "activity-checklist-added": "新增待辦清單至 %s", - "activity-checklist-item-added": "added checklist item to '%s' in %s", + "activity-checklist-item-added": "新增待辦清單項目從 %s 到 %s", "add": "新增", "add-attachment": "新增附件", "add-board": "新增看板", @@ -56,7 +56,7 @@ "and-n-other-card": "和其他 __count__ 個卡片", "and-n-other-card_plural": "和其他 __count__ 個卡片", "apply": "送出", - "app-is-offline": "Wekan is loading, please wait. Refreshing the page will cause data loss. If Wekan does not load, please check that Wekan server has not stopped.", + "app-is-offline": "請稍候,資料讀取中,重整頁面可能會導致資料遺失。如果一直讀取,請檢查 Wekan 的伺服器是否正確運行。", "archive": "刪除", "archive-all": "全部刪除", "archive-board": "刪除看板", @@ -139,15 +139,15 @@ "color-red": "紅色", "color-sky": "天藍", "color-yellow": "黃色", - "comment": "評論", + "comment": "留言", "comment-placeholder": "新增評論", "comment-only": "只可以發表評論", "comment-only-desc": "只可以對卡片發表評論", "computer": "從本機上傳", - "copy-card-link-to-clipboard": "Copy card link to clipboard", + "copy-card-link-to-clipboard": "將卡片連結複製到剪貼板", "create": "建立", "createBoardPopup-title": "建立看板", - "chooseBoardSourcePopup-title": "Import board", + "chooseBoardSourcePopup-title": "匯入看板", "createLabelPopup-title": "建立標籤", "current": "目前", "date": "日期", @@ -192,7 +192,7 @@ "error-user-notAllowSelf": "不允許對自己執行此操作", "error-user-notCreated": "該使用者未能成功建立", "error-username-taken": "這個使用者名稱已被使用", - "error-email-taken": "Email has already been taken", + "error-email-taken": "電子信箱已被使用", "export-board": "Export board", "filter": "過濾", "filter-cards": "過濾卡片", @@ -208,22 +208,22 @@ "headerBarCreateBoardPopup-title": "建立看板", "home": "首頁", "import": "匯入", - "import-board": "import board", - "import-board-c": "Import board", + "import-board": "匯入看板", + "import-board-c": "匯入看板", "import-board-title-trello": "匯入在 Trello 的看板", - "import-board-title-wekan": "Import board from Wekan", - "import-sandstorm-warning": "Imported board will delete all existing data on board and replace it with imported board.", - "from-trello": "From Trello", - "from-wekan": "From Wekan", + "import-board-title-wekan": "從 Wekan 匯入看板", + "import-sandstorm-warning": "匯入資料將會移除所有現有的看版資料,並取代成此次匯入的看板資料", + "from-trello": "來自 Trello", + "from-wekan": "來自 Wekan", "import-board-instruction-trello": "在你的Trello看板中,點選“功能表”,然後選擇“更多”,“列印與匯出”,“匯出為 JSON” 並拷貝結果文本", - "import-board-instruction-wekan": "In your Wekan board, go to 'Menu', then 'Export board', and copy the text in the downloaded file.", + "import-board-instruction-wekan": "在 Wekan 看板中點選“功能表”,然後選擇“匯出看版”且複製文字到下載的檔案", "import-json-placeholder": "貼上您有效的 JSON 資料至此", "import-map-members": "複製成員", "import-members-map": "您匯入的看板有一些成員。請將您想匯入的成員映射到 Wekan 使用者。", "import-show-user-mapping": "核對成員映射", "import-user-select": "選擇您想將此成員映射到的 Wekan 使用者", "importMapMembersAddPopup-title": "選擇 Wekan 成員", - "info": "Version", + "info": "版本", "initials": "縮寫", "invalid-date": "無效的日期", "joined": "關聯", @@ -366,24 +366,26 @@ "email-invite-register-text": "親愛的 __user__,\n\n__inviter__ 邀請您加入 Wekan 一同協作\n\n請點擊下列連結:\n__url__\n\n您的邀請碼為:__icode__\n\n謝謝。", "error-invitation-code-not-exist": "邀請碼不存在", "error-notAuthorized": "沒有適合的權限觀看", - "outgoing-webhooks": "Outgoing Webhooks", - "outgoingWebhooksPopup-title": "Outgoing Webhooks", - "Wekan_version": "Wekan version", - "Node_version": "Node version", - "OS_Arch": "OS Arch", - "OS_Cpus": "OS CPU Count", - "OS_Freemem": "OS Free Memory", - "OS_Loadavg": "OS Load Average", - "OS_Platform": "OS Platform", - "OS_Release": "OS Release", - "OS_Totalmem": "OS Total Memory", - "OS_Type": "OS Type", - "OS_Uptime": "OS Uptime", - "hours": "hours", - "minutes": "minutes", - "seconds": "seconds", - "yes": "Yes", - "no": "No", - "accounts": "Accounts", - "accounts-allowEmailChange": "Allow Email Change" + "outgoing-webhooks": "設定 Webhooks", + "outgoingWebhooksPopup-title": "設定 Webhooks", + "new-integration": "New integration", + "no-name": "(Unknown)", + "Wekan_version": "Wekan 版本", + "Node_version": "Node 版本", + "OS_Arch": "系統架構", + "OS_Cpus": "系統\b CPU 數", + "OS_Freemem": "undefined", + "OS_Loadavg": "系統平均讀取", + "OS_Platform": "系統平臺", + "OS_Release": "系統發佈版本", + "OS_Totalmem": "系統總記憶體", + "OS_Type": "系統類型", + "OS_Uptime": "系統運行時間", + "hours": "小時", + "minutes": "分鐘", + "seconds": "秒", + "yes": "是", + "no": "否", + "accounts": "帳號", + "accounts-allowEmailChange": "准許變更電子信箱" }
\ No newline at end of file diff --git a/models/activities.js b/models/activities.js index 208dd629..c732a940 100644 --- a/models/activities.js +++ b/models/activities.js @@ -140,9 +140,9 @@ if (Meteor.isServer) { Notifications.notify(user, title, description, params); }); - const integration = Integrations.findOne({ boardId: board._id, type: 'outgoing-webhooks', enabled: true }); - if (integration) { - Meteor.call('outgoingWebhooks', integration, description, params); + const integrations = Integrations.find({ boardId: board._id, type: 'outgoing-webhooks', enabled: true, activities: { '$in': [description, 'all'] } }).fetch(); + if (integrations.length > 0) { + Meteor.call('outgoingWebhooks', integrations, description, params); } }); } diff --git a/models/checklists.js b/models/checklists.js index ab4fe61d..2521412f 100644 --- a/models/checklists.js +++ b/models/checklists.js @@ -164,21 +164,32 @@ if (Meteor.isServer) { // The future is now Checklists.after.update((userId, doc, fieldNames, modifier) => { if (fieldNames.includes('items')) { - Activities.insert({ - userId, - activityType: 'addChecklistItem', - cardId: doc.cardId, - boardId: Cards.findOne(doc.cardId).boardId, - checklistId: doc._id, - checklistItemId: modifier.$addToSet.items._id, - }); + if (modifier.$addToSet) { + Activities.insert({ + userId, + activityType: 'addChecklistItem', + cardId: doc.cardId, + boardId: Cards.findOne(doc.cardId).boardId, + checklistId: doc._id, + checklistItemId: modifier.$addToSet.items._id, + }); + } else if (modifier.$pull) { + const activity = Activities.findOne({ + checklistItemId: modifier.$pull.items._id, + }); + if (activity) { + Activities.remove(activity._id); + } + } } }); Checklists.before.remove((userId, doc) => { - const activity = Activities.findOne({ checklistId: doc._id }); - if (activity) { - Activities.remove(activity._id); + const activities = Activities.find({ checklistId: doc._id }); + if (activities) { + activities.forEach((activity) => { + Activities.remove(activity._id); + }); } }); } diff --git a/models/integrations.js b/models/integrations.js index b9bf248f..826873ce 100644 --- a/models/integrations.js +++ b/models/integrations.js @@ -11,6 +11,11 @@ Integrations.attachSchema(new SimpleSchema({ }, type: { type: String, + defaultValue: 'outgoing-webhooks', + }, + activities: { + type: [String], + defaultValue: ['all'], }, url: { // URL validation regex (https://mathiasbynens.be/demo/url-regex) type: String, @@ -35,11 +40,6 @@ Integrations.attachSchema(new SimpleSchema({ }, userId: { type: String, - autoValue() { // eslint-disable-line consistent-return - if (this.isInsert || this.isUpdate) { - return this.userId; - } - }, }, })); @@ -50,5 +50,141 @@ Integrations.allow({ update(userId, doc) { return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId)); }, + remove(userId, doc) { + return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId)); + }, fetch: ['boardId'], }); + +//INTEGRATIONS REST API +if (Meteor.isServer) { + // Get all integrations in board + JsonRoutes.add('GET', '/api/boards/:boardId/integrations', function(req, res, next) { + const paramBoardId = req.params.boardId; + Authentication.checkBoardAccess(req.userId, paramBoardId); + + const data = Integrations.find({ boardId: paramBoardId }, { fields: { token: 0 } }).map(function(doc) { + return doc; + }); + + JsonRoutes.sendResult(res, {code: 200, data}); + }); + + // Get a single integration in board + JsonRoutes.add('GET', '/api/boards/:boardId/integrations/:intId', function(req, res, next) { + const paramBoardId = req.params.boardId; + const paramIntId = req.params.intId; + Authentication.checkBoardAccess(req.userId, paramBoardId); + + JsonRoutes.sendResult(res, { + code: 200, + data: Integrations.findOne({ _id: paramIntId, boardId: paramBoardId }, { fields: { token: 0 } }), + }); + }); + + // Create a new integration + JsonRoutes.add('POST', '/api/boards/:boardId/integrations', function(req, res, next) { + const paramBoardId = req.params.boardId; + Authentication.checkBoardAccess(req.userId, paramBoardId); + + const id = Integrations.insert({ + userId: req.userId, + boardId: paramBoardId, + url: req.body.url, + }); + + JsonRoutes.sendResult(res, { + code: 200, + data: { + _id: id, + }, + }); + }); + + // Edit integration data + JsonRoutes.add('PUT', '/api/boards/:boardId/integrations/:intId', function (req, res, next) { + const paramBoardId = req.params.boardId; + const paramIntId = req.params.intId; + Authentication.checkBoardAccess(req.userId, paramBoardId); + + if (req.body.hasOwnProperty('enabled')) { + const newEnabled = req.body.enabled; + Integrations.direct.update({_id: paramIntId, boardId: paramBoardId}, + {$set: {enabled: newEnabled}}); + } + if (req.body.hasOwnProperty('title')) { + const newTitle = req.body.title; + Integrations.direct.update({_id: paramIntId, boardId: paramBoardId}, + {$set: {title: newTitle}}); + } + if (req.body.hasOwnProperty('url')) { + const newUrl = req.body.url; + Integrations.direct.update({_id: paramIntId, boardId: paramBoardId}, + {$set: {url: newUrl}}); + } + if (req.body.hasOwnProperty('token')) { + const newToken = req.body.token; + Integrations.direct.update({_id: paramIntId, boardId: paramBoardId}, + {$set: {token: newToken}}); + } + if (req.body.hasOwnProperty('activities')) { + const newActivities = req.body.activities; + Integrations.direct.update({_id: paramIntId, boardId: paramBoardId}, + {$set: {activities: newActivities}}); + } + + JsonRoutes.sendResult(res, { + code: 200, + data: { + _id: paramIntId, + }, + }); + }); + + // Delete subscribed activities + JsonRoutes.add('DELETE', '/api/boards/:boardId/integrations/:intId/activities', function (req, res, next) { + const paramBoardId = req.params.boardId; + const paramIntId = req.params.intId; + const newActivities = req.body.activities; + Authentication.checkBoardAccess(req.userId, paramBoardId); + + Integrations.direct.update({_id: paramIntId, boardId: paramBoardId}, + {$pullAll: {activities: newActivities}}); + + JsonRoutes.sendResult(res, { + code: 200, + data: Integrations.findOne({_id: paramIntId, boardId: paramBoardId}, { fields: {_id: 1, activities: 1}}), + }); + }); + + // Add subscribed activities + JsonRoutes.add('POST', '/api/boards/:boardId/integrations/:intId/activities', function (req, res, next) { + const paramBoardId = req.params.boardId; + const paramIntId = req.params.intId; + const newActivities = req.body.activities; + Authentication.checkBoardAccess(req.userId, paramBoardId); + + Integrations.direct.update({_id: paramIntId, boardId: paramBoardId}, + {$addToSet: {activities: { $each: newActivities}}}); + + JsonRoutes.sendResult(res, { + code: 200, + data: Integrations.findOne({_id: paramIntId, boardId: paramBoardId}, { fields: {_id: 1, activities: 1}}), + }); + }); + + // Delete integration + JsonRoutes.add('DELETE', '/api/boards/:boardId/integrations/:intId', function (req, res, next) { + const paramBoardId = req.params.boardId; + const paramIntId = req.params.intId; + Authentication.checkBoardAccess(req.userId, paramBoardId); + + Integrations.direct.remove({_id: paramIntId, boardId: paramBoardId}); + JsonRoutes.sendResult(res, { + code: 200, + data: { + _id: paramIntId, + }, + }); + }); +} diff --git a/package.json b/package.json index 2c4f79a1..65783ced 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wekan", - "version": "0.34.0", + "version": "0.35.0", "description": "The open-source Trello-like kanban", "private": true, "scripts": { diff --git a/sandstorm-pkgdef.capnp b/sandstorm-pkgdef.capnp index 32ee8c5f..bd8a0533 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 = 21, + appVersion = 22, # Increment this for every release. - appMarketingVersion = (defaultText = "0.34.0~2017-08-30"), + appMarketingVersion = (defaultText = "0.35.0~2017-09-02"), # Human-readable presentation of the app version. minUpgradableAppVersion = 0, diff --git a/server/notifications/outgoing.js b/server/notifications/outgoing.js index c227366e..07a0a903 100644 --- a/server/notifications/outgoing.js +++ b/server/notifications/outgoing.js @@ -9,8 +9,8 @@ const postCatchError = Meteor.wrapAsync((url, options, resolve) => { }); Meteor.methods({ - outgoingWebhooks(integration, description, params) { - check(integration, Object); + outgoingWebhooks(integrations, description, params) { + check(integrations, Array); check(description, String); check(params, Object); @@ -19,7 +19,8 @@ Meteor.methods({ if (quoteParams[key]) quoteParams[key] = `"${params[key]}"`; }); - const user = Users.findOne(integration.userId); + const userId = (params.userId)?params.userId:integrations[0].userId; + const user = Users.findOne(userId); const text = `${params.user} ${TAPi18n.__(description, quoteParams, user.getLanguage())}\n${params.url}`; if (text.length === 0) return; @@ -31,7 +32,7 @@ Meteor.methods({ ['cardId', 'listId', 'oldListId', 'boardId'].forEach((key) => { if (params[key]) value[key] = params[key]; }); - value.$description = description; + value.description = description; const options = { headers: { @@ -41,12 +42,14 @@ Meteor.methods({ data: value, }; - const response = postCatchError(integration.url, options); + integrations.forEach((integration) => { + const response = postCatchError(integration.url, options); - if (response && response.statusCode && response.statusCode === 200) { - return true; // eslint-disable-line consistent-return - } else { - throw new Meteor.Error('error-invalid-webhook-response'); - } + if (response && response.statusCode && response.statusCode === 200) { + return true; // eslint-disable-line consistent-return + } else { + throw new Meteor.Error('error-invalid-webhook-response'); + } + }); }, }); |