소스 검색

Merge pull request #2 from wekan/master

Merge Wekan
NicoP-S 5 년 전
부모
커밋
e47ff25d45
92개의 변경된 파일1241개의 추가작업 그리고 680개의 파일을 삭제
  1. 1 1
      .sandstorm-meteor-1.8/package-lock.json
  2. 1 1
      .sandstorm-meteor-1.8/package.json
  3. 35 2
      CHANGELOG.md
  4. 1 1
      Stackerfile.yml
  5. 157 190
      client/components/activities/activities.jade
  6. 72 39
      client/components/activities/activities.js
  7. 0 7
      client/components/activities/comments.js
  8. 0 14
      client/components/boards/boardHeader.jade
  9. 0 4
      client/components/boards/boardHeader.js
  10. 1 1
      client/components/cards/attachments.jade
  11. 7 4
      client/components/cards/cardDetails.jade
  12. 1 1
      client/components/cards/minicard.styl
  13. 1 6
      client/components/main/editor.jade
  14. 19 47
      client/components/main/editor.js
  15. 2 0
      client/components/main/header.jade
  16. 1 1
      client/components/main/header.styl
  17. 10 0
      client/components/notifications/notification.jade
  18. 28 0
      client/components/notifications/notification.js
  19. 57 0
      client/components/notifications/notification.styl
  20. 53 0
      client/components/notifications/notificationIcon.jade
  21. 5 0
      client/components/notifications/notifications.jade
  22. 32 0
      client/components/notifications/notifications.js
  23. 17 0
      client/components/notifications/notifications.styl
  24. 16 0
      client/components/notifications/notificationsDrawer.jade
  25. 38 0
      client/components/notifications/notificationsDrawer.js
  26. 57 0
      client/components/notifications/notificationsDrawer.styl
  27. 4 0
      client/components/sidebar/sidebar.jade
  28. 4 0
      client/components/sidebar/sidebar.js
  29. 0 204
      client/lib/popup.js
  30. 8 2
      i18n/ar.i18n.json
  31. 8 2
      i18n/bg.i18n.json
  32. 8 2
      i18n/br.i18n.json
  33. 8 2
      i18n/ca.i18n.json
  34. 19 13
      i18n/cs.i18n.json
  35. 8 2
      i18n/da.i18n.json
  36. 8 2
      i18n/de.i18n.json
  37. 8 2
      i18n/el.i18n.json
  38. 8 2
      i18n/en-GB.i18n.json
  39. 8 2
      i18n/en.i18n.json
  40. 8 2
      i18n/eo.i18n.json
  41. 8 2
      i18n/es-AR.i18n.json
  42. 8 2
      i18n/es.i18n.json
  43. 8 2
      i18n/eu.i18n.json
  44. 8 2
      i18n/fa.i18n.json
  45. 8 2
      i18n/fi.i18n.json
  46. 8 2
      i18n/fr.i18n.json
  47. 8 2
      i18n/gl.i18n.json
  48. 8 2
      i18n/he.i18n.json
  49. 8 2
      i18n/hi.i18n.json
  50. 8 2
      i18n/hu.i18n.json
  51. 8 2
      i18n/hy.i18n.json
  52. 8 2
      i18n/id.i18n.json
  53. 8 2
      i18n/ig.i18n.json
  54. 8 2
      i18n/it.i18n.json
  55. 8 2
      i18n/ja.i18n.json
  56. 8 2
      i18n/ka.i18n.json
  57. 8 2
      i18n/km.i18n.json
  58. 8 2
      i18n/ko.i18n.json
  59. 8 2
      i18n/lv.i18n.json
  60. 8 2
      i18n/mk.i18n.json
  61. 8 2
      i18n/mn.i18n.json
  62. 8 2
      i18n/nb.i18n.json
  63. 8 2
      i18n/nl.i18n.json
  64. 8 2
      i18n/oc.i18n.json
  65. 8 2
      i18n/pl.i18n.json
  66. 9 3
      i18n/pt-BR.i18n.json
  67. 8 2
      i18n/pt.i18n.json
  68. 8 2
      i18n/ro.i18n.json
  69. 8 2
      i18n/ru.i18n.json
  70. 8 2
      i18n/sl.i18n.json
  71. 10 4
      i18n/sr.i18n.json
  72. 8 2
      i18n/sv.i18n.json
  73. 8 2
      i18n/sw.i18n.json
  74. 8 2
      i18n/ta.i18n.json
  75. 8 2
      i18n/th.i18n.json
  76. 8 2
      i18n/tr.i18n.json
  77. 8 2
      i18n/uk.i18n.json
  78. 8 2
      i18n/vi.i18n.json
  79. 8 2
      i18n/zh-CN.i18n.json
  80. 8 2
      i18n/zh-HK.i18n.json
  81. 8 2
      i18n/zh-TW.i18n.json
  82. 6 6
      models/attachments.js
  83. 6 0
      models/lists.js
  84. 30 3
      models/users.js
  85. 1 1
      package-lock.json
  86. 1 1
      package.json
  87. 29 15
      public/api/wekan.html
  88. 11 3
      public/api/wekan.yml
  89. 2 2
      sandstorm-pkgdef.capnp
  90. 3 7
      server/notifications/profile.js
  91. 101 0
      server/publications/notifications.js
  92. 1 1
      start-wekan.sh

+ 1 - 1
.sandstorm-meteor-1.8/package-lock.json

@@ -1,6 +1,6 @@
 {
   "name": "wekan",
-  "version": "v3.86.0",
+  "version": "v3.88.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {

+ 1 - 1
.sandstorm-meteor-1.8/package.json

@@ -1,6 +1,6 @@
 {
   "name": "wekan",
-  "version": "v3.86.0",
+  "version": "v3.88.0",
   "description": "Open-Source kanban",
   "private": true,
   "scripts": {

+ 35 - 2
CHANGELOG.md

@@ -1,11 +1,44 @@
-# Upcoming Wekan release
+# v3.88 2020-04-02 Wekan release
 
-This release fixes the following bugs:
+This release adds the following new features:
+
+- [Notification drawer](https://github.com/wekan/wekan/pull/2975) [like Trello](https://github.com/wekan/wekan/issues/2471).
+  Thanks to jtbairdsr and xet7.
+
+and makes the following UI changes:
 
+- [Minicard labels on the top and title on bottom](https://github.com/wekan/wekan/issues/2980).
+  Thanks to helioguardabaxo and xet7.
+
+and fixes the following bugs:
+
+- [Fix start-wekan.sh MongoDB port to 27017](https://github.com/wekan/wekan/commit/c60a092fc0ed9fe15c417bcb443b1e3e3aaedf7e).
+  Thanks to Keelan and xet7.
+    
+Thanks to above GitHub users for their contributions and translators for their translations.
+
+# v3.87 2020-04-01 Wekan release
+
+This release makes the following UI changes:
+
+- [Move "Rules" from "Board View" to "Board Settings"](https://github.com/wekan/wekan/issues/2973).
+  Thanks to helioguardabaxo and xet7.
+- [Improvements on card details visualization](https://github.com/wekan/wekan/issues/2974).
+  Thanks to helioguardabaxo and xet7.
 - [Hide duplicate "Hide system messages" at Change Settings/Member Settings, because it's also on card
   slider](https://github.com/wekan/wekan/issues/2837).
   Thanks to notohiro and xet7.
 
+and fixes the following bugs:
+
+- [Fix Browser always reload the whole page when I change one of the card
+  color](https://github.com/wekan/wekan/commit/3546d7aa02bc65cf1183cb493adeb543ba51945d).
+  Fixed by making label colors and text again editable.
+  Regression from [Wekan v3.86 2)](https://github.com/wekan/wekan/commit/b9099a8b7ea6f63c79bdcbb871cb993b2cb7e325).
+  Thanks to javen9881 and xet7.
+- [Fix richer editor submit did not clear edit area](https://github.com/wekan/wekan/commit/033d6710470b2ecd7a0ec0b2f0741ff459e68b32).
+  Thanks to xet7.
+
 Thanks to above GitHub users for their contributions and translators for their translations.
 
 # v3.86 2020-03-24 Wekan release

+ 1 - 1
Stackerfile.yml

@@ -1,5 +1,5 @@
 appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
-appVersion: "v3.86.0"
+appVersion: "v3.88.0"
 files:
   userUploads:
     - README.md

+ 157 - 190
client/components/activities/activities.jade

@@ -8,234 +8,201 @@ template(name="activities")
       +cardActivities
 
 template(name="boardActivities")
-  each currentBoard.activities
-    .activity
-      +userAvatar(userId=user._id)
-      p.activity-desc
-        +memberName(user=user)
+  each activityData in currentBoard.activities
+    +activity(activity=activityData card=card mode=mode)
 
-        if($eq activityType 'deleteAttachment')
-          | {{{_ 'activity-delete-attach' cardLink}}}.
+template(name="cardActivities")
+  each activityData in currentCard.activities
+    +activity(activity=activityData card=card mode=mode)
+
+template(name="activity")
+  .activity
+    +userAvatar(userId=activity.user._id)
+    p.activity-desc
+      +memberName(user=activity.user)
+
+      //- attachment activity -------------------------------------------------
+      if($eq activity.activityType 'deleteAttachment')
+        | {{{_ 'activity-delete-attach' cardLink}}}.
+
+      if($eq activity.activityType 'addAttachment')
+        | {{{_ 'activity-attached' attachmentLink cardLink}}}.
+        if($neq mode 'board')
+          if activity.attachment.isImage
+            img.attachment-image-preview(src=activity.attachment.url)
+
+      //- board activity ------------------------------------------------------
+      if($eq mode 'board')
+        if($eq activity.activityType 'createBoard')
+          | {{_ 'activity-created' boardLabel}}.
 
-        if($eq activityType 'addAttachment')
-          | {{{_ 'activity-attached' attachmentLink cardLink}}}.
+        if($eq activity.activityType 'importBoard')
+          | {{{_ 'activity-imported-board' boardLabel sourceLink}}}.
 
-        if($eq activityType 'addBoardMember')
+        if($eq activity.activityType 'addBoardMember')
           | {{{_ 'activity-added' memberLink boardLabel}}}.
 
-        if($eq activityType 'addComment')
-          | {{{_ 'activity-on' cardLink}}}
-          a.activity-comment(href="{{ card.absoluteUrl }}")
-            +viewer
-              = comment.text
-
-        if($eq activityType 'addChecklist')
-          | {{{_ 'activity-checklist-added' cardLink}}}.
-          .activity-checklist(href="{{ card.absoluteUrl }}")
-            +viewer
-              = checklist.title
-        if($eq activityType 'removeChecklist')
-          | {{{_ 'activity-checklist-removed' cardLink}}}.
-
-        if($eq activityType 'checkedItem')
-          | {{{_ 'activity-checked-item' checkItem checklist.title cardLink}}}.
-
-        if($eq activityType 'uncheckedItem')
-          | {{{_ 'activity-unchecked-item' checkItem checklist.title cardLink}}}.
-
-        if($eq activityType 'checklistCompleted')
-          | {{{_ 'activity-checklist-completed' checklist.title cardLink}}}.
+        if($eq activity.activityType 'removeBoardMember')
+          | {{{_ 'activity-excluded' memberLink boardLabel}}}.
 
-        if($eq activityType 'checklistUncompleted')
-          | {{{_ 'activity-checklist-uncompleted' checklist.title cardLink}}}.
+      //- card activity -------------------------------------------------------
+      if($eq activity.activityType 'createCard')
+        if($eq mode 'card')
+          | {{{_ 'activity-added' cardLabel activity.listName}}}.
+        else
+          | {{{_ 'activity-added' cardLabel boardLabel}}}.
 
-        if($eq activityType 'addChecklistItem')
-          | {{{_ 'activity-checklist-item-added' checklist.title cardLink}}}.
-          .activity-checklist(href="{{ card.absoluteUrl }}")
-            +viewer
-              = checklistItem.title
-        if($eq activityType 'removedChecklistItem')
-          | {{{_ 'activity-checklist-item-removed' checklist.title cardLink}}}.
+      if($eq activity.activityType 'importCard')
+        | {{{_ 'activity-imported' cardLink boardLabel sourceLink}}}.
 
-        if($eq activityType 'archivedCard')
-          | {{{_ 'activity-archived' cardLink}}}.
+      if($eq activity.activityType 'moveCard')
+        | {{{_ 'activity-moved' cardLabel activity.oldList.title activity.list.title}}}.
 
-        if($eq activityType 'archivedList')
-          | {{_ 'activity-archived' list.title}}.
+      if($eq activity.activityType 'moveCardBoard')
+        | {{{_ 'activity-moved' cardLink activity.oldBoardName activity.boardName}}}.
 
-        if($eq activityType 'archivedSwimlane')
-          | {{_ 'activity-archived' swimlane.title}}.
+      if($eq activity.activityType 'archivedCard')
+        | {{{_ 'activity-archived' cardLink}}}.
 
-        if($eq activityType 'createBoard')
-          | {{_ 'activity-created' boardLabel}}.
+      if($eq activity.activityType 'restoredCard')
+        | {{{_ 'activity-sent' cardLink boardLabel}}}.
 
-        if($eq activityType 'createCard')
-          | {{{_ 'activity-added' cardLink boardLabel}}}.
+      //- checklist activity --------------------------------------------------
+      if($eq activity.activityType 'addChecklist')
+        | {{{_ 'activity-checklist-added' cardLink}}}.
+        if($eq mode 'card')
+          .activity-checklist
+            +viewer
+              = activity.checklist.title
+        else
+          a.activity-checklist(href="{{ activity.card.absoluteUrl }}")
+            +viewer
+              = activity.checklist.title
 
-        if($eq activityType 'createCustomField')
-          | {{_ 'activity-customfield-created' customField}}.
+      if($eq activity.activityType 'removedChecklist')
+        | {{{_ 'activity-checklist-removed' cardLink}}}.
 
-        if($eq activityType 'createList')
-          | {{_ 'activity-added' list.title boardLabel}}.
+      if($eq activity.activityType 'completeChecklist')
+        | {{{_ 'activity-checklist-completed' activity.checklist.title cardLink}}}.
 
-        if($eq activityType 'createSwimlane')
-          | {{_ 'activity-added' swimlane.title boardLabel}}.
+      if($eq activity.activityType 'uncompleteChecklist')
+        | {{{_ 'activity-checklist-uncompleted' activity.checklist.title cardLink}}}.
 
-        if($eq activityType 'removeList')
-          | {{_ 'activity-removed' title boardLabel}}.
+      if($eq activity.activityType 'checkedItem')
+        | {{{_ 'activity-checked-item' checkItem activity.checklist.title cardLink}}}.
 
-        if($eq activityType 'importBoard')
-          | {{{_ 'activity-imported-board' boardLabel sourceLink}}}.
+      if($eq activity.activityType 'uncheckedItem')
+        | {{{_ 'activity-unchecked-item' checkItem activity.checklist.title cardLink}}}.
 
-        if($eq activityType 'importCard')
-          | {{{_ 'activity-imported' cardLink boardLabel sourceLink}}}.
+      if($eq activity.activityType 'addChecklistItem')
+        | {{{_ 'activity-checklist-item-added' activity.checklist.title cardLink}}}.
+        .activity-checklist(href="{{ activity.card.absoluteUrl }}")
+          +viewer
+            = activity.checklistItem.title
 
-        if($eq activityType 'importList')
-          | {{{_ 'activity-imported' listLabel boardLabel sourceLink}}}.
+      if($eq activity.activityType 'removedChecklistItem')
+        | {{{_ 'activity-checklist-item-removed' activity.checklist.title cardLink}}}.
 
-        if($eq activityType 'joinMember')
-          if($eq user._id member._id)
-            | {{{_ 'activity-joined' cardLink}}}.
+      //- comment activity ----------------------------------------------------
+      if($eq mode 'card')
+        //- if we are in card mode we display the comment in a way that it
+        //- can be edited by the owner
+        if($eq activity.activityType 'addComment')
+          +inlinedForm(classNames='js-edit-comment')
+            +editor(autofocus=true)
+              = activity.comment.text
+            .edit-controls
+              button.primary(type="submit") {{_ 'edit'}}
           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}}}.
-
-        if($eq activityType 'removeBoardMember')
-          | {{{_ 'activity-excluded' memberLink boardLabel}}}.
+            .activity-comment
+              +viewer
+                = activity.comment.text
+            span(title=activity.createdAt).activity-meta {{ moment activity.createdAt }}
+              if ($eq currentUser._id activity.comment.userId)
+                = ' - '
+                a.js-open-inlined-form {{_ "edit"}}
+                = ' - '
+                a.js-delete-comment {{_ "delete"}}
 
-        if($eq activityType 'restoredCard')
-          | {{{_ 'activity-sent' cardLink boardLabel}}}.
+        if($eq activity.activityType 'deleteComment')
+          | {{{_ 'activity-deleteComment' currentData.commentId}}}.
 
-        if($eq activityType 'addedLabel')
-          | {{{_ 'activity-added-label' lastLabel cardLink}}}.
+        if($eq activity.activityType 'editComment')
+          | {{{_ 'activity-editComment' currentData.commentId}}}.
+      else
+        //- if we are not in card mode we only display a summary of the comment
+        if($eq activity.activityType 'addComment')
+          | {{{_ 'activity-on' cardLink}}}
+          a.activity-comment(href="{{ activity.card.absoluteUrl }}")
+            +viewer
+              = activity.comment.text
 
-        if($eq activityType 'removedLabel')
-          | {{{_ 'activity-removed-label' lastLabel cardLink}}}.
+      //- customField activity ------------------------------------------------
+      if($eq mode 'board')
+        if($eq activity.activityType 'createCustomField')
+          | {{_ 'activity-customfield-created' customField}}.
 
-        if($eq activityType 'setCustomField')
+        if($eq activity.activityType 'setCustomField')
           | {{{_ 'activity-set-customfield' lastCustomField lastCustomFieldValue cardLink}}}.
 
-        if($eq activityType 'unsetCustomField')
+        if($eq activity.activityType 'unsetCustomField')
           | {{{_ 'activity-unset-customfield' lastCustomField cardLink}}}.
 
-        if($eq activityType 'unjoinMember')
-          if($eq user._id member._id)
-            | {{{_ 'activity-unjoined' cardLink}}}.
-          else
-            | {{{_ 'activity-removed' memberLink cardLink}}}.
+      //- label activity ------------------------------------------------------
+      if($eq activity.activityType 'addedLabel')
+        | {{{_ 'activity-added-label' lastLabel cardLink}}}.
 
-        span(title=createdAt).activity-meta {{ moment createdAt }}
+      if($eq activity.activityType 'removedLabel')
+        | {{{_ 'activity-removed-label' lastLabel cardLink}}}.
 
-template(name="cardActivities")
-  each currentCard.activities
-    .activity
-      +userAvatar(userId=user._id)
-      p.activity-desc
-        +memberName(user=user)
-        if($eq activityType 'createCard')
-          | {{_ 'activity-added' cardLabel listName}}.
-        if($eq activityType 'importCard')
-          | {{{_ 'activity-imported' cardLabel list.title sourceLink}}}.
-        if($eq activityType 'joinMember')
-          if($eq user._id member._id)
-            | {{_ 'activity-joined' cardLabel}}.
-          else
-            | {{{_ 'activity-added' memberLink cardLabel}}}.
-        if($eq activityType 'unjoinMember')
-          if($eq user._id member._id)
-            | {{_ 'activity-unjoined' cardLabel}}.
-          else
-            | {{{_ 'activity-removed' cardLabel memberLink}}}.
-        if($eq activityType 'archivedCard')
-          | {{_ 'activity-archived' cardLabel}}.
-
-        if($eq activityType 'addedLabel')
-          | {{{_ 'activity-added-label-card' lastLabel }}}.
+      //- list activity -------------------------------------------------------
+      if($neq mode 'card')
+        if($eq activity.activityType 'createList')
+          | {{{_ 'activity-added' listLabel boardLabel}}}.
 
-        if($eq activityType 'removedLabel')
-          | {{{_ 'activity-removed-label-card' lastLabel }}}.
+        if($eq activity.activityType 'importList')
+          | {{{_ 'activity-imported' listLabel boardLabel sourceLink}}}.
 
-        if($eq activityType 'removeChecklist')
-          | {{{_ 'activity-checklist-removed' cardLabel}}}.
+        if($eq activity.activityType 'removeList')
+          | {{{_ 'activity-removed' activity.title boardLabel}}}.
 
-        if($eq activityType 'checkedItem')
-          | {{{_ 'activity-checked-item-card' checkItem checklist.title }}}.
+        if($eq activity.activityType 'archivedList')
+          | {{_ 'activity-archived' listLabel}}.
 
-        if($eq activityType 'uncheckedItem')
-          | {{{_ 'activity-unchecked-item-card' checkItem checklist.title }}}.
+      //- member activity ----------------------------------------------------
+      if($eq activity.activityType 'joinMember')
+        if($eq user._id activity.member._id)
+          | {{{_ 'activity-joined' cardLink}}}.
+        else
+          | {{{_ 'activity-added' memberLink cardLink}}}.
 
-        if($eq activityType 'checklistCompleted')
-          | {{{_ 'activity-checklist-completed-card' checklist.title }}}.
+      if($eq activity.activityType 'unjoinMember')
+        if($eq user._id activity.member._id)
+          | {{{_ 'activity-unjoined' cardLink}}}.
+        else
+          | {{{_ 'activity-removed' memberLink cardLink}}}.
 
-        if($eq activityType 'checklistUncompleted')
-          | {{{_ 'activity-checklist-uncompleted-card' checklist.title }}}.
+      //- swimlane activity --------------------------------------------------
+      if($neq mode 'card')
+        if($eq activity.activityType 'createSwimlane')
+          | {{{_ 'activity-added' activity.swimlane.title boardLabel}}}.
 
-        if($eq activityType 'restoredCard')
-          | {{_ 'activity-sent' cardLabel boardLabel}}.
-        if($eq activityType 'moveCard')
-          | {{_ 'activity-moved' cardLabel oldList.title list.title}}.
+        if($eq activity.activityType 'archivedSwimlane')
+          | {{_ 'activity-archived' activity.swimlane.title}}.
 
-        if($eq activityType 'moveCardBoard')
-          | {{{_ 'activity-moved' cardLink oldBoardName boardName}}}.
 
-        if($eq activityType 'addAttachment')
-          | {{{_ 'activity-attached' attachmentLink cardLabel}}}.
-          if attachment.isImage
-            img.attachment-image-preview(src=attachment.url)
-        if($eq activityType 'deleteAttachment')
-          | {{{_ 'activity-delete-attach'  cardLabel}}}.
-        if($eq activityType 'removedChecklist')
-          | {{{_ 'activity-checklist-removed' cardLabel}}}.
-        if($eq activityType 'addChecklist')
-          | {{{_ 'activity-checklist-added' cardLabel}}}.
-          .activity-checklist
-            +viewer
-              = checklist.title
-        if($eq activityType 'addChecklistItem')
-          | {{{_ 'activity-checklist-item-added' checklist.title cardLink}}}.
-          .activity-checklist(href="{{ card.absoluteUrl }}")
-            +viewer
-              = checklistItem.title
-
-        if(currentData.timeKey)
-          | {{{_ activityType }}}
+      //- I don't understand this part ----------------------------------------
+      if(currentData.timeKey)
+        | {{{_ activity.activityType }}}
+        = ' '
+        i(title=currentData.timeValue).activity-meta {{ moment currentData.timeValue 'LLL' }}
+        if (currentData.timeOldValue)
           = ' '
-          i(title=currentData.timeValue).activity-meta {{ moment currentData.timeValue 'LLL' }}
-          if (currentData.timeOldValue)
-              = ' '
-              | {{{_ "previous_as" }}}
-              = ' '
-              i(title=currentData.timeOldValue).activity-meta {{ moment currentData.timeOldValue 'LLL' }}
-          = ' @'
-        else if(currentData.timeValue)
-          | {{{_ activityType currentData.timeValue}}}
-
-
-        if($eq activityType 'deleteComment')
-          | {{{_ 'activity-deleteComment' currentData.commentId}}}.
-        if($eq activityType 'editComment')
-          | {{{_ 'activity-editComment' currentData.commentId}}}.
-        if($eq activityType 'addComment')
-          +inlinedForm(classNames='js-edit-comment')
-            +editor(autofocus=true)
-              = comment.text
-            .edit-controls
-              button.primary(type="submit") {{_ 'edit'}}
-          else
-            .activity-comment
-              +viewer
-                = comment.text
-            span(title=createdAt).activity-meta {{ moment createdAt }}
-              if ($eq currentUser._id comment.userId)
-                = ' - '
-                a.js-open-inlined-form {{_ "edit"}}
-                = ' - '
-                a.js-delete-comment {{_ "delete"}}
-
-        else
-          span(title=createdAt).activity-meta {{ moment createdAt }}
+            | {{{_ "previous_as" }}}
+            = ' '
+            i(title=currentData.timeOldValue).activity-meta {{ moment currentData.timeOldValue 'LLL' }}
+        = ' @'
+      else if(currentData.timeValue)
+        | {{{_ activity.activityType currentData.timeValue}}}
+
+      span(title=activity.createdAt).activity-meta {{ moment activity.createdAt }}

+ 72 - 39
client/components/activities/activities.js

@@ -41,7 +41,9 @@ BlazeComponent.extendComponent({
       });
     });
   },
+}).register('activities');
 
+BlazeComponent.extendComponent({
   loadNextPage() {
     if (this.loadNextPageLocked === false) {
       this.page.set(this.page.get() + 1);
@@ -50,41 +52,37 @@ BlazeComponent.extendComponent({
   },
 
   checkItem() {
-    const checkItemId = this.currentData().checklistItemId;
+    const checkItemId = this.currentData().activity.checklistItemId;
     const checkItem = ChecklistItems.findOne({ _id: checkItemId });
-    return checkItem.title;
+    return checkItem && checkItem.title;
   },
 
   boardLabel() {
+    const data = this.currentData();
+    if (data.mode !== 'board') {
+      return createBoardLink(data.activity.board(), data.activity.listName);
+    }
     return TAPi18n.__('this-board');
   },
 
   cardLabel() {
+    const data = this.currentData();
+    if (data.mode !== 'card') {
+      return createCardLink(this.currentData().activity.card());
+    }
     return TAPi18n.__('this-card');
   },
 
   cardLink() {
-    const card = this.currentData().card();
-    return (
-      card &&
-      Blaze.toHTML(
-        HTML.A(
-          {
-            href: card.absoluteUrl(),
-            class: 'action-card',
-          },
-          card.title,
-        ),
-      )
-    );
+    return createCardLink(this.currentData().activity.card());
   },
 
   lastLabel() {
-    const lastLabelId = this.currentData().labelId;
+    const lastLabelId = this.currentData().activity.labelId;
     if (!lastLabelId) return null;
-    const lastLabel = Boards.findOne(Session.get('currentBoard')).getLabelById(
-      lastLabelId,
-    );
+    const lastLabel = Boards.findOne(
+      this.currentData().activity.boardId,
+    ).getLabelById(lastLabelId);
     if (lastLabel && (lastLabel.name === undefined || lastLabel.name === '')) {
       return lastLabel.color;
     } else {
@@ -94,7 +92,7 @@ BlazeComponent.extendComponent({
 
   lastCustomField() {
     const lastCustomField = CustomFields.findOne(
-      this.currentData().customFieldId,
+      this.currentData().activity.customFieldId,
     );
     if (!lastCustomField) return null;
     return lastCustomField.name;
@@ -102,10 +100,10 @@ BlazeComponent.extendComponent({
 
   lastCustomFieldValue() {
     const lastCustomField = CustomFields.findOne(
-      this.currentData().customFieldId,
+      this.currentData().activity.customFieldId,
     );
     if (!lastCustomField) return null;
-    const value = this.currentData().value;
+    const value = this.currentData().activity.value;
     if (
       lastCustomField.settings.dropdownItems &&
       lastCustomField.settings.dropdownItems.length > 0
@@ -122,11 +120,13 @@ BlazeComponent.extendComponent({
   },
 
   listLabel() {
-    return this.currentData().list().title;
+    const activity = this.currentData().activity;
+    const list = activity.list();
+    return (list && list.title) || activity.title;
   },
 
   sourceLink() {
-    const source = this.currentData().source;
+    const source = this.currentData().activity.source;
     if (source) {
       if (source.url) {
         return Blaze.toHTML(
@@ -146,30 +146,31 @@ BlazeComponent.extendComponent({
 
   memberLink() {
     return Blaze.toHTMLWithData(Template.memberName, {
-      user: this.currentData().member(),
+      user: this.currentData().activity.member(),
     });
   },
 
   attachmentLink() {
-    const attachment = this.currentData().attachment();
+    const attachment = this.currentData().activity.attachment();
     // trying to display url before file is stored generates js errors
     return (
-      attachment &&
-      attachment.url({ download: true }) &&
-      Blaze.toHTML(
-        HTML.A(
-          {
-            href: attachment.url({ download: true }),
-            target: '_blank',
-          },
-          attachment.name(),
-        ),
-      )
+      (attachment &&
+        attachment.url({ download: true }) &&
+        Blaze.toHTML(
+          HTML.A(
+            {
+              href: attachment.url({ download: true }),
+              target: '_blank',
+            },
+            attachment.name(),
+          ),
+        )) ||
+      this.currentData().activity.attachmentName
     );
   },
 
   customField() {
-    const customField = this.currentData().customField();
+    const customField = this.currentData().activity.customField();
     if (!customField) return null;
     return customField.name;
   },
@@ -199,4 +200,36 @@ BlazeComponent.extendComponent({
       },
     ];
   },
-}).register('activities');
+}).register('activity');
+
+function createCardLink(card) {
+  return (
+    card &&
+    Blaze.toHTML(
+      HTML.A(
+        {
+          href: card.absoluteUrl(),
+          class: 'action-card',
+        },
+        card.title,
+      ),
+    )
+  );
+}
+
+function createBoardLink(board, list) {
+  let text = board.title;
+  if (list) text += `: ${list}`;
+  return (
+    board &&
+    Blaze.toHTML(
+      HTML.A(
+        {
+          href: board.absoluteUrl(),
+          class: 'action-board',
+        },
+        text,
+      ),
+    )
+  );
+}

+ 0 - 7
client/components/activities/comments.js

@@ -33,13 +33,6 @@ BlazeComponent.extendComponent({
               cardId,
             });
             resetCommentInput(input);
-            // With Richer editor is in use, and comment is submitted,
-            // clear comment form with JQuery. Id #summernote is defined
-            // at client/components/main/editor.jade where it previously was
-            // id=id, now it is id="summernote".
-            if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR === 'true') {
-              $('#summernote').summernote('code', '');
-            }
             Tracker.flush();
             autosize.update(input);
             input.trigger('submitted');

+ 0 - 14
client/components/boards/boardHeader.jade

@@ -193,20 +193,6 @@ template(name="boardChangeViewPopup")
           | {{_ 'board-view-cal'}}
           if $eq Utils.boardView "board-view-cal"
             i.fa.fa-check
-    if currentUser.isAdmin
-      hr
-      li
-        with "board-view-rules"
-          a.js-open-rules-view(title="{{_ 'rules'}}")
-            i.fa.fa-magic
-            | {{_ 'rules'}}
-    else if currentUser.isBoardAdmin
-      hr
-      li
-        with "board-view-rules"
-          a.js-open-rules-view(title="{{_ 'rules'}}")
-            i.fa.fa-magic
-            | {{_ 'rules'}}
 
 template(name="createBoard")
   form

+ 0 - 4
client/components/boards/boardHeader.js

@@ -191,10 +191,6 @@ Template.boardChangeViewPopup.events({
     Utils.setBoardView('board-view-cal');
     Popup.close();
   },
-  'click .js-open-rules-view'() {
-    Modal.openWide('rulesMain');
-    Popup.close();
-  },
 });
 
 const CreateBoard = BlazeComponent.extendComponent({

+ 1 - 1
client/components/cards/attachments.jade

@@ -55,5 +55,5 @@ template(name="attachmentsGalery")
         unless currentUser.isWorker
           //li.attachment-item.add-attachment
           a.js-add-attachment
-            i.fa.fa-paperclip
+            i.fa.fa-plus
             | {{_ 'add-attachment' }}

+ 7 - 4
client/components/cards/cardDetails.jade

@@ -203,6 +203,7 @@ template(name="cardDetails")
     if canModifyCard
       unless currentUser.isWorker
         if currentBoard.allowsDescriptionTitle
+          hr
           h3
             i.fa.fa-align-left
             card-details-item-title {{_ 'description'}}
@@ -229,6 +230,7 @@ template(name="cardDetails")
                   a.js-close-inlined-form {{_ 'discard'}}
     else if getDescription
       if currentBoard.allowsDescriptionTitle
+        hr
         h3.card-details-item-title {{_ 'description'}}
       if currentBoard.allowsDescriptionText
         +viewer
@@ -237,15 +239,16 @@ template(name="cardDetails")
     .card-checklist-attachmentGalerys
       .card-checklist-attachmentGalery.card-checklists
         if currentBoard.allowsChecklists
+          hr
           +checklists(cardId = _id)
         if currentBoard.allowsSubtasks
           hr
           +subtasks(cardId = _id)
       if currentBoard.allowsAttachments
-        //- hr
-        //- h3
-        //- i.fa.fa-paperclip
-        //- | {{_ 'attachments'}}
+        hr
+        h3
+          i.fa.fa-paperclip
+          | {{_ 'attachments'}}
         .card-checklist-attachmentGalery.card-attachmentGalery
           +attachmentsGalery
 

+ 1 - 1
client/components/cards/minicard.styl

@@ -79,7 +79,7 @@
     border-radius: top 2px
 
   .minicard-labels
-    float: right
+    float: none
     display: flex
     flex-wrap: wrap
 

+ 1 - 6
client/components/main/editor.jade

@@ -1,13 +1,8 @@
 template(name="editor")
-  // With Richer editor is in use, and comment is submitted,
-  // clear comment form with JQuery Comment at
-  // client/components/activities/comments.js . Id #summernote is defined
-  // here at client/components/main/editor.jade where it previously was
-  // id=id, now it is id="summernote".
   textarea.editor(
     dir="auto"
     class="{{class}}"
-    id="summernote"
+    id=id
     autofocus=autofocus
     placeholder="{{_ 'comment-placeholder'}}")
     +Template.contentBlock

+ 19 - 47
client/components/main/editor.js

@@ -30,7 +30,7 @@ Template.editor.onRendered(() => {
     autosize($textarea);
     $textarea.escapeableTextComplete(mentions);
   };
-  if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR === 'true') {
+  if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR !== false) {
     const isSmall = Utils.isMiniScreen();
     const toolbar = isSmall
       ? [
@@ -108,45 +108,17 @@ Template.editor.onRendered(() => {
         }
         return undefined;
       };
-      // Prevent @member mentions on Add Comment input field
-      // from closing card, part 1.
-      let popupShown = false;
       inputs.each(function(idx, input) {
         mSummernotes[idx] = $(input).summernote({
           placeholder,
-          // Prevent @member mentions on Add Comment input field
-          // from closing card, part 2.
-          onKeydown(e) {
-            if (popupShown) {
-              e.preventDefault();
-            }
-          },
-          onKeyup(e) {
-            if (popupShown) {
-              e.preventDefault();
-            }
-          },
           callbacks: {
-            // Prevent @member mentions on Add Comment input field
-            // from closing card, part 3.
-            onKeydown(e) {
-              if (popupShown) {
-                e.preventDefault();
-              }
-            },
-            onKeyup(e) {
-              if (popupShown) {
-                e.preventDefault();
-              }
-            },
             onInit(object) {
               const originalInput = this;
-              $(originalInput).on('input', function() {
+              $(originalInput).on('submitted', function() {
                 // when comment is submitted, the original textarea will be set to '', so shall we
                 if (!this.value) {
                   const sn = getSummernote(this);
-                  sn && sn.summernote('reset');
-                  object && object.editingArea.find('.note-placeholder').show();
+                  sn && sn.summernote('code', '');
                 }
               });
               const jEditor = object && object.editable;
@@ -163,6 +135,7 @@ Template.editor.onRendered(() => {
                 });
               }
             },
+
             onImageUpload(files) {
               const $summernote = getSummernote(this);
               if (files && files.length > 0) {
@@ -249,7 +222,7 @@ Template.editor.onRendered(() => {
                 // == Fix End ==
                 const original = someNote.summernote('code');
                 const cleaned = cleanPastedHTML(original); //this is where to call whatever clean function you want. I have mine in a different file, called CleanPastedHTML.
-                someNote.summernote('reset'); //clear original
+                someNote.summernote('code', ''); //clear original
                 someNote.summernote('pasteHTML', cleaned); //this sets the displayed content editor to the cleaned pasted code.
               };
               setTimeout(function() {
@@ -316,15 +289,15 @@ Blaze.Template.registerHelper(
 
     let currentMention;
     while ((currentMention = mentionRegex.exec(content)) !== null) {
-      const [fullMention, username] = currentMention;
+      const [fullMention, quoteduser, simple] = currentMention;
+      const username = quoteduser || simple;
       const knowedUser = _.findWhere(knowedUsers, { username });
       if (!knowedUser) {
         continue;
       }
 
       const linkValue = [' ', at, knowedUser.username];
-      //let linkClass = 'atMention js-open-member';
-      let linkClass = 'atMention';
+      let linkClass = 'atMention js-open-member';
       if (knowedUser.userId === Meteor.userId()) {
         linkClass += ' me';
       }
@@ -357,25 +330,24 @@ Template.viewer.events({
   // the corresponding text). Clicking a link shouldn't fire these actions, stop
   // we stop these event at the viewer component level.
   'click a'(event, templateInstance) {
-    event.stopPropagation();
-
-    // XXX We hijack the build-in browser action because we currently don't have
-    // `_blank` attributes in viewer links, and the transformer function is
-    // handled by a third party package that we can't configure easily. Fix that
-    // by using directly `_blank` attribute in the rendered HTML.
-    event.preventDefault();
-
+    let prevent = true;
     const userId = event.currentTarget.dataset.userid;
     if (userId) {
-      // Prevent @member mentions on Add Comment input field
-      // from closing card, part 4.
-      PopupNoClose.open('member').call({ userId }, event, templateInstance);
-      event.preventDefault();
+      Popup.open('member').call({ userId }, event, templateInstance);
     } else {
       const href = event.currentTarget.href;
       if (href) {
         window.open(href, '_blank');
       }
     }
+    if (prevent) {
+      event.stopPropagation();
+
+      // XXX We hijack the build-in browser action because we currently don't have
+      // `_blank` attributes in viewer links, and the transformer function is
+      // handled by a third party package that we can't configure easily. Fix that
+      // by using directly `_blank` attribute in the rendered HTML.
+      event.preventDefault();
+    }
   },
 });

+ 2 - 0
client/components/main/header.jade

@@ -35,6 +35,8 @@ template(name="header")
       a#header-new-board-icon.js-create-board
         i.fa.fa-plus(title="Create a new board")
 
+      +notifications
+
       +headerUserBar
 
   #header(class=currentBoard.colorClass)

+ 1 - 1
client/components/main/header.styl

@@ -99,7 +99,7 @@
   height: 28px
   font-size: 12px
   display: flex
-  z-index: 17
+  z-index: 21
 
   #header-user-bar,
   #header-new-board-icon,

+ 10 - 0
client/components/notifications/notification.jade

@@ -0,0 +1,10 @@
+template(name='notification')
+  li.notification(class="{{#if read}}read{{/if}}")
+    .read-status
+      .materialCheckBox(class="{{#if read}}is-checked{{/if}}")
+      +notificationIcon(activityData)
+    .details
+      +activity(activity=activityData mode='none')
+    if read
+      .remove
+        a.fa.fa-trash

+ 28 - 0
client/components/notifications/notification.js

@@ -0,0 +1,28 @@
+Template.notification.events({
+  'click .read-status .materialCheckBox'() {
+    const update = {};
+    update[`profile.notifications.${this.index}.read`] = this.read
+      ? null
+      : Date.now();
+    Users.update(Meteor.userId(), { $set: update });
+  },
+  'click .remove a'() {
+    Meteor.user().removeNotification(this.activityData._id);
+  },
+});
+
+Template.notification.helpers({
+  mode: 'board',
+  isOfActivityType(activityId, type) {
+    const activity = Activities.findOne(activityId);
+    return activity && activity.activityType === type;
+  },
+  activityType(activityId) {
+    const activity = Activities.findOne(activityId);
+    return activity ? activity.activityType : '';
+  },
+  activityUser(activityId) {
+    const activity = Activities.findOne(activityId);
+    return activity && activity.userId;
+  },
+});

+ 57 - 0
client/components/notifications/notification.styl

@@ -0,0 +1,57 @@
+#notifications-drawer
+  &.show-read .notification.read
+    display: flex
+
+  .notification
+    display: flex
+    float: none
+    padding: 12px 8px 8px
+    color: black
+    border-bottom: 1px solid #dbdbdb
+
+    &.read
+      display: none
+
+    .read-status
+      width: 30px
+
+      input
+        width: 24px
+        height: 24px
+
+      .activity-type
+        margin: 16px 0 0
+        width: 17px
+        height: 17px
+        font-size: 17px
+        display: block
+        color: #bbb
+
+    .details
+      width: calc(100% - 30px)
+
+      .activity
+        display: flex
+
+        .activity-desc
+          width: 100%;
+
+        .activity-comment
+          display: block
+          width: 100%
+          border-radius: 3px
+          background: #fff
+          text-decoration: none
+          box-shadow: 0 1px 2px rgba(0,0,0,0.2)
+          margin-top: 5px
+          padding: 5px
+
+        .activity-meta
+          display: block
+          font-size: 0.8em
+          color: #999
+          font-style: italic
+
+    .remove
+      a:hover
+        color #eb4646 !important

+ 53 - 0
client/components/notifications/notificationIcon.jade

@@ -0,0 +1,53 @@
+template(name='notificationIcon')
+  if($in activityType 'deleteAttachment' 'addAttachment')
+    i.fa.fa-paperclip.activity-type(title="attachment")
+  else if($in activityType 'createBoard' 'importBoard')
+    i.fa.fa-chalkboard.activity-type(title="board")
+
+  else if($in activityType 'createCard' 'importCard' 'moveCard')
+    +cardNotificationIcon
+  else if($in activityType 'moveCardBoard' 'archivedCard' 'restoredCard')
+    +cardNotificationIcon
+    //- $in can only handle up to 3 cases so we have to break this case over 2 cases... use a simple template to keep it
+    //- DRY and consistant
+
+  else if($in activityType 'addChecklist' 'removedChecklist' 'completeChecklist')
+    +checklistNotificationIcon
+  else if($in activityType 'uncompleteChecklist')
+    +checklistNotificationIcon
+    //- $in can only handle up to 3 cases so we have to break this case over 2 cases... use a simple template to keep it
+    //- DRY and consistant
+
+  else if($in activityType 'checkedItem' 'uncheckedItem' 'addChecklistItem' 'removedChecklistItem')
+    i.fa.fa-check-square.activity-type(title="checklist item")
+  else if($in activityType 'addComment')
+    i.fa.fa-comment-o.activity-type(title="comment")
+  else if($in activityType 'createCustomField' 'setCustomField' 'unsetCustomField')
+    i.fa.fa-code.activity-type(title="custom field")
+  else if($in activityType 'addedLabel' 'removedLabel')
+    i.fa.fa-tag.activity-type(title="label")
+
+  else if($in activityType 'createList' 'removeList' 'archivedList')
+    +listNotificationIcon
+  else if($in activityType  'importList')
+    +listNotificationIcon
+    //- $in can only handle up to 3 cases so we have to break this case over 2 cases... use a simple template to keep it
+    //- DRY and consistant
+
+    //- elswhere in the app we use fa-trello to indicate lists...
+    //- i personally like fa-columns a bit better
+  else if($in activityType 'unjoinMember' 'addBoardMember' 'joinMember' 'removeBoardMember')
+    i.fa.fa-user.activity-type(title="member")
+  else if($in activityType 'createSwimlane' 'archivedSwimlane')
+    i.fa.fa-th-large.activity-type(title="swimlane")
+  else
+    i.fa.fa-bug.activity-type(title="can't find icon for #{activityType}")
+
+template(name='cardNotificationIcon')
+  i.fa.fa-clone.activity-type(title="card")
+
+template(name='checklistNotificationIcon')
+  i.fa.fa-list.activity-type(title="checklist")
+
+template(name='listNotificationIcon')
+  i.fa.fa-columns.activity-type(title="list")

+ 5 - 0
client/components/notifications/notifications.jade

@@ -0,0 +1,5 @@
+template(name='notifications')
+  #notifications.board-header-btns.right
+    a.notifications-drawer-toggle.fa.fa-bell(class="{{#if $gt unreadNotifications 0}}alert{{/if}}")
+    if $.Session.get 'showNotificationsDrawer'
+      +notificationsDrawer(unreadNotifications=unreadNotifications)

+ 32 - 0
client/components/notifications/notifications.js

@@ -0,0 +1,32 @@
+// this hides the notifications drawer if anyone clicks off of the panel
+Template.body.events({
+  click(event) {
+    if (
+      !$(event.target).is('#notifications *') &&
+      Session.get('showNotificationsDrawer')
+    ) {
+      toggleNotificationsDrawer();
+    }
+  },
+});
+
+Template.notifications.helpers({
+  unreadNotifications() {
+    const notifications = Users.findOne(Meteor.userId()).notifications();
+    const unreadNotifications = _.filter(notifications, v => !v.read);
+    return unreadNotifications.length;
+  },
+});
+
+Template.notifications.events({
+  'click .notifications-drawer-toggle'() {
+    toggleNotificationsDrawer();
+  },
+});
+
+export function toggleNotificationsDrawer() {
+  Session.set(
+    'showNotificationsDrawer',
+    !Session.get('showNotificationsDrawer'),
+  );
+}

+ 17 - 0
client/components/notifications/notifications.styl

@@ -0,0 +1,17 @@
+#notifications
+  position: relative
+
+  .notifications-drawer-toggle
+    display: block
+    line-height: 28px
+    color: #f2f2f2
+    margin: 0 10px
+    width: 28px
+    height: 28px
+    text-align: center
+    border: 0
+    padding: 0
+
+    &.alert
+      background-color: #eb4646;
+

+ 16 - 0
client/components/notifications/notificationsDrawer.jade

@@ -0,0 +1,16 @@
+template(name='notificationsDrawer')
+  section#notifications-drawer(class="{{#if $.Session.get 'showReadNotifications'}}show-read{{/if}}")
+    .header
+      if $.Session.get 'showReadNotifications'
+        a.toggle-read {{_ 'filter-by-unread'}}
+      else
+        a.toggle-read {{_ 'view-all'}}
+      h5 {{_ 'notifications'}}
+        if($gt unreadNotifications 0)
+          |(#{unreadNotifications})
+      a.fa.fa-times-thin.close
+    ul.notifications
+      each transformedProfile.notifications
+        +notification(activityData=activity index=dbIndex read=read)
+    if($gt unreadNotifications 0)
+      a.all-read {{_ 'mark-all-as-read'}}

+ 38 - 0
client/components/notifications/notificationsDrawer.js

@@ -0,0 +1,38 @@
+import { toggleNotificationsDrawer } from './notifications.js';
+
+Template.notificationsDrawer.onCreated(function() {
+  Meteor.subscribe('notificationActivities');
+  Meteor.subscribe('notificationCards');
+  Meteor.subscribe('notificationUsers');
+  Meteor.subscribe('notificationsAttachments');
+  Meteor.subscribe('notificationChecklistItems');
+  Meteor.subscribe('notificationChecklists');
+  Meteor.subscribe('notificationComments');
+  Meteor.subscribe('notificationLists');
+  Meteor.subscribe('notificationSwimlanes');
+});
+
+Template.notificationsDrawer.helpers({
+  transformedProfile() {
+    return Users.findOne(Meteor.userId());
+  },
+});
+
+Template.notificationsDrawer.events({
+  'click .all-read'() {
+    const notifications = Meteor.user().profile.notifications;
+    for (const index in notifications) {
+      if (notifications.hasOwnProperty(index) && !notifications[index].read) {
+        const update = {};
+        update[`profile.notifications.${index}.read`] = Date.now();
+        Users.update(Meteor.userId(), { $set: update });
+      }
+    }
+  },
+  'click .close'() {
+    toggleNotificationsDrawer();
+  },
+  'click .toggle-read'() {
+    Session.set('showReadNotifications', !Session.get('showReadNotifications'));
+  },
+});

+ 57 - 0
client/components/notifications/notificationsDrawer.styl

@@ -0,0 +1,57 @@
+belize = #2980b9
+
+section#notifications-drawer
+  position: fixed
+  top: 28px
+  right: 0
+  width: 400px
+  background-color: #fafafa
+  box-shadow: 0 1px 2px rgba(0,0,0,0.15)
+  border-radius: 2px
+  max-height: calc(100vh - 28px - 36px)
+  color: black
+  padding-top 36px;
+  overflow: scroll
+
+  a:hover
+    color: belize !important
+
+  .header
+    position: fixed
+    top 28px
+    right 0
+    width calc(400px - 32px)
+    padding: 8px 16px
+    background: #ededed
+    border-bottom: 1px solid #dbdbdb
+    z-index 2
+
+    .toggle-read
+      position absolute
+      left 16px
+      top calc(50% - 8px)
+      color belize
+
+    h5
+      text-align: center
+      margin: 0
+
+    .close
+      position: absolute
+      top: calc(50% - 12px)
+      right: 12px
+      font-size: 24px
+      height: 24px
+      line-height: 24px
+      opacity 1
+
+  .all-read
+    color belize
+    background-color: #fafafa
+    margin 8px 16px 12px
+    display inline-block
+
+  ul.notifications
+    display: block
+    padding: 0px 16px
+    margin: 0

+ 4 - 0
client/components/sidebar/sidebar.jade

@@ -267,6 +267,10 @@ template(name="outgoingWebhooksPopup")
 
 template(name="boardMenuPopup")
   ul.pop-over-list
+    li
+      a.js-open-rules-view(title="{{_ 'rules'}}")
+        i.fa.fa-magic
+        | {{_ 'rules'}}
     li
       a.js-custom-fields
         i.fa.fa-list-alt

+ 4 - 0
client/components/sidebar/sidebar.js

@@ -182,6 +182,10 @@ Template.memberPopup.helpers({
 
 Template.boardMenuPopup.events({
   'click .js-rename-board': Popup.open('boardChangeTitle'),
+  'click .js-open-rules-view'() {
+    Modal.openWide('rulesMain');
+    Popup.close();
+  },
   'click .js-custom-fields'() {
     Sidebar.setView('customFields');
     Popup.close();

+ 0 - 204
client/lib/popup.js

@@ -206,207 +206,3 @@ escapeActions.forEach(actionName => {
     },
   );
 });
-
-// Prevent @member mentions on Add Comment input field
-// from closing card, part 5.
-// This duplicate below of above popup function is needed, because at
-// wekan/components/main/editor.js at bottom is popping up visible
-// @member mention, and it seems to trigger closing also card popup,
-// so in below closing popup is disabled.
-window.PopupNoClose = new (class {
-  constructor() {
-    // The template we use to render popups
-    this.template = Template.popup;
-
-    // We only want to display one popup at a time and we keep the view object
-    // in this `Popup.current` variable. If there is no popup currently opened
-    // the value is `null`.
-    this.current = null;
-
-    // It's possible to open a sub-popup B from a popup A. In that case we keep
-    // the data of popup A so we can return back to it. Every time we open a new
-    // popup the stack grows, every time we go back the stack decrease, and if
-    // we close the popup the stack is reseted to the empty stack [].
-    this._stack = [];
-
-    // We invalidate this internal dependency every time the top of the stack
-    // has changed and we want to re-render a popup with the new top-stack data.
-    this._dep = new Tracker.Dependency();
-  }
-
-  /// This function returns a callback that can be used in an event map:
-  ///   Template.tplName.events({
-  ///     'click .elementClass': Popup.open("popupName"),
-  ///   });
-  /// The popup inherit the data context of its parent.
-  open(name) {
-    const self = this;
-    const popupName = `${name}Popup`;
-    function clickFromPopup(evt) {
-      return $(evt.target).closest('.js-pop-over').length !== 0;
-    }
-    return function(evt) {
-      // If a popup is already opened, clicking again on the opener element
-      // should close it -- and interrupt the current `open` function.
-      /*
-      if (self.isOpen()) {
-        const previousOpenerElement = self._getTopStack().openerElement;
-        if (previousOpenerElement === evt.currentTarget) {
-          self.close();
-          return;
-        } else {
-          $(previousOpenerElement).removeClass('is-active');
-        }
-      }
-      */
-      // We determine the `openerElement` (the DOM element that is being clicked
-      // and the one we take in reference to position the popup) from the event
-      // if the popup has no parent, or from the parent `openerElement` if it
-      // has one. This allows us to position a sub-popup exactly at the same
-      // position than its parent.
-      let openerElement;
-      if (clickFromPopup(evt)) {
-        openerElement = self._getTopStack().openerElement;
-      } else {
-        self._stack = [];
-        openerElement = evt.currentTarget;
-      }
-      $(openerElement).addClass('is-active');
-      evt.preventDefault();
-
-      // We push our popup data to the stack. The top of the stack is always
-      // used as the data source for our current popup.
-      self._stack.push({
-        popupName,
-        openerElement,
-        hasPopupParent: clickFromPopup(evt),
-        title: self._getTitle(popupName),
-        depth: self._stack.length,
-        offset: self._getOffset(openerElement),
-        dataContext: (this && this.currentData && this.currentData()) || this,
-      });
-
-      // If there are no popup currently opened we use the Blaze API to render
-      // one into the DOM. We use a reactive function as the data parameter that
-      // return the complete along with its top element and depends on our
-      // internal dependency that is being invalidated every time the top
-      // element of the stack has changed and we want to update the popup.
-      //
-      // Otherwise if there is already a popup open we just need to invalidate
-      // our internal dependency, and since we just changed the top element of
-      // our internal stack, the popup will be updated with the new data.
-      if (!self.isOpen()) {
-        self.current = Blaze.renderWithData(
-          self.template,
-          () => {
-            self._dep.depend();
-            return { ...self._getTopStack(), stack: self._stack };
-          },
-          document.body,
-        );
-      } else {
-        self._dep.changed();
-      }
-    };
-  }
-
-  /// This function returns a callback that can be used in an event map:
-  ///   Template.tplName.events({
-  ///     'click .elementClass': Popup.afterConfirm("popupName", function() {
-  ///       // What to do after the user has confirmed the action
-  ///     }),
-  ///   });
-  afterConfirm(name, action) {
-    const self = this;
-
-    return function(evt, tpl) {
-      const context = (this.currentData && this.currentData()) || this;
-      context.__afterConfirmAction = action;
-      self.open(name).call(context, evt, tpl);
-    };
-  }
-
-  /// The public reactive state of the popup.
-  isOpen() {
-    this._dep.changed();
-    return Boolean(this.current);
-  }
-
-  /// In case the popup was opened from a parent popup we can get back to it
-  /// with this `Popup.back()` function. You can go back several steps at once
-  /// by providing a number to this function, e.g. `Popup.back(2)`. In this case
-  /// intermediate popup won't even be rendered on the DOM. If the number of
-  /// steps back is greater than the popup stack size, the popup will be closed.
-  back(n = 1) {
-    if (this._stack.length > n) {
-      _.times(n, () => this._stack.pop());
-      this._dep.changed();
-    }
-    // else {
-    //  this.close();
-    //}
-  }
-
-  /// Close the current opened popup.
-  /*
-  close() {
-    if (this.isOpen()) {
-      Blaze.remove(this.current);
-      this.current = null;
-
-      const openerElement = this._getTopStack().openerElement;
-      $(openerElement).removeClass('is-active');
-
-      this._stack = [];
-    }
-  }
-  */
-
-  getOpenerComponent() {
-    const { openerElement } = Template.parentData(4);
-    return BlazeComponent.getComponentForElement(openerElement);
-  }
-
-  // An utility fonction that returns the top element of the internal stack
-  _getTopStack() {
-    return this._stack[this._stack.length - 1];
-  }
-
-  // We automatically calculate the popup offset from the reference element
-  // position and dimensions. We also reactively use the window dimensions to
-  // ensure that the popup is always visible on the screen.
-  _getOffset(element) {
-    const $element = $(element);
-    return () => {
-      Utils.windowResizeDep.depend();
-
-      if (Utils.isMiniScreen()) return { left: 0, top: 0 };
-
-      const offset = $element.offset();
-      const popupWidth = 300 + 15;
-      return {
-        left: Math.min(offset.left, $(window).width() - popupWidth),
-        top: offset.top + $element.outerHeight(),
-      };
-    };
-  }
-
-  // We get the title from the translation files. Instead of returning the
-  // result, we return a function that compute the result and since `TAPi18n.__`
-  // is a reactive data source, the title will be changed reactively.
-  _getTitle(popupName) {
-    return () => {
-      const translationKey = `${popupName}-title`;
-
-      // XXX There is no public API to check if there is an available
-      // translation for a given key. So we try to translate the key and if the
-      // translation output equals the key input we deduce that no translation
-      // was available and returns `false`. There is a (small) risk a false
-      // positives.
-      const title = TAPi18n.__(translationKey);
-      // when popup showed as full of small screen, we need a default header to clearly see [X] button
-      const defaultTitle = Utils.isMiniScreen() ? '' : false;
-      return title !== translationKey ? title : defaultTitle;
-    };
-  }
-})();

+ 8 - 2
i18n/ar.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "ازالة تحقق %s من قائمة التحقق %s من %s",
   "activity-checklist-added": "أضاف قائمة تحقق إلى %s",
   "activity-checklist-removed": "ازالة قائمة التحقق من %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "لم يتم انجاز قائمة التحقق %s من %s",
   "activity-checklist-item-added": "تم اضافة عنصر قائمة التحقق الى '%s' في %s",
   "activity-checklist-item-removed": "تم ازالة عنصر قائمة التحقق الى '%s' في %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/bg.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "размаркира %s от списък със задачи %s на %s",
   "activity-checklist-added": "добави списък със задачи към %s",
   "activity-checklist-removed": "премахна списък със задачи от %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "\"отзавърши\" чеклистта %s в %s",
   "activity-checklist-item-added": "добави точка към '%s' в/във %s",
   "activity-checklist-item-removed": "премахна точка от '%s' в %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/br.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/ca.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "Checklist afegida a %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "afegida entrada de checklist de '%s' a %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 19 - 13
i18n/cs.i18n.json

@@ -22,8 +22,8 @@
   "act-createBoard": "přidal(a) tablo __board__",
   "act-createSwimlane": "created swimlane __swimlane__ to board __board__",
   "act-createCard": "přidal(a) kartu __card__ do sloupce __list__ ve swimlane __swimlane__ na tablu __board__",
-  "act-createCustomField": "created custom field __customField__ at board __board__",
-  "act-deleteCustomField": "deleted custom field __customField__ at board __board__",
+  "act-createCustomField": "přidal(a) pole __customField__ na tablo __board__",
+  "act-deleteCustomField": "odebral(a) pole __customField__ na tablu __board__",
   "act-setCustomField": "edited custom field __customField__: __customFieldValue__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
   "act-createList": "přidal(a) sloupec __list__ do tabla __board__",
   "act-addBoardMember": "přidal(a) člena __member__ do tabla __board__",
@@ -64,7 +64,7 @@
   "activity-unchecked-item": "nedokončen %s v seznamu %s z %s",
   "activity-checklist-added": "přidán checklist do %s",
   "activity-checklist-removed": "odstraněn checklist z %s",
-  "activity-checklist-completed": "dokončil(a) zaškrtávací seznam __checklist__ na kartě __card__ ve sloupci __list__ ve swimlane __swimlane__ na tablu __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "nedokončen seznam %s z %s",
   "activity-checklist-item-added": "přidána položka checklist do '%s' v %s",
   "activity-checklist-item-removed": "odstraněna položka seznamu do '%s' v %s",
@@ -137,7 +137,7 @@
   "board-view": "Náhled tabla",
   "board-view-cal": "Kalendář",
   "board-view-swimlanes": "Swimlanes",
-  "board-view-collapse": "Collapse",
+  "board-view-collapse": "Sbalit",
   "board-view-lists": "Sloupce",
   "bucket-example": "Například \"O čem sním\"",
   "cancel": "Zrušit",
@@ -320,8 +320,8 @@
   "filter-no-label": "Žádný štítek",
   "filter-no-member": "Žádný člen",
   "filter-no-custom-fields": "Žádné vlastní pole",
-  "filter-show-archive": "Show archived lists",
-  "filter-hide-empty": "Hide empty lists",
+  "filter-show-archive": "Zobrazit archivované listy",
+  "filter-hide-empty": "Skrýt prázdné listy",
   "filter-on": "Filtr je zapnut",
   "filter-on-desc": "Filtrujete karty tohoto tabla. Pro úpravu filtru klikni sem.",
   "filter-to-selection": "Filtrovat výběr",
@@ -749,15 +749,21 @@
   "act-pastdue": "was reminding the current due (__timeValue__) of __card__ is past",
   "act-duenow": "was reminding the current due (__timeValue__) of __card__ is now",
   "act-atUserComment": "You were mentioned in [__board__] __list__/__card__",
-  "delete-user-confirm-popup": "Are you sure you want to delete this account? There is no undo.",
-  "accounts-allowUserDelete": "Allow users to self delete their account",
+  "delete-user-confirm-popup": "Jste si jisti, že chcete smazat tento účet? Tuto akci nelze vrátit zpět.",
+  "accounts-allowUserDelete": "Dovolit uživatelům smazat vlastní účet",
   "hide-minicard-label-text": "Hide minicard label text",
   "show-desktop-drag-handles": "Show desktop drag handles",
   "assignee": "Assignee",
   "cardAssigneesPopup-title": "Assignee",
-  "addmore-detail": "Add a more detailed description",
-  "show-on-card": "Show on Card",
-  "new": "New",
-  "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "addmore-detail": "Přidat detailnější popis",
+  "show-on-card": "Zobrazit na kartě",
+  "new": "Nový",
+  "editUserPopup-title": "Editovat uživatele",
+  "newUserPopup-title": "Nový uživatel",
+  "notifications": "Upozornění",
+  "view-all": "Zobrazit vše",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Označit vše jako přečtené",
+  "allow-rename": "Povolit přejmenování",
+  "allowRenamePopup-title": "Povolit přejmenování"
 }

+ 8 - 2
i18n/da.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/de.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "hat %s in Checkliste %s von %s abgewählt",
   "activity-checklist-added": "hat eine Checkliste zu %s hinzugefügt",
   "activity-checklist-removed": "entfernte eine Checkliste von %s",
-  "activity-checklist-completed": "hat Checkliste __checklist__ der Karte __card__ auf der Liste __list__ in Swimlane __swimlane__ in Board __board__ vervollständigt",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "unvervollständigte die Checkliste %s von %s",
   "activity-checklist-item-added": "hat ein Checklistenelement zu '%s' in %s hinzugefügt",
   "activity-checklist-item-removed": "hat ein Checklistenelement von '%s' in %s entfernt",
@@ -759,5 +759,11 @@
   "show-on-card": "Zeige auf Karte",
   "new": "Neu",
   "editUserPopup-title": "Benutzer ändern",
-  "newUserPopup-title": "Neuer Benutzer"
+  "newUserPopup-title": "Neuer Benutzer",
+  "notifications": "Benachrichtigungen",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/el.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/en-GB.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/en.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -762,5 +762,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/eo.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/es-AR.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "agregada lista de tareas a %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "agregado item de lista de tareas a '%s' en %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/es.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "desmarcado %s en lista  %s de %s",
   "activity-checklist-added": "ha añadido una lista de verificación a %s",
   "activity-checklist-removed": "eliminada una lista de verificación desde %s",
-  "activity-checklist-completed": "completada la lista de verificación __checklist__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "no completado la lista %s de %s",
   "activity-checklist-item-added": "ha añadido el elemento de la lista de verificación a '%s' en %s",
   "activity-checklist-item-removed": "eliminado un elemento de la lista de verificación desde '%s' en %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Mostrar en la tarjeta",
   "new": "Nuevo",
   "editUserPopup-title": "Editar el usuario",
-  "newUserPopup-title": "Nuevo usuario"
+  "newUserPopup-title": "Nuevo usuario",
+  "notifications": "Notificaciones",
+  "view-all": "Ver todo",
+  "filter-by-unread": "Filtrar por no leído",
+  "mark-all-as-read": "Marcar todo como leido",
+  "allow-rename": "Permitir renombrar",
+  "allowRenamePopup-title": "Permitir renombrar"
 }

+ 8 - 2
i18n/eu.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "egiaztaketa zerrenda %s(e)ra gehituta",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "egiaztaketa zerrendako elementuak '%s'(e)ra gehituta %s(e)n",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/fa.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "چک نشده  %s در چک لیست %s از %s",
   "activity-checklist-added": "سیاهه به %s اضافه شد",
   "activity-checklist-removed": "از چک لیست حذف گردید",
-  "activity-checklist-completed": "سیاهه __checklist__ را در کارت __card__ در لیست __list__ در مسیر شناور __swimlane__ در برد __board__ کامل کرد",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "تمام نشده ها در چک لیست %s از %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "حذف شده از چک لیست  '%s' در %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/fi.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "poistettu ruksi %s tarkistuslistassa %s / %s",
   "activity-checklist-added": "lisätty tarkistuslista kortille %s",
   "activity-checklist-removed": "poistettu tarkistuslista kohteesta %s",
-  "activity-checklist-completed": "valmistui tarkistuslista __checklist__ kortilla __card__ listalla __list__ swimlanella __swimlane__ taululla __board__",
+  "activity-checklist-completed": "saatiin valmiiksi tarkistuslista %s / %s",
   "activity-checklist-uncompleted": "ei saatu valmiiksi tarkistuslista %s / %s",
   "activity-checklist-item-added": "lisäsi kohdan tarkistuslistaan '%s' kortilla %s",
   "activity-checklist-item-removed": "poistettu tarkistuslistan kohta '%s' / %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Näytä kortilla",
   "new": "Uusi",
   "editUserPopup-title": "Muokkaa käyttäjää",
-  "newUserPopup-title": "Uusi käyttäjä"
+  "newUserPopup-title": "Uusi käyttäjä",
+  "notifications": "Ilmoitukset",
+  "view-all": "Näytä kaikki",
+  "filter-by-unread": "Suodata lukemattomat",
+  "mark-all-as-read": "Merkkaa kaikki luetuksi",
+  "allow-rename": "Salli uudelleennimeäminen",
+  "allowRenamePopup-title": "Salli uudelleennimeäminen"
 }

+ 8 - 2
i18n/fr.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "a décoché %s dans la checklist %s de %s",
   "activity-checklist-added": "a ajouté une checklist à %s",
   "activity-checklist-removed": "a supprimé une checklist de %s",
-  "activity-checklist-completed": "a complété la checklist __checklist__ de la carte __card__ de la liste __list__ du couloir __swimlane__ du tableau __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "a rendu incomplète la checklist %s de %s",
   "activity-checklist-item-added": "a ajouté un élément à la checklist '%s' dans %s",
   "activity-checklist-item-removed": "a supprimé une checklist de '%s' dans %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Afficher sur la carte",
   "new": "Nouveau",
   "editUserPopup-title": "Éditer l'utilisateur",
-  "newUserPopup-title": "Nouvel utilisateur"
+  "newUserPopup-title": "Nouvel utilisateur",
+  "notifications": "Notifications",
+  "view-all": "Voir tout",
+  "filter-by-unread": "Filtrer par non lu",
+  "mark-all-as-read": "Marquer comme lus",
+  "allow-rename": "Autoriser le renommage",
+  "allowRenamePopup-title": "Autoriser le renommage"
 }

+ 8 - 2
i18n/gl.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/he.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "בוטל הסימון של %s ברשימת המשימות %s מתוך %s",
   "activity-checklist-added": "נוספה רשימת משימות אל %s",
   "activity-checklist-removed": "הוסרה רשימת משימות מ־%s",
-  "activity-checklist-completed": "רשימת המטלות __checklist__ בכרטיס __card__ שברשימה __list__ תחת המסלול __swimlane__ בלוח __board__ הושלמה",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "רשימת המשימות %s מתוך %s סומנה כבלתי מושלמת",
   "activity-checklist-item-added": "נוסף פריט רשימת משימות אל ‚%s‘ תחת %s",
   "activity-checklist-item-removed": "הוסר פריט מרשימת המשימות ‚%s’ תחת %s",
@@ -759,5 +759,11 @@
   "show-on-card": "הצגה על הכרטיס",
   "new": "חדש",
   "editUserPopup-title": "עריכת משתמש",
-  "newUserPopup-title": "משתמש חדש"
+  "newUserPopup-title": "משתמש חדש",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/hi.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "अचिह्नित %s अंदर में चिह्नांकन-सूची %s of %s",
   "activity-checklist-added": "संकलित चिह्नांकन-सूची तक %s",
   "activity-checklist-removed": "हटा दिया एक चिह्नांकन-सूची से %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "अपूर्ण चिह्नांकन-सूची %s of %s",
   "activity-checklist-item-added": "संकलित चिह्नांकन-सूची विषय तक '%s' अंदर में %s",
   "activity-checklist-item-removed": "हटा दिया एक चिह्नांकन-सूची विषय से '%s' अंदर में %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/hu.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "ellenőrzőlista hozzáadva ehhez: %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "ellenőrzőlista elem hozzáadva ehhez: „%s”, ebben: %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/hy.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/id.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "daftar periksa ditambahkan ke %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/ig.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/it.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "disattivato %s nella checklist %s di %s",
   "activity-checklist-added": "aggiunta checklist a %s",
   "activity-checklist-removed": "È stata rimossa una checklist da%s",
-  "activity-checklist-completed": "checklist  __checklist__ completata nella scheda __card__ della lista __list__ della corsia __swimlane__  nella bacheca __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "La checklist non è stata completata",
   "activity-checklist-item-added": "Aggiunto l'elemento checklist a '%s' in %s",
   "activity-checklist-item-removed": "è stato rimosso un elemento della checklist da '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Mostra sulla scheda",
   "new": "Nuovo",
   "editUserPopup-title": "Modifica utente",
-  "newUserPopup-title": "Nuovo utente"
+  "newUserPopup-title": "Nuovo utente",
+  "notifications": "Notifiche",
+  "view-all": "Mostra Tutto",
+  "filter-by-unread": "Filtra per non Letto",
+  "mark-all-as-read": "Segna come letto",
+  "allow-rename": "Consenti Rinomina",
+  "allowRenamePopup-title": "Consenti Rinomina"
 }

+ 8 - 2
i18n/ja.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "チェックが外されました %s チェックリスト %s / %s",
   "activity-checklist-added": "%s にチェックリストを追加しました",
   "activity-checklist-removed": "チェックリストを %s から削除しました",
-  "activity-checklist-completed": "チェックリスト __checklist__ ボード __board__, スイムレーン __swimlane__, リスト __list__, カード __card__ が完了しました",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "チェックリスト %s / %s が未完了になりました",
   "activity-checklist-item-added": "チェックリスト項目を '%s' / %s に追加しました",
   "activity-checklist-item-removed": "'%s' の チェックリスト %s の項目を削除しました",
@@ -759,5 +759,11 @@
   "show-on-card": "カードに表示する項目",
   "new": "新規作成",
   "editUserPopup-title": "ユーザーを編集",
-  "newUserPopup-title": "新規ユーザー"
+  "newUserPopup-title": "新規ユーザー",
+  "notifications": "通知",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/ka.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "დაემატა ჩამონათვალი %s-ს",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "დამატებულია ჩამონათვალის ელემენტები '%s'  %s-ში",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/km.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/ko.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "%s에 체크리스트를 추가함",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "알림",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/lv.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/mk.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "размаркира %s от списък със задачи %s на %s",
   "activity-checklist-added": "добави списък със задачи към %s",
   "activity-checklist-removed": "премахна списък със задачи от %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "\"отзавърши\" чеклистта %s в %s",
   "activity-checklist-item-added": "добави точка към '%s' в/във %s",
   "activity-checklist-item-removed": "премахна точка от '%s' в %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/mn.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/nb.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "la til sjekkliste til %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/nl.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "%s uitgevinkt in checklist %s van %s",
   "activity-checklist-added": "checklist toegevoegd aan %s",
   "activity-checklist-removed": "checklist verwijderd van %s",
-  "activity-checklist-completed": "heeft checklist __checklist__ afgewerkt op kaart __card__ van lijst __list__ in swimlane __swimlane__ op bord __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "checklist %s onafgewerkt van %s",
   "activity-checklist-item-added": "checklist item toegevoegd aan '%s' in '%s'",
   "activity-checklist-item-removed": "checklist item verwijderd van '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Toon op kaart",
   "new": "Nieuw",
   "editUserPopup-title": "Wijzig gebruiker",
-  "newUserPopup-title": "Nieuwe gebruiker"
+  "newUserPopup-title": "Nieuwe gebruiker",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/oc.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "as descroiat %s dins la checklist %s de %s",
   "activity-checklist-added": "as apondut a checklist a %s",
   "activity-checklist-removed": "as tirat la checklist de %s",
-  "activity-checklist-completed": "as acabat la checklist __checklist__ de la carta __card__ de la tièra __list__ del corredor __swimlane__ del tablèu __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "as rendut incomplet la checklist %s de %s",
   "activity-checklist-item-added": "as apondut un element a la checklist '%s' dins %s",
   "activity-checklist-item-removed": "as tirat un element a la checklist '%s' dins %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/pl.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "odznaczono %s w liście zadań %s z %s",
   "activity-checklist-added": "dodał(a) listę zadań do %s",
   "activity-checklist-removed": "usunął listę zadań z %s",
-  "activity-checklist-completed": "wykonał(a) wszystkie zadania z listy __checklist__ na karcie __card__ na liście __list__ na diagramie czynności __swimlane__ na tablicy __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "nieukończono listy zadań %s z %s",
   "activity-checklist-item-added": "dodał(a) zadanie '%s' do %s",
   "activity-checklist-item-removed": "usunął element z listy zadań '%s' w %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Pokaż na karcie",
   "new": "Nowy",
   "editUserPopup-title": "Edytuj użytkownika",
-  "newUserPopup-title": "Nowy użytkownik"
+  "newUserPopup-title": "Nowy użytkownik",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 9 - 3
i18n/pt-BR.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "desmarcado %s na lista de verificação %s de %s",
   "activity-checklist-added": "Adicionada lista de verificação a %s",
   "activity-checklist-removed": "removida a lista de verificação de %s",
-  "activity-checklist-completed": "completada a lista de verificação __checklist__ no cartão __card__ na lista __list__ em raia __swimlane__ no quadro __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "não-completada a lista de verificação %s de %s",
   "activity-checklist-item-added": "adicionado o item de lista de verificação para '%s' em %s",
   "activity-checklist-item-removed": "removida o item de lista de verificação de '%s' na %s",
@@ -182,7 +182,7 @@
   "changeLanguagePopup-title": "Alterar Idioma",
   "changePasswordPopup-title": "Alterar Senha",
   "changePermissionsPopup-title": "Alterar Permissões",
-  "changeSettingsPopup-title": "Altera configurações",
+  "changeSettingsPopup-title": "Alterar configurações",
   "subtasks": "Subtarefas",
   "checklists": "Listas de verificação",
   "click-to-star": "Marcar quadro como favorito.",
@@ -759,5 +759,11 @@
   "show-on-card": "Mostrar no Cartão",
   "new": "Novo",
   "editUserPopup-title": "Editar usuário",
-  "newUserPopup-title": "Novo usuário"
+  "newUserPopup-title": "Novo usuário",
+  "notifications": "Notificações",
+  "view-all": "Ver tudo",
+  "filter-by-unread": "Filtrar não lidas",
+  "mark-all-as-read": "Marcar todas como lidas",
+  "allow-rename": "Permitir renomear",
+  "allowRenamePopup-title": "Permitir renomear"
 }

+ 8 - 2
i18n/pt.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "desmarcou %s na lista de verificação %s de %s",
   "activity-checklist-added": "adicionou a lista de verificação a %s",
   "activity-checklist-removed": "removeu a lista de verificação de %s",
-  "activity-checklist-completed": "completou a lista de verificação __checklist__ no cartão __card__ na lista __list__ na pista __swimlane__ no quadro __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "descompletou a lista de verificação %s de %s",
   "activity-checklist-item-added": "adicionou o item a '%s' em %s",
   "activity-checklist-item-removed": "removeu o item de '%s' na %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/ro.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/ru.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "снял %s в контрольном списке %s в %s",
   "activity-checklist-added": "добавил контрольный список в %s",
   "activity-checklist-removed": "удалил контрольный список из %s",
-  "activity-checklist-completed": "завершил контрольный список __checklist__ в карточке __card__ в списке __list__ на дорожке __swimlane__ доски __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "вновь открыл контрольный список %s в %s",
   "activity-checklist-item-added": "добавил пункт в контрольный список '%s' в карточке %s",
   "activity-checklist-item-removed": "удалил пункт из контрольного списка '%s' в карточке %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Показать на карточке",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Уведомления",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/sl.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "odkljukal %s na kontrolnem seznamu %s od %s",
   "activity-checklist-added": "dodal kontrolni seznam na %s",
   "activity-checklist-removed": "odstranil kontrolni seznam iz %s",
-  "activity-checklist-completed": "dokončal kontrolni seznam __checklist__ na kartici __card__ na seznamu __list__ na plavalni stezi __swimlane__ na tabli __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "nedokončal kontrolni seznam %s od %s",
   "activity-checklist-item-added": "dodal postavko kontrolnega seznama na '%s' v %s",
   "activity-checklist-item-removed": "odstranil postavko kontrolnega seznama iz '%s' v %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Prikaži na kartici",
   "new": "Novo",
   "editUserPopup-title": "Uredi uporabnika",
-  "newUserPopup-title": "Nov uporabnik"
+  "newUserPopup-title": "Nov uporabnik",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 10 - 4
i18n/sr.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "lista je dodata u %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -757,7 +757,13 @@
   "cardAssigneesPopup-title": "Asignat",
   "addmore-detail": "Dodaj detaljaniji opis",
   "show-on-card": "Prikaži na kartici",
-  "new": "New",
-  "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "new": "Novo",
+  "editUserPopup-title": "Uredi korisnika",
+  "newUserPopup-title": "Novi korisnik",
+  "notifications": "Obaveštenja",
+  "view-all": "Prikaži sve",
+  "filter-by-unread": "Filtriraj nepročitano",
+  "mark-all-as-read": "Označi sve kao pročitano",
+  "allow-rename": "Dozvoli preimenovanje",
+  "allowRenamePopup-title": "Dozvoli preimenovanje"
 }

+ 8 - 2
i18n/sv.i18n.json

@@ -64,7 +64,7 @@
   "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": "slutförde checklista __checklist__ i kort __card__ i lista __list__ i  simbana __swimlane__ på anslagstavla __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "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",
@@ -759,5 +759,11 @@
   "show-on-card": "Visa på kort",
   "new": "Ny",
   "editUserPopup-title": "Redigera användare",
-  "newUserPopup-title": "Ny användare"
+  "newUserPopup-title": "Ny användare",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/sw.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/ta.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/th.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "รายการถูกเพิ่มไป %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/tr.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "%s içine yapılacak listesi ekledi",
   "activity-checklist-removed": "%s Tarafından yapılacaklar listesi silinmiştir",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "%s içinde %s yapılacak listesine öğe ekledi",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Bildirim",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/uk.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "Додано контрольний список до %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/vi.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "đã thêm checklist vào %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/zh-CN.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "未勾选 %s  于清单 %s 共 %s",
   "activity-checklist-added": "已经将清单添加到 %s",
   "activity-checklist-removed": "已从%s移除待办清单",
-  "activity-checklist-completed": "完成检查列表__checklist__ 卡片 __card__ 列表 __list__ 泳道  __swimlane__ 看板 __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "未完成清单 %s 共 %s",
   "activity-checklist-item-added": "添加清单项至'%s' 于 %s",
   "activity-checklist-item-removed": "已从 '%s' 于 %s中 移除一个清单项",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "提示",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/zh-HK.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "unchecked %s in checklist %s of %s",
   "activity-checklist-added": "added checklist to %s",
   "activity-checklist-removed": "removed a checklist from %s",
-  "activity-checklist-completed": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "uncompleted the checklist %s of %s",
   "activity-checklist-item-added": "added checklist item to '%s' in %s",
   "activity-checklist-item-removed": "removed a checklist item from '%s' in %s",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 8 - 2
i18n/zh-TW.i18n.json

@@ -64,7 +64,7 @@
   "activity-unchecked-item": "未勾選 %s  於清單 %s 共 %s",
   "activity-checklist-added": "已新增待辦清單 %s",
   "activity-checklist-removed": "已刪除%s的待辦清單",
-  "activity-checklist-completed": "完成檢查清單__checklist__ 卡片 __card__ 清單 __list__ 泳道  __swimlane__ 看板 __board__",
+  "activity-checklist-completed": "completed checklist %s of %s",
   "activity-checklist-uncompleted": "未完成清單 %s 共 %s",
   "activity-checklist-item-added": "新增待辦清單項目從 %s 到 %s",
   "activity-checklist-item-removed": "已從 '%s' 於 %s中 移除一個清單項",
@@ -759,5 +759,11 @@
   "show-on-card": "Show on Card",
   "new": "New",
   "editUserPopup-title": "Edit User",
-  "newUserPopup-title": "New User"
+  "newUserPopup-title": "New User",
+  "notifications": "Notifications",
+  "view-all": "View All",
+  "filter-by-unread": "Filter by Unread",
+  "mark-all-as-read": "Mark all as read",
+  "allow-rename": "Allow Rename",
+  "allowRenamePopup-title": "Allow Rename"
 }

+ 6 - 6
models/attachments.js

@@ -219,6 +219,9 @@ if (Meteor.isServer) {
         type: 'card',
         activityType: 'addAttachment',
         attachmentId: doc._id,
+        // this preserves the name so that notifications can be meaningful after
+        // this file is removed
+        attachmentName: doc.original.name,
         boardId: doc.boardId,
         cardId: doc.cardId,
         listId: doc.listId,
@@ -246,18 +249,15 @@ if (Meteor.isServer) {
       type: 'card',
       activityType: 'deleteAttachment',
       attachmentId: doc._id,
+      // this preserves the name so that notifications can be meaningful after
+      // this file is removed
+      attachmentName: doc.original.name,
       boardId: doc.boardId,
       cardId: doc.cardId,
       listId: doc.listId,
       swimlaneId: doc.swimlaneId,
     });
   });
-
-  Attachments.files.after.remove((userId, doc) => {
-    Activities.remove({
-      attachmentId: doc._id,
-    });
-  });
 }
 
 export default Attachments;

+ 6 - 0
models/lists.js

@@ -369,6 +369,9 @@ if (Meteor.isServer) {
       activityType: 'createList',
       boardId: doc.boardId,
       listId: doc._id,
+      // this preserves the name so that the activity can be useful after the
+      // list is deleted
+      title: doc.title,
     });
   });
 
@@ -397,6 +400,9 @@ if (Meteor.isServer) {
         activityType: 'archivedList',
         listId: doc._id,
         boardId: doc.boardId,
+        // this preserves the name so that the activity can be useful after the
+        // list is deleted
+        title: doc.title,
       });
     }
   });

+ 30 - 3
models/users.js

@@ -165,7 +165,20 @@ Users.attachSchema(
       /**
        * enabled notifications for the user
        */
-      type: [String],
+      type: [Object],
+      optional: true,
+    },
+    'profile.notifications.$.activity': {
+      /**
+       * The id of the activity this notification references
+       */
+      type: String,
+    },
+    'profile.notifications.$.read': {
+      /**
+       * the date on which this notification was read
+       */
+      type: Date,
       optional: true,
     },
     'profile.showCardsCountAt': {
@@ -429,6 +442,20 @@ Users.helpers({
     return _.contains(notifications, activityId);
   },
 
+  notifications() {
+    const { notifications = [] } = this.profile || {};
+    for (const index in notifications) {
+      if (!notifications.hasOwnProperty(index)) continue;
+      const notification = notifications[index];
+      // this preserves their db sort order for editing
+      notification.dbIndex = index;
+      notification.activity = Activities.findOne(notification.activity);
+    }
+    // this sorts them newest to oldest to match Trello's behavior
+    notifications.reverse();
+    return notifications;
+  },
+
   hasShowDesktopDragHandles() {
     const profile = this.profile || {};
     return profile.showDesktopDragHandles || false;
@@ -573,7 +600,7 @@ Users.mutations({
   addNotification(activityId) {
     return {
       $addToSet: {
-        'profile.notifications': activityId,
+        'profile.notifications': { activity: activityId },
       },
     };
   },
@@ -581,7 +608,7 @@ Users.mutations({
   removeNotification(activityId) {
     return {
       $pull: {
-        'profile.notifications': activityId,
+        'profile.notifications': { activity: activityId },
       },
     };
   },

+ 1 - 1
package-lock.json

@@ -1,6 +1,6 @@
 {
   "name": "wekan",
-  "version": "v3.86.0",
+  "version": "v3.88.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "wekan",
-  "version": "v3.86.0",
+  "version": "v3.88.0",
   "description": "Open-Source kanban",
   "private": true,
   "scripts": {

+ 29 - 15
public/api/wekan.html

@@ -1524,7 +1524,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
 	  	<ul class="toc-list-h1">
         
           <li>
-            <a href="#wekan-rest-api" class="toc-h1 toc-link" data-title="Wekan REST API v3.86">Wekan REST API v3.86</a>
+            <a href="#wekan-rest-api" class="toc-h1 toc-link" data-title="Wekan REST API v3.88">Wekan REST API v3.88</a>
             
           </li>
         
@@ -2017,7 +2017,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
     <div class="page-wrapper">
       <div class="dark-box"></div>
       <div class="content">
-        <h1 id="wekan-rest-api">Wekan REST API v3.86</h1>
+        <h1 id="wekan-rest-api">Wekan REST API v3.88</h1>
 <blockquote>
 <p>Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.</p>
 </blockquote>
@@ -11665,9 +11665,9 @@ System.out.println(response.toString());
       <span class="hljs-string">"string"</span>
     ],
     <span class="hljs-attr">"language"</span>: <span class="hljs-string">"string"</span>,
-    <span class="hljs-attr">"notifications"</span>: [
-      <span class="hljs-string">"string"</span>
-    ],
+    <span class="hljs-attr">"notifications"</span>: [],
+    <span class="hljs-attr">"activity"</span>: <span class="hljs-string">"string"</span>,
+    <span class="hljs-attr">"read"</span>: <span class="hljs-string">"string"</span>,
     <span class="hljs-attr">"showCardsCountAt"</span>: <span class="hljs-number">0</span>,
     <span class="hljs-attr">"starredBoards"</span>: [
       <span class="hljs-string">"string"</span>
@@ -12320,9 +12320,9 @@ System.out.println(response.toString());
       <span class="hljs-string">"string"</span>
     ],
     <span class="hljs-attr">"language"</span>: <span class="hljs-string">"string"</span>,
-    <span class="hljs-attr">"notifications"</span>: [
-      <span class="hljs-string">"string"</span>
-    ],
+    <span class="hljs-attr">"notifications"</span>: [],
+    <span class="hljs-attr">"activity"</span>: <span class="hljs-string">"string"</span>,
+    <span class="hljs-attr">"read"</span>: <span class="hljs-string">"string"</span>,
     <span class="hljs-attr">"showCardsCountAt"</span>: <span class="hljs-number">0</span>,
     <span class="hljs-attr">"starredBoards"</span>: [
       <span class="hljs-string">"string"</span>
@@ -15625,9 +15625,9 @@ UserSecurity
       <span class="hljs-string">"string"</span>
     ],
     <span class="hljs-attr">"language"</span>: <span class="hljs-string">"string"</span>,
-    <span class="hljs-attr">"notifications"</span>: [
-      <span class="hljs-string">"string"</span>
-    ],
+    <span class="hljs-attr">"notifications"</span>: [],
+    <span class="hljs-attr">"activity"</span>: <span class="hljs-string">"string"</span>,
+    <span class="hljs-attr">"read"</span>: <span class="hljs-string">"string"</span>,
     <span class="hljs-attr">"showCardsCountAt"</span>: <span class="hljs-number">0</span>,
     <span class="hljs-attr">"starredBoards"</span>: [
       <span class="hljs-string">"string"</span>
@@ -15793,9 +15793,9 @@ UserSecurity
     <span class="hljs-string">"string"</span>
   ],
   <span class="hljs-attr">"language"</span>: <span class="hljs-string">"string"</span>,
-  <span class="hljs-attr">"notifications"</span>: [
-    <span class="hljs-string">"string"</span>
-  ],
+  <span class="hljs-attr">"notifications"</span>: [],
+  <span class="hljs-attr">"activity"</span>: <span class="hljs-string">"string"</span>,
+  <span class="hljs-attr">"read"</span>: <span class="hljs-string">"string"</span>,
   <span class="hljs-attr">"showCardsCountAt"</span>: <span class="hljs-number">0</span>,
   <span class="hljs-attr">"starredBoards"</span>: [
     <span class="hljs-string">"string"</span>
@@ -15887,12 +15887,26 @@ UserSecurity
 </tr>
 <tr>
 <td>notifications</td>
-<td>[string]</td>
+<td>[<a href="#schemausersprofilenotifications">UsersProfileNotifications</a>]</td>
 <td>false</td>
 <td>none</td>
 <td>enabled notifications for the user</td>
 </tr>
 <tr>
+<td>activity</td>
+<td>string</td>
+<td>true</td>
+<td>none</td>
+<td>The id of the activity this notification references</td>
+</tr>
+<tr>
+<td>read</td>
+<td>string</td>
+<td>false</td>
+<td>none</td>
+<td>the date on which this notification was read</td>
+</tr>
+<tr>
 <td>showCardsCountAt</td>
 <td>number</td>
 <td>false</td>

+ 11 - 3
public/api/wekan.yml

@@ -1,7 +1,7 @@
 swagger: '2.0'
 info:
   title: Wekan REST API
-  version: v3.86
+  version: v3.88
   description: |
     The REST API allows you to control and extend Wekan with ease.
 
@@ -3025,8 +3025,15 @@ definitions:
            enabled notifications for the user
         type: array
         items:
-          type: string
-          x-nullable: true
+          $ref: "#/definitions/UsersProfileNotifications"
+      activity:
+        description: |
+           The id of the activity this notification references
+        type: string
+      read:
+        description: |
+           the date on which this notification was read
+        type: string
       showCardsCountAt:
         description: |
            showCardCountAt field of the user
@@ -3078,6 +3085,7 @@ definitions:
            Reference to the board templates swimlane Id
         type: string
     required:
+      - activity
       - templatesBoardId
       - cardTemplatesSwimlaneId
       - listTemplatesSwimlaneId

+ 2 - 2
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 = 386,
+    appVersion = 388,
     # Increment this for every release.
 
-    appMarketingVersion = (defaultText = "3.86.0~2020-03-24"),
+    appMarketingVersion = (defaultText = "3.88.0~2020-04-02"),
     # Human-readable presentation of the app version.
 
     minUpgradableAppVersion = 0,

+ 3 - 7
server/notifications/profile.js

@@ -1,9 +1,5 @@
 Meteor.startup(() => {
-  // XXX: add activity id to profile.notifications,
-  // it can be displayed and rendered on web or mobile UI
-  // will uncomment the following code once UI implemented
-  //
-  // Notifications.subscribe('profile', (user, title, description, params) => {
-  // user.addNotification(params.activityId);
-  // });
+  Notifications.subscribe('profile', (user, title, description, params) => {
+    user.addNotification(params.activityId);
+  });
 });

+ 101 - 0
server/publications/notifications.js

@@ -0,0 +1,101 @@
+// We use these when displaying notifications in the notificationsDrawer
+
+// gets all activities associated with the current user
+Meteor.publish('notificationActivities', () => {
+  return activities();
+});
+
+// gets all attachments associated with activities associated with the current user
+Meteor.publish('notificationAttachments', function() {
+  return Attachments.find({
+    _id: {
+      $in: activities()
+        .map(v => v.attachmentId)
+        .filter(v => !!v),
+    },
+  });
+});
+
+// gets all cards associated with activities associated with the current user
+Meteor.publish('notificationCards', function() {
+  return Cards.find({
+    _id: {
+      $in: activities()
+        .map(v => v.cardId)
+        .filter(v => !!v),
+    },
+  });
+});
+
+// gets all checklistItems associated with activities associated with the current user
+Meteor.publish('notificationChecklistItems', function() {
+  return ChecklistItems.find({
+    _id: {
+      $in: activities()
+        .map(v => v.checklistItemId)
+        .filter(v => !!v),
+    },
+  });
+});
+
+// gets all checklists associated with activities associated with the current user
+Meteor.publish('notificationChecklists', function() {
+  return Checklists.find({
+    _id: {
+      $in: activities()
+        .map(v => v.checklistId)
+        .filter(v => !!v),
+    },
+  });
+});
+
+// gets all comments associated with activities associated with the current user
+Meteor.publish('notificationComments', function() {
+  return CardComments.find({
+    _id: {
+      $in: activities()
+        .map(v => v.commentId)
+        .filter(v => !!v),
+    },
+  });
+});
+
+// gets all lists associated with activities associated with the current user
+Meteor.publish('notificationLists', function() {
+  return Lists.find({
+    _id: {
+      $in: activities()
+        .map(v => v.listId)
+        .filter(v => !!v),
+    },
+  });
+});
+
+// gets all swimlanes associated with activities associated with the current user
+Meteor.publish('notificationSwimlanes', function() {
+  return Swimlanes.find({
+    _id: {
+      $in: activities()
+        .map(v => v.swimlaneId)
+        .filter(v => !!v),
+    },
+  });
+});
+
+// gets all users associated with activities associated with the current user
+Meteor.publish('notificationUsers', function() {
+  return Users.find({
+    _id: {
+      $in: activities()
+        .map(v => v.userId)
+        .filter(v => !!v),
+    },
+  });
+});
+
+function activities() {
+  const notifications = Meteor.user().profile.notifications || [];
+  return Activities.find({
+    _id: { $in: notifications.map(v => v.activity) },
+  });
+}

+ 1 - 1
start-wekan.sh

@@ -7,7 +7,7 @@
       # Debug OIDC OAuth2 etc.
       #export DEBUG=true
       #---------------------------------------------
-      export MONGO_URL='mongodb://127.0.0.1:27018/wekan'
+      export MONGO_URL='mongodb://127.0.0.1:27017/wekan'
       #---------------------------------------------
       # Production: https://example.com/wekan
       # Local: http://localhost:2000