Compare commits

...
371 Commits
Author SHA1 Message Date
Lauri Ojansivu 48c763dbe3 v7.03 2023-08-02 20:27:39 +03:00
Lauri Ojansivu 10a9aef974 Updated translations. 2023-08-02 20:24:03 +03:00
Lauri Ojansivu eecb143977 Updated ChangeLog. 2023-08-02 20:22:33 +03:00
Lauri Ojansivu 767bbc5195 Merge pull request #5049 from cloudron-io/displayAuthenticationMethod-only-refers-to-select
Move authentication UI handling in correct place
2023-08-02 20:13:39 +03:00
Johannes Zellner b107fb0017 Move authentication UI handling in correct place
The connectionMethod component only deals with the authentication method
select input.

Fixes #5048
2023-08-02 18:36:15 +02:00
Lauri Ojansivu a94cc5351f Merge pull request #5047 from Pandetthe/master
Fix return value of edit_custom_field_dropdown_item
2023-08-02 15:26:45 +03:00
Jakub Jurczyk 7865368153 Fix return value of edit_custom_field_dropdown_item 2023-08-02 14:11:47 +02:00
Lauri Ojansivu 1be3a5c918 v7.02 2023-08-02 07:35:51 +03:00
Lauri Ojansivu 10d90046b9 Updated dependencies. 2023-08-02 07:16:41 +03:00
Lauri Ojansivu 16eb499806 Updated translations. 2023-08-02 07:07:50 +03:00
Lauri Ojansivu ef39dfc051 Updated ChangeLog. 2023-08-02 07:04:25 +03:00
Lauri Ojansivu 9f6e6bdc81 Upgrade to Node.js 14.21.4 at build scripts and remaining Docker containers.
Thanks to Meteor and xet7 !
2023-08-02 06:58:45 +03:00
Lauri Ojansivu a60102f6c6 Updated ChangeLog. 2023-08-02 06:10:43 +03:00
Lauri Ojansivu f0620ce880 Upgrade WeKan StackSmith to Node.js 14.21.4 .
Thanks to Meteor and xet7 !
2023-08-02 06:09:24 +03:00
Lauri Ojansivu c40b27d9ad Updated ChangeLog. 2023-08-02 06:02:25 +03:00
Lauri Ojansivu 0161f19ba7 Upgrade WeKan Snap Candidate to Node.js 14.21.4 .
Thanks to Meteor and xet7 !
2023-08-02 06:01:00 +03:00
Lauri Ojansivu 4885934477 Updated translations. 2023-08-02 04:05:39 +03:00
Lauri Ojansivu f7b34bc85b Updated ChangeLog. 2023-08-02 04:04:01 +03:00
Lauri Ojansivu f9ed7e1baf Merge pull request #5043 from Pandetthe/master
Fix assignees description
2023-08-01 18:45:03 +03:00
Jakub Jurczyk aca6ba5270 Fix assignees description 2023-08-01 17:30:14 +02:00
Lauri Ojansivu 31636eb0c0 Updated ChangeLog. 2023-08-01 16:49:08 +03:00
Lauri Ojansivu a773abaf2f Upgrade to MongoDB 6.0.8 in Snap Candidate.
Thanks to MongoDB developers!
2023-08-01 16:47:17 +03:00
Lauri Ojansivu 7001f8edaf Updated ChangeLog. 2023-08-01 16:45:10 +03:00
Lauri Ojansivu 7b607b2aaf Fixed v7.01.0 fresh install in listview first column small.
Thanks to intellekta and xet7 !

Fixes #5034
2023-08-01 16:42:58 +03:00
Lauri Ojansivu f3845549fe Updated translations. 2023-08-01 16:38:16 +03:00
Lauri Ojansivu d3a87beef1 Updated ChangeLog. 2023-08-01 16:27:21 +03:00
Lauri Ojansivu 62c2d59f46 Drag board made translateable.
Thanks to xet7 !
2023-08-01 16:25:41 +03:00
Lauri Ojansivu b73e65d63e Updated translations. 2023-08-01 15:30:53 +03:00
Lauri Ojansivu 0b1f906576 Updated ChangeLog. 2023-08-01 15:28:15 +03:00
Lauri Ojansivu e5423989a1 Merge pull request #5041 from cloudron-io/login-layout-code-cleanup
Login layout code cleanup
2023-08-01 15:27:03 +03:00
Lauri Ojansivu a8197a990e Updated ChangeLog. 2023-08-01 15:25:53 +03:00
Lauri Ojansivu e4ae57bf7f Merge pull request #5040 from Pandetthe/master
Fix get_board_cards_count
2023-08-01 15:23:55 +03:00
Lauri Ojansivu 6ad5ede317 Updated ChangeLog. 2023-08-01 15:22:56 +03:00
Johannes Zellner 1271409989 Avoid further UI flickering on load and show/hide OR in login screen if more than one is active
Fixes #5028
2023-08-01 12:58:38 +02:00
Johannes Zellner d17d12e719 The oidc button text is actually set in the DOM tree change later in the file 2023-08-01 12:58:38 +02:00
Johannes Zellner a5f918c670 Remove unneccary and dead code to handle case where custom logo is not set 2023-08-01 12:58:38 +02:00
Jakub Jurczyk 5d6367f404 Fix get_board_cards_count 2023-08-01 12:32:04 +02:00
Lauri Ojansivu 8dc7aa490a Update WeKan Docker to Node.js 14.21.4. Thanks to Meteor and xet7! 2023-08-01 10:36:05 +03:00
Lauri Ojansivu bf0187f2c4 Updated translations. 2023-08-01 07:00:41 +03:00
Lauri Ojansivu 6c34b75061 Updated ChangeLog. 2023-07-31 23:52:08 +03:00
Lauri Ojansivu c4fdc5987b Merge pull request #5037 from mfilser/first_registration_must_be_an_admin_user
first registration after installation must be an admin account
2023-07-31 23:44:40 +03:00
Martin Filser 70c2f0f89f first registration after installation must be an admin account 2023-07-31 21:41:00 +02:00
Lauri Ojansivu bcdad79621 Updated translations. 2023-07-31 17:27:23 +03:00
Lauri Ojansivu d9a4d7a521 Updated ChangeLog. 2023-07-31 17:21:57 +03:00
Lauri Ojansivu a50cc9fb8c Merge pull request #5032 from cloudron-io/stable-login-form
Only selectively show login elements once settings is loaded
2023-07-31 17:16:48 +03:00
Johannes Zellner ab19bbce8e Only selectively show login elements once settings is loaded
Fixes #5029
2023-07-30 13:43:03 +02:00
Lauri Ojansivu 25c8f07c62 Updated ChangeLog. 2023-07-30 02:15:19 +03:00
Lauri Ojansivu db40c94f02 Updated ChangeLog. 2023-07-30 02:10:12 +03:00
Lauri Ojansivu 871f68058e Updated dependencies. 2023-07-30 02:08:05 +03:00
Lauri Ojansivu 3f91dd23bc Updated translations. 2023-07-30 02:07:46 +03:00
Lauri Ojansivu 7baf7d2256 Don't translate width and height minimum value.
Thanks to xet7 !
2023-07-30 01:55:40 +03:00
Lauri Ojansivu 76b9ce4fe3 Merge branch 'mark-i-m-master' 2023-07-30 01:42:52 +03:00
Lauri Ojansivu a2f479f4bd Merge branch 'master' of https://github.com/mark-i-m/wekan into mark-i-m-master 2023-07-30 01:41:45 +03:00
Lauri Ojansivu fafd8a077f Updated ChangeLog. 2023-07-30 01:38:57 +03:00
Lauri Ojansivu caa8d08738 Upgrade to Meteor 2.13 and Node.js 14.21.4 .
Thanks to Meteor developers !
2023-07-30 01:36:01 +03:00
Lauri Ojansivu 13979389ca v7.01 2023-07-21 02:00:24 +03:00
Lauri Ojansivu 350a52935a Updated translations. 2023-07-21 01:56:26 +03:00
Lauri Ojansivu 945e57bb43 Updated ChangeLog. 2023-07-21 01:06:11 +03:00
Lauri Ojansivu 3c374a2891 Merge pull request #5023 from mfilser/attachment_rename_and_delete_for_non_board_admins
Attachment rename and delete works now again for non board admins
2023-07-21 01:05:17 +03:00
Lauri Ojansivu c9074bd8d9 Updated ChangeLog. 2023-07-21 01:03:56 +03:00
Martin Filser bc685c59e0 Attachment rename and delete works now again for non board admins 2023-07-20 23:44:22 +02:00
Lauri Ojansivu aa53ad38fc Merge pull request #5022 from mfilser/removing_utils_getCurrentSetting
removing Utils.getCurrentSetting() and use ReactiveCache directly
2023-07-21 00:41:37 +03:00
Martin Filser 875442f1ce removing Utils.getCurrentSetting() and use ReactiveCache directly 2023-07-20 21:11:29 +02:00
Lauri Ojansivu a8c071f04c Updated translations. 2023-07-20 21:35:44 +03:00
Lauri Ojansivu ef6c9c66af Updated ChangeLog. 2023-07-20 20:00:07 +03:00
Lauri Ojansivu 3df38447e9 Updated ChangeLog. 2023-07-20 19:55:35 +03:00
Lauri Ojansivu 338aabc02f Merge pull request #5021 from mfilser/minicard_show_assignee
Minicard didn't show the assignee
2023-07-20 19:53:59 +03:00
Martin Filser 912717ebf9 Minicard didn't show the assignee 2023-07-20 17:16:47 +02:00
Lauri Ojansivu 9f1a2ec625 Updated dependencies. 2023-07-20 14:44:52 +03:00
Lauri Ojansivu 93f0a69c53 Updated ChangeLog. 2023-07-20 14:44:26 +03:00
Lauri Ojansivu 2846522450 Merge pull request #5019 from DimDz/master
Fix for Calendar View Create Card
2023-07-20 14:34:44 +03:00
DimDz be8374d100 Update boardBody.js 2023-07-20 14:30:42 +03:00
DimDz 399f63cef6 Update boardBody.css 2023-07-20 14:28:31 +03:00
Lauri Ojansivu adf8f7b69a 7.00 2023-07-19 22:24:37 +03:00
Lauri Ojansivu 8e9206bdee Updated dependencies. 2023-07-19 22:07:09 +03:00
Lauri Ojansivu 1946ba150d v7.01 2023-07-19 22:03:24 +03:00
Lauri Ojansivu 60cb5fb017 Added missing @babel/runtime.
Thanks to xet7 !
2023-07-19 21:53:15 +03:00
Lauri Ojansivu 1892a17855 v7.00 2023-07-19 21:26:24 +03:00
Lauri Ojansivu 588e051f0f Updated translations. 2023-07-19 21:18:26 +03:00
Lauri Ojansivu 1c5857f064 Forked meteor-globals and meteor-reactive-cache to @wekanteam/meteor-globals and @wekanteam/meteor-reactive-cache to update to newest non-vulnerable dependencies.
Thanks to xet7 !
2023-07-19 21:08:21 +03:00
Martin Filser 1067542b94 Move every Attachments.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:29 +02:00
Martin Filser 538e197147 Move every Avatars.find(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:29 +02:00
Martin Filser 36db6c6e2d Move every CardCommentReactions.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser e53b63541e Move every Attachments.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser d6ca13a61d Move every CardComments.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 7caf817c81 Move every Activities.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 286617e7be Move every Integrations.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser a423f7883e Move every Triggers.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 6d949ccdb4 Move every Actions.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 0e0ac36788 Move every Rules.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 99ab6d13d4 Move every Team.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser dcf7232958 Move every Org.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser a4408b55ed Move every Checklists.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 06f0ceebd1 Move every ChecklistItems.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 5fe78a477c removing Meteor.publish('customFields', ...) because it's not used (dead code) 2023-07-18 21:25:29 +02:00
Martin Filser 7ef8de50bd Move every CustomFields.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 6646b8638e Move every Users.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 46840c9373 Move every Swimlanes.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 76bd3bfe1d Move every Lists.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 2a2ed1eb2c Move every Cards.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser a533605608 Move every Boards.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 7749c0bd9a server/publications files, adding return parameter for easier time measure (e.g. console.time()) 2023-07-18 21:25:29 +02:00
Martin Filser a37caf459e back to ReactiveCache.getCards and still fixing the flip "Card Drag/Drop" issue 2023-07-18 21:25:29 +02:00
Martin Filser 1c0a1e021a ReactiveCache, adding parameter "getCursor" 2023-07-18 21:25:29 +02:00
Martin Filser f483b162ce Speed up board loading, skip loading the full sidebar
- only load the sidebar when viewing
2023-07-18 21:25:29 +02:00
Martin Filser 42fad8fb98 ReactiveMiniMongoIndex, added getCardCommentsWithCardId 2023-07-18 21:25:29 +02:00
Martin Filser 316acd0366 ReactiveMiniMongoIndex, added getChecklistItemsWithChecklistId 2023-07-18 21:25:29 +02:00
Martin Filser f80ecded0a ReactiveMiniMongoIndex, added getChecklistsWithCardId 2023-07-18 21:25:29 +02:00
Martin Filser 40a5422e75 ReactiveMiniMongoIndex created, Javascript Index of MiniMongo Client Database
- I didn't find a solution to have indexes in MiniMongo on client. As i see /
  believe there isn't this feature yet in Meteor (v2.10).
- I got this and many more results while looking for an solution:

  https://forums.meteor.com/t/adding-indexing-to-minimongo/9130/12
  https://github.com/meteor/meteor-feature-requests/issues/66

So to speed up the MiniMongo i decided to create a own class for this,
currently per query. Of course, this isn't the best solution, but works for now
good.
2023-07-18 21:25:29 +02:00
Martin Filser 726fd5d60d Card Drag/Drop doesn't flip anymore
- .fetch() is causing a short flip after card dragging
2023-07-18 21:25:29 +02:00
Martin Filser 211656e9da removing unused method "activeMembers2()" 2023-07-18 21:25:29 +02:00
Martin Filser 5eb4eb04c4 Move every Attachments.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser fb3b47e2bb Move every Attachments.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:29 +02:00
Martin Filser 14ac099e87 Move every Attachments.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:29 +02:00
Martin Filser f83ee124d0 Move every Boards.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:29 +02:00
Martin Filser 59ee616304 Move every CardComments.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser 25989b9736 Move every CardComments.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:29 +02:00
Martin Filser fef6433b75 Move every Activities.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:29 +02:00
Martin Filser ea72ce1fa2 Move every Integrations.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:29 +02:00
Martin Filser 26e326a204 Move every Integrations.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:29 +02:00
Martin Filser ebb356cf2d Move every Triggers.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:29 +02:00
Martin Filser d6142e4b75 Move every Triggers.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:29 +02:00
Martin Filser c7b554afd9 Move every Actions.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 30c1b5cca8 Move every Rules.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 0c58bcf99c Move every Rules.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:28 +02:00
Martin Filser f3d58339ae Move every Team.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 67c6dd7bee Move every Team.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:28 +02:00
Martin Filser f2d52b55c8 Move every Org.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 8c72531e6d Move every Org.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:28 +02:00
Martin Filser b2f19ed714 Move every Checklists.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:28 +02:00
Martin Filser e5359dc838 Move every Checklists.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 6fd3c0fa6b Move every ChecklistItems.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 981a641bce Move every CustomFields.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 47c70f03a2 Move every CustomFields.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:28 +02:00
Martin Filser 030359aa0e Move every Users.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 81c9bb6899 Move every Users.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:28 +02:00
Martin Filser 4d192a0165 Move every Swimlanes.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:28 +02:00
Martin Filser 33a8de7bb5 Move every Swimlanes.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 9125ab440d Move every Swimlanes.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:28 +02:00
Martin Filser 1c966ed7b4 Move every Lists.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:28 +02:00
Martin Filser 6a4b03324c Move every Lists.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 4a8dcde8ee Move every Lists.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:28 +02:00
Martin Filser c2139662cd Move every Cards.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory server/) 2023-07-18 21:25:28 +02:00
Martin Filser c0ecfb87b0 Move every Cards.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory models/) 2023-07-18 21:25:28 +02:00
Martin Filser 7673c77c57 Move every Cards.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:28 +02:00
Martin Filser 66c2140911 replace Array#forEach() ... Array#push with Array#map 2023-07-18 21:25:28 +02:00
Martin Filser ea3144492e board page didn't always show the list counters 2023-07-18 21:25:28 +02:00
Martin Filser 10a9306abd Move every Boards.find(idOrFirstObjectSelector, options) to the ReactiveCache (directory client/) 2023-07-18 21:25:28 +02:00
Martin Filser 76aae41637 Move every InvitationCodes.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 49071ca5fd Move every SessionData.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 08e3ca3435 Move every Activities.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 6b7b464acc Move every Integrations.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 767d8e66e7 Move every ImpersonatedUsers.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser e30edce73e Move every CardCommentReactions.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser f5796faa84 Move every Triggers.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser b48297df22 Move every Actions.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser c262620993 Move every Rules.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 41685536d7 removing comment code 2023-07-18 21:25:28 +02:00
Martin Filser 92052458f5 Move every Meteor.users.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 6c3170360b Move every Team.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser cd3a27941c Move every Org.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 8a98f03f1a Move every ChecklistItems.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 5552c17eba Move every Checklists.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 92733b24d1 Move every CardComments.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 806ad78637 Move every CustomFields.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 9e557f6887 Move every Lists.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser ad9daba60d Move every Users.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 2c92524cf4 Move every Boards.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 06e374f0ff Move every Cards.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 48ba81eb3d Move every Swimlanes.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 0767f50af8 Move every Users.findOne(idOrFirstObjectSelector, options) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 68610e5066 fix if userId in _meteorSession is undefined 2023-07-18 21:25:28 +02:00
Martin Filser ba9e2debe2 ReactiveCache, adding options to every method 2023-07-18 21:25:28 +02:00
Martin Filser 6c8a5cc580 ReactiveCache, adding methods for Mongo.Collection#find 2023-07-18 21:25:28 +02:00
Martin Filser 3a7eece244 ReactiveCache, id Methods can contain now selector to get the first object (findOne()) 2023-07-18 21:25:28 +02:00
Martin Filser bf27ffb92e Move every Checklists.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 3fc9c6efe7 Move every Attachments.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser fe2015735a Move every Team.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 2ab34d3b87 Move every Org.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 79ea4d6d1e Move every Activities.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 54f7361767 Move every CustomFields.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 0a7ffe4cb0 Move every CardComments.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 0e714a90e0 Move every ChecklistItems.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 5e3a9dc059 Move every Meteor.user() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 6e1ef3d94a Move every Users.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser bf48d4371c Move every Swimlanes.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 2f2aa7b08a insert linked card at search dialog set's now the next card number too 2023-07-18 21:25:28 +02:00
Martin Filser 20b0422024 insert linked board set's now the next card number too 2023-07-18 21:25:28 +02:00
Martin Filser dcb9fb7465 insert linked card set's now the next card number too 2023-07-18 21:25:28 +02:00
Martin Filser 3a287a494b insert linked card at search dialog also add the card at top/bottom 2023-07-18 21:25:28 +02:00
Martin Filser 0926943670 Move every Lists.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 06e26d8d89 insert linked card dialog, sort swimlanes, lists and cards by field "sort" 2023-07-18 21:25:28 +02:00
Martin Filser 94953a1c97 use card.getRealId() 2023-07-18 21:25:28 +02:00
Martin Filser 02e9795816 insert linked board at top/bottom 2023-07-18 21:25:28 +02:00
Martin Filser c29cff3822 insert linked card, move sortIndex to function 2023-07-18 21:25:28 +02:00
Martin Filser 29216599e4 insert linked card at top/bottom of list 2023-07-18 21:25:28 +02:00
Martin Filser 3b65113d05 Move every Cards.findOne() to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser a182482cfb Move every Boards.findOne(boardId) to the ReactiveCache (Part 2) 2023-07-18 21:25:28 +02:00
Martin Filser 9022e9949f Move every Boards.findOne(Session.get('currentBoard')) to the ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser cecf69af02 fix wrong function / variable name (currentSetting -> currentAnnouncements) 2023-07-18 21:25:28 +02:00
Martin Filser b7dbeba7de add currentSetting to ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser c6ee58ef88 add "currentList" to ReactiveCache 2023-07-18 21:25:28 +02:00
Martin Filser 1b3135a79f models/cards.js, use getRealId() for setter too 2023-07-18 21:25:28 +02:00
Martin Filser 131959e050 minicard.js, reduce this.data().board() call 2023-07-18 21:25:28 +02:00
Martin Filser 3f3b4746a9 adding ReactiveCache to other source code 2023-07-18 21:25:28 +02:00
Martin Filser 30d154724a currentBoard is very often called in jade files, so use there the cache too 2023-07-18 21:25:27 +02:00
Martin Filser 16130b3f73 Move ReactiveCache to imports
- so it's available for the Server too
2023-07-18 21:25:27 +02:00
Martin Filser 47427f89b0 Adding new ReactiveCache 2023-07-18 21:25:27 +02:00
Martin Filser 384d80a647 card.js, clean up redudant code 2023-07-18 21:25:27 +02:00
Martin Filser 43d11af631 Performance, improving page load about 40% faster 2023-07-18 21:25:27 +02:00
Martin Filser 9bda4372a5 insert meteor-reactive-cache npm module
$ meteor npm install --save meteor-reactive-cache
2023-07-18 21:25:27 +02:00
Lauri Ojansivu 61223503e3 v6.99.9 2023-07-18 01:18:33 +03:00
Lauri Ojansivu 4d2ad079dc Updated dependencies. 2023-07-17 01:20:48 +03:00
Lauri Ojansivu 50c071682b Updated translations. 2023-07-17 01:20:33 +03:00
Lauri Ojansivu 015ccb7a28 Updated ChangeLog. 2023-07-17 00:52:08 +03:00
Lauri Ojansivu b9aed314f3 Merge pull request #5011 from NotTheEvilOne/pr/fix-oidc-without-groups
Fix "PROPAGATE_OIDC_DATA" mechanism if "info.groups" is undefined
2023-07-17 00:50:07 +03:00
Tobias Wolf 452e2e2408 Fix "PROPAGATE_OIDC_DATA" mechanism if "info.groups" is undefined
This may happen if no group information is shared via OAuth2/OIDC but synchronization of user data is intended by WeKan administration. Without the patch the following exception is raised:
Error in OAuth Server: groups is not iterable
2023-07-16 23:13:46 +02:00
Lauri Ojansivu 9370c1d472 v6.99.8 2023-07-13 12:11:36 +03:00
Lauri Ojansivu 8143dc9196 Updated ChangeLog. 2023-07-13 10:48:20 +03:00
Lauri Ojansivu 98ba18b052 Merge pull request #5009 from helioguardabaxo/fix-csv-import
Fix card creation. Now date fields are checked if they are empty.
2023-07-13 10:06:32 +03:00
helioguardabaxo 9860f20be3 Fix card creation. Now date fields are checked if they are empty. 2023-07-12 11:14:41 -03:00
Lauri Ojansivu cfbb06ed1f Updated translations. 2023-07-12 00:57:38 +03:00
Lauri Ojansivu e39760eb19 v6.99.7 2023-07-11 18:20:22 +03:00
Lauri Ojansivu b3da55f85c Merge pull request #5008 from wekan/dependabot/npm_and_yarn/semver-6.3.1
Bump semver from 6.3.0 to 6.3.1
2023-07-11 18:15:03 +03:00
dependabot[bot] bc4b637f06 Bump semver from 6.3.0 to 6.3.1
Bumps [semver](https://github.com/npm/node-semver) from 6.3.0 to 6.3.1.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v6.3.1/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v6.3.0...v6.3.1)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-11 15:13:49 +00:00
Lauri Ojansivu c993c8f47e v6.99.6 2023-07-11 18:13:18 +03:00
Lauri Ojansivu 40470bedb3 Updated ChangeLog. 2023-07-11 18:08:23 +03:00
Lauri Ojansivu 912479baa4 Added back datepicker.
Thanks to xet7 !

Fixes #5007
2023-07-11 18:06:19 +03:00
Lauri Ojansivu cfbf3e320c Updated ChangeLog. 2023-07-10 15:12:13 +03:00
Lauri Ojansivu 4431ec5a27 Added missing character.
Thanks to xet7 !
2023-07-10 15:04:46 +03:00
Lauri Ojansivu d7784a8d38 Merge pull request #5004 from VidVidex/master
Fix setting background image
2023-07-10 14:53:07 +03:00
Vid Smole 2c4ed5f298 Fix setting background image 2023-07-10 13:19:19 +02:00
Lauri Ojansivu 6a97aeb60c v6.99.5 2023-07-10 06:30:41 +03:00
Lauri Ojansivu c7dc912dd4 Reverted bold of minicard title.
Thanks to xet7 !
2023-07-10 06:25:37 +03:00
Lauri Ojansivu 0ee886692e v6.99.4 2023-07-10 05:07:02 +03:00
Lauri Ojansivu 34fef627a1 Disable migration attachment-cardCopy-fix-boardId-etc. Part 3.
Thanks to xet7 !
2023-07-10 05:02:04 +03:00
Lauri Ojansivu 52d36d3780 v6.99.3 2023-07-10 03:10:24 +03:00
Lauri Ojansivu 8555c24eb2 Fix migration attachment-cardCopy-fix-boardId-etc. Part 2.
Thanks to xet7 !
2023-07-10 03:05:55 +03:00
Lauri Ojansivu c41c26e5a1 v6.99.2 2023-07-10 01:34:37 +03:00
Lauri Ojansivu 35cc9b3fcc Merge pull request #5001 from wekan/dependabot/npm_and_yarn/semver-and-mapbox/node-pre-gyp-7.5.4
Bump semver and @mapbox/node-pre-gyp
2023-07-10 01:29:14 +03:00
dependabot[bot] dbfd219491 Bump semver and @mapbox/node-pre-gyp
Bumps [semver](https://github.com/npm/node-semver) to 7.5.4 and updates ancestor dependency [@mapbox/node-pre-gyp](https://github.com/mapbox/node-pre-gyp). These dependencies need to be updated together.


Updates `semver` from 6.3.0 to 7.5.4
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v6.3.0...v7.5.4)

Updates `@mapbox/node-pre-gyp` from 1.0.10 to 1.0.10
- [Changelog](https://github.com/mapbox/node-pre-gyp/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mapbox/node-pre-gyp/compare/v1.0.10...v1.0.10)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
- dependency-name: "@mapbox/node-pre-gyp"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-09 22:19:13 +00:00
Lauri Ojansivu 0da5f26668 Updated ChangeLog. 2023-07-10 01:18:14 +03:00
Lauri Ojansivu 8bf40e219a Added back npm packages: fibers and @mapbox/node-pre-gyp.
Thanks to xet7 !
2023-07-10 01:11:37 +03:00
Lauri Ojansivu 8f1f8c0fb9 v6.99.1 2023-07-10 00:39:29 +03:00
Lauri Ojansivu 386a65d6c6 Updated ChangeLog. 2023-07-10 00:34:22 +03:00
Lauri Ojansivu a73ce72e46 Merge pull request #4999 from mfilser/fix_migration_attachment-cardCopy-fix-boardId-etc
fix for migration "attachment-cardCopy-fix-boardId-etc"
2023-07-10 00:30:39 +03:00
Lauri Ojansivu d0616d8d67 Updated ChangeLog. 2023-07-10 00:21:57 +03:00
Martin Filser 6ad007a5f1 fix for migration "attachment-cardCopy-fix-boardId-etc"
- every card must have a boardId, listId and swimlaneId, if not, the database
  data is corrupt, but the migration should also not break wekan from startup
2023-07-09 23:20:37 +02:00
Lauri Ojansivu 95d3e5cdc6 Updated dependencies.
Thanks to developers of dependencies !
2023-07-10 00:19:18 +03:00
Lauri Ojansivu 08a3506f12 v6.99 2023-07-09 23:11:22 +03:00
Lauri Ojansivu 520f295733 Updated translations. 2023-07-09 23:01:44 +03:00
Lauri Ojansivu 7da5121ddd Updated translations. 2023-07-09 22:57:43 +03:00
Lauri Ojansivu 3222625286 Updated ChangeLog. 2023-07-08 21:05:32 +03:00
Lauri Ojansivu 05d952b864 Merge pull request #4997 from VidVidex/master
Fix attachment viewer not being hidden
2023-07-08 21:03:07 +03:00
Vid Smole a3837ccbc7 Fix attachment viewer not being hidden 2023-07-08 19:22:40 +02:00
Lauri Ojansivu ac8199177f Updated ChangeLog. 2023-07-08 04:00:27 +03:00
Lauri Ojansivu 140a134a11 Fixed maximum call stack exceeded by removing bootstrap 3, datepicker and summernote. Updated jquery. Disabled attachments viewer that opens empty when opening card. Fixes all npm audit errors.
Fixes #4994,
fixes #3614

Thanks to xet7 !
2023-07-08 03:52:42 +03:00
Lauri Ojansivu c1b3e5367c Updated ChangeLog. 2023-07-08 01:35:22 +03:00
Lauri Ojansivu b637a8e8ea Revert first list width change.
Related https://github.com/wekan/wekan/pull/4993

Thanks to xet7 !
2023-07-08 01:30:55 +03:00
Lauri Ojansivu 999323526c Merge pull request #4993 from VidVidex/master
Small UI improvements
2023-07-08 01:30:14 +03:00
Lauri Ojansivu 2e0168283e Updated translations. 2023-07-08 01:25:11 +03:00
Lauri Ojansivu 13039c895a Updated ChangeLog. 2023-07-08 01:23:39 +03:00
Lauri Ojansivu 4148238af3 Removed horka:swipebox.
Thanks to VidVidex and xet7 !
2023-07-08 01:20:35 +03:00
Vid Smole 7a98445370 Better attachment viewer 2023-07-06 20:35:49 +02:00
Vid Smole 7ef3bba9f7 Better attachment gallery 2023-07-06 20:29:36 +02:00
Vid Smole 492306453c Fix first list being narrower than others 2023-07-06 13:22:38 +02:00
Vid Smole e12353bd7e Merge branch 'wekan:master' into master 2023-07-06 12:57:29 +02:00
Vid Smole a3622ddc1d Display card title in bold 2023-07-06 12:57:06 +02:00
Lauri Ojansivu ac95be9e41 Updated ChangeLog. 2023-07-05 14:14:27 +03:00
Lauri Ojansivu 4a3fc42d1f Merge pull request #4992 from VidVidex/master
Fix attachment urls in PR #4991
2023-07-05 07:13:19 -04:00
Vid Smole 557f9709ac Fix attachment urls 2023-07-05 12:52:18 +02:00
Lauri Ojansivu 4468c71d98 Updated ChangeLog. 2023-07-05 12:14:49 +03:00
Lauri Ojansivu c8491749e0 Merge pull request #4991 from VidVidex/master
Fix /api/boards/{boardId}/attachments endpoint
2023-07-05 05:13:14 -04:00
Vid Smole e5123f2d81 Merge branch 'wekan:master' into master 2023-07-05 11:06:11 +02:00
Vid Smole 41664f16a3 Fix /api/board/{boardId}/attachments 2023-07-05 11:05:37 +02:00
Lauri Ojansivu 8c9c0e9316 Updated translations. 2023-07-04 22:09:29 +03:00
Lauri Ojansivu f21bd16cec Updated translations. 2023-07-03 10:27:21 +03:00
Lauri Ojansivu edc5a5b6a2 Updated translations. 2023-07-01 21:12:02 +03:00
Lauri Ojansivu 7d4de21be0 Updated ChangeLog. 2023-07-01 00:56:08 +03:00
Lauri Ojansivu 5babe0358d MongoDB 6.0.7 at Snap.
Thanks to MongoDB developers !
2023-07-01 00:54:05 +03:00
Lauri Ojansivu 62ef1fe7cc Updated ChangeLog. 2023-07-01 00:36:03 +03:00
Lauri Ojansivu 4be5727a18 Fix PDF preview to have full width, close at top, and improve viewing at mobile.
Thanks to xet7 !
2023-07-01 00:30:05 +03:00
Lauri Ojansivu e128a5775d Updated ChangeLog. 2023-06-30 18:08:26 +03:00
Lauri Ojansivu ba9f9705d4 Show Meteor dependency chain with rebuild-wekan.sh .
Thanks to xet7 !
2023-06-30 18:06:44 +03:00
Lauri Ojansivu 3aae07695c Updated translations. 2023-06-30 17:43:10 +03:00
Lauri Ojansivu 4393deb130 Updated ChangeLog. 2023-06-30 17:41:24 +03:00
Lauri Ojansivu 83ae1d4a19 Added translation to support viewing PDFs.
Thanks to xet7 !

Fixes https://github.com/wekan/wekan/pull/4989#pullrequestreview-1507053336
2023-06-30 17:31:17 +03:00
Lauri Ojansivu 94992fca44 Merge pull request #4989 from VidVidex/master
Add support for viewing pdfs
2023-06-30 10:03:20 -04:00
Vid Smole a8af5343a7 Fix typo 2023-06-30 12:48:23 +02:00
Vid Smole 070e8831b4 Add support for viewing pdfs 2023-06-30 12:48:18 +02:00
Lauri Ojansivu f177e416ee Updated ChangeLog. 2023-06-29 12:07:51 +03:00
Lauri Ojansivu ffea7aff99 If there is no Custom Field label at minicard, show value full width.
Thanks to koluka and xet7 !

Fixes #4988
2023-06-29 12:05:25 +03:00
Lauri Ojansivu 01b16566c8 Updated ChangeLog. 2023-06-29 00:32:27 +03:00
Lauri Ojansivu 549b15000b Set background color only if it exists. Part 3.
Thanks to xet7 !
2023-06-29 00:31:44 +03:00
Lauri Ojansivu d05b84dff9 Updated ChangeLog. 2023-06-29 00:23:28 +03:00
Lauri Ojansivu c6cad13f1e Set background color only if it exists. Part 2.
Thanks to xet7 !
2023-06-29 00:22:25 +03:00
Lauri Ojansivu a8d1210655 Updated ChangeLog. 2023-06-29 00:04:12 +03:00
Lauri Ojansivu 45d33fa2e4 Set background color only if it exists.
Thanks to xet7 !
2023-06-29 00:03:00 +03:00
Lauri Ojansivu 81ceb1ca0f Updated ChangeLog. 2023-06-28 23:34:37 +03:00
Lauri Ojansivu 923d26ad81 Merge pull request #4987 from mfilser/move_canModifyCard_and_canModifyBoard_to_utils_class
Utils of canModifyCard and canModifyBoard + move this general functions to Utils class
2023-06-28 16:32:02 -04:00
Martin Filser 583f114c68 Utils of canModifyCard and canModifyBoard + move this general functions to Utils class 2023-06-28 22:21:36 +02:00
Lauri Ojansivu b29ec93c34 Updated ChangeLog. 2023-06-28 23:14:09 +03:00
Lauri Ojansivu c7ee585a62 Merge pull request #4986 from mfilser/global_search_found_cards_count_is_now_substituted_by_the_translation_function_itself
Global search, found cards count is now substituted by the translation function itself
2023-06-28 16:13:17 -04:00
Martin Filser a7721b9048 Global search, found cards count is now substituted by the translation function itself 2023-06-28 22:08:58 +02:00
Lauri Ojansivu 184fd3abdd Updated ChangeLog. 2023-06-28 23:08:27 +03:00
Lauri Ojansivu 5fd2f1ee8a Merge pull request #4985 from mfilser/admin_report_fixing_filesize_if_not_a_number
Admin Report, fixing filesize if not a number
2023-06-28 16:07:26 -04:00
Martin Filser 23218d3808 Admin Report, fixing filesize if not a number 2023-06-28 22:02:28 +02:00
Lauri Ojansivu 9b8de53bfe Updated ChangeLog. 2023-06-28 23:02:04 +03:00
Lauri Ojansivu 9130410f09 Merge pull request #4984 from mfilser/global_search_limit_0_is_no_limit
Global Search, limit 0 is no limit
2023-06-28 15:54:34 -04:00
Martin Filser 1f57a3f62e Global Search, limit 0 is no limit 2023-06-28 21:49:44 +02:00
Lauri Ojansivu 6938cec583 Updated ChangeLog. 2023-06-28 22:45:33 +03:00
Lauri Ojansivu 3c2cc351f4 Added Snap MONGO_URL to rebuild-wekan.sh dev options. Part 2.
Thanks to xet7 !
2023-06-28 22:44:26 +03:00
Lauri Ojansivu ebeadeef60 Updated ChangeLog. 2023-06-28 22:42:47 +03:00
Lauri Ojansivu 7d59ae93f9 Added Snap MONGO_URL to rebuild-wekan.sh dev options.
Thanks to xet7 !
2023-06-28 22:41:11 +03:00
Lauri Ojansivu 59e15d262f Updated ChangeLog. 2023-06-28 22:37:14 +03:00
Lauri Ojansivu 712417b379 Merge pull request #4983 from mfilser/admin_attachment_view_was_missing_the_column_header_S3FileId
Admin attachment view was missing the column header "S3FileId"
2023-06-28 15:35:57 -04:00
Martin Filser cad55d57d7 Admin attachment view was missing the column header "S3FileId" 2023-06-28 21:30:01 +02:00
Lauri Ojansivu cca7e59eb2 Updated ChangeLog. 2023-06-28 22:27:49 +03:00
Lauri Ojansivu 59a358903a Merge pull request #4982 from mfilser/attachment_copy_changes_now_boardId_listId_and_swimlaneId
attachment copy changes now the boardId, listId and swimlaneId in the collection data
2023-06-28 15:25:52 -04:00
Martin Filser 2eadd3eb8b attachment copy changes now the boardId, listId and swimlaneId in the collection data
- fixing admin attachment view, copied card attachments were wrong if copied to another board / list / swimlane
2023-06-28 21:21:09 +02:00
Lauri Ojansivu 0261bb592e Updated ChangeLog. 2023-06-28 22:12:43 +03:00
Lauri Ojansivu 7862e280ec Merge pull request #4981 from mfilser/copy_checklist_only_copied_the_checklist_items_the_first_time
Copy Checklist only copied the checklist items at the first time, now always
2023-06-28 15:11:40 -04:00
Martin Filser 13fecfae27 Copy Checklist only copied the checklist items at the first time, now always 2023-06-28 21:05:25 +02:00
Lauri Ojansivu b7819cad69 Updated ChangeLog. 2023-06-28 21:39:24 +03:00
Lauri Ojansivu 028fba9996 Merge pull request #4980 from mfilser/copy_checklist_dialog_set_last_selected_board
Copy Checklist dialog now set's the last selected board
2023-06-28 14:36:00 -04:00
Martin Filser ce94433c46 Copy Checklist dialog now set's the last selected board 2023-06-26 18:28:07 +02:00
Lauri Ojansivu 442eefbe6b Updated ChangeLog. 2023-06-26 16:44:44 +03:00
Lauri Ojansivu 84c3b38052 Updated ChangeLog. 2023-06-26 16:42:08 +03:00
Martin Filser 8557d91468 new popup scrolls to top and restore it's previous position after closing again works now at attachments too 2023-06-25 10:44:20 +02:00
Martin Filser 949a3a1337 new popup scrolls to top and restore it's previous position after closing again 2023-06-25 10:44:20 +02:00
Lauri Ojansivu 24288919e2 Merge pull request #4977 from wekan/dependabot/npm_and_yarn/fast-xml-parser-4.2.5
Bump fast-xml-parser from 4.2.4 to 4.2.5
2023-06-22 16:57:53 -04:00
dependabot[bot] 92c57fc91e Bump fast-xml-parser from 4.2.4 to 4.2.5
Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 4.2.4 to 4.2.5.
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.2.4...v4.2.5)

---
updated-dependencies:
- dependency-name: fast-xml-parser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-22 19:32:48 +00:00
Lauri Ojansivu 9d1e7abd07 v6.98 2023-06-22 22:32:19 +03:00
Lauri Ojansivu 8dfdbe7a16 Updated ChangeLog. 2023-06-22 22:24:09 +03:00
Lauri Ojansivu 15fbe7ca50 Merge pull request #4976 from mfilser/drag_drop_reduce_list_scroll_speed
reduce list scroll speed while drag/drop the minicard
2023-06-22 12:30:04 -04:00
Martin Filser 9aa8bc8921 reduce list scroll speed while drag/drop the minicard 2023-06-22 17:17:40 +02:00
Lauri Ojansivu e90791fdbc Merge pull request #4975 from mfilser/rounding_sort_number_to_next_integer
Rounding sort number to next integer
2023-06-21 17:35:58 -04:00
Martin Filser b869e3efb6 after moving, e.g. minicards, to the list start / end the index is rounded to the next index 2023-06-21 23:16:55 +02:00
Martin Filser 7e8073d621 after moving, e.g. the minicard, round the index to the next integer
- before: at index -1           and -9 the new index was -5
- now   : at index -1 (or -1.1) and -9 the new index is  -2
2023-06-21 23:16:55 +02:00
Martin Filser c10f7b6134 Utils#calculateIndex re-uses the logic of Utils#calculateIndexData
- nearly the same implementation, so use common code base
2023-06-21 23:16:55 +02:00
Lauri Ojansivu 1a71abbc1d Updated ChangeLog. 2023-06-22 00:16:12 +03:00
Lauri Ojansivu 0a46d06c1f Merge pull request #4974 from mfilser/add_checklistitem_at_top
Add checklist-item at top
2023-06-21 17:13:17 -04:00
Martin Filser 23595674cf Add checklist-item at top 2023-06-21 23:09:29 +02:00
Lauri Ojansivu 6fead14c11 Updated ChangeLog. 2023-06-22 00:03:38 +03:00
Martin Filser 52d54f35a3 Add checklist at top 2023-06-21 21:59:48 +02:00
Lauri Ojansivu 3c1eff6241 Updated translations. 2023-06-20 00:26:44 +03:00
Lauri Ojansivu fb2972396a Updated ChangeLog. 2023-06-20 00:24:30 +03:00
Lauri Ojansivu 4d9f76cc68 Merge pull request #4969 from nebulade/favicon-fix
Always fetch favicons from / path
2023-06-19 17:16:51 -04:00
Lauri Ojansivu 924c579680 Merge pull request #4971 from wekan/dependabot/github_actions/docker/build-push-action-4.1.1
Bump docker/build-push-action from 4.1.0 to 4.1.1
2023-06-19 17:15:58 -04:00
Lauri Ojansivu ca2ea2c13e Merge pull request #4970 from wekan/dependabot/github_actions/docker/metadata-action-4.6.0
Bump docker/metadata-action from 4.5.0 to 4.6.0
2023-06-19 17:15:34 -04:00
dependabot[bot] b579dc598b Bump docker/build-push-action from 4.1.0 to 4.1.1
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/44ea916f6c540f9302d50c2b1e5a8dc071f15cdf...2eb1c1961a95fc15694676618e422e8ba1d63825)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 20:58:45 +00:00
dependabot[bot] 04c5f60287 Bump docker/metadata-action from 4.5.0 to 4.6.0
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4.5.0 to 4.6.0.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/2c0bd771b40637d97bf205cbccdd294a32112176...818d4b7b91585d195f67373fd9cb0332e31a7175)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-19 20:58:41 +00:00
Johannes Zellner 123789aff0 Always fetch favicons from / path 2023-06-19 14:33:36 +02:00
Lauri Ojansivu 74b66fdcaf Updated translations. 2023-06-18 03:31:48 +03:00
Lauri Ojansivu 3f09b54e04 Merge pull request #4968 from simon816/fix-language-not-persisting
Wait until user has logged in before fetching language preference
2023-06-17 20:26:54 -04:00
simon816 c39403c307 Wait until user has logged in before fetching language preference. Fixes #4967 2023-06-18 00:58:16 +01:00
Lauri Ojansivu 13ea7bf3d7 Updated ChangeLog. 2023-06-17 21:01:11 +03:00
Lauri Ojansivu dc2835d341 Added translations: Cantonese (China) (yue_CN) and Chinese Traditional (zh-Hant).
Thanks to translators !
2023-06-17 20:58:21 +03:00
Lauri Ojansivu 94ff2d6a9e Updated ChangeLog. 2023-06-16 12:24:37 +03:00
Lauri Ojansivu 6479c6a5c5 Update rebuild-wekan.sh to use local network IP address.
Thanks to xet7 !
2023-06-16 12:22:18 +03:00
mark 4b04af9a9c popup titles 2023-06-14 14:06:53 -05:00
mark 26d2efdedb make swimlane height adjustable 2023-06-13 13:43:09 -05:00
mark 0ec9c4c37b min working example with listWidth 2023-06-13 12:54:18 -05:00
mark f2e4a280d7 add listWidths to user profile 2023-06-12 22:14:06 -05:00
Lauri Ojansivu a1ddf8e6d2 Merge pull request #4961 from wekan/dependabot/github_actions/docker/login-action-2.2.0
Bump docker/login-action from 2.1.0 to 2.2.0
2023-06-13 00:24:50 +03:00
Lauri Ojansivu 102b39cd29 Merge pull request #4963 from wekan/dependabot/github_actions/docker/build-push-action-4.1.0
Bump docker/build-push-action from 4.0.0 to 4.1.0
2023-06-13 00:24:32 +03:00
Lauri Ojansivu b7373a27b8 Merge pull request #4962 from wekan/dependabot/github_actions/docker/metadata-action-4.5.0
Bump docker/metadata-action from 4.4.0 to 4.5.0
2023-06-13 00:24:16 +03:00
dependabot[bot] fb0b762293 Bump docker/build-push-action from 4.0.0 to 4.1.0
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/3b5e8027fcad23fda98b2e3ac259d8d67585f671...44ea916f6c540f9302d50c2b1e5a8dc071f15cdf)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 20:58:03 +00:00
dependabot[bot] 5b799b4536 Bump docker/metadata-action from 4.4.0 to 4.5.0
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/c4ee3adeed93b1fa6a762f209fb01608c1a22f1e...2c0bd771b40637d97bf205cbccdd294a32112176)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 20:58:00 +00:00
dependabot[bot] 8050d7353d Bump docker/login-action from 2.1.0 to 2.2.0
Bumps [docker/login-action](https://github.com/docker/login-action) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/f4ef78c080cd8ba55a85445d5b36e214a81df20a...465a07811f14bebb1938fbed4728c6a1ff8901fc)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-12 20:57:57 +00:00
Lauri Ojansivu 66b1736bb3 Updated translations. 2023-06-12 14:23:04 -04:00
305 changed files with 9276 additions and 7880 deletions

No files matched your search

+10 -6
View File
@@ -10,8 +10,8 @@ ENV DEBIAN_FRONTEND=noninteractive
ENV \
DEBUG=false \
NODE_VERSION=v14.21.3 \
METEOR_RELEASE=1.10.2 \
NODE_VERSION=v14.21.4 \
METEOR_RELEASE=METEOR@2.13 \
USE_EDGE=false \
METEOR_EDGE=1.5-beta.17 \
NPM_VERSION=latest \
@@ -162,14 +162,18 @@ RUN set -o xtrace \
&& apt-get install --assume-yes --no-install-recommends apt-utils apt-transport-https ca-certificates 2>&1 \
&& apt-get install --assume-yes --no-install-recommends ${BUILD_DEPS}
# OLD:
# && curl -fsSLO --compressed "https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-$ARCHITECTURE.tar.xz" \
# && curl -fsSLO --compressed "https://nodejs.org/dist/$NODE_VERSION/SHASUMS256.txt.asc" \
# Install NodeJS
RUN set -o xtrace \
&& cd /tmp \
&& curl -fsSLO --compressed "https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-$ARCHITECTURE.tar.xz" \
&& curl -fsSLO --compressed "https://nodejs.org/dist/$NODE_VERSION/SHASUMS256.txt.asc" \
&& grep " node-$NODE_VERSION-$ARCHITECTURE.tar.xz\$" SHASUMS256.txt.asc | sha256sum -c - \
&& curl -fsSLO --compressed "https://github.com/wekan/node-v14-esm/releases/download/${NODE_VERSION}/node-${NODE_VERSION}-${ARCHITECTURE}.tar.xz" \
&& curl -fsSLO --compressed "https://github.com/wekan/node-v14-esm/releases/download/${NODE_VERSION}/SHASUMS256.txt" \
&& grep " node-$NODE_VERSION-$ARCHITECTURE.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-$NODE_VERSION-$ARCHITECTURE.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
&& rm "node-$NODE_VERSION-$ARCHITECTURE.tar.xz" SHASUMS256.txt.asc \
&& rm "node-$NODE_VERSION-$ARCHITECTURE.tar.xz" SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs \
&& mkdir -p /usr/local/lib/node_modules/fibers/.node-gyp /root/.node-gyp/${NODE_VERSION} /home/wekan/.config \
&& npm install -g npm@${NPM_VERSION} \
+3 -3
View File
@@ -38,7 +38,7 @@ jobs:
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@@ -48,14 +48,14 @@ jobs:
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@c4ee3adeed93b1fa6a762f209fb01608c1a22f1e
uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
+86 -55
View File
@@ -21,7 +21,7 @@ cottz:publish-relations
dburles:collection-helpers
idmontie:migrations
easy:search
mongo@1.16.6
mongo@1.16.7
mquandalle:collection-mutations
# Account system
@@ -47,28 +47,105 @@ tracker@1.3.2
underscore@1.0.13
arillo:flow-router-helpers
audit-argument-checks@1.0.7
kadira:blaze-layout
kadira:dochead
mquandalle:autofocus
ongoworks:speakingurl
raix:handlebar-helpers
http@2.0.0! # force new http package
# Datepicker
rajit:bootstrap3-datepicker
rajit:bootstrap3-datepicker-de
rajit:bootstrap3-datepicker-tr
rajit:bootstrap3-datepicker-ja
rajit:bootstrap3-datepicker-fr
rajit:bootstrap3-datepicker-it
rajit:bootstrap3-datepicker-th
rajit:bootstrap3-datepicker-nl
rajit:bootstrap3-datepicker-es
rajit:bootstrap3-datepicker-lv
rajit:bootstrap3-datepicker-sv
rajit:bootstrap3-datepicker-gl
rajit:bootstrap3-datepicker-eu
rajit:bootstrap3-datepicker-vi
rajit:bootstrap3-datepicker-no
rajit:bootstrap3-datepicker-en-gb
rajit:bootstrap3-datepicker-ro
rajit:bootstrap3-datepicker-rs
rajit:bootstrap3-datepicker-ru
rajit:bootstrap3-datepicker-bs
rajit:bootstrap3-datepicker-mn
rajit:bootstrap3-datepicker-id
rajit:bootstrap3-datepicker-fa
rajit:bootstrap3-datepicker-ko
rajit:bootstrap3-datepicker-pt
rajit:bootstrap3-datepicker-sl
rajit:bootstrap3-datepicker-sq
rajit:bootstrap3-datepicker-cy
rajit:bootstrap3-datepicker-ka
rajit:bootstrap3-datepicker-sr
rajit:bootstrap3-datepicker-az
rajit:bootstrap3-datepicker-cs
rajit:bootstrap3-datepicker-me
rajit:bootstrap3-datepicker-ta
rajit:bootstrap3-datepicker-eo
rajit:bootstrap3-datepicker-oc
rajit:bootstrap3-datepicker-he
rajit:bootstrap3-datepicker-sw
rajit:bootstrap3-datepicker-rs-latin
rajit:bootstrap3-datepicker-da
rajit:bootstrap3-datepicker-pt-br
rajit:bootstrap3-datepicker-br
rajit:bootstrap3-datepicker-it-ch
rajit:bootstrap3-datepicker-en-za
rajit:bootstrap3-datepicker-en-ie
rajit:bootstrap3-datepicker-en-ca
rajit:bootstrap3-datepicker-uz-latn
rajit:bootstrap3-datepicker-ms
rajit:bootstrap3-datepicker-uk
rajit:bootstrap3-datepicker-hu
rajit:bootstrap3-datepicker-fo
rajit:bootstrap3-datepicker-kr
rajit:bootstrap3-datepicker-hi
rajit:bootstrap3-datepicker-km
rajit:bootstrap3-datepicker-fi
rajit:bootstrap3-datepicker-is
rajit:bootstrap3-datepicker-kh
rajit:bootstrap3-datepicker-bg
rajit:bootstrap3-datepicker-bn
rajit:bootstrap3-datepicker-pl
rajit:bootstrap3-datepicker-et
rajit:bootstrap3-datepicker-ar
rajit:bootstrap3-datepicker-ca
rajit:bootstrap3-datepicker-kk
rajit:bootstrap3-datepicker-sk
rajit:bootstrap3-datepicker-el
rajit:bootstrap3-datepicker-hy
rajit:bootstrap3-datepicker-hr
rajit:bootstrap3-datepicker-tg
rajit:bootstrap3-datepicker-nb
rajit:bootstrap3-datepicker-mk
rajit:bootstrap3-datepicker-nl-be
rajit:bootstrap3-datepicker-zh-cn
rajit:bootstrap3-datepicker-ar-tn
rajit:bootstrap3-datepicker-en-au
rajit:bootstrap3-datepicker-fr-ch
rajit:bootstrap3-datepicker-zh-tw
rajit:bootstrap3-datepicker-uz-cyrl
rajit:bootstrap3-datepicker-sr-latin
rajit:bootstrap3-datepicker-en-nz
# UI components
blaze
ostrio:i18n
reactive-var@1.0.12
fortawesome:fontawesome
mousetrap:mousetrap
mquandalle:jquery-textcomplete
mquandalle:mousetrap-bindglobal
peerlibrary:blaze-components
templates:tabs
meteor-autosize
rajit:bootstrap3-datepicker
shell-server@0.5.0
email@2.2.5
horka:swipebox
dynamic-import@0.7.3
cfs:gridfs
rzymek:fullcalendar
@@ -82,55 +159,6 @@ percolate:synced-cron
cfs:filesystem
ostrio:cookies
ostrio:files@2.3.0
rajit:bootstrap3-datepicker-fi
rajit:bootstrap3-datepicker-ar
rajit:bootstrap3-datepicker-bg
rajit:bootstrap3-datepicker-br
rajit:bootstrap3-datepicker-ca
rajit:bootstrap3-datepicker-cs
rajit:bootstrap3-datepicker-da
rajit:bootstrap3-datepicker-de
rajit:bootstrap3-datepicker-el
rajit:bootstrap3-datepicker-en-gb
rajit:bootstrap3-datepicker-eo
rajit:bootstrap3-datepicker-es
rajit:bootstrap3-datepicker-eu
rajit:bootstrap3-datepicker-fa
rajit:bootstrap3-datepicker-fr
rajit:bootstrap3-datepicker-gl
rajit:bootstrap3-datepicker-he
rajit:bootstrap3-datepicker-hi
rajit:bootstrap3-datepicker-hu
rajit:bootstrap3-datepicker-hy
rajit:bootstrap3-datepicker-id
rajit:bootstrap3-datepicker-it
rajit:bootstrap3-datepicker-ja
rajit:bootstrap3-datepicker-ka
rajit:bootstrap3-datepicker-km
rajit:bootstrap3-datepicker-ko
rajit:bootstrap3-datepicker-lv
rajit:bootstrap3-datepicker-mk
rajit:bootstrap3-datepicker-mn
rajit:bootstrap3-datepicker-nb
rajit:bootstrap3-datepicker-nl
rajit:bootstrap3-datepicker-oc
rajit:bootstrap3-datepicker-pl
rajit:bootstrap3-datepicker-pt-br
rajit:bootstrap3-datepicker-pt
rajit:bootstrap3-datepicker-ro
rajit:bootstrap3-datepicker-ru
rajit:bootstrap3-datepicker-sl
rajit:bootstrap3-datepicker-sr
rajit:bootstrap3-datepicker-sv
rajit:bootstrap3-datepicker-sw
rajit:bootstrap3-datepicker-ta
rajit:bootstrap3-datepicker-th
rajit:bootstrap3-datepicker-tr
rajit:bootstrap3-datepicker-uk
rajit:bootstrap3-datepicker-vi
rajit:bootstrap3-datepicker-zh-cn
rajit:bootstrap3-datepicker-zh-tw
easylogic:summernote
pascoual:pdfkit
lmieulet:meteor-coverage
meteortesting:mocha@2.0.3
@@ -142,3 +170,6 @@ spacebars
service-configuration@1.3.1
communitypackages:picker
minifier-css@1.6.4
blaze
kadira:blaze-layout
peerlibrary:blaze-components
+1 -1
View File
@@ -1 +1 @@
METEOR@2.12
METEOR@2.13
+34 -6
View File
@@ -48,12 +48,11 @@ ddp@1.4.1
ddp-client@2.6.1
ddp-common@1.4.0
ddp-rate-limiter@1.2.0
ddp-server@2.6.1
ddp-server@2.6.2
deps@1.0.12
diff-sequence@1.1.2
dynamic-import@0.7.3
easy:search@2.2.1
easylogic:summernote@0.8.8
easysearch:components@2.2.2
easysearch:core@2.2.2
ecmascript@0.16.7
@@ -66,7 +65,6 @@ es5-shim@4.8.0
fetch@0.1.3
fortawesome:fontawesome@4.7.0
geojson-utils@1.0.11
horka:swipebox@1.0.2
hot-code-push@1.0.4
html-tools@1.1.3
htmljs@1.1.1
@@ -85,7 +83,7 @@ localstorage@1.2.0
logging@1.3.2
matb33:collection-hooks@1.2.2
mdg:validation-error@0.5.1
meteor@1.11.2
meteor@1.11.3
meteor-autosize@5.0.1
meteor-base@1.5.1
meteorhacks:aggregate@1.3.0
@@ -103,7 +101,7 @@ modern-browsers@0.1.9
modules@0.19.0
modules-runtime@0.13.1
momentjs:moment@2.29.3
mongo@1.16.6
mongo@1.16.7
mongo-decimal@0.1.3
mongo-dev-server@1.1.0
mongo-id@1.0.8
@@ -139,50 +137,81 @@ raix:eventemitter@0.1.3
raix:handlebar-helpers@0.2.5
rajit:bootstrap3-datepicker@1.7.1_1
rajit:bootstrap3-datepicker-ar@1.7.1
rajit:bootstrap3-datepicker-ar-tn@1.7.1
rajit:bootstrap3-datepicker-az@1.7.1
rajit:bootstrap3-datepicker-bg@1.7.1
rajit:bootstrap3-datepicker-bn@1.7.1
rajit:bootstrap3-datepicker-br@1.7.1
rajit:bootstrap3-datepicker-bs@1.7.1
rajit:bootstrap3-datepicker-ca@1.7.1
rajit:bootstrap3-datepicker-cs@1.7.1
rajit:bootstrap3-datepicker-cy@1.7.1
rajit:bootstrap3-datepicker-da@1.7.1
rajit:bootstrap3-datepicker-de@1.7.1
rajit:bootstrap3-datepicker-el@1.7.1
rajit:bootstrap3-datepicker-en-au@1.7.1
rajit:bootstrap3-datepicker-en-ca@1.7.1
rajit:bootstrap3-datepicker-en-gb@1.7.1
rajit:bootstrap3-datepicker-en-ie@1.7.1
rajit:bootstrap3-datepicker-en-nz@1.7.1
rajit:bootstrap3-datepicker-en-za@1.7.1
rajit:bootstrap3-datepicker-eo@1.7.1
rajit:bootstrap3-datepicker-es@1.7.1
rajit:bootstrap3-datepicker-et@1.7.1
rajit:bootstrap3-datepicker-eu@1.7.1
rajit:bootstrap3-datepicker-fa@1.7.1
rajit:bootstrap3-datepicker-fi@1.7.1
rajit:bootstrap3-datepicker-fo@1.7.1
rajit:bootstrap3-datepicker-fr@1.7.1
rajit:bootstrap3-datepicker-fr-ch@1.7.1
rajit:bootstrap3-datepicker-gl@1.7.1
rajit:bootstrap3-datepicker-he@1.7.1
rajit:bootstrap3-datepicker-hi@1.7.1
rajit:bootstrap3-datepicker-hr@1.7.1
rajit:bootstrap3-datepicker-hu@1.7.1
rajit:bootstrap3-datepicker-hy@1.7.1
rajit:bootstrap3-datepicker-id@1.7.1
rajit:bootstrap3-datepicker-is@1.7.1
rajit:bootstrap3-datepicker-it@1.7.1
rajit:bootstrap3-datepicker-it-ch@1.7.1
rajit:bootstrap3-datepicker-ja@1.7.1
rajit:bootstrap3-datepicker-ka@1.7.1
rajit:bootstrap3-datepicker-kh@1.7.1
rajit:bootstrap3-datepicker-kk@1.7.1
rajit:bootstrap3-datepicker-km@1.7.1
rajit:bootstrap3-datepicker-ko@1.7.1
rajit:bootstrap3-datepicker-kr@1.7.1
rajit:bootstrap3-datepicker-lv@1.7.1
rajit:bootstrap3-datepicker-me@1.7.1
rajit:bootstrap3-datepicker-mk@1.7.1
rajit:bootstrap3-datepicker-mn@1.7.1
rajit:bootstrap3-datepicker-ms@1.7.1
rajit:bootstrap3-datepicker-nb@1.7.1
rajit:bootstrap3-datepicker-nl@1.7.1
rajit:bootstrap3-datepicker-nl-be@1.7.1
rajit:bootstrap3-datepicker-no@1.7.1
rajit:bootstrap3-datepicker-oc@1.7.1
rajit:bootstrap3-datepicker-pl@1.7.1
rajit:bootstrap3-datepicker-pt@1.7.1
rajit:bootstrap3-datepicker-pt-br@1.7.1
rajit:bootstrap3-datepicker-ro@1.7.1
rajit:bootstrap3-datepicker-rs@1.7.1
rajit:bootstrap3-datepicker-rs-latin@1.7.1
rajit:bootstrap3-datepicker-ru@1.7.1
rajit:bootstrap3-datepicker-sk@1.7.1
rajit:bootstrap3-datepicker-sl@1.7.1
rajit:bootstrap3-datepicker-sq@1.7.1
rajit:bootstrap3-datepicker-sr@1.7.1
rajit:bootstrap3-datepicker-sr-latin@1.7.1
rajit:bootstrap3-datepicker-sv@1.7.1
rajit:bootstrap3-datepicker-sw@1.7.1
rajit:bootstrap3-datepicker-ta@1.7.1
rajit:bootstrap3-datepicker-tg@1.7.1
rajit:bootstrap3-datepicker-th@1.7.1
rajit:bootstrap3-datepicker-tr@1.7.1
rajit:bootstrap3-datepicker-uk@1.7.1
rajit:bootstrap3-datepicker-uz-cyrl@1.7.1
rajit:bootstrap3-datepicker-uz-latn@1.7.1
rajit:bootstrap3-datepicker-vi@1.7.1
rajit:bootstrap3-datepicker-zh-cn@1.7.1
rajit:bootstrap3-datepicker-zh-tw@1.7.1
@@ -214,7 +243,6 @@ templating-compiler@1.4.1
templating-runtime@1.5.0
templating-tools@1.2.2
tracker@1.3.2
twbs:bootstrap@3.3.6
ui@1.0.13
underscore@1.0.13
url@1.3.2
+283 -3
View File
@@ -1,5 +1,7 @@
[Mac ChangeLog](https://github.com/wekan/wekan/wiki/Mac)
Newest Node.js is at https://github.com/wekan/node-v14-esm/releases/tag/v14.21.4
Required versions of Node.js, MongoDB etc are listed at https://wekan.github.io
Download section.
@@ -18,13 +20,291 @@ Note:
[How to upgrade WeKan](https://github.com/wekan/wekan/issues/4585)
# Upcoming v7.00 WeKan ® release
# v7.03 2023-08-02 WeKan ® release
This version number and and some before it is reserved for upcoming PR from mfilser.
This release fixes the following bugs:
- [Fix return value of edit_custom_field_dropdown_item](https://github.com/wekan/wekan/pull/5047).
Thanks to Pandetthe.
- [Move authentication UI handling in correct place](https://github.com/wekan/wekan/pull/5049).
Thanks to nebulade.
Thanks to above GitHub users for their contributions and translators for their translations.
# v7.02 2023-08-02 WeKan ® release
This release adds the following new features:
- Speed improvements to Board and List loading.
- [Make swimlane height and list width adjustable](https://github.com/wekan/wekan/pull/4964).
Thanks to mark-i-m.
- [Don't translate swimlane height and list width minimum value](https://github.com/wekan/wekan/commit/7baf7d2256b87f66aa31ee282e08ebbd4564202d).
Thanks to xet7.
and adds the following updates:
- [Upgrade to Meteor 2.13 and Node.js 14.21.4](https://github.com/wekan/wekan/commit/caa8d087389b3f212c5eb4b7f538f3ad7c8c1227).
Thanks to Meteor developers.
- [Upgrade WeKan Docker to Node.js 14.21.4](https://github.com/wekan/wekan/commit/8dc7aa490a456cbf3207d266470febe69c0d5b6a).
Thanks to Meteor and xet7.
- [Upgrade to MongoDB 6.0.8 in Snap Candidate](https://github.com/wekan/wekan/commit/a773abaf2f4c77cbf586e2b0cba7b9ce412527ef).
Thanks to MongoDB developers.
- [Upgrade WeKan Snap Candidate to Node.js 14.21.4](https://github.com/wekan/wekan/commit/0161f19ba7ac63c40933bb4550f5397ddecd3452).
Thanks to Meteor and xet7.
- [Upgrade WeKan StackSmith to Node.js 14.21.4](https://github.com/wekan/wekan/commit/f0620ce8800eccff4da822048f90ee4812560937).
Thanks to Meteor and xet7.
- [Upgrade to Node.js 14.21.4 at build scripts and remaining Docker containers](https://github.com/wekan/wekan/commit/9f6e6bdc8193d86387166468578a6a24811ca9ec).
Thanks to Meteor and xet7.
and fixes the following bugs:
- [Only selectively show login elements once settings is loaded](https://github.com/wekan/wekan/pull/5032).
Thanks to nebulade.
- [First registration after installation must be an admin account](https://github.com/wekan/wekan/pull/5037).
Thanks to mfilser.
- [Fix get_board_cards_count](https://github.com/wekan/wekan/pull/5040).
Thanks to Pandetthe.
- [Login layout code cleanup](https://github.com/wekan/wekan/pull/5041).
Thanks to nebulade.
- [Drag board made translateable](https://github.com/wekan/wekan/commit/62c2d59f469a3e4d11df010ed65561defdda991f).
Thanks to xet7.
- [Fixed v7.01.0 fresh install in listview first column small](https://github.com/wekan/wekan/commit/7b607b2aaf852b550d968c2f1ec17f53fb5d686e).
Thanks to intellekta and xet7.
- [Fix assignees description](https://github.com/wekan/wekan/pull/5043).
Thanks to Pandetthe.
Thanks to above GitHub users for their contributions and translators for their translations.
# v7.01 2023-07-21 WeKan ® release
This release fixes the following bugs:
- [Fix for Calendar View Create Card](https://github.com/wekan/wekan/pull/5019).
Thanks to DimDz.
- [Minicard didn't show the assignee](https://github.com/wekan/wekan/pull/5021).
Thanks to mfilser.
- [Helm Chart: Add imagePullPolicy to initContainer. Needed for running wekan when restarting while offline](https://github.com/wekan/charts/pull/21).
Thanks to jadams.
- [Removing Utils.getCurrentSetting() and use ReactiveCache directly](https://github.com/wekan/wekan/pull/5022).
Thanks to mfilser.
- [Attachment rename and delete works now again for non board admins](https://github.com/wekan/wekan/pull/5023).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v7.00 2023-07-19 WeKan ® release
This release adds the following new features:
- [Speed improvements to Board and List loading](https://github.com/wekan/wekan/pull/5014).
Thanks to mfilser.
and adds the following updates:
- [Forked meteor-globals and meteor-reactive-cache to @wekanteam/meteor-globals and @wekanteam/meteor-reactive-cache to update to newest dependencies](https://github.com/wekan/wekan/commit/1c5857f0646658b121d7612b6176ec5e09c68592).
Thanks to xet7.
and fixes the following bugs:
- [Added missing @babel/runtime](https://github.com/wekan/wekan/commit/60cb5fb0176ecb623d494613aab196f252c16752).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.99.9 2023-07-18 WeKan ® release
This release fixes the following bugs:
- [Fix "PROPAGATE_OIDC_DATA" mechanism if "info.groups" is undefined](https://github.com/wekan/wekan/pull/5011).
Thanks to NotTheEvilOne.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.99.8 2023-07-13 WeKan ® release
This release fixes the following bugs:
- [Fix card creation. Now date fields are checked if they are empty](https://github.com/wekan/wekan/pull/5009).
Thanks to helioguardabaxo.
- [Helm Chart: Changes for Openshift](https://github.com/wekan/charts/pull/20).
Thanks to salleman33.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.99.7 2023-07-11 WeKan ® release
This release adds the following updates:
- [Updated dependencies](https://github.com/wekan/wekan/pull/5008).
Thanks to dependabot.
and fixes the following bugs:
- [Fix setting background image](https://github.com/wekan/wekan/pull/5004).
Thanks to VidVidex.
- [Added missing character](https://github.com/wekan/wekan/commit/4431ec5a2761d56685d2fca1202679b9bdcd9b81).
Thanks to xet7.
- [Added back datepicker](https://github.com/wekan/wekan/commit/912479baa48354a68bc807737a3db7975a4cb95c).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.99.5 2023-07-10 WeKan ® release
This release fixes the following bugs:
- [Reverted bold of minicard title](https://github.com/wekan/wekan/commit/c7dc912dd4403845a123d9202e930c886788db5b).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.99.4 2023-07-10 WeKan ® release
This release fixes the following bugs:
- [Disable migration attachment-cardCopy-fix-boardId-etc. Part 3](https://github.com/wekan/wekan/commit/34fef627a1c02700650fa97fb0fd1d3a36d79776).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.99.3 2023-07-10 WeKan ® release
This release fixes the following bugs:
- [Fix migration attachment-cardCopy-fix-boardId-etc. Part 2](https://github.com/wekan/wekan/commit/8555c24eb21134eda9b4d71494676b39d126ef35).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.99.2 2023-07-10 WeKan ® release
This release adds the following updates:
- [Updated dependencies](https://github.com/wekan/wekan/pull/5001).
Thanks to dependabot.
and fixes the following bugs:
- [Added back npm packages: fibers and @mapbox/node-pre-gyp](https://github.com/wekan/wekan/commit/8bf40e219a9fa55b8f2ef19dbf6acc58d646b968).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.99.1 2023-07-10 WeKan ® release
This release adds the following updates:
- [Updated dependencies](https://github.com/wekan/wekan/commit/95d3e5cdc6136a9778bf7c84812a6d62ef6d4044).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Fix for migration "attachment-cardCopy-fix-boardId-etc"](https://github.com/wekan/wekan/pull/4999).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.99 2023-07-09 WeKan ® release
This release adds the following new features:
- [Preview PDF](https://github.com/wekan/wekan/pull/4989).
Thanks to VidVidex.
- [Preview PDF translations](https://github.com/wekan/wekan/commit/83ae1d4a19925363d8f176553fb10a98a77420be).
Thanks xet7.
- [Preview PDF to have full width, close at top, and improve viewing at mobile](https://github.com/wekan/wekan/commit/4be5727a18472920ed775b8a2024b9c8ca2fdf0a).
Thanks to xet7.
- [Show Meteor dependency chain with rebuild-wekan.sh](https://github.com/wekan/wekan/commit/ba9f9705d43189d2491266af1fd4817ff34a3b59).
Thanks to xet7.
and adds the following updates:
- [Updated dependencies](https://github.com/wekan/wekan/commit/92c57fc91ea063914730647d0add8dae77187424).
Thanks to developers of dependencies.
- Added Snap MONGO_URL to rebuild-wekan.sh dev options.
[Part 1](https://github.com/wekan/wekan/commit/7d59ae93f9263c383a1c8c8605490d54b1e09ed7),
[Part 2](https://github.com/wekan/wekan/commit/3c2cc351f4bbe82b6870bab0e1891823c359e789).
Thanks to xet7.
- [MongoDB 6.0.7 at Snap](https://github.com/wekan/wekan/commit/5babe0358deae4b01261ee8655ec0e5a38f0344d).
Thanks to MongoDB developers.
and fixes the following bugs:
- [New popup scrolls to top and restore previous position after closing again](https://github.com/wekan/wekan/pull/4979).
Thanks to mfilser.
- [Copy Checklist dialog now set's the last selected board](https://github.com/wekan/wekan/pull/4980).
Thanks to mfilser.
- [Copy Checklist only copied the checklist items at the first time, now always](https://github.com/wekan/wekan/pull/4981).
Thanks to mfilser.
- [Attachment copy changes now the boardId, listId and swimlaneId in the collection data](https://github.com/wekan/wekan/pull/4982).
Thanks to mfilser.
- [Admin attachment view was missing the column header "S3FileId"](https://github.com/wekan/wekan/pull/4983).
Thanks to mfilser.
- [Global Search, limit 0 is no limit](https://github.com/wekan/wekan/pull/4984).
Thanks to mfilser.
- [Admin Report, fixing filesize if not a number](https://github.com/wekan/wekan/pull/4985).
Thanks to mfilser.
- [Global search, found cards count is now substituted by the translation function itself](https://github.com/wekan/wekan/pull/4986).
Thanks to mfilser.
- [Utils of canModifyCard and canModifyBoard + move this general functions to Utils class](https://github.com/wekan/wekan/pull/4987).
Thanks to mfilser.
- Set background color only if it exists.
[Part 1](https://github.com/wekan/wekan/commit/45d33fa2e459717064969a1729e016d4004e5435),
[Part 2](https://github.com/wekan/wekan/commit/c6cad13f1e86fea44c7c16e1a194c6d7164e824a),
[Part 3](https://github.com/wekan/wekan/commit/549b15000b538d6e5013cc978c0f49e753fd903a).
Thanks to xet7.
- [If there is no Custom Field label at minicard, show value full width](https://github.com/wekan/wekan/commit/ffea7aff99db555d357876e1415f9015154782cc).
Thanks to koluka and xet7.
- API: Fix /api/boards/{boardId}/attachments endpoint.
[Part 1](https://github.com/wekan/wekan/pull/4991),
[Part 2](https://github.com/wekan/wekan/pull/4992).
Thanks to VidVidex.
- [Improved attachment gallery and attachment viewer](https://github.com/wekan/wekan/pull/4995).
Thanks to VidVidex.
- [Removed horka:swipebox](https://github.com/wekan/wekan/commit/4148238af31ad31b6190221ad69db865f9ed5ccc).
Thanks to VidVidex and xet7.
- [Bold minicard custom field title](https://github.com/wekan/wekan/pull/4993).
Thanks to VidVidex.
- [Revert first list width change](https://github.com/wekan/wekan/pull/4993).
Thanks to xet7.
- [Fixed maximum call stack exceeded by removing bootstrap 3, datepicker and summernote. Updated jquery. Disabled attachments viewer that opens empty when opening card. Fixes all npm audit errors](https://github.com/wekan/wekan/commit/140a134a11d0b262f69e4f343dddddb87c978748).
Thanks to xet7.
- [Fix attachment viewer not being hidden](https://github.com/wekan/wekan/pull/4997).
Thanks to VidVidex.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.98 2023-06-22 WeKan ® release
This release adds the following new features:
- Add checklist at top.
[Part 1](https://github.com/wekan/wekan/pull/4973),
[Part 2](https://github.com/wekan/wekan/pull/4974).
Thanks to mfilser.
and adds the following updates:
- [Update rebuild-wekan.sh to use local network IP address](https://github.com/wekan/wekan/commit/6479c6a5c516ade68d50849115367be90d3199a2).
Thanks to xet7.
- Update GitHub Actions.
[Part 1](https://github.com/wekan/wekan/pull/4970),
[Part 2](https://github.com/wekan/wekan/pull/4971).
Thanks to dependabot.
and adds the following upcoming translations:
- [Added translations: Cantonese (China) (yue_CN) and Chinese Traditional (zh-Hant)](https://github.com/wekan/wekan/commit/dc2835d3410fcd7fd376a2be765c63236696605e).
Thanks to translators.
and fixes the following bugs:
- [Wait until user has logged in before fetching language preference](https://github.com/wekan/wekan/pull/4968).
Thanks to simon816.
- [Always fetch favicons from / path](https://github.com/wekan/wekan/commit/4d9f76cc68f435b1bbeeb51833dbce931f626b6d).
Thanks to nebulade.
- [Rounding sort number to next integer](https://github.com/wekan/wekan/pull/4975).
Thanks to mfilser.
- [Reduce list scroll speed while drag/drop the minicard](https://github.com/wekan/wekan/pull/4976).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
+10 -6
View File
@@ -21,8 +21,8 @@ ARG DEBIAN_FRONTEND=noninteractive
ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-essential git ca-certificates python3" \
DEBUG=false \
NODE_VERSION=v14.21.3 \
METEOR_RELEASE=METEOR@2.12-beta.2 \
NODE_VERSION=v14.21.4 \
METEOR_RELEASE=METEOR@2.13 \
USE_EDGE=false \
METEOR_EDGE=1.5-beta.17 \
NPM_VERSION=latest \
@@ -185,13 +185,17 @@ RUN \
ln -sf $(which bsdtar) $(which tar) && \
\
# Download nodejs
wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
wget https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt.asc && \
wget https://github.com/wekan/node-v14-esm/releases/download/${NODE_VERSION}/node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
wget https://github.com/wekan/node-v14-esm/releases/download/${NODE_VERSION}/SHASUMS256.txt && \
#wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
#wget https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt.asc && \
#---------------------------------------------------------------------------------------------
\
# Verify nodejs authenticity
grep ${NODE_VERSION}-${ARCHITECTURE}.tar.gz SHASUMS256.txt.asc | shasum -a 256 -c - && \
rm -f SHASUMS256.txt.asc && \
grep node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz SHASUMS256.txt | shasum -a 256 -c - && \
rm -f SHASUMS256.txt && \
#grep ${NODE_VERSION}-${ARCHITECTURE}.tar.gz SHASUMS256.txt.asc | shasum -a 256 -c - && \
#rm -f SHASUMS256.txt.asc && \
\
# Install Node
tar xvzf node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
+5 -3
View File
@@ -4,7 +4,7 @@ FROM amd64/alpine:3.7 AS builder
ENV QEMU_VERSION=v4.2.0-6 \
QEMU_ARCHITECTURE=aarch64 \
NODE_ARCHITECTURE=linux-arm64 \
NODE_VERSION=v14.21.3 \
NODE_VERSION=v14.21.4 \
WEKAN_VERSION=latest \
WEKAN_ARCHITECTURE=arm64 \
NODE_OPTIONS="--max_old_space_size=4096"
@@ -33,8 +33,10 @@ RUN apk update && apk add ca-certificates outils-sha1 && \
unzip wekan-${WEKAN_VERSION}-${WEKAN_ARCHITECTURE}.zip && \
\
# Download node and shasums
wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-${NODE_ARCHITECTURE}.tar.gz && \
wget https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt.asc && \
#wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-${NODE_ARCHITECTURE}.tar.gz && \
#wget https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt.asc && \
#wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-${NODE_ARCHITECTURE}.tar.gz && \
#wget https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt.asc && \
\
# Verify nodejs authenticity
grep node-${NODE_VERSION}-${NODE_ARCHITECTURE}.tar.gz SHASUMS256.txt.asc | sha256sum -c - && \
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v6.97.0"
appVersion: "v7.03.0"
files:
userUploads:
- README.md
+15 -13
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import DOMPurify from 'dompurify';
import { TAPi18n } from '/imports/i18n';
@@ -24,7 +25,7 @@ BlazeComponent.extendComponent({
searchId = Session.get(`current${capitalizedMode}`);
}
const limit = this.page.get() * activitiesPerPage;
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
const hideSystem = user ? user.hasHiddenSystemMessages() : false;
if (searchId === null) return;
@@ -65,7 +66,7 @@ Template.activities.helpers({
BlazeComponent.extendComponent({
checkItem() {
const checkItemId = this.currentData().activity.checklistItemId;
const checkItem = ChecklistItems.findOne({ _id: checkItemId });
const checkItem = ReactiveCache.getChecklistItem(checkItemId);
return checkItem && checkItem.title;
},
@@ -145,7 +146,7 @@ BlazeComponent.extendComponent({
lastLabel() {
const lastLabelId = this.currentData().activity.labelId;
if (!lastLabelId) return null;
const lastLabel = Boards.findOne(
const lastLabel = ReactiveCache.getBoard(
this.currentData().activity.boardId,
).getLabelById(lastLabelId);
if (lastLabel && (lastLabel.name === undefined || lastLabel.name === '')) {
@@ -158,7 +159,7 @@ BlazeComponent.extendComponent({
},
lastCustomField() {
const lastCustomField = CustomFields.findOne(
const lastCustomField = ReactiveCache.getCustomField(
this.currentData().activity.customFieldId,
);
if (!lastCustomField) return null;
@@ -166,7 +167,7 @@ BlazeComponent.extendComponent({
},
lastCustomFieldValue() {
const lastCustomField = CustomFields.findOne(
const lastCustomField = ReactiveCache.getCustomField(
this.currentData().activity.customFieldId,
);
if (!lastCustomField) return null;
@@ -282,10 +283,10 @@ Template.activity.helpers({
Template.commentReactions.events({
'click .reaction'(event) {
if (Meteor.user().isBoardMember()) {
if (ReactiveCache.getCurrentUser().isBoardMember()) {
const codepoint = event.currentTarget.dataset['codepoint'];
const commentId = Template.instance().data.commentId;
const cardComment = CardComments.findOne({_id: commentId});
const cardComment = ReactiveCache.getCardComment(commentId);
cardComment.toggleReaction(codepoint);
}
},
@@ -294,10 +295,10 @@ Template.commentReactions.events({
Template.addReactionPopup.events({
'click .add-comment-reaction'(event) {
if (Meteor.user().isBoardMember()) {
if (ReactiveCache.getCurrentUser().isBoardMember()) {
const codepoint = event.currentTarget.dataset['codepoint'];
const commentId = Template.instance().data.commentId;
const cardComment = CardComments.findOne({_id: commentId});
const cardComment = ReactiveCache.getCardComment(commentId);
cardComment.toggleReaction(codepoint);
}
Popup.back();
@@ -325,12 +326,13 @@ Template.addReactionPopup.helpers({
Template.commentReactions.helpers({
isSelected(userIds) {
return userIds.includes(Meteor.user()._id);
return Meteor.userId() && userIds.includes(Meteor.userId());
},
userNames(userIds) {
return Users.find({_id: {$in: userIds}})
.map(user => user.profile.fullname)
.join(', ');
const ret = ReactiveCache.getUsers({_id: {$in: userIds}})
.map(user => user.profile.fullname)
.join(', ');
return ret;
}
})
+3 -1
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
const commentFormIsOpen = new ReactiveVar(false);
BlazeComponent.extendComponent({
@@ -24,7 +26,7 @@ BlazeComponent.extendComponent({
let boardId = card.boardId;
let cardId = card._id;
if (card.isLinkedCard()) {
boardId = Cards.findOne(card.linkedId).boardId;
boardId = ReactiveCache.getCard(card.linkedId).boardId;
cardId = card.linkedId;
} else if (card.isLinkedBoard()) {
boardId = card.linkedId;
+9 -6
View File
@@ -1,19 +1,22 @@
import { ReactiveCache } from '/imports/reactiveCache';
BlazeComponent.extendComponent({
onCreated() {
this.subscribe('archivedBoards');
},
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
archivedBoards() {
return Boards.find(
const ret = ReactiveCache.getBoards(
{ archived: true },
{
sort: { archivedAt: -1, modifiedAt: -1 },
},
);
return ret;
},
events() {
@@ -25,8 +28,8 @@ BlazeComponent.extendComponent({
Meteor.settings &&
Meteor.settings.public &&
Meteor.settings.public.sandstorm;
if (isSandstorm && Session.get('currentBoard')) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (isSandstorm && Utils.getCurrentBoardId()) {
const currentBoard = Utils.getCurrentBoard();
currentBoard.archive();
}
const board = this.currentData();
@@ -39,8 +42,8 @@ BlazeComponent.extendComponent({
Meteor.settings &&
Meteor.settings.public &&
Meteor.settings.public.sandstorm;
if (isSandstorm && Session.get('currentBoard')) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (isSandstorm && Utils.getCurrentBoardId()) {
const currentBoard = Utils.getCurrentBoard();
Boards.remove(currentBoard._id);
}
Boards.remove(this._id);
+19 -1
View File
@@ -168,11 +168,28 @@
color: #fff !important;
}
/* Modal Styles */
.modal {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
background-color: rgba(0, 0, 0, 0.5);
width: 100%;
height: 100%;
}
.modal-dialog {
display: flex;
justify-content: center;
align-items: center;
height: 70%;
height: 25%; /* Adjust the height to make it smaller */
position: relative;
margin: 10% auto; /* This margin will help center the modal vertically */
max-width: 400px; /* Adjust the max-width to make it smaller */
background-color: #fff;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
.modal-header {
display: flex;
@@ -203,4 +220,5 @@
top: 5px;
right: 5px;
font-size: 25px;
cursor: pointer;
}
+57 -51
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
const subManager = new SubsManager();
@@ -43,9 +44,9 @@ BlazeComponent.extendComponent({
this.mouseHasEnterCardDetails = false;
// fix swimlanes sort field if there are null values
const currentBoardData = Boards.findOne(Session.get('currentBoard'));
const currentBoardData = Utils.getCurrentBoard();
const nullSortSwimlanes = currentBoardData.nullSortSwimlanes();
if (nullSortSwimlanes.count() > 0) {
if (nullSortSwimlanes.length > 0) {
const swimlanes = currentBoardData.swimlanes();
let count = 0;
swimlanes.forEach(s => {
@@ -60,7 +61,7 @@ BlazeComponent.extendComponent({
// fix lists sort field if there are null values
const nullSortLists = currentBoardData.nullSortLists();
if (nullSortLists.count() > 0) {
if (nullSortLists.length > 0) {
const lists = currentBoardData.lists();
let count = 0;
lists.forEach(l => {
@@ -204,33 +205,26 @@ BlazeComponent.extendComponent({
}
// Disable drag-dropping if the current user is not a board member
//$swimlanesDom.sortable('option', 'disabled', !userIsMember());
$swimlanesDom.sortable(
'option',
'disabled',
!Meteor.user() || !Meteor.user().isBoardAdmin(),
!ReactiveCache.getCurrentUser()?.isBoardAdmin(),
);
});
function userIsMember() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
}
// If there is no data in the board (ie, no lists) we autofocus the list
// creation form by clicking on the corresponding element.
const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (userIsMember() && currentBoard.lists().count() === 0) {
const currentBoard = Utils.getCurrentBoard();
if (Utils.canModifyBoard() && currentBoard.lists().length === 0) {
boardComponent.openNewListForm();
}
Utils.setBackgroundImage();
},
notDisplayThisBoard() {
let allowPrivateVisibilityOnly = TableVisibilityModeSettings.findOne('tableVisibilityMode-allowPrivateOnly');
let currentBoard = Boards.findOne(Session.get('currentBoard'));
let currentBoard = Utils.getCurrentBoard();
if (allowPrivateVisibilityOnly !== undefined && allowPrivateVisibilityOnly.booleanValue && currentBoard.permission == 'public') {
return true;
}
@@ -239,7 +233,7 @@ BlazeComponent.extendComponent({
},
isViewSwimlanes() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).boardView === 'board-view-swimlanes';
} else {
@@ -250,7 +244,7 @@ BlazeComponent.extendComponent({
},
isViewLists() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).boardView === 'board-view-lists';
} else {
@@ -259,7 +253,7 @@ BlazeComponent.extendComponent({
},
isViewCalendar() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).boardView === 'board-view-cal';
} else {
@@ -350,7 +344,7 @@ BlazeComponent.extendComponent({
},
locale: TAPi18n.getLanguage(),
events(start, end, timezone, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
const events = [];
const pushEvent = function (card, title, start, end, extraCls) {
start = start || card.startAt;
@@ -396,7 +390,7 @@ BlazeComponent.extendComponent({
},
eventResize(event, delta, revertFunc) {
let isOk = false;
const card = Cards.findOne(event.id);
const card = ReactiveCache.getCard(event.id);
if (card) {
card.setEnd(event.end.toDate());
@@ -408,7 +402,7 @@ BlazeComponent.extendComponent({
},
eventDrop(event, delta, revertFunc) {
let isOk = false;
const card = Cards.findOne(event.id);
const card = ReactiveCache.getCard(event.id);
if (card) {
// TODO: add a flag for allDay events
if (!event.allDay) {
@@ -423,35 +417,37 @@ BlazeComponent.extendComponent({
revertFunc();
}
},
select: function(startDate) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentUser = Meteor.user();
const $modal = $(`
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog justify-content-center align-items-center" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">${TAPi18n.__('r-create-card')}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body text-center">
<input type="text" class="form-control" id="card-title-input" placeholder="">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="create-card-button">${TAPi18n.__('add-card')}</button>
</div>
</div>
select: function (startDate) {
const currentBoard = Utils.getCurrentBoard();
const currentUser = ReactiveCache.getCurrentUser();
const modalElement = document.createElement('div');
modalElement.classList.add('modal', 'fade');
modalElement.setAttribute('tabindex', '-1');
modalElement.setAttribute('role', 'dialog');
modalElement.innerHTML = `
<div class="modal-dialog justify-content-center align-items-center" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">${TAPi18n.__('r-create-card')}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body text-center">
<input type="text" class="form-control" id="card-title-input" placeholder="">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="create-card-button">${TAPi18n.__('add-card')}</button>
</div>
</div>
`);
$modal.modal('show');
$modal.find('#create-card-button').click(function() {
const myTitle = $modal.find('#card-title-input').val();
</div>
`;
const createCardButton = modalElement.querySelector('#create-card-button');
createCardButton.addEventListener('click', function () {
const myTitle = modalElement.querySelector('#card-title-input').value;
if (myTitle) {
const firstList = currentBoard.draggableLists().fetch()[0];
const firstSwimlane = currentBoard.swimlanes().fetch()[0];
const firstList = currentBoard.draggableLists()[0];
const firstSwimlane = currentBoard.swimlanes()[0];
Meteor.call('createCardWithDueDate', currentBoard._id, firstList._id, myTitle, startDate.toDate(), firstSwimlane._id, function(error, result) {
if (error) {
console.log(error);
@@ -459,14 +455,24 @@ BlazeComponent.extendComponent({
console.log("Card Created", result);
}
});
$modal.modal('hide');
closeModal();
}
});
},
document.body.appendChild(modalElement);
const openModal = function() {
modalElement.style.display = 'flex';
};
const closeModal = function() {
modalElement.style.display = 'none';
};
const closeButton = modalElement.querySelector('[data-dismiss="modal"]');
closeButton.addEventListener('click', closeModal);
openModal();
}
};
},
isViewCalendar() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).boardView === 'board-view-cal';
} else {
+3 -3
View File
@@ -1976,7 +1976,7 @@
background-color: #ccc;
color: #222;
}
.board-color-moderndark .attachments-galery .attachment-item {
.board-color-moderndark .attachments-gallery .attachment-item {
color: #222;
}
.board-color-moderndark .minicard-description {
@@ -2148,10 +2148,10 @@
.board-color-exodark .sidebar-content {
box-shadow: 0 0 7px 0 #00897b;
}
.board-color-exodark .attachments-galery .attachment-item {
.board-color-exodark .attachments-gallery .attachment-item {
background: #2b2b2b;
}
.board-color-exodark .attachments-galery .attachment-item:hover {
.board-color-exodark .attachments-gallery .attachment-item:hover {
border: 1px solid #00897b;
background: #2b2b2b;
}
+18 -24
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
/*
@@ -18,14 +19,14 @@ Template.boardMenuPopup.events({
'click .js-change-board-color': Popup.open('boardChangeColor'),
'click .js-change-language': Popup.open('changeLanguage'),
'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
currentBoard.archive();
// XXX We should have some kind of notification on top of the page to
// confirm that the board was successfully archived.
FlowRouter.go('home');
}),
'click .js-delete-board': Popup.afterConfirm('deleteBoard', function() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
Popup.back();
Boards.remove(currentBoard._id);
FlowRouter.go('home');
@@ -58,24 +59,24 @@ Template.boardChangeTitlePopup.events({
BlazeComponent.extendComponent({
watchLevel() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return currentBoard && currentBoard.getWatchLevel(Meteor.userId());
},
isStarred() {
const boardId = Session.get('currentBoard');
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
return user && user.hasStarred(boardId);
},
// Only show the star counter if the number of star is greater than 2
showStarCounter() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return currentBoard && currentBoard.stars >= 2;
},
/*
showSort() {
return Meteor.user().hasSortBy();
return ReactiveCache.getCurrentUser().hasSortBy();
},
directionClass() {
return this.currentDirection() === -1 ? DOWNCLS : UPCLS;
@@ -85,10 +86,10 @@ BlazeComponent.extendComponent({
Meteor.call('setListSortBy', direction + this.currentListSortBy());
},
currentDirection() {
return Meteor.user().getListSortByDirection();
return ReactiveCache.getCurrentUser().getListSortByDirection();
},
currentListSortBy() {
return Meteor.user().getListSortBy();
return ReactiveCache.getCurrentUser().getListSortBy();
},
listSortShortDesc() {
return `list-label-short-${this.currentListSortBy()}`;
@@ -99,7 +100,7 @@ BlazeComponent.extendComponent({
{
'click .js-edit-board-title': Popup.open('boardChangeTitle'),
'click .js-star-board'() {
Meteor.user().toggleBoardStar(Session.get('currentBoard'));
ReactiveCache.getCurrentUser().toggleBoardStar(Session.get('currentBoard'));
},
'click .js-open-board-menu': Popup.open('boardMenu'),
'click .js-change-visibility': Popup.open('boardChangeVisibility'),
@@ -158,13 +159,6 @@ BlazeComponent.extendComponent({
}).register('boardHeaderBar');
Template.boardHeaderBar.helpers({
canModifyBoard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
boardView() {
return Utils.boardView();
},
@@ -313,7 +307,7 @@ const CreateBoard = BlazeComponent.extendComponent({
onSubmit(event) {
super.onSubmit(event);
// Immediately star boards crated with the headerbar popup.
Meteor.user().toggleBoardStar(this.boardId.get());
ReactiveCache.getCurrentUser().toggleBoardStar(this.boardId.get());
}
}.register('headerBarCreateBoardPopup'));
@@ -322,12 +316,12 @@ BlazeComponent.extendComponent({
return !TableVisibilityModeSettings.findOne('tableVisibilityMode-allowPrivateOnly').booleanValue;
},
visibilityCheck() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return this.currentData() === currentBoard.permission;
},
selectBoardVisibility() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
const visibility = this.currentData();
currentBoard.setVisibility(visibility);
Popup.back();
@@ -344,7 +338,7 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
watchLevel() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return currentBoard.getWatchLevel(Meteor.userId());
},
@@ -384,7 +378,7 @@ BlazeComponent.extendComponent({
allowedSortValues() {
const types = [];
const pushed = {};
Meteor.user()
ReactiveCache.getCurrentUser()
.getListSortTypes()
.forEach(type => {
const key = type.replace(/^-/, '');
@@ -400,16 +394,16 @@ BlazeComponent.extendComponent({
return types;
},
Direction() {
return Meteor.user().getListSortByDirection() === -1
return ReactiveCache.getCurrentUser().getListSortByDirection() === -1
? this.downClass
: this.upClass;
},
sortby() {
return Meteor.user().getListSortBy();
return ReactiveCache.getCurrentUser().getListSortBy();
},
setSortBy(type = null) {
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
if (type === null) {
type = user._getListSortBy();
} else {
+2 -2
View File
@@ -65,7 +65,7 @@ template(name="boardList")
if isTouchScreenOrShowDesktopDragHandles
i.fa.board-handle(
class="fa-arrows"
title="{{_ 'Drag board'}}")
title="{{_ 'drag-board'}}")
else
if isSandstorm
i.fa.js-clone-board(
@@ -119,7 +119,7 @@ template(name="boardList")
if isTouchScreenOrShowDesktopDragHandles
i.fa.board-handle(
class="fa-arrows"
title="{{_ 'Drag board'}}")
title="{{_ 'drag-board'}}")
else
if isSandstorm
i.fa.js-clone-board(
+33 -60
View File
@@ -1,11 +1,9 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
const subManager = new SubsManager();
Template.boardList.helpers({
currentSetting() {
return Settings.findOne();
},
hideCardCounterList() {
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
return Utils.isMiniScreen() && Session.get('currentBoard'); */
@@ -33,10 +31,10 @@ Template.boardListHeaderBar.helpers({
//}
},
templatesBoardId() {
return Meteor.user() && Meteor.user().getTemplatesBoardId();
return ReactiveCache.getCurrentUser()?.getTemplatesBoardId();
},
templatesBoardSlug() {
return Meteor.user() && Meteor.user().getTemplatesBoardSlug();
return ReactiveCache.getCurrentUser()?.getTemplatesBoardSlug();
},
});
@@ -44,7 +42,7 @@ BlazeComponent.extendComponent({
onCreated() {
Meteor.subscribe('setting');
Meteor.subscribe('tableVisibilityModeSettings');
let currUser = Meteor.user();
let currUser = ReactiveCache.getCurrentUser();
let userLanguage;
if (currUser && currUser.profile) {
userLanguage = currUser.profile.language
@@ -102,51 +100,34 @@ BlazeComponent.extendComponent({
});
},
userHasTeams() {
if (Meteor.user() != null && Meteor.user().teams && Meteor.user().teams.length > 0)
if (ReactiveCache.getCurrentUser()?.teams?.length > 0)
return true;
else
return false;
},
teamsDatas() {
if (Meteor.user().teams)
return Meteor.user().teams.sort((a, b) => a.teamDisplayName.localeCompare(b.teamDisplayName));
const teams = ReactiveCache.getCurrentUser()?.teams
if (teams)
return teams.sort((a, b) => a.teamDisplayName.localeCompare(b.teamDisplayName));
else
return [];
},
userHasOrgs() {
if (Meteor.user() != null && Meteor.user().orgs && Meteor.user().orgs.length > 0)
if (ReactiveCache.getCurrentUser()?.orgs?.length > 0)
return true;
else
return false;
},
/*
userHasTemplates(){
if(Meteor.user() != null && Meteor.user().orgs && Meteor.user().orgs.length > 0)
return true;
else
return false;
},
*/
orgsDatas() {
if (Meteor.user().orgs)
return Meteor.user().orgs.sort((a, b) => a.orgDisplayName.localeCompare(b.orgDisplayName));
const orgs = ReactiveCache.getCurrentUser()?.orgs;
if (orgs)
return orgs.sort((a, b) => a.orgDisplayName.localeCompare(b.orgDisplayName));
else
return [];
},
userHasOrgsOrTeams() {
let boolUserHasOrgs;
if (Meteor.user() != null && Meteor.user().orgs && Meteor.user().orgs.length > 0)
boolUserHasOrgs = true;
else
boolUserHasOrgs = false;
let boolUserHasTeams;
if (Meteor.user() != null && Meteor.user().teams && Meteor.user().teams.length > 0)
boolUserHasTeams = true;
else
boolUserHasTeams = false;
return (boolUserHasOrgs || boolUserHasTeams);
const ret = this.userHasOrgs() || this.userHasTeams();
return ret;
},
boards() {
let query = {
@@ -168,14 +149,7 @@ BlazeComponent.extendComponent({
if (allowPrivateVisibilityOnly !== undefined && allowPrivateVisibilityOnly.booleanValue) {
query.$and.push({ 'permission': 'private' });
}
const currUser = Users.findOne(Meteor.userId());
// const currUser = Users.findOne(Meteor.userId(), {
// fields: {
// orgs: 1,
// teams: 1,
// },
// });
const currUser = ReactiveCache.getCurrentUser();
let orgIdsUserBelongs = currUser !== undefined && currUser.teams !== 'undefined' ? currUser.orgIdsUserBelongs() : '';
if (orgIdsUserBelongs && orgIdsUserBelongs != '') {
@@ -207,27 +181,28 @@ BlazeComponent.extendComponent({
};
}
return Boards.find(query, {
const ret = ReactiveCache.getBoards(query, {
sort: { sort: 1 /* boards default sorting */ },
});
return ret;
},
boardLists(boardId) {
let boardLists = [];
const lists = Lists.find({ 'boardId': boardId, 'archived': false },{sort: ['sort','asc']});
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
lists.forEach(list => {
let cardCount = Cards.find({ 'boardId': boardId, 'listId': list._id }).count()
boardLists.push(`${list.title}: ${cardCount}`);
const lists = ReactiveCache.getLists({ 'boardId': boardId, 'archived': false },{sort: ['sort','asc']});
const ret = lists.map(list => {
let cardCount = ReactiveCache.getCards({ 'boardId': boardId, 'listId': list._id }).length;
return `${list.title}: ${cardCount}`;
});
return ret;
*/
return boardLists;
return [];
},
boardMembers(boardId) {
let boardMembers = [];
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
const lists = Boards.findOne({ '_id': boardId })
let members = lists.members;
const lists = ReactiveCache.getBoard(boardId)
let members = lists.members
members.forEach(member => {
boardMembers.push(member.userId);
});
@@ -236,26 +211,24 @@ BlazeComponent.extendComponent({
},
isStarred() {
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
return user && user.hasStarred(this.currentData()._id);
},
isAdministrable() {
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
return user && user.isBoardAdmin(this.currentData()._id);
},
hasOvertimeCards() {
subManager.subscribe('board', this.currentData()._id, false);
return this.currentData().hasOvertimeCards();
},
hasSpentTimeCards() {
subManager.subscribe('board', this.currentData()._id, false);
return this.currentData().hasSpentTimeCards();
},
isInvited() {
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
return user && user.isInvitedTo(this.currentData()._id);
},
@@ -265,18 +238,18 @@ BlazeComponent.extendComponent({
'click .js-add-board': Popup.open('createBoard'),
'click .js-star-board'(evt) {
const boardId = this.currentData()._id;
Meteor.user().toggleBoardStar(boardId);
ReactiveCache.getCurrentUser().toggleBoardStar(boardId);
evt.preventDefault();
},
'click .js-clone-board'(evt) {
let title = getSlug(Boards.findOne(this.currentData()._id).title) || 'cloned-board';
let title = getSlug(ReactiveCache.getBoard(this.currentData()._id).title) || 'cloned-board';
Meteor.call(
'copyBoard',
this.currentData()._id,
{
sort: Boards.find({ archived: false }).count(),
sort: ReactiveCache.getBoards({ archived: false }).length,
type: 'board',
title: Boards.findOne(this.currentData()._id).title,
title: ReactiveCache.getBoard(this.currentData()._id).title,
},
(err, res) => {
if (err) {
@@ -350,7 +323,7 @@ BlazeComponent.extendComponent({
query.$and[2].$or.push({ 'orgs.orgId': { $in: selectedOrgsValues } });
}
let filteredBoards = Boards.find(query, {}).fetch();
let filteredBoards = ReactiveCache.getBoards(query, {});
let allBoards = document.getElementsByClassName("js-board");
let currBoard;
if (filteredBoards.length > 0) {
+159 -59
View File
@@ -1,90 +1,190 @@
.slide {
/* swipebox slide background gradient of black to blue, so that back SVG images are visible */
background: rgb(2,0,36);
background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 14%, rgba(0,212,255,1) 100%);
.hidden {
display: none;
}
.attachment-upload {
text-align: center;
font-weight: bold;
}
.attachments-galery {
.attachment-gallery {
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
.attachments-galery .attachment-item {
width: 31.33%;
margin: 10px 1% 0;
text-align: center;
border-radius: 3px;
overflow: auto;
background: #ededed;
min-height: 120px;
.attachment-item {
display: flex;
flex-direction: row;
align-items: center;
margin-top: 16px;
}
.attachments-galery .attachment-item:hover {
.attachment-item:hover {
background: #e0e0e0;
}
.attachments-galery .attachment-item.add-attachment {
display: flex;
align-items: center;
}
.attachments-galery .attachment-item.add-attachment a {
.attachment-thumbnail-container {
display: block;
margin: auto;
width: 150px;
min-width: 150px;
max-height: 150px;
padding-right: 16px;
}
.attachments-galery .attachment-item .attachment-thumbnail {
height: 80px;
.attachment-thumbnail {
max-width: 150px;
max-height: 150px;
min-height: 2em;
cursor: pointer;
}
.attachment-thumbnail-text {
min-height: 2em;
display: flex;
align-items: center;
justify-content: center;
position: relative;
font-size: 2em;
cursor: pointer;
border: 1px solid #ccc;
border-radius: 5px;
}
.attachments-galery .attachment-item .attachment-thumbnail .attachment-thumbnail-img {
max-height: 100%;
.attachment-details-container {
display: block;
flex-grow: 1;
}
.attachment-details {
display: flex;
justify-content: space-between;
margin-right: 25px; /* Make sure the icons are not to far to the right */
}
.attachment-actions {
display: flex;
flex-direction: row;
align-items: center;
}
.add-attachment {
display: flex;
align-items: center;
justify-content: center;
border: 1px dashed #555;
border-radius: 5px;
padding: 10px;
cursor: pointer;
margin-top: 16px;
}
.icon {
font-size: 1.5em;
cursor: pointer;
margin-left: 10px;
}
.icon:hover {
color: #666;
}
#viewer-overlay {
width: 100%;
height: 100vh;
position: fixed;
top: 48px; /* height of the navbar */
left: 0;
z-index: 9999 !important;
background: rgba(13,13,13,0.95);
}
#viewer-container {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100%;
}
#viewer-top-bar {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
padding: 16px;
}
#attachment-name {
color: white;
font-size: 1.5em;
max-width: calc(100% - 50px); /* Make sure the name does not overlap the close button */
}
#viewer-close {
color:white;
cursor: pointer;
font-size: 4em;
top: 0;
right: 8px;
position: absolute;
}
.attachment-arrow {
font-size: 4em;
color:white;
cursor: pointer;
align-self: center;
margin: 0 20px;
}
#image-viewer {
background:
repeating-conic-gradient(#808080 0% 25%, transparent 0% 50%)
50% / 20px 20px; /* Checkerboard background for transparent images */
max-width: 100%;
}
.attachments-galery .attachment-item .attachment-thumbnail .attachment-thumbnail-ext {
text-transform: uppercase;
font-size: 1.6em;
#pdf-viewer {
width: 40vw;
height: 100vh;
}
.attachments-galery .attachment-item .attachment-details {
font-size: 0.75em;
margin: 3px;
#txt-viewer{
background-color: white;
width: 40vw;
height: 100vh;
}
.attachments-galery .attachment-item .attachment-details .attachment-details-actions a {
.pdf-preview-error {
margin-top: 20vh;
display: block;
font-size: 2em;
color: white;
}
.attachments-galery .attachment-item .attachment-details .attachment-details-actions a.attachment-details-menu {
padding-top: 10px;
}
.attachment-image-preview {
max-width: 100px;
display: block;
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
}
.preview-clipboard-image {
width: 280px;
max-width: 100%;
height: 200px;
display: block;
border: 1px solid #000;
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
@media screen and (max-width: 1600px) {
#pdf-viewer {
width: 60vw;
}
}
@media screen and (max-width: 800px) {
.attachments-galery .attachment-item {
width: 48%;
#viewer-container {
display: block;
}
.attachments-galery .attachment-item .attachment-thumbnail {
height: 130px;
.attachment-arrow{
position: absolute;
bottom: 2.2em;
font-size: 1.6em;
padding: 16px;
}
.attachments-galery .attachment-item .attachment-details {
font-size: 1.1em;
#prev-attachment{
left: 0;
}
}
@media screen and (max-width: 360px) {
.attachments-galery .attachment-item {
#next-attachment{
right: 0;
}
#pdf-viewer {
width: 100%;
height: calc(100vh - 155px); /* Full height - height of top and bottom bars */
}
#txt-viewer {
width: 100%;
height: calc(100vh - 155px); /* Full height - height of top and bottom bars */
}
#audio-viewer {
margin-top: 20%;
width: 100%;
}
.attachments-galery .attachment-item .attachment-thumbnail {
height: 200px;
.attachment-thumbnail-container {
width: 100px;
min-width: 100px;
}
.attachment-thumbnail {
max-width: 100px;
}
.attachment-details {
flex-direction: column;
margin-right: 0px;
}
.attachment-actions {
flex-direction: row;
margin-top: 10px;
}
}
+54 -35
View File
@@ -30,47 +30,72 @@ template(name="attachmentDeletePopup")
p {{_ "attachment-delete-pop"}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
template(name="attachmentsGalery")
.attachments-galery
if currentUser.isBoardMember
unless currentUser.isCommentOnly
unless currentUser.isWorker
//li.attachment-item.add-attachment
a.js-add-attachment(title="{{_ 'add-attachment' }}")
i.fa.fa-plus
template(name="attachmentViewer")
#viewer-overlay.hidden
#viewer-top-bar
span#attachment-name
a#viewer-close.fa.fa-times-thin
#viewer-container
i.fa.fa-chevron-left.attachment-arrow#prev-attachment
#viewer-content
img#image-viewer.hidden
video#video-viewer.hidden(controls="true")
audio#audio-viewer.hidden(controls="true")
object#pdf-viewer.hidden(type="application/pdf")
span.pdf-preview-error {{_ 'preview-pdf-not-supported' }}
object#txt-viewer.hidden(type="text/plain")
i.fa.fa-chevron-right.attachment-arrow#next-attachment
template(name="attachmentGallery")
.attachment-gallery
a.attachment-item.add-attachment.js-add-attachment
i.fa.fa-plus.icon
each attachments
.attachment-item
a.attachment-thumbnail.swipebox(href="{{link}}" title="{{sanitize name}}")
.attachment-thumbnail-container.open-preview(data-attachment-id="{{_id}}" data-card-id="{{ meta.cardId }}")
if link
if($eq extension 'svg')
img.attachment-thumbnail-img(src="{{link}}" title="{{sanitize name}}" type="image/svg+xml")
else if isImage
img.attachment-thumbnail-img(src="{{link}}" title="{{sanitize name}}")
if(isImage)
img.attachment-thumbnail(src="{{link}}" title="{{sanitize name}}")
else if($eq extension 'svg')
img.attachment-thumbnail(src="{{link}}" title="{{sanitize name}}" type="image/svg+xml")
else if($eq extension 'mp3')
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
video.attachment-thumbnail(title="{{sanitize name}}")
source(src="{{link}}" type="audio/mpeg")
else if($eq extension 'ogg')
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
video.attachment-thumbnail(title="{{sanitize name}}")
source(src="{{link}}" type="video/ogg")
else if($eq extension 'webm')
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
video.attachment-thumbnail(title="{{sanitize name}}")
source(src="{{link}}" type="video/webm")
else if($eq extension 'mp4')
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
video.attachment-thumbnail(title="{{sanitize name}}")
source(src="{{link}}" type="video/mp4")
else
span.attachment-thumbnail-ext= extension
p.attachment-details
= name
span.file-size ({{fileSize size}})
span.attachment-details-actions
a.js-download(href="{{link}}?download=true", download="{{name}}")
i.fa.fa-download
| {{_ 'download'}}
if currentUser.isBoardMember
unless currentUser.isCommentOnly
unless currentUser.isWorker
a.fa.fa-navicon.attachment-details-menu.js-open-attachment-menu(title="{{_ 'attachmentActionsPopup-title'}}")
span.attachment-thumbnail-text= extension
.attachment-details-container
.attachment-details
div
b
= name
span.file-size ({{fileSize size}})
.attachment-actions
a.js-download(href="{{link}}?download=true", download="{{name}}")
i.fa.fa-download.icon(title="{{_ 'download'}}")
if currentUser.isBoardMember
unless currentUser.isCommentOnly
unless currentUser.isWorker
a.js-rename
i.fa.fa-pencil-square-o.icon(title="{{_ 'rename'}}")
a.js-confirm-delete
i.fa.fa-trash.icon(title="{{_ 'delete'}}")
a.fa.fa-navicon.icon.js-open-attachment-menu(data-attachment-link="{{link}}" title="{{_ 'attachmentActionsPopup-title'}}")
template(name="attachmentActionsPopup")
ul.pop-over-list
@@ -91,12 +116,6 @@ template(name="attachmentActionsPopup")
| {{_ 'remove-background-image'}}
else
| {{_ 'add-background-image'}}
a.js-rename
i.fa.fa-pencil-square-o
| {{_ 'rename'}}
a.js-confirm-delete
i.fa.fa-close
| {{_ 'delete'}}
p.attachment-storage
| {{versions.original.storage}}
+162 -17
View File
@@ -1,10 +1,28 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { ObjectID } from 'bson';
import DOMPurify from 'dompurify';
const filesize = require('filesize');
const prettyMilliseconds = require('pretty-ms');
Template.attachmentsGalery.events({
// We store current card ID and the ID of currently opened attachment in a
// global var. This is used so that we know what's the next attachment to open
// when the user clicks on the prev/next button in the attachment viewer.
let cardId = null;
let openAttachmentId = null;
// Stores link to the attachment for which attachment actions popup was opened
attachmentActionsLink = null;
Template.attachmentGallery.events({
'click .open-preview'(event) {
openAttachmentId = $(event.currentTarget).attr("data-attachment-id");
cardId = $(event.currentTarget).attr("data-card-id");
openAttachmentViewer(openAttachmentId);
},
'click .js-add-attachment': Popup.open('cardAttachments'),
// If we let this event bubble, FlowRouter will handle it and empty the page
// content, see #101.
@@ -12,11 +30,144 @@ Template.attachmentsGalery.events({
event.stopPropagation();
},
'click .js-open-attachment-menu': Popup.open('attachmentActions'),
'mouseover .js-open-attachment-menu'(event) { // For some reason I cannot combine handlers for "click .js-open-attachment-menu" and "mouseover .js-open-attachment-menu" events so this is a quick workaround.
attachmentActionsLink = event.currentTarget.getAttribute("data-attachment-link");
},
'click .js-rename': Popup.open('attachmentRename'),
'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', function() {
Attachments.remove(this._id);
Popup.back(2);
}),
});
Template.attachmentsGalery.helpers({
function getNextAttachmentId(currentAttachmentId) {
const attachments = ReactiveCache.getAttachments({'meta.cardId': cardId});
let i = 0;
for (; i < attachments.length; i++) {
if (attachments[i]._id === currentAttachmentId) {
break;
}
}
return attachments[(i + 1 + attachments.length) % attachments.length]._id;
}
function getPrevAttachmentId(currentAttachmentId) {
const attachments = ReactiveCache.getAttachments({'meta.cardId': cardId});
let i = 0;
for (; i < attachments.length; i++) {
if (attachments[i]._id === currentAttachmentId) {
break;
}
}
return attachments[(i - 1 + attachments.length) % attachments.length]._id;
}
function openAttachmentViewer(attachmentId){
const attachment = ReactiveCache.getAttachment(attachmentId);
$("#attachment-name").text(attachment.name);
// IMPORTANT: if you ever add a new viewer, make sure you also implement
// cleanup in the closeAttachmentViewer() function
switch(true){
case (attachment.isImage):
$("#image-viewer").attr("src", attachment.link());
$("#image-viewer").removeClass("hidden");
break;
case (attachment.isPDF):
$("#pdf-viewer").attr("data", attachment.link());
$("#pdf-viewer").removeClass("hidden");
break;
case (attachment.isVideo):
// We have to create a new <source> DOM element and append it to the video
// element, otherwise the video won't load
let videoSource = document.createElement('source');
videoSource.setAttribute('src', attachment.link());
$("#video-viewer").append(videoSource);
$("#video-viewer").removeClass("hidden");
break;
case (attachment.isAudio):
// We have to create a new <source> DOM element and append it to the audio
// element, otherwise the audio won't load
let audioSource = document.createElement('source');
audioSource.setAttribute('src', attachment.link());
$("#audio-viewer").append(audioSource);
$("#audio-viewer").removeClass("hidden");
break;
case (attachment.isText):
case (attachment.isJSON):
$("#txt-viewer").attr("data", attachment.link());
$("#txt-viewer").removeClass("hidden");
break;
}
$("#viewer-overlay").removeClass("hidden");
}
function closeAttachmentViewer() {
$("#viewer-overlay").addClass("hidden");
// We need to reset the viewers to avoid showing previous attachments
$("#image-viewer").attr("src", "");
$("#image-viewer").addClass("hidden");
$("#pdf-viewer").attr("data", "");
$("#pdf-viewer").addClass("hidden");
$("#txt-viewer").attr("data", "");
$("#txt-viewer").addClass("hidden");
$("#video-viewer").get(0).pause(); // Stop playback
$("#video-viewer").get(0).currentTime = 0;
$("#video-viewer").empty();
$("#video-viewer").addClass("hidden");
$("#audio-viewer").get(0).pause(); // Stop playback
$("#audio-viewer").get(0).currentTime = 0;
$("#audio-viewer").empty();
$("#audio-viewer").addClass("hidden");
}
Template.attachmentViewer.events({
'click #viewer-container'(event) {
// Make sure the click was on #viewer-container and not on any of its children
if(event.target !== event.currentTarget) return;
closeAttachmentViewer();
},
'click #viewer-content'(event) {
// Make sure the click was on #viewer-content and not on any of its children
if(event.target !== event.currentTarget) return;
closeAttachmentViewer();
},
'click #viewer-close'() {
closeAttachmentViewer();
},
'click #next-attachment'(event) {
closeAttachmentViewer()
const id = getNextAttachmentId(openAttachmentId);
openAttachmentId = id;
openAttachmentViewer(id);
},
'click #prev-attachment'(event) {
closeAttachmentViewer()
const id = getPrevAttachmentId(openAttachmentId);
openAttachmentId = id;
openAttachmentViewer(id);
}
});
Template.attachmentGallery.helpers({
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
fileSize(size) {
const ret = filesize(size);
@@ -172,40 +323,34 @@ Template.previewClipboardImagePopup.events({
BlazeComponent.extendComponent({
isCover() {
const ret = Cards.findOne(this.data().meta.cardId).coverId == this.data()._id;
const ret = ReactiveCache.getCard(this.data().meta.cardId).coverId == this.data()._id;
return ret;
},
isBackgroundImage() {
//const currentBoard = Boards.findOne(Session.get('currentBoard'));
//const currentBoard = Utils.getCurrentBoard();
//return currentBoard.backgroundImageURL === $(".attachment-thumbnail-img").attr("src");
return false;
},
events() {
return [
{
'click .js-rename': Popup.open('attachmentRename'),
'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', function() {
Attachments.remove(this._id);
Popup.back(2);
}),
'click .js-add-cover'() {
Cards.findOne(this.data().meta.cardId).setCover(this.data()._id);
ReactiveCache.getCard(this.data().meta.cardId).setCover(this.data()._id);
Popup.back();
},
'click .js-remove-cover'() {
Cards.findOne(this.data().meta.cardId).unsetCover();
ReactiveCache.getCard(this.data().meta.cardId).unsetCover();
Popup.back();
},
'click .js-add-background-image'() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const url=$(".attachment-thumbnail-img").attr("src");
currentBoard.setBackgroundImageURL(url);
Utils.setBackgroundImage(url);
const currentBoard = Utils.getCurrentBoard();
currentBoard.setBackgroundImageURL(attachmentActionsLink);
Utils.setBackgroundImage(attachmentActionsLink);
Popup.back();
event.preventDefault();
},
'click .js-remove-background-image'() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
currentBoard.setBackgroundImageURL("");
Utils.setBackgroundImage("");
Popup.back();
@@ -37,14 +37,6 @@ const CardCustomField = BlazeComponent.extendComponent({
self.card = Utils.getCurrentCard();
self.customFieldId = this.data()._id;
},
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
});
CardCustomField.register('cardCustomField');
-11
View File
@@ -2,17 +2,6 @@ import moment from 'moment/min/moment-with-locales';
import { TAPi18n } from '/imports/i18n';
import { DatePicker } from '/client/lib/datepicker';
Template.dateBadge.helpers({
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
});
// editCardReceivedDatePopup
(class extends DatePicker {
onCreated() {
+6 -5
View File
@@ -541,8 +541,8 @@ template(name="cardDetails")
+viewer
= getDescription
.card-checklist-attachmentGalerys
.card-checklist-attachmentGalery.card-checklists
.card-checklist-attachmentGalleries
.card-checklist-attachmentGallery.card-checklists
if currentBoard.allowsChecklists
hr
+checklists(cardId = _id)
@@ -555,14 +555,15 @@ template(name="cardDetails")
i.fa.fa-paperclip
| {{_ 'attachments'}}
if Meteor.settings.public.attachmentsUploadMaxSize
| {{_ 'max-upload-filesize'}} {{Meteor.settings.public.attachmentsUploadMaxSize}}
| {{_ 'max-upload-filesize'}} {{Meteor.settings.public.attachmentsUploadMaxSize}}
br
if Meteor.settings.public.attachmentsUploadMimeTypes
| {{_ 'allowed-upload-filetypes'}} {{Meteor.settings.public.attachmentsUploadMimeTypes}}
br
| {{_ 'invalid-file'}}
.card-checklist-attachmentGalery.card-attachmentGalery
+attachmentsGalery
.card-checklist-attachmentGallery.card-attachmentGallery
+attachmentViewer
+attachmentGallery
hr
.card-details-right
+37 -96
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import moment from 'moment/min/moment-with-locales';
import { TAPi18n } from '/imports/i18n';
import { DatePicker } from '/client/lib/datepicker';
@@ -63,25 +64,16 @@ BlazeComponent.extendComponent({
},
hiddenSystemMessages() {
return Meteor.user().hasHiddenSystemMessages();
return ReactiveCache.getCurrentUser().hasHiddenSystemMessages();
},
customFieldsGrid() {
return Meteor.user().hasCustomFieldsGrid();
return ReactiveCache.getCurrentUser().hasCustomFieldsGrid();
},
cardMaximized() {
return !Utils.getPopupCardId() && Meteor.user().hasCardMaximized();
},
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
return !Utils.getPopupCardId() && ReactiveCache.getCurrentUser().hasCardMaximized();
},
scrollParentContainer() {
@@ -152,7 +144,7 @@ BlazeComponent.extendComponent({
const card = this.currentData();
let result = '#';
if (card) {
const board = Boards.findOne(card.boardId);
const board = ReactiveCache.getBoard(card.boardId);
if (board) {
result = FlowRouter.path('card', {
boardId: card.boardId,
@@ -201,15 +193,15 @@ BlazeComponent.extendComponent({
cardId: card._id,
boardId: card.boardId,
listId: card.listId,
user: Meteor.user().username,
user: ReactiveCache.getCurrentUser().username,
url: '',
};
const integrations = Integrations.find({
const integrations = ReactiveCache.getIntegrations({
boardId: { $in: [card.boardId, Integrations.Const.GLOBAL_WEBHOOK_ID] },
enabled: true,
activities: { $in: ['CardDetailsRendered', 'all'] },
}).fetch();
});
if (integrations.length > 0) {
integrations.forEach((integration) => {
@@ -296,7 +288,7 @@ BlazeComponent.extendComponent({
});
function userIsMember() {
return Meteor.user() && Meteor.user().isBoardMember();
return ReactiveCache.getCurrentUser()?.isBoardMember();
}
// Disable sorting if the current user is not a board member
@@ -660,15 +652,7 @@ Template.cardDetailsActionsPopup.helpers({
},
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
},
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
});
@@ -744,19 +728,8 @@ BlazeComponent.extendComponent({
}).register('editCardTitleForm');
Template.cardMembersPopup.onCreated(function () {
let currBoard = Boards.findOne(Session.get('currentBoard'));
let currBoard = Utils.getCurrentBoard();
let members = currBoard.activeMembers();
// let query = {
// "teams.teamId": { $in: currBoard.teams.map(t => t.teamId) },
// };
// let boardTeamUsers = Users.find(query, {
// sort: { sort: 1 },
// });
// members = currBoard.activeMembers2(members, boardTeamUsers);
this.members = new ReactiveVar(members);
});
@@ -774,24 +747,14 @@ Template.cardMembersPopup.helpers({
});
const filterMembers = (filterTerm) => {
let currBoard = Boards.findOne(Session.get('currentBoard'));
let currBoard = Utils.getCurrentBoard();
let members = currBoard.activeMembers();
// let query = {
// "teams.teamId": { $in: currBoard.teams.map(t => t.teamId) },
// };
// let boardTeamUsers = Users.find(query, {
// sort: { sort: 1 },
// });
// members = currBoard.activeMembers2(members, boardTeamUsers);
if (filterTerm) {
members = members
.map(member => ({
member,
user: Users.findOne(member.userId)
user: ReactiveCache.getUser(member.userId)
}))
.filter(({ user }) =>
(user.profile.fullname !== undefined && user.profile.fullname.toLowerCase().indexOf(filterTerm.toLowerCase()) !== -1)
@@ -830,11 +793,11 @@ Template.editCardAssignerForm.events({
/** Move Card Dialog */
(class extends DialogWithBoardSwimlaneList {
getDialogOptions() {
const ret = Meteor.user().getMoveAndCopyDialogOptions();
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
return ret;
}
setDone(boardId, swimlaneId, listId, options) {
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
const card = this.data();
const minOrder = card.getMinSort(listId, swimlaneId);
card.move(boardId, swimlaneId, listId, minOrder - 1);
@@ -844,11 +807,11 @@ Template.editCardAssignerForm.events({
/** Copy Card Dialog */
(class extends DialogWithBoardSwimlaneList {
getDialogOptions() {
const ret = Meteor.user().getMoveAndCopyDialogOptions();
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
return ret;
}
setDone(boardId, swimlaneId, listId, options) {
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
const card = this.data();
// const textarea = $('#copy-card-title');
@@ -871,11 +834,11 @@ Template.editCardAssignerForm.events({
/** Convert Checklist-Item to card dialog */
(class extends DialogWithBoardSwimlaneList {
getDialogOptions() {
const ret = Meteor.user().getMoveAndCopyDialogOptions();
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
return ret;
}
setDone(boardId, swimlaneId, listId, options) {
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
const card = this.data();
const textarea = this.$('#copy-card-title');
@@ -889,7 +852,7 @@ Template.editCardAssignerForm.events({
swimlaneId: swimlaneId,
sort: 0,
});
const card = Cards.findOne(_id);
const card = ReactiveCache.getCard(_id);
const minOrder = card.getMinSort();
card.move(card.boardId, card.swimlaneId, card.listId, minOrder - 1);
@@ -901,11 +864,11 @@ Template.editCardAssignerForm.events({
/** Copy many cards dialog */
(class extends DialogWithBoardSwimlaneList {
getDialogOptions() {
const ret = Meteor.user().getMoveAndCopyDialogOptions();
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
return ret;
}
setDone(boardId, swimlaneId, listId, options) {
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
const card = this.data();
const textarea = this.$('#copy-card-title');
@@ -977,27 +940,27 @@ BlazeComponent.extendComponent({
},
boards() {
return Boards.find(
const ret = ReactiveCache.getBoards(
{
archived: false,
'members.userId': Meteor.userId(),
_id: {
$ne: Meteor.user().getTemplatesBoardId(),
},
_id: { $ne: ReactiveCache.getCurrentUser().getTemplatesBoardId() },
},
{
sort: { sort: 1 /* boards default sorting */ },
},
);
return ret;
},
cards() {
const currentId = Utils.getCurrentCardId();
if (this.parentBoard.get()) {
return Cards.find({
const ret = ReactiveCache.getCards({
boardId: this.parentBoard.get(),
_id: { $ne: currentId },
});
return ret;
} else {
return [];
}
@@ -1021,7 +984,7 @@ BlazeComponent.extendComponent({
setParentCardId(cardId) {
if (cardId) {
this.parentCard = Cards.findOne(cardId);
this.parentCard = ReactiveCache.getCard(cardId);
} else {
this.parentCard = null;
}
@@ -1040,7 +1003,7 @@ BlazeComponent.extendComponent({
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
Popup.close();
// verify that there are no linked cards
if (Cards.find({ linkedId: this._id }).count() === 0) {
if (ReactiveCache.getCards({ linkedId: this._id }).length === 0) {
Cards.remove(this._id);
} else {
// TODO: Maybe later we can list where the linked cards are.
@@ -1579,8 +1542,8 @@ EscapeActions.register(
() => {
// if card description diverges from database due to editing
// ask user whether changes should be applied
if (Meteor.user()) {
if (Meteor.user().profile.rescueCardDescription == true) {
if (ReactiveCache.getCurrentUser()) {
if (ReactiveCache.getCurrentUser().profile.rescueCardDescription == true) {
currentDescription = document.getElementsByClassName("editor js-new-description-input").item(0)
if (currentDescription?.value && !(currentDescription.value === Utils.getCurrentCard().getDescription())) {
if (confirm(TAPi18n.__('rescue-card-description-dialogue'))) {
@@ -1614,19 +1577,8 @@ EscapeActions.register(
);
Template.cardAssigneesPopup.onCreated(function () {
let currBoard = Boards.findOne(Session.get('currentBoard'));
let currBoard = Utils.getCurrentBoard();
let members = currBoard.activeMembers();
// let query = {
// "teams.teamId": { $in: currBoard.teams.map(t => t.teamId) },
// };
// let boardTeamUsers = Users.find(query, {
// sort: { sort: 1 },
// });
// members = currBoard.activeMembers2(members, boardTeamUsers);
this.members = new ReactiveVar(members);
});
@@ -1656,13 +1608,13 @@ Template.cardAssigneesPopup.helpers({
},
user() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
});
Template.cardAssigneePopup.helpers({
userData() {
return Users.findOne(this.userId, {
return ReactiveCache.getUser(this.userId, {
fields: {
profile: 1,
username: 1,
@@ -1671,21 +1623,10 @@ Template.cardAssigneePopup.helpers({
},
memberType() {
const user = Users.findOne(this.userId);
const user = ReactiveCache.getUser(this.userId);
return user && user.isBoardAdmin() ? 'admin' : 'normal';
},
/*
presenceStatusClassName() {
const user = Users.findOne(this.userId);
const userPresence = presences.findOne({ userId: this.userId });
if (user && user.isInvitedTo(Session.get('currentBoard'))) return 'pending';
else if (!userPresence) return 'disconnected';
else if (Session.equals('currentBoard', userPresence.state.currentBoardId))
return 'active';
else return 'idle';
},
*/
isCardAssignee() {
const card = Template.parentData();
const cardAssignees = card.getAssignees();
@@ -1694,13 +1635,13 @@ Template.cardAssigneePopup.helpers({
},
user() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
});
Template.cardAssigneePopup.events({
'click .js-remove-assignee'() {
Cards.findOne(this.cardId).unassignAssignee(this.userId);
ReactiveCache.getCard(this.cardId).unassignAssignee(this.userId);
Popup.back();
},
'click .js-edit-profile': Popup.open('editProfile'),
-10
View File
@@ -83,13 +83,3 @@ BlazeComponent.extendComponent({
];
},
}).register('cardSpentTime');
Template.timeBadge.helpers({
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
});
+15
View File
@@ -164,6 +164,21 @@ textarea.js-edit-checklist-item {
color: #222;
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
}
.add-checklist-top {
/* more space to checklists title */
padding-left: 20px;
/* + is easier clickable */
padding-right: 20px;
}
.add-checklist-top.js-open-inlined-form:hover {
background: #dbdbdb;
color: #222;
box-shadow: 0 1px 2px rgba(0,0,0,.2);
}
.card-details-item-title {
/* max width for adding checklist at top */
width: 100%;
}
.checklist-details-menu {
float: right;
padding: 6px 10px 6px 10px;
+14 -4
View File
@@ -3,6 +3,12 @@ template(name="checklists")
h3.card-details-item-title
i.fa.fa-check
| {{_ 'checklists'}}
if canModifyCard
+inlinedForm(autoclose=false classNames="js-add-checklist" cardId = cardId position="top")
+addChecklistItemForm
else
a.add-checklist-top.js-open-inlined-form(title="{{_ 'add-checklist'}}")
i.fa.fa-plus
if currentUser.isBoardMember
.material-toggle-switch(title="{{_ 'hide-checked-items'}}")
//span.toggle-switch-title
@@ -86,6 +92,13 @@ template(name="editChecklistItemForm")
| {{_ 'convertChecklistItemToCardPopup-title'}}
template(name="checklistItems")
if checklist.items.length
if canModifyCard
+inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist position="top")
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true)
else
a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}")
i.fa.fa-plus
.checklist-items.js-checklist-items
each item in checklist.items
+inlinedForm(classNames="js-edit-checklist-item" item = item checklist = checklist)
@@ -140,10 +153,7 @@ template(name="copyAndMoveChecklist")
label {{_ 'boards'}}:
select.js-select-boards(autofocus)
each boards
if $eq _id currentBoard._id
option(value="{{_id}}" selected) {{_ 'current'}}
else
option(value="{{_id}}" selected="{{#if isDialogOptionBoardId _id}}selected{{/if}}") {{title}}
option(value="{{_id}}" selected="{{#if isDialogOptionBoardId _id}}selected{{/if}}") {{title}}
label {{_ 'swimlanes'}}:
select.js-select-swimlanes
+40 -59
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
import Cards from '/models/cards';
import Boards from '/models/boards';
@@ -54,7 +55,7 @@ BlazeComponent.extendComponent({
});
function userIsMember() {
return Meteor.user() && Meteor.user().isBoardMember();
return ReactiveCache.getCurrentUser()?.isBoardMember();
}
// Disable sorting if the current user is not a board member
@@ -71,15 +72,6 @@ BlazeComponent.extendComponent({
});
},
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
/** returns the finished percent of the checklist */
finishedPercent() {
const ret = this.data().checklist.finishedPercent();
@@ -93,20 +85,32 @@ BlazeComponent.extendComponent({
const textarea = this.find('textarea.js-add-checklist-item');
const title = textarea.value.trim();
let cardId = this.currentData().cardId;
const card = Cards.findOne(cardId);
const card = ReactiveCache.getCard(cardId);
//if (card.isLinked()) cardId = card.linkedId;
if (card.isLinkedCard()) cardId = card.linkedId;
if (card.isLinkedCard()) {
cardId = card.linkedId;
}
let sortIndex;
let checklistItemIndex;
if (this.currentData().position === 'top') {
sortIndex = Utils.calculateIndexData(null, card.firstChecklist()).base;
checklistItemIndex = 0;
} else {
sortIndex = Utils.calculateIndexData(card.lastChecklist(), null).base;
checklistItemIndex = -1;
}
if (title) {
Checklists.insert({
cardId,
title,
sort: card.checklists().count(),
sort: sortIndex,
});
this.closeAllInlinedForms();
setTimeout(() => {
this.$('.add-checklist-item')
.last()
.eq(checklistItemIndex)
.click();
}, 100);
}
@@ -122,13 +126,22 @@ BlazeComponent.extendComponent({
let checklistItems = [title];
if (newlineBecomesNewChecklistItem.checked) {
checklistItems = title.split('\n').map(_value => _value.trim());
if (this.currentData().position === 'top') {
checklistItems = checklistItems.reverse();
}
}
for (let checklistItem of checklistItems) {
let sortIndex;
if (this.currentData().position === 'top') {
sortIndex = Utils.calculateIndexData(null, checklist.firstItem()).base;
} else {
sortIndex = Utils.calculateIndexData(checklist.lastItem(), null).base;
}
ChecklistItems.insert({
title: checklistItem,
checklistId: checklist._id,
cardId: checklist.cardId,
sort: Utils.calculateIndexData(checklist.lastItem()).base,
sort: sortIndex,
});
}
}
@@ -137,15 +150,6 @@ BlazeComponent.extendComponent({
textarea.focus();
},
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
deleteItem() {
const checklist = this.currentData().checklist;
const item = this.currentData().item;
@@ -229,25 +233,26 @@ BlazeComponent.extendComponent({
},
boards() {
return Boards.find(
const ret = ReactiveCache.getBoards(
{
archived: false,
'members.userId': Meteor.userId(),
_id: { $ne: Meteor.user().getTemplatesBoardId() },
_id: { $ne: ReactiveCache.getCurrentUser().getTemplatesBoardId() },
},
{
sort: { sort: 1 /* boards default sorting */ },
},
);
return ret;
},
swimlanes() {
const board = Boards.findOne(this.selectedBoardId.get());
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
return board.swimlanes();
},
aBoardLists() {
const board = Boards.findOne(this.selectedBoardId.get());
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
return board.lists();
},
@@ -265,12 +270,12 @@ BlazeComponent.extendComponent({
Template.checklists.helpers({
checklists() {
const card = Cards.findOne(this.cardId);
const card = ReactiveCache.getCard(this.cardId);
const ret = card.checklists();
return ret;
},
hideCheckedItems() {
const currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) return currentUser.hasHideCheckedItems();
return false;
},
@@ -280,14 +285,6 @@ BlazeComponent.extendComponent({
onRendered() {
autosize(this.$('textarea.js-add-checklist-item'));
},
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
events() {
return [
{
@@ -325,14 +322,6 @@ BlazeComponent.extendComponent({
onRendered() {
autosize(this.$('textarea.js-edit-checklist-item'));
},
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
events() {
return [
{
@@ -349,16 +338,8 @@ BlazeComponent.extendComponent({
}).register('editChecklistItemForm');
Template.checklistItemDetail.helpers({
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
hideCheckedItems() {
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
if (user) return user.hasHideCheckedItems();
return false;
},
@@ -384,11 +365,11 @@ BlazeComponent.extendComponent({
/** Move Checklist Dialog */
(class extends DialogWithBoardSwimlaneListCard {
getDialogOptions() {
const ret = Meteor.user().getMoveChecklistDialogOptions();
const ret = ReactiveCache.getCurrentUser().getMoveChecklistDialogOptions();
return ret;
}
setDone(cardId, options) {
Meteor.user().setMoveChecklistDialogOption(this.currentBoardId, options);
ReactiveCache.getCurrentUser().setMoveChecklistDialogOption(this.currentBoardId, options);
this.data().checklist.move(cardId);
}
}).register('moveChecklistPopup');
@@ -396,11 +377,11 @@ BlazeComponent.extendComponent({
/** Copy Checklist Dialog */
(class extends DialogWithBoardSwimlaneListCard {
getDialogOptions() {
const ret = Meteor.user().getCopyChecklistDialogOptions();
const ret = ReactiveCache.getCurrentUser().getCopyChecklistDialogOptions();
return ret;
}
setDone(cardId, options) {
Meteor.user().setCopyChecklistDialogOption(this.currentBoardId, options);
ReactiveCache.getCurrentUser().setCopyChecklistDialogOption(this.currentBoardId, options);
this.data().checklist.copy(cardId);
}
}).register('copyChecklistPopup');
+7 -5
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
let labelColors;
Meteor.startup(() => {
labelColors = Boards.simpleSchema()._schema['labels.$.color'].allowedValues;
@@ -32,7 +34,7 @@ Template.createLabelPopup.helpers({
// is not already used in the board (although it's not a problem if two
// labels have the same color).
defaultColor() {
const labels = Boards.findOne(Session.get('currentBoard')).labels;
const labels = Utils.getCurrentBoard().labels;
const usedColors = _.pluck(labels, 'color');
const availableColors = _.difference(labelColors, usedColors);
return availableColors.length > 1 ? availableColors[0] : labelColors[0];
@@ -117,7 +119,7 @@ Template.createLabelPopup.events({
// Create the new label
'submit .create-label'(event, templateInstance) {
event.preventDefault();
const board = Boards.findOne(Session.get('currentBoard'));
const board = Utils.getCurrentBoard();
const name = templateInstance
.$('#labelName')
.val()
@@ -130,13 +132,13 @@ Template.createLabelPopup.events({
Template.editLabelPopup.events({
'click .js-delete-label': Popup.afterConfirm('deleteLabel', function () {
const board = Boards.findOne(Session.get('currentBoard'));
const board = Utils.getCurrentBoard();
board.removeLabel(this._id);
Popup.back(2);
}),
'submit .edit-label'(event, templateInstance) {
event.preventDefault();
const board = Boards.findOne(Session.get('currentBoard'));
const board = Utils.getCurrentBoard();
const name = templateInstance
.$('#labelName')
.val()
@@ -149,6 +151,6 @@ Template.editLabelPopup.events({
Template.cardLabelsPopup.helpers({
isLabelSelected(cardId) {
return _.contains(Cards.findOne(cardId).labelIds, this._id);
return _.contains(ReactiveCache.getCard(cardId).labelIds, this._id);
},
});
+7
View File
@@ -120,6 +120,13 @@
max-width: 100px;
margin-right: 4px;
}
.minicard .minicard-custom-field-item-fullwidth {
flex-grow: 1;
display: block;
word-wrap: break-word;
max-width: 100%;
margin-right: 4px;
}
.minicard .handle {
width: 20px;
height: 20px;
+39 -19
View File
@@ -71,25 +71,45 @@ template(name="minicard")
if definition.showOnCard
if trueValue
.minicard-custom-field
// If there is custom field label, show label at left,
// and value at right
if definition.showLabelOnMiniCard
.minicard-custom-field-item
+viewer
= definition.name
.minicard-custom-field-item
if $eq definition.type "currency"
+viewer
= formattedCurrencyCustomFieldValue(definition)
else if $eq definition.type "date"
.date
+minicardCustomFieldDate
else if $eq definition.type "checkbox"
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
else if $eq definition.type "stringtemplate"
+viewer
= formattedStringtemplateCustomFieldValue(definition)
else
+viewer
= trueValue
.minicard-custom-field-item
if $eq definition.type "currency"
+viewer
= formattedCurrencyCustomFieldValue(definition)
else if $eq definition.type "date"
.date
+minicardCustomFieldDate
else if $eq definition.type "checkbox"
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
else if $eq definition.type "stringtemplate"
+viewer
= formattedStringtemplateCustomFieldValue(definition)
else
+viewer
= trueValue
else
// If there is no custom field label,
// show value full width
.minicard-custom-field-item-fullwidth
if $eq definition.type "currency"
+viewer
= formattedCurrencyCustomFieldValue(definition)
else if $eq definition.type "date"
.date
+minicardCustomFieldDate
else if $eq definition.type "checkbox"
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
else if $eq definition.type "stringtemplate"
+viewer
= formattedStringtemplateCustomFieldValue(definition)
else
+viewer
= trueValue
if showAssignee
if getAssignees
@@ -109,11 +129,11 @@ template(name="minicard")
.badges
unless currentUser.isNoComments
if comments.count
.badge(title="{{_ 'card-comments-title' comments.count }}")
if comments.length
.badge(title="{{_ 'card-comments-title' comments.length }}")
span.badge-icon.fa.fa-comment-o.badge-comment
= ' '
= comments.count
= comments.length
//span.badge-comment.badge-text
//| {{_ 'comment'}}
if getDescription
@@ -136,7 +156,7 @@ template(name="minicard")
.badge
span.badge-icon.fa.fa-paperclip
span.badge-text= attachments.length
if checklists.count
if checklists.length
.badge(class="{{#if checklistFinished}}is-finished{{/if}}")
span.badge-icon.fa.fa-check-square-o
span.badge-text.check-list-text {{checklistFinishedCount}}/{{checklistItemCount}}
+32 -23
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
import { CustomFieldStringTemplate } from '/client/lib/customFields'
@@ -37,37 +38,45 @@ BlazeComponent.extendComponent({
},
showCreator() {
if (this.data().board()) {
return (
this.data().board.allowsCreator === null ||
this.data().board().allowsCreator === undefined ||
this.data().board().allowsCreator
);
// return this.data().board().allowsCreator;
// cache "board" to reduce the mini-mongodb access
const board = this.data().board();
let ret = false;
if (board) {
ret =
board.allowsCreator === null ||
board.allowsCreator === undefined ||
board.allowsCreator
;
}
return false;
return ret;
},
showMembers() {
if (this.data().board()) {
return (
this.data().board.allowsMembers === null ||
this.data().board().allowsMembers === undefined ||
this.data().board().allowsMembers
);
// cache "board" to reduce the mini-mongodb access
const board = this.data().board();
let ret = false;
if (board) {
ret =
board.allowsMembers === null ||
board.allowsMembers === undefined ||
board.allowsMembers
;
}
return false;
return ret;
},
showAssignee() {
if (this.data().board()) {
return (
this.data().board.allowsAssignee === null ||
this.data().board().allowsAssignee === undefined ||
this.data().board().allowsAssignee
);
// cache "board" to reduce the mini-mongodb access
const board = this.data().board();
let ret = false;
if (board) {
ret =
board.allowsAssignee === null ||
board.allowsAssignee === undefined ||
board.allowsAssignee
;
}
return false;
return ret;
},
/** opens the card label popup only if clicked onto a label
@@ -105,7 +114,7 @@ BlazeComponent.extendComponent({
Template.minicard.helpers({
hiddenMinicardLabelText() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).hiddenMinicardLabelText;
} else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
+5 -34
View File
@@ -1,13 +1,4 @@
BlazeComponent.extendComponent({
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
}).register('subtaskDetail');
import { ReactiveCache } from '/imports/reactiveCache';
BlazeComponent.extendComponent({
addSubtask(event) {
@@ -15,19 +6,19 @@ BlazeComponent.extendComponent({
const textarea = this.find('textarea.js-add-subtask-item');
const title = textarea.value.trim();
const cardId = this.currentData().cardId;
const card = Cards.findOne(cardId);
const card = ReactiveCache.getCard(cardId);
const sortIndex = -1;
const crtBoard = Boards.findOne(card.boardId);
const crtBoard = ReactiveCache.getBoard(card.boardId);
const targetBoard = crtBoard.getDefaultSubtasksBoard();
const listId = targetBoard.getDefaultSubtasksListId();
//Get the full swimlane data for the parent task.
const parentSwimlane = Swimlanes.findOne({
const parentSwimlane = ReactiveCache.getSwimlane({
boardId: crtBoard._id,
_id: card.swimlaneId,
});
//find the swimlane of the same name in the target board.
const targetSwimlane = Swimlanes.findOne({
const targetSwimlane = ReactiveCache.getSwimlane({
boardId: targetBoard._id,
title: parentSwimlane.title,
});
@@ -70,15 +61,6 @@ BlazeComponent.extendComponent({
textarea.focus();
},
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
deleteSubtask() {
const subtask = this.currentData().subtask;
if (subtask && subtask._id) {
@@ -117,17 +99,6 @@ BlazeComponent.extendComponent({
},
}).register('subtasks');
Template.subtaskItemDetail.helpers({
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
});
BlazeComponent.extendComponent({
// ...
}).register('subtaskItemDetail');
+3 -1
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
export function csvGetMembersToMap(data) {
// we will work on the list itself (an ordered array of objects) when a
// mapping is done, we add a 'wekan' field to the object representing the
@@ -28,7 +30,7 @@ export function csvGetMembersToMap(data) {
username: importedMember,
id: importedMember,
};
const wekanUser = Users.findOne({ username: importedMember.username });
const wekanUser = ReactiveCache.getUser({ username: importedMember.username });
if (wekanUser) importedMember.wekanId = wekanUser._id;
membersToMap.push(importedMember);
}
+3 -2
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { trelloGetMembersToMap } from './trelloMembersMapper';
import { wekanGetMembersToMap } from './wekanMembersMapper';
import { csvGetMembersToMap } from './csvMembersMapper';
@@ -174,9 +175,9 @@ BlazeComponent.extendComponent({
this._refreshMembers(
this.members().map(member => {
if (!member.wekanId) {
let user = Users.findOne({ username: member.username });
let user = ReactiveCache.getUser({ username: member.username });
if (!user) {
user = Users.findOne({ importUsernames: member.username });
user = ReactiveCache.getUser({ importUsernames: member.username });
}
if (user) {
// eslint-disable-next-line no-console
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
export function trelloGetMembersToMap(data) {
// we will work on the list itself (an ordered array of objects) when a
// mapping is done, we add a 'wekan' field to the object representing the
@@ -5,7 +7,7 @@ export function trelloGetMembersToMap(data) {
const membersToMap = data.members;
// auto-map based on username
membersToMap.forEach(importedMember => {
const wekanUser = Users.findOne({ username: importedMember.username });
const wekanUser = ReactiveCache.getUser({ username: importedMember.username });
if (wekanUser) {
importedMember.wekanId = wekanUser._id;
}
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
export function wekanGetMembersToMap(data) {
// we will work on the list itself (an ordered array of objects) when a
// mapping is done, we add a 'wekan' field to the object representing the
@@ -15,7 +17,7 @@ export function wekanGetMembersToMap(data) {
importedMember.fullName = user.profile.fullname;
}
importedMember.username = user.username;
const wekanUser = Users.findOne({ username: importedMember.username });
const wekanUser = ReactiveCache.getUser({ username: importedMember.username });
if (wekanUser) {
importedMember.wekanId = wekanUser._id;
}
+5 -2
View File
@@ -7,8 +7,8 @@
border-left: 1px solid #ccc;
padding: 0;
float: left;
min-width: 270px;
max-width: 270px;
min-width: 100px; /* TODO(mark-i-m): hardcoded? */
/*max-width: 270px;*/
/* Reverted incomplete change list width: */
/* https://github.com/wekan/wekan/issues/4558 */
/* Orinal width: 270px. Changes not saved yet: */
@@ -179,6 +179,9 @@
#js-wip-limit-edit div {
float: left;
}
#js-list-width-edit .list-width-error {
display: none;
}
@media screen and (max-width: 800px) {
.mini-list {
flex: 0 0 60px;
+2 -1
View File
@@ -1,5 +1,6 @@
template(name='list')
.list.js-list(id="js-list-{{_id}}")
.list.js-list(id="js-list-{{_id}}"
style="width:{{listWidth}}px;")
+listHeader
+listBody
+13 -14
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
require('/client/lib/jquery-ui.js')
@@ -23,14 +24,6 @@ BlazeComponent.extendComponent({
onRendered() {
const boardComponent = this.parentComponent().parentComponent();
function userIsMember() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
}
const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
const $cards = this.$('.js-minicards');
@@ -60,6 +53,7 @@ BlazeComponent.extendComponent({
distance: 7,
items: itemsSelector,
placeholder: 'minicard-wrapper placeholder',
scrollSpeed: 10,
start(evt, ui) {
ui.helper.css('z-index', 1000);
ui.placeholder.height(ui.helper.height());
@@ -74,7 +68,7 @@ BlazeComponent.extendComponent({
const nCards = MultiSelection.isActive() ? MultiSelection.count() : 1;
const sortIndex = calculateIndex(prevCardDom, nextCardDom, nCards);
const listId = Blaze.getData(ui.item.parents('.list').get(0))._id;
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
const defaultSwimlaneId = currentBoard.getDefaultSwimline()._id;
let targetSwimlaneId = null;
@@ -96,7 +90,7 @@ BlazeComponent.extendComponent({
$cards.sortable('cancel');
if (MultiSelection.isActive()) {
Cards.find(MultiSelection.getMongoSelector(), { sort: ['sort'] }).forEach((card, i) => {
ReactiveCache.getCards(MultiSelection.getMongoSelector(), { sort: ['sort'] }).forEach((card, i) => {
const newSwimlaneId = targetSwimlaneId
? targetSwimlaneId
: card.swimlaneId || defaultSwimlaneId;
@@ -168,9 +162,9 @@ BlazeComponent.extendComponent({
'option',
'disabled',
// Disable drag-dropping when user is not member
!userIsMember(),
!Utils.canModifyBoard(),
// Not disable drag-dropping while in multi-selection mode
// MultiSelection.isActive() || !userIsMember(),
// MultiSelection.isActive() || !Utils.canModifyBoard(),
);
}
});
@@ -180,14 +174,13 @@ BlazeComponent.extendComponent({
const currentBoardId = Tracker.nonreactive(() => {
return Session.get('currentBoard');
});
Cards.find({ boardId: currentBoardId }).fetch();
Tracker.afterFlush(() => {
$cards.find(itemsSelector).droppable({
hoverClass: 'draggable-hover-card',
accept: '.js-member,.js-label',
drop(event, ui) {
const cardId = Blaze.getData(this)._id;
const card = Cards.findOne(cardId);
const card = ReactiveCache.getCard(cardId);
if (ui.draggable.hasClass('js-member')) {
const memberId = Blaze.getData(ui.draggable.get(0)).userId;
@@ -201,6 +194,12 @@ BlazeComponent.extendComponent({
});
});
},
listWidth() {
const user = Meteor.user();
const list = Template.currentData();
return user.getListWidth(list.boardId, list._id);
},
}).register('list');
Template.miniList.events({
+2 -2
View File
@@ -1,7 +1,7 @@
template(name="listBody")
.list-body
.minicards.clearfix.js-minicards(class="{{#if reachedWipLimit}}js-list-full{{/if}}")
if cards.count
if cards.length
+inlinedForm(autoclose=false position="top")
+addCardForm(listId=_id position="top")
ul.sidebar-list
@@ -95,7 +95,7 @@ template(name="linkCardPopup")
label {{_ 'cards'}}:
select.js-select-cards
each cards
option(value="{{getId}}") {{getTitle}}
option(value="{{getRealId}}") {{getTitle}}
.edit-controls.clearfix
input.primary.confirm.js-done(type="button" value="{{_ 'link'}}")
+108 -77
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
import { Spinner } from '/client/lib/spinner';
@@ -15,10 +16,11 @@ BlazeComponent.extendComponent({
},
customFieldsSum() {
return CustomFields.find({
const ret = ReactiveCache.getCustomFields({
boardIds: { $in: [Session.get('currentBoard')] },
showSumAtTopOfList: true,
});
return ret;
},
openForm(options) {
@@ -64,7 +66,7 @@ BlazeComponent.extendComponent({
swimlaneId = this.parentComponent()
.parentComponent()
.data()._id; // Always swimlanes view
const swimlane = Swimlanes.findOne(swimlaneId);
const swimlane = ReactiveCache.getSwimlane(swimlaneId);
// If this is the card templates swimlane, insert a card template
if (swimlane.isCardTemplatesSwimlane()) cardType = 'template-card';
// If this is the board templates swimlane, insert a board template and a linked card
@@ -112,7 +114,7 @@ BlazeComponent.extendComponent({
// to appear
const cardCount = this.data()
.cards(this.idOrNull(swimlaneId))
.count();
.length;
if (this.cardlimit.get() < cardCount) {
this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter);
}
@@ -200,25 +202,23 @@ BlazeComponent.extendComponent({
archived: false,
};
if (swimlaneId) selector.swimlaneId = swimlaneId;
return Cards.find(Filter.mongoSelector(selector), {
const ret = ReactiveCache.getCards(Filter.mongoSelector(selector), {
// sort: ['sort'],
sort: sortBy,
limit,
});
}, true);
return ret;
},
showSpinner(swimlaneId) {
const list = Template.currentData();
return list.cards(swimlaneId).count() > this.cardlimit.get();
return list.cards(swimlaneId).length > this.cardlimit.get();
},
canSeeAddCard() {
return (
!this.reachedWipLimit() &&
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
Utils.canModifyCard()
);
},
@@ -227,7 +227,7 @@ BlazeComponent.extendComponent({
return (
!list.getWipLimit('soft') &&
list.getWipLimit('enabled') &&
list.getWipLimit('value') <= list.cards().count()
list.getWipLimit('value') <= list.cards().length
);
},
@@ -269,9 +269,8 @@ BlazeComponent.extendComponent({
const currentBoardId = Session.get('currentBoard');
arr = [];
_.forEach(
Boards.findOne(currentBoardId)
.customFields()
.fetch(),
ReactiveCache.getBoard(currentBoardId)
.customFields(),
function (field) {
if (field.automaticallyOnCard || field.alwaysOnCard)
arr.push({ _id: field._id, value: null });
@@ -288,8 +287,8 @@ BlazeComponent.extendComponent({
getLabels() {
const currentBoardId = Session.get('currentBoard');
if (Boards.findOne(currentBoardId).labels) {
return Boards.findOne(currentBoardId).labels.filter(label => {
if (ReactiveCache.getBoard(currentBoardId).labels) {
return ReactiveCache.getBoard(currentBoardId).labels.filter(label => {
return this.labels.get().indexOf(label._id) > -1;
});
}
@@ -349,10 +348,10 @@ BlazeComponent.extendComponent({
{
match: /\B@([\w.-]*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
callback(
$.map(currentBoard.activeMembers(), member => {
const user = Users.findOne(member.userId);
const user = ReactiveCache.getUser(member.userId);
return user.username.indexOf(term) === 0 ? user : null;
}),
);
@@ -374,7 +373,7 @@ BlazeComponent.extendComponent({
{
match: /\B#(\w*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
callback(
$.map(currentBoard.labels, label => {
if (label.name == undefined) {
@@ -430,10 +429,10 @@ BlazeComponent.extendComponent({
this.boardId = Session.get('currentBoard');
// In order to get current board info
subManager.subscribe('board', this.boardId, false);
this.board = Boards.findOne(this.boardId);
this.board = ReactiveCache.getBoard(this.boardId);
// List where to insert card
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
this.listId = Blaze.getData(list[0])._id;
this.list = $(Popup._getTopStack().openerElement).closest('.js-list');
this.listId = Blaze.getData(this.list[0])._id;
// Swimlane where to insert card
const swimlane = $(Popup._getTopStack().openerElement).closest(
'.js-swimlane',
@@ -442,11 +441,11 @@ BlazeComponent.extendComponent({
if (Utils.boardView() === 'board-view-swimlanes')
this.swimlaneId = Blaze.getData(swimlane[0])._id;
else if (Utils.boardView() === 'board-view-lists' || !Utils.boardView)
this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id;
this.swimlaneId = ReactiveCache.getSwimlane({ boardId: this.boardId })._id;
},
boards() {
const boards = Boards.find(
const ret = ReactiveCache.getBoards(
{
archived: false,
'members.userId': Meteor.userId(),
@@ -457,16 +456,22 @@ BlazeComponent.extendComponent({
sort: { sort: 1 /* boards default sorting */ },
},
);
return boards;
return ret;
},
swimlanes() {
if (!this.selectedBoardId.get()) {
return [];
}
const swimlanes = Swimlanes.find({ boardId: this.selectedBoardId.get() });
if (swimlanes.count())
this.selectedSwimlaneId.set(swimlanes.fetch()[0]._id);
const swimlanes = ReactiveCache.getSwimlanes(
{
boardId: this.selectedBoardId.get()
},
{
sort: { sort: 1 },
});
if (swimlanes.length)
this.selectedSwimlaneId.set(swimlanes[0]._id);
return swimlanes;
},
@@ -474,8 +479,14 @@ BlazeComponent.extendComponent({
if (!this.selectedBoardId.get()) {
return [];
}
const lists = Lists.find({ boardId: this.selectedBoardId.get() });
if (lists.count()) this.selectedListId.set(lists.fetch()[0]._id);
const lists = ReactiveCache.getLists(
{
boardId: this.selectedBoardId.get()
},
{
sort: { sort: 1 },
});
if (lists.length) this.selectedListId.set(lists[0]._id);
return lists;
},
@@ -483,10 +494,9 @@ BlazeComponent.extendComponent({
if (!this.board) {
return [];
}
const ownCardsIds = this.board.cards().map(card => {
return card.linkedId || card._id;
});
return Cards.find({
const ownCardsIds = this.board.cards().map(card => card.getRealId());
const ret = ReactiveCache.getCards(
{
boardId: this.selectedBoardId.get(),
swimlaneId: this.selectedSwimlaneId.get(),
listId: this.selectedListId.get(),
@@ -494,7 +504,24 @@ BlazeComponent.extendComponent({
linkedId: { $nin: ownCardsIds },
_id: { $nin: ownCardsIds },
type: { $nin: ['template-card'] },
},
{
sort: { sort: 1 },
});
return ret;
},
getSortIndex() {
const position = this.currentData().position;
let ret;
if (position === 'top') {
const firstCardDom = this.list.find('.js-minicard:first')[0];
ret = Utils.calculateIndex(null, firstCardDom).base;
} else if (position === 'bottom') {
const lastCardDom = this.list.find('.js-minicard:last')[0];
ret = Utils.calculateIndex(lastCardDom, null).base;
}
return ret;
},
events() {
@@ -519,16 +546,17 @@ BlazeComponent.extendComponent({
Popup.back();
return;
}
const nextCardNumber = this.board.getNextCardNumber();
const sortIndex = this.getSortIndex();
const _id = Cards.insert({
title: $('.js-select-cards option:selected').text(), //dummy
listId: this.listId,
swimlaneId: this.swimlaneId,
boardId: this.boardId,
sort: Lists.findOne(this.listId)
.cards()
.count(),
sort: sortIndex,
type: 'cardType-linkedCard',
linkedId,
cardNumber: nextCardNumber,
});
Filter.addException(_id);
Popup.back();
@@ -540,21 +568,22 @@ BlazeComponent.extendComponent({
const impBoardId = $('.js-select-boards option:selected').val();
if (
!impBoardId ||
Cards.findOne({ linkedId: impBoardId, archived: false })
ReactiveCache.getCard({ linkedId: impBoardId, archived: false })
) {
Popup.back();
return;
}
const nextCardNumber = this.board.getNextCardNumber();
const sortIndex = this.getSortIndex();
const _id = Cards.insert({
title: $('.js-select-boards option:selected').text(), //dummy
listId: this.listId,
swimlaneId: this.swimlaneId,
boardId: this.boardId,
sort: Lists.findOne(this.listId)
.cards()
.count(),
sort: sortIndex,
type: 'cardType-linkedBoard',
linkedId: impBoardId,
cardNumber: nextCardNumber,
});
Filter.addException(_id);
Popup.back();
@@ -587,36 +616,27 @@ BlazeComponent.extendComponent({
this.isListTemplateSearch ||
this.isSwimlaneTemplateSearch ||
this.isBoardTemplateSearch;
let board = {};
this.board = {};
if (this.isTemplateSearch) {
//board = Boards.findOne((Meteor.user().profile || {}).templatesBoardId);
board._id = (Meteor.user().profile || {}).templatesBoardId;
const boardId = (ReactiveCache.getCurrentUser().profile || {}).templatesBoardId;
if (boardId) {
this.board = ReactiveCache.getBoard(boardId);
}
} else {
// Prefetch first non-current board id
board = Boards.find({
archived: false,
'members.userId': Meteor.userId(),
_id: {
$nin: [
Session.get('currentBoard'),
(Meteor.user().profile || {}).templatesBoardId,
],
},
});
this.board = Utils.getCurrentBoard();
}
if (!board) {
if (!this.board) {
Popup.back();
return;
}
const boardId = board._id;
this.boardId = this.board._id;
// Subscribe to this board
subManager.subscribe('board', boardId, false);
this.selectedBoardId = new ReactiveVar(boardId);
subManager.subscribe('board', this.boardId, false);
this.selectedBoardId = new ReactiveVar(this.boardId);
this.list = $(Popup._getTopStack().openerElement).closest('.js-list');
if (!this.isBoardTemplateSearch) {
this.boardId = Session.get('currentBoard');
// In order to get current board info
subManager.subscribe('board', this.boardId, false);
this.swimlaneId = '';
// Swimlane where to insert card
const swimlane = $(Popup._getTopStack().openerElement).parents(
@@ -624,16 +644,15 @@ BlazeComponent.extendComponent({
);
if (Utils.boardView() === 'board-view-swimlanes')
this.swimlaneId = Blaze.getData(swimlane[0])._id;
else this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id;
else this.swimlaneId = ReactiveCache.getSwimlane({ boardId: this.boardId })._id;
// List where to insert card
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
this.listId = Blaze.getData(list[0])._id;
this.listId = Blaze.getData(this.list[0])._id;
}
this.term = new ReactiveVar('');
},
boards() {
const boards = Boards.find(
const ret = ReactiveCache.getBoards(
{
archived: false,
'members.userId': Meteor.userId(),
@@ -644,14 +663,14 @@ BlazeComponent.extendComponent({
sort: { sort: 1 /* boards default sorting */ },
},
);
return boards;
return ret;
},
results() {
if (!this.selectedBoardId) {
return [];
}
const board = Boards.findOne(this.selectedBoardId.get());
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
if (!this.isTemplateSearch || this.isCardTemplateSearch) {
return board.searchCards(this.term.get(), false);
} else if (this.isListTemplateSearch) {
@@ -669,6 +688,19 @@ BlazeComponent.extendComponent({
}
},
getSortIndex() {
const position = this.data().position;
let ret;
if (position === 'top') {
const firstCardDom = this.list.find('.js-minicard:first')[0];
ret = Utils.calculateIndex(null, firstCardDom).base;
} else if (position === 'bottom') {
const lastCardDom = this.list.find('.js-minicard:last')[0];
ret = Utils.calculateIndex(lastCardDom, null).base;
}
return ret;
},
events() {
return [
{
@@ -692,9 +724,8 @@ BlazeComponent.extendComponent({
if (!this.isTemplateSearch || this.isCardTemplateSearch) {
// Card insertion
// 1. Common
element.sort = Lists.findOne(this.listId)
.cards()
.count();
element.cardNumber = this.board.getNextCardNumber();
element.sort = this.getSortIndex();
// 1.A From template
if (this.isTemplateSearch) {
element.type = 'cardType-card';
@@ -707,15 +738,15 @@ BlazeComponent.extendComponent({
Filter.addException(_id);
// List insertion
} else if (this.isListTemplateSearch) {
element.sort = Swimlanes.findOne(this.swimlaneId)
element.sort = ReactiveCache.getSwimlane(this.swimlaneId)
.lists()
.count();
.length;
element.type = 'list';
_id = element.copy(this.boardId, this.swimlaneId);
} else if (this.isSwimlaneTemplateSearch) {
element.sort = Boards.findOne(this.boardId)
element.sort = ReactiveCache.getBoard(this.boardId)
.swimlanes()
.count();
.length;
element.type = 'swimlane';
_id = element.copy(this.boardId);
} else if (this.isBoardTemplateSearch) {
@@ -723,7 +754,7 @@ BlazeComponent.extendComponent({
'copyBoard',
element.linkedId,
{
sort: Boards.find({ archived: false }).count(),
sort: ReactiveCache.getBoards({ archived: false }).length,
type: 'board',
title: element.title,
},
@@ -757,7 +788,7 @@ BlazeComponent.extendComponent({
Meteor.settings.public.sandstorm;
if (isSandstorm) {
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
if (user) {
if (Utils.boardView() === 'board-view-swimlanes') {
this.swimlaneId = this.parentComponent()
+22 -4
View File
@@ -15,11 +15,11 @@ template(name="listHeader")
= title
if wipLimit.enabled
|&nbsp;(
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.count}}
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}}
|/#{wipLimit.value})
if showCardsCountForList cards.count
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.count}}
if showCardsCountForList cards.length
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}}
if isMiniScreen
if currentList
@@ -62,6 +62,11 @@ template(name="listActionPopup")
i.fa.fa-arrow-down
| {{_ 'add-card-to-bottom-of-list'}}
hr
ul.pop-over-list
li
a.js-set-list-width
i.fa.fa-arrows-h
| {{_ 'set-list-width'}}
ul.pop-over-list
li
a.js-toggle-watch-list
@@ -79,7 +84,7 @@ template(name="listActionPopup")
i.fa.fa-paint-brush
| {{_ 'set-color-list'}}
ul.pop-over-list
if cards.count
if cards.length
li
a.js-select-cards
i.fa.fa-check-square
@@ -156,6 +161,19 @@ template(name="wipLimitErrorPopup")
p {{_ 'wipLimitErrorPopup-dialog-pt2'}}
button.full.js-back-view(type="submit") {{_ 'cancel'}}
template(name="setListWidthPopup")
#js-list-width-edit
label {{_ 'set-list-width-value'}}
p
input.list-width-value(type="number" value="{{ listWidthValue }}" min="100")
input.list-width-apply(type="submit" value="{{_ 'apply'}}")
input.list-width-error
template(name="listWidthErrorPopup")
.list-width-invalid
p {{_ 'list-width-error-message'}} '&gt;=100'
button.full.js-back-view(type="submit") {{_ 'cancel'}}
template(name="setListColorPopup")
form.edit-label
.palette-colors: each colors
+59 -19
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
let listsColors;
@@ -12,12 +13,12 @@ BlazeComponent.extendComponent({
(!list.getWipLimit('enabled') ||
list.getWipLimit('soft') ||
!this.reachedWipLimit()) &&
!Meteor.user().isWorker()
!ReactiveCache.getCurrentUser().isWorker()
);
},
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
starred(check = undefined) {
const list = Template.currentData();
@@ -47,9 +48,9 @@ BlazeComponent.extendComponent({
},
limitToShowCardsCount() {
const currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return Meteor.user().getLimitToShowCardsCount();
return currentUser.getLimitToShowCardsCount();
} else {
return false;
}
@@ -63,14 +64,15 @@ BlazeComponent.extendComponent({
.parentComponent()
.data()._id;
return list.cards(swimlaneId).count();
const ret = list.cards(swimlaneId).length;
return ret;
},
reachedWipLimit() {
const list = Template.currentData();
return (
list.getWipLimit('enabled') &&
list.getWipLimit('value') <= list.cards().count()
list.getWipLimit('value') <= list.cards().length
);
},
@@ -78,7 +80,7 @@ BlazeComponent.extendComponent({
const list = Template.currentData();
return (
list.getWipLimit('enabled') &&
list.getWipLimit('value') < list.cards().count()
list.getWipLimit('value') < list.cards().length
);
},
@@ -123,13 +125,13 @@ BlazeComponent.extendComponent({
Template.listHeader.helpers({
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
}
});
Template.listActionPopup.helpers({
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
isWipLimitEnabled() {
@@ -151,6 +153,7 @@ Template.listActionPopup.events({
});
Popup.back();
},
'click .js-set-list-width': Popup.open('setListWidth'),
'click .js-set-color-list': Popup.open('setListColor'),
'click .js-select-cards'() {
const cardIds = this.allCards().map(card => card._id);
@@ -183,7 +186,7 @@ BlazeComponent.extendComponent({
10,
);
if (limit < list.cards().count() && !list.getWipLimit('soft')) {
if (limit < list.cards().length && !list.getWipLimit('soft')) {
Template.instance()
.$('.wip-limit-error')
.click();
@@ -198,9 +201,9 @@ BlazeComponent.extendComponent({
if (
list.getWipLimit('soft') &&
list.getWipLimit('value') < list.cards().count()
list.getWipLimit('value') < list.cards().length
) {
list.setWipLimit(list.cards().count());
list.setWipLimit(list.cards().length);
}
Meteor.call('enableSoftLimit', Template.currentData()._id);
},
@@ -210,9 +213,9 @@ BlazeComponent.extendComponent({
// Prevent user from using previously stored wipLimit.value if it is less than the current number of cards in the list
if (
!list.getWipLimit('enabled') &&
list.getWipLimit('value') < list.cards().count()
list.getWipLimit('value') < list.cards().length
) {
list.setWipLimit(list.cards().count());
list.setWipLimit(list.cards().length);
}
Meteor.call('enableWipLimit', list._id);
},
@@ -244,17 +247,16 @@ BlazeComponent.extendComponent({
Template.listMorePopup.events({
'click .js-delete': Popup.afterConfirm('listDelete', function() {
Popup.back();
// TODO how can we avoid the fetch call?
const allCards = this.allCards().fetch();
const allCards = this.allCards();
const allCardIds = _.pluck(allCards, '_id');
// it's okay if the linked cards are on the same list
if (
Cards.find({
ReactiveCache.getCards({
$and: [
{ listId: { $ne: this._id } },
{ linkedId: { $in: allCardIds } },
],
}).count() === 0
}).length === 0
) {
allCardIds.map(_id => Cards.remove(_id));
Lists.remove(this._id);
@@ -279,7 +281,7 @@ Template.listMorePopup.events({
Template.listHeader.helpers({
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
});
@@ -319,3 +321,41 @@ BlazeComponent.extendComponent({
];
},
}).register('setListColorPopup');
BlazeComponent.extendComponent({
applyListWidth() {
const list = Template.currentData();
const board = list.boardId;
const width = parseInt(
Template.instance()
.$('.list-width-value')
.val(),
10,
);
// FIXME(mark-i-m): where do we put constants?
if (width < 100 || !width) {
Template.instance()
.$('.list-width-error')
.click();
} else {
Meteor.call('applyListWidth', board, list._id, width);
Popup.back();
}
},
listWidthValue() {
const list = Template.currentData();
const board = list.boardId;
return Meteor.user().getListWidth(board, list._id);
},
events() {
return [
{
'click .list-width-apply': this.applyListWidth,
'click .list-width-error': Popup.open('listWidthError'),
},
];
},
}).register('setListWidthPopup');
+2 -1
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { CardSearchPagedComponent } from '../../lib/cardSearch';
import {
OPERATOR_HAS,
@@ -66,7 +67,7 @@ class DueCardsComponent extends CardSearchPagedComponent {
});
if (Utils.dueCardsView() !== 'all') {
queryParams.addPredicate(OPERATOR_USER, Meteor.user().username);
queryParams.addPredicate(OPERATOR_USER, ReactiveCache.getCurrentUser().username);
}
this.runGlobalSearch(queryParams);
+6 -4
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
const specialHandles = [
{userId: 'board_members', username: 'board_members'},
{userId: 'card_members', username: 'card_members'}
@@ -13,13 +15,13 @@ BlazeComponent.extendComponent({
{
match: /\B@([\w.-]*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
callback(
_.union(
currentBoard
.activeMembers()
.map(member => {
const user = Users.findOne(member.userId);
const user = ReactiveCache.getUser(member.userId);
const username = user.username;
const fullName = user.profile && user.profile !== undefined && user.profile.fullname ? user.profile.fullname : "";
return username.includes(term) || fullName.includes(term) ? user : null;
@@ -328,13 +330,13 @@ Blaze.Template.registerHelper(
new Template('mentions', function() {
const view = this;
let content = Blaze.toHTML(view.templateContentBlock);
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
if (!currentBoard)
return HTML.Raw(
DOMPurify.sanitize(content, { ALLOW_UNKNOWN_PROTOCOLS: true }),
);
const knowedUsers = _.union(currentBoard.members.map(member => {
const u = Users.findOne(member.userId);
const u = ReactiveCache.getUser(member.userId);
if (u) {
member.username = u.username;
}
+3 -5
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
Meteor.subscribe('user-admin');
Meteor.subscribe('boards');
Meteor.subscribe('setting');
@@ -9,7 +11,7 @@ Template.header.onCreated(function(){
Meteor.subscribe('setting', {
onReady() {
templateInstance.currentSetting.set(Settings.findOne());
templateInstance.currentSetting.set(ReactiveCache.getCurrentSetting());
let currSetting = templateInstance.currentSetting.curValue;
if(currSetting && currSetting !== undefined && currSetting.customLoginLogoImageUrl !== undefined && document.getElementById("headerIsSettingDatabaseCallDone") != null)
document.getElementById("headerIsSettingDatabaseCallDone").style.display = 'none';
@@ -24,10 +26,6 @@ Template.header.helpers({
return !Session.get('currentBoard');
},
currentSetting() {
return Settings.findOne();
},
hideLogo() {
return Utils.isMiniScreen() && Session.get('currentBoard');
},
+3 -3
View File
@@ -559,14 +559,14 @@ a:not(.disabled).is-active i.fa {
top: 45px;
left: 10px;
}
#isSettingDatabaseCallDone {
display: none;
}
.at-link {
color: #17683a;
text-decoration: underline;
text-decoration-color: #17683a;
}
.at-pwd-form, .at-sep, .at-oauth {
display: none;
}
@-moz-keyframes fadeIn {
from {
opacity: 0;
+8 -9
View File
@@ -6,12 +6,12 @@ head
where the application is deployed with a path prefix, but it seems to be
difficult to do that cleanly with Blaze -- at least without adding extra
packages.
link(rel="shortcut icon" type="image/x-icon" href="favicon.ico")
link(rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png")
link(rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png")
link(rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png")
link(rel="shortcut icon" type="image/x-icon" href="/favicon.ico")
link(rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png")
link(rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png")
link(rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png")
link(rel="manifest" crossOrigin="use-credentials" href="/site.webmanifest")
link(rel="mask-icon" href="safari-pinned-tab.svg" color="#5bbad5")
link(rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5")
meta(name="apple-mobile-web-app-title" content="Wekan")
meta(name="application-name" content="Wekan")
meta(name="msapplication-TileColor" content="#00aba9")
@@ -34,10 +34,9 @@ template(name="userFormsLayout")
unless currentSetting.customLoginLogoLinkUrl
img(src="{{currentSetting.customLoginLogoImageUrl}}" width="300" height="auto")
br
unless currentSetting.customLoginLogoImageUrl
div#isSettingDatabaseCallDone
img(src="{{pathFor '/wekan-logo.svg'}}" alt="" width="300" height="auto")
br
else
img(src="{{pathFor '/wekan-logo.svg'}}" alt="" width="300" height="auto")
br
if currentSetting.textBelowCustomLoginLogo
+viewer
| {{currentSetting.textBelowCustomLoginLogo}}
+57 -63
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
BlazeLayout.setRoot('body');
@@ -19,80 +20,73 @@ const validator = {
},
};
// let isSettingDatabaseFctCallDone = false;
Template.userFormsLayout.onCreated(function () {
const templateInstance = this;
templateInstance.currentSetting = new ReactiveVar();
templateInstance.isLoading = new ReactiveVar(false);
Meteor.subscribe('setting', {
onReady() {
templateInstance.currentSetting.set(Settings.findOne());
let currSetting = templateInstance.currentSetting.curValue;
let oidcBtnElt = $("#at-oidc");
if(currSetting && currSetting !== undefined && currSetting.oidcBtnText !== undefined && oidcBtnElt != null && oidcBtnElt != undefined){
let htmlvalue = "<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
oidcBtnElt.html(htmlvalue);
if (!ReactiveCache.getCurrentUser()?.profile) {
Meteor.call('isOidcRedirectionEnabled', (_, result) => {
if (result) {
AccountsTemplates.options.socialLoginStyle = 'redirect';
options = {
loginStyle: AccountsTemplates.options.socialLoginStyle,
};
Meteor.loginWithOidc(options);
}
// isSettingDatabaseFctCallDone = true;
if (currSetting && currSetting !== undefined && currSetting.customLoginLogoImageUrl !== undefined)
document.getElementById("isSettingDatabaseCallDone").style.display = 'none';
else
document.getElementById("isSettingDatabaseCallDone").style.display = 'block';
return this.stop();
},
});
Meteor.call('isPasswordLoginDisabled', (_, result) => {
if (result) {
$('.at-pwd-form').hide();
}
});
if (!Meteor.user()?.profile) {
Meteor.call('isOidcRedirectionEnabled', (_, result) => {
if (result) {
AccountsTemplates.options.socialLoginStyle = 'redirect';
options = {
loginStyle: AccountsTemplates.options.socialLoginStyle,
};
Meteor.loginWithOidc(options);
}
//else console.log("oidc redirect not set");
});
});
}
Meteor.call('isDisableRegistration', (_, result) => {
if (result) {
$('.at-signup-link').hide();
}
});
Meteor.call('isDisableForgotPassword', (_, result) => {
if (result) {
$('.at-pwd-link').hide();
}
});
});
Template.userFormsLayout.onRendered(() => {
AccountsTemplates.state.form.keys = new Proxy(
AccountsTemplates.state.form.keys,
validator,
);
EscapeActions.executeAll();
Meteor.call('getAuthenticationsEnabled', (_, result) => {
let enabledAuthenticationMethods = [ 'password' ]; // we show/hide this based on isPasswordLoginEnabled
if (result) {
Object.keys(result).forEach((m) => {
if (result[m]) enabledAuthenticationMethods.push(m);
});
}
Meteor.call('isPasswordLoginEnabled', (_, result) => {
if (result) {
$('.at-pwd-form').show();
}
if (result && enabledAuthenticationMethods.length > 1) {
$('.at-sep').show();
}
});
Meteor.call('isDisableRegistration', (_, result) => {
if (result) {
$('.at-signup-link').hide();
}
});
Meteor.call('isDisableForgotPassword', (_, result) => {
if (result) {
$('.at-pwd-link').hide();
}
});
if (enabledAuthenticationMethods.indexOf('oauth2') !== -1) {
// TODO find better way to run this code once the oauth2 UI is injected in the DOM
(function waitForElementAndShow() {
if (!$('.at-oauth')[0]) return setTimeout(waitForElementAndShow, 100);
$('.at-oauth').show();
})();
}
AccountsTemplates.state.form.keys = new Proxy(
AccountsTemplates.state.form.keys,
validator,
);
EscapeActions.executeAll();
});
});
Template.userFormsLayout.helpers({
currentSetting() {
return Template.instance().currentSetting.get();
},
// isSettingDatabaseCallDone(){
// return isSettingDatabaseFctCallDone;
// },
isLegalNoticeLinkExist() {
const currSet = Template.instance().currentSetting.get();
if (currSet && currSet !== undefined && currSet != null) {
@@ -164,7 +158,7 @@ Template.userFormsLayout.events({
},
'DOMSubtreeModified #at-oidc'(event) {
if (alreadyCheck <= 2) {
let currSetting = Settings.findOne();
let currSetting = ReactiveCache.getCurrentSetting();
let oidcBtnElt = $("#at-oidc");
if (currSetting && currSetting !== undefined && currSetting.oidcBtnText !== undefined && oidcBtnElt != null && oidcBtnElt != undefined) {
let htmlvalue = "<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
@@ -185,7 +179,7 @@ Template.userFormsLayout.events({
'DOMSubtreeModified .at-form'(event) {
if (alreadyCheck <= 2 && !isCheckDone) {
if (document.getElementById("at-oidc") != null) {
let currSetting = Settings.findOne();
let currSetting = ReactiveCache.getCurrentSetting();
let oidcBtnElt = $("#at-oidc");
if (currSetting && currSetting !== undefined && currSetting.oidcBtnText !== undefined && oidcBtnElt != null && oidcBtnElt != undefined) {
let htmlvalue = "<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
Template.notification.events({
'click .read-status .materialCheckBox'() {
const update = {};
@@ -7,22 +9,22 @@ Template.notification.events({
Users.update(Meteor.userId(), { $set: update });
},
'click .remove a'() {
Meteor.user().removeNotification(this.activityData._id);
ReactiveCache.getCurrentUser().removeNotification(this.activityData._id);
},
});
Template.notification.helpers({
mode: 'board',
isOfActivityType(activityId, type) {
const activity = Activities.findOne(activityId);
const activity = ReactiveCache.getActivity(activityId);
return activity && activity.activityType === type;
},
activityType(activityId) {
const activity = Activities.findOne(activityId);
const activity = ReactiveCache.getActivity(activityId);
return activity ? activity.activityType : '';
},
activityUser(activityId) {
const activity = Activities.findOne(activityId);
const activity = ReactiveCache.getActivity(activityId);
return activity && activity.userId;
},
});
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
// this hides the notifications drawer if anyone clicks off of the panel
Template.body.events({
click(event) {
@@ -12,7 +14,7 @@ Template.body.events({
Template.notifications.helpers({
unreadNotifications() {
const notifications = Users.findOne(Meteor.userId()).notifications();
const notifications = ReactiveCache.getCurrentUser().notifications();
const unreadNotifications = _.filter(notifications, v => !v.read);
return unreadNotifications.length;
},
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { toggleNotificationsDrawer } from './notifications.js';
Template.notificationsDrawer.onCreated(function() {
@@ -14,11 +15,11 @@ Template.notificationsDrawer.onCreated(function() {
Template.notificationsDrawer.helpers({
transformedProfile() {
return Users.findOne(Meteor.userId());
return ReactiveCache.getCurrentUser();
},
readNotifications() {
const readNotifications = _.filter(
Meteor.user().profile.notifications,
ReactiveCache.getCurrentUser().profile.notifications,
v => !!v.read,
);
return readNotifications.length;
@@ -27,7 +28,7 @@ Template.notificationsDrawer.helpers({
Template.notificationsDrawer.events({
'click .all-read'() {
const notifications = Meteor.user().profile.notifications;
const notifications = ReactiveCache.getCurrentUser().profile.notifications;
for (const index in notifications) {
if (notifications.hasOwnProperty(index) && !notifications[index].read) {
const update = {};
@@ -43,7 +44,7 @@ Template.notificationsDrawer.events({
Session.set('showReadNotifications', !Session.get('showReadNotifications'));
},
'click .remove-read'() {
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
for (const notification of user.profile.notifications) {
if (notification.read) {
user.removeNotification(notification.activity);
@@ -1,20 +1,22 @@
import { ReactiveCache } from '/imports/reactiveCache';
BlazeComponent.extendComponent({
onCreated() {},
boards() {
const boards = Boards.find(
const ret = ReactiveCache.getBoards(
{
archived: false,
'members.userId': Meteor.userId(),
_id: {
$ne: Meteor.user().getTemplatesBoardId(),
$ne: ReactiveCache.getCurrentUser().getTemplatesBoardId(),
},
},
{
sort: { sort: 1 /* boards default sorting */ },
},
);
return boards;
return ret;
},
events() {
@@ -18,7 +18,7 @@ BlazeComponent.extendComponent({
},
labels() {
const labels = Boards.findOne(Session.get('currentBoard')).labels;
const labels = Utils.getCurrentBoard().labels;
for (let i = 0; i < labels.length; i++) {
if (labels[i].name === '' || labels[i].name === undefined) {
labels[i].name = labels[i].color.toUpperCase();
+6 -12
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
BlazeComponent.extendComponent({
onCreated() {
this.subscribe('allRules');
@@ -7,24 +9,16 @@ BlazeComponent.extendComponent({
trigger() {
const ruleId = this.data().ruleId;
const rule = Rules.findOne({
_id: ruleId.get(),
});
const trigger = Triggers.findOne({
_id: rule.triggerId,
});
const rule = ReactiveCache.getRule(ruleId.get());
const trigger = ReactiveCache.getTrigger(rule.triggerId);
const desc = trigger.description();
const upperdesc = desc.charAt(0).toUpperCase() + desc.substr(1);
return upperdesc;
},
action() {
const ruleId = this.data().ruleId;
const rule = Rules.findOne({
_id: ruleId.get(),
});
const action = Actions.findOne({
_id: rule.actionId,
});
const rule = ReactiveCache.getRule(ruleId.get());
const action = ReactiveCache.getAction(rule.actionId);
const desc = action.description();
const upperdesc = desc.charAt(0).toUpperCase() + desc.substr(1);
return upperdesc;
+4 -1
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
BlazeComponent.extendComponent({
onCreated() {
this.currentActions = new ReactiveVar('board');
@@ -33,7 +35,8 @@ BlazeComponent.extendComponent({
},
rules() {
return Rules.find({});
const ret = ReactiveCache.getRules({});
return ret;
},
name() {
+4 -1
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
BlazeComponent.extendComponent({
onCreated() {
this.subscribe('allRules');
@@ -5,9 +7,10 @@ BlazeComponent.extendComponent({
rules() {
const boardId = Session.get('currentBoard');
return Rules.find({
const ret = ReactiveCache.getRules({
boardId,
});
return ret;
},
events() {
return [{}];
+3 -1
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
BlazeComponent.extendComponent({
onCreated() {
this.rulesCurrentTab = new ReactiveVar('rulesList');
@@ -55,7 +57,7 @@ BlazeComponent.extendComponent({
let trigger = this.triggerVar.get();
trigger.userId = '*';
if (username !== undefined) {
const userFound = Users.findOne({ username });
const userFound = ReactiveCache.getUser({ username });
if (userFound !== undefined) {
trigger.userId = userFound._id;
this.triggerVar.set(trigger);
+4 -1
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
BlazeComponent.extendComponent({
onCreated() {
this.showBoardTrigger = new ReactiveVar(true);
@@ -31,7 +33,8 @@ BlazeComponent.extendComponent({
},
rules() {
return Rules.find({});
const ret = ReactiveCache.getRules({});
return ret;
},
name() {
@@ -5,7 +5,7 @@ BlazeComponent.extendComponent({
this.subscribe('allRules');
},
labels() {
const labels = Boards.findOne(Session.get('currentBoard')).labels;
const labels = Utils.getCurrentBoard().labels;
for (let i = 0; i < labels.length; i++) {
if (labels[i].name === '' || labels[i].name === undefined) {
labels[i].name = labels[i].color;
+21 -21
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
import { AttachmentStorage } from '/models/attachments';
import { CardSearchPagedComponent } from '/client/lib/cardSearch';
@@ -115,12 +116,15 @@ class AdminReport extends BlazeComponent {
}
fileSize(size) {
const ret = filesize(size);
let ret = "";
if (_.isNumber(size)) {
ret = filesize(size);
}
return ret;
}
abbreviate(text) {
if (text.length > 30) {
if (text?.length > 30) {
return `${text.substr(0, 29)}...`;
}
return text;
@@ -137,7 +141,7 @@ class AdminReport extends BlazeComponent {
results() {
const rules = [];
Rules.find().forEach(rule => {
ReactiveCache.getRules().forEach(rule => {
rules.push({
_id: rule._id,
title: rule.title,
@@ -158,17 +162,13 @@ class AdminReport extends BlazeComponent {
collection = Boards;
userNames(members) {
let text = '';
members.forEach(member => {
const user = Users.findOne(member.userId);
text += text ? ', ' : '';
if (user) {
text += user.username;
} else {
text += member.userId
}
});
return text;
const ret = (members || [])
.map(_member => {
const _ret = ReactiveCache.getUser(_member.userId)?.username || _member.userId;
return _ret;
})
.join(", ");
return ret;
}
}.register('boardsReport'));
@@ -176,13 +176,13 @@ class AdminReport extends BlazeComponent {
collection = Cards;
userNames(userIds) {
let text = '';
userIds.forEach(userId => {
const user = Users.findOne(userId);
text += text ? ', ' : '';
text += user.username;
});
return text;
const ret = (userIds || [])
.map(_userId => {
const _ret = ReactiveCache.getUser(_userId)?.username;
return _ret;
})
.join(", ");
return ret
}
}.register('cardsReport'));
@@ -58,6 +58,7 @@ template(name="moveBoardAttachments")
th {{_ 'version-name'}}
th {{_ 'size'}}
th GridFsFileId
th S3FileId
th {{_ 'storage'}}
th {{_ 'action'}}
+4 -3
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import Attachments, { fileStoreStrategyFactory } from '/models/attachments';
const filesize = require('filesize');
@@ -44,7 +45,7 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
getBoardsWithAttachments() {
this.attachments = Attachments.find().get();
this.attachments = ReactiveCache.getAttachments();
this.attachmentsByBoardId = _.chain(this.attachments)
.groupBy(fileObj => fileObj.meta.boardId)
.value();
@@ -61,14 +62,14 @@ BlazeComponent.extendComponent({
return _version;
});
});
const board = Boards.findOne(boardId);
const board = ReactiveCache.getBoard(boardId);
board.attachments = boardAttachments;
return board;
})
return ret;
},
getBoardData(boardid) {
const ret = Boards.findOne(boardId);
const ret = ReactiveCache.getBoard(boardId);
return ret;
},
events() {
@@ -16,10 +16,12 @@ Template.connectionMethod.onCreated(function() {
// If only the default authentication available, hides the select boxe
const content = $('.at-form-authentication');
if (!(this.authenticationMethods.get().length > 1)) {
content.hide();
} else {
// OAuth method is a separate button, so ignore it in the count
const formAuthenticationMethods = this.authenticationMethods.get().filter((method) => method.value !== 'oauth2');
if (formAuthenticationMethods > 1) {
content.show();
} else {
content.hide();
}
});
});
@@ -41,7 +41,10 @@ BlazeComponent.extendComponent({
},
fileSize(size) {
const ret = filesize(size);
let ret = "";
if (_.isNumber(size)) {
ret = filesize(size);
}
return ret;
},
}).register('statistics');
+3 -1
View File
@@ -1,7 +1,9 @@
import { ReactiveCache } from '/imports/reactiveCache';
Template.invitationCode.onRendered(function() {
Meteor.subscribe('setting', {
onReady() {
const setting = Settings.findOne();
const setting = ReactiveCache.getCurrentSetting();
if (!setting || !setting.disableRegistration) {
$('#invitationcode').hide();
+44 -37
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
const orgsPerPage = 25;
const teamsPerPage = 25;
const usersPerPage = 25;
@@ -143,27 +145,27 @@ BlazeComponent.extendComponent({
this.loading.set(w);
},
orgList() {
const orgs = Org.find(this.findOrgsOptions.get(), {
const orgs = ReactiveCache.getOrgs(this.findOrgsOptions.get(), {
sort: { orgDisplayName: 1 },
fields: { _id: true },
});
this.numberOrgs.set(orgs.count(false));
this.numberOrgs.set(orgs.length);
return orgs;
},
teamList() {
const teams = Team.find(this.findTeamsOptions.get(), {
const teams = ReactiveCache.getTeams(this.findTeamsOptions.get(), {
sort: { teamDisplayName: 1 },
fields: { _id: true },
});
this.numberTeams.set(teams.count(false));
this.numberTeams.set(teams.length);
return teams;
},
peopleList() {
const users = Users.find(this.findUsersOptions.get(), {
const users = ReactiveCache.getUsers(this.findUsersOptions.get(), {
sort: { username: 1 },
fields: { _id: true },
});
this.numberPeople.set(users.count(false));
this.numberPeople.set(users.length);
return users;
},
orgNumber() {
@@ -190,19 +192,19 @@ BlazeComponent.extendComponent({
Template.orgRow.helpers({
orgData() {
return Org.findOne(this.orgId);
return ReactiveCache.getOrg(this.orgId);
},
});
Template.teamRow.helpers({
teamData() {
return Team.findOne(this.teamId);
return ReactiveCache.getTeam(this.teamId);
},
});
Template.peopleRow.helpers({
userData() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
});
@@ -227,7 +229,7 @@ Template.editUserPopup.onCreated(function () {
Template.editOrgPopup.helpers({
org() {
return Org.findOne(this.orgId);
return ReactiveCache.getOrg(this.orgId);
},
errorMessage() {
return Template.instance().errorMessage.get();
@@ -236,7 +238,7 @@ Template.editOrgPopup.helpers({
Template.editTeamPopup.helpers({
team() {
return Team.findOne(this.teamId);
return ReactiveCache.getTeam(this.teamId);
},
errorMessage() {
return Template.instance().errorMessage.get();
@@ -245,25 +247,27 @@ Template.editTeamPopup.helpers({
Template.editUserPopup.helpers({
user() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
authentications() {
return Template.instance().authenticationMethods.get();
},
orgsDatas() {
return Org.find({}, {sort: { orgDisplayName: 1 }});
const ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});
return ret;
},
teamsDatas() {
return Team.find({}, {sort: { teamDisplayName: 1 }});
const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
return ret;
},
isSelected(match) {
const userId = Template.instance().data.userId;
const selected = Users.findOne(userId).authenticationMethod;
const selected = ReactiveCache.getUser(userId).authenticationMethod;
return selected === match;
},
isLdap() {
const userId = Template.instance().data.userId;
const selected = Users.findOne(userId).authenticationMethod;
const selected = ReactiveCache.getUser(userId).authenticationMethod;
return selected === 'ldap';
},
errorMessage() {
@@ -300,7 +304,7 @@ Template.newUserPopup.onCreated(function () {
Template.newOrgPopup.helpers({
org() {
return Org.findOne(this.orgId);
return ReactiveCache.getOrg(this.orgId);
},
errorMessage() {
return Template.instance().errorMessage.get();
@@ -309,7 +313,7 @@ Template.newOrgPopup.helpers({
Template.newTeamPopup.helpers({
team() {
return Team.findOne(this.teamId);
return ReactiveCache.getTeam(this.teamId);
},
errorMessage() {
return Template.instance().errorMessage.get();
@@ -318,21 +322,23 @@ Template.newTeamPopup.helpers({
Template.newUserPopup.helpers({
user() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
authentications() {
return Template.instance().authenticationMethods.get();
},
orgsDatas() {
return Org.find({}, {sort: { orgDisplayName: 1 }});
const ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});
return ret;
},
teamsDatas() {
return Team.find({}, {sort: { teamDisplayName: 1 }});
const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
return ret;
},
isSelected(match) {
const userId = Template.instance().data.userId;
if(userId){
const selected = Users.findOne(userId).authenticationMethod;
const selected = ReactiveCache.getUser(userId).authenticationMethod;
return selected === match;
}
else{
@@ -341,7 +347,7 @@ Template.newUserPopup.helpers({
},
isLdap() {
const userId = Template.instance().data.userId;
const selected = Users.findOne(userId).authenticationMethod;
const selected = ReactiveCache.getUser(userId).authenticationMethod;
return selected === 'ldap';
},
errorMessage() {
@@ -352,7 +358,7 @@ Template.newUserPopup.helpers({
BlazeComponent.extendComponent({
onCreated() {},
org() {
return Org.findOne(this.orgId);
return ReactiveCache.getOrg(this.orgId);
},
events() {
return [
@@ -367,7 +373,7 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
onCreated() {},
team() {
return Team.findOne(this.teamId);
return ReactiveCache.getTeam(this.teamId);
},
events() {
return [
@@ -382,7 +388,7 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
onCreated() {},
user() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
events() {
return [
@@ -417,7 +423,8 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
onCreated() {},
teamsDatas() {
return Team.find({}, {sort: { teamDisplayName: 1 }});
const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
return ret;
},
events() {
return [
@@ -440,7 +447,7 @@ BlazeComponent.extendComponent({
if(document.getElementById('addAction').checked){
for(let i = 0; i < selectedUserChkBoxUserIds.length; i++){
currentUser = Users.findOne(selectedUserChkBoxUserIds[i]);
currentUser = ReactiveCache.getUser(selectedUserChkBoxUserIds[i]);
userTms = currentUser.teams;
if(userTms == undefined || userTms.length == 0){
userTms = [];
@@ -469,7 +476,7 @@ BlazeComponent.extendComponent({
}
else{
for(let i = 0; i < selectedUserChkBoxUserIds.length; i++){
currentUser = Users.findOne(selectedUserChkBoxUserIds[i]);
currentUser = ReactiveCache.getUser(selectedUserChkBoxUserIds[i]);
userTms = currentUser.teams;
if(userTms !== undefined || userTms.length > 0)
{
@@ -562,7 +569,7 @@ BlazeComponent.extendComponent({
Template.editOrgPopup.events({
submit(event, templateInstance) {
event.preventDefault();
const org = Org.findOne(this.orgId);
const org = ReactiveCache.getOrg(this.orgId);
const orgDisplayName = templateInstance
.find('.js-orgDisplayName')
@@ -603,7 +610,7 @@ Template.editOrgPopup.events({
Template.editTeamPopup.events({
submit(event, templateInstance) {
event.preventDefault();
const team = Team.findOne(this.teamId);
const team = ReactiveCache.getTeam(this.teamId);
const teamDisplayName = templateInstance
.find('.js-teamDisplayName')
@@ -647,7 +654,7 @@ Template.editTeamPopup.events({
Template.editUserPopup.events({
submit(event, templateInstance) {
event.preventDefault();
const user = Users.findOne(this.userId);
const user = ReactiveCache.getUser(this.userId);
const username = templateInstance.find('.js-profile-username').value.trim();
const fullname = templateInstance.find('.js-profile-fullname').value.trim();
const initials = templateInstance.find('.js-profile-initials').value.trim();
@@ -1071,7 +1078,7 @@ Template.newUserPopup.events({
Template.settingsOrgPopup.events({
'click #deleteButton'(event) {
event.preventDefault();
if(Users.find({"orgs.orgId": this.orgId}).count() > 0)
if (ReactiveCache.getUsers({"orgs.orgId": this.orgId}).length > 0)
{
let orgClassList = document.getElementById("deleteOrgWarningMessage").classList;
if(orgClassList.contains('hide'))
@@ -1089,7 +1096,7 @@ Template.settingsOrgPopup.events({
Template.settingsTeamPopup.events({
'click #deleteButton'(event) {
event.preventDefault();
if(Users.find({"teams.teamId": this.teamId}).count() > 0)
if (ReactiveCache.getUsers({"teams.teamId": this.teamId}).length > 0)
{
let teamClassList = document.getElementById("deleteTeamWarningMessage").classList;
if(teamClassList.contains('hide'))
@@ -1139,19 +1146,19 @@ Template.settingsUserPopup.events({
Template.settingsUserPopup.helpers({
user() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
authentications() {
return Template.instance().authenticationMethods.get();
},
isSelected(match) {
const userId = Template.instance().data.userId;
const selected = Users.findOne(userId).authenticationMethod;
const selected = ReactiveCache.getUser(userId).authenticationMethod;
return selected === match;
},
isLdap() {
const userId = Template.instance().data.userId;
const selected = Users.findOne(userId).authenticationMethod;
const selected = ReactiveCache.getUser(userId).authenticationMethod;
return selected === 'ldap';
},
errorMessage() {
+3 -3
View File
@@ -171,15 +171,15 @@ template(name='announcementSettings')
ul#announcement-setting.setting-detail
li
a.flex.js-toggle-activemessage
.materialCheckBox(class="{{#if currentSetting.enabled}}is-checked{{/if}}")
.materialCheckBox(class="{{#if currentAnnouncements.enabled}}is-checked{{/if}}")
span {{_ 'admin-announcement-active'}}
li
.admin-announcement(class="{{#if currentSetting.enabled}}{{else}}hide{{/if}}")
.admin-announcement(class="{{#if currentAnnouncements.enabled}}{{else}}hide{{/if}}")
ul
li
.title {{_ 'admin-announcement-title'}}
textarea#admin-announcement.wekan-form-control= currentSetting.body
textarea#admin-announcement.wekan-form-control= currentAnnouncements.body
li
button.js-announcement-save.primary {{_ 'save'}}
+13 -14
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
import { ALLOWED_WAIT_SPINNERS } from '/config/const';
@@ -42,12 +43,8 @@ BlazeComponent.extendComponent({
}
},
currentSetting() {
return Settings.findOne();
},
boards() {
return Boards.find(
const ret = ReactiveCache.getBoards(
{
archived: false,
'members.userId': Meteor.userId(),
@@ -57,19 +54,20 @@ BlazeComponent.extendComponent({
sort: { sort: 1 /* boards default sorting */ },
},
);
return ret;
},
toggleForgotPassword() {
this.setLoading(true);
const forgotPasswordClosed = this.currentSetting().disableForgotPassword;
Settings.update(Settings.findOne()._id, {
const forgotPasswordClosed = ReactiveCache.getCurrentSetting().disableForgotPassword;
Settings.update(ReactiveCache.getCurrentSetting()._id, {
$set: { disableForgotPassword: !forgotPasswordClosed },
});
this.setLoading(false);
},
toggleRegistration() {
this.setLoading(true);
const registrationClosed = this.currentSetting().disableRegistration;
Settings.update(Settings.findOne()._id, {
const registrationClosed = ReactiveCache.getCurrentSetting().disableRegistration;
Settings.update(ReactiveCache.getCurrentSetting()._id, {
$set: { disableRegistration: !registrationClosed },
});
this.setLoading(false);
@@ -165,7 +163,7 @@ BlazeComponent.extendComponent({
.trim();
const from = this.checkField('#mail-server-from');
const tls = $('#mail-server-tls.is-checked').length > 0;
Settings.update(Settings.findOne()._id, {
Settings.update(ReactiveCache.getCurrentSetting()._id, {
$set: {
'mailServer.host': host,
'mailServer.port': port,
@@ -245,7 +243,7 @@ BlazeComponent.extendComponent({
const spinnerName = $('#spinnerName').val();
try {
Settings.update(Settings.findOne()._id, {
Settings.update(ReactiveCache.getCurrentSetting()._id, {
$set: {
productName,
hideLogo: hideLogoChange,
@@ -416,7 +414,7 @@ BlazeComponent.extendComponent({
this.loading.set(w);
},
currentSetting() {
currentAnnouncements() {
return Announcements.findOne();
},
@@ -431,8 +429,9 @@ BlazeComponent.extendComponent({
toggleActive() {
this.setLoading(true);
const isActive = this.currentSetting().enabled;
Announcements.update(Announcements.findOne()._id, {
const announcements = this.currentAnnouncements();
const isActive = announcements.enabled;
Announcements.update(announcements._id, {
$set: { enabled: !isActive },
});
this.setLoading(false);
+2 -1
View File
@@ -13,7 +13,8 @@ template(name="sidebar")
h2
a.fa.fa-chevron-left.js-back-home
= getViewTitle
+Template.dynamic(template=getViewTemplate)
if isOpen
+Template.dynamic(template=getViewTemplate)
template(name='homeSidebar')
hr
+74 -74
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
Sidebar = null;
@@ -111,7 +112,7 @@ BlazeComponent.extendComponent({
'click .js-toggle-sidebar': this.toggle,
'click .js-back-home': this.setView,
'click .js-toggle-minicard-label-text'() {
currentUser = Meteor.user();
currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
Meteor.call('toggleMinicardLabelText');
} else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
@@ -137,7 +138,7 @@ Blaze.registerHelper('Sidebar', () => Sidebar);
Template.homeSidebar.helpers({
hiddenMinicardLabelText() {
currentUser = Meteor.user();
currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).hiddenMinicardLabelText;
} else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
@@ -149,9 +150,6 @@ Template.homeSidebar.helpers({
});
Template.boardInfoOnMyBoardsPopup.helpers({
currentSetting() {
return Settings.findOne();
},
hideCardCounterList() {
return Utils.isMiniScreen() && Session.get('currentBoard');
},
@@ -172,15 +170,15 @@ EscapeActions.register(
Template.memberPopup.helpers({
user() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
memberType() {
const type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal';
const type = ReactiveCache.getUser(this.userId).isBoardAdmin() ? 'admin' : 'normal';
if (type === 'normal') {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
const commentOnly = currentBoard.hasCommentOnly(this.userId);
const noComments = currentBoard.hasNoComments(this.userId);
const worker = currentBoard.hasWorker(this.userId);
@@ -198,7 +196,7 @@ Template.memberPopup.helpers({
}
},
isInvited() {
return Users.findOne(this.userId).isInvitedTo(Session.get('currentBoard'));
return ReactiveCache.getUser(this.userId).isInvitedTo(Session.get('currentBoard'));
},
});
@@ -222,14 +220,14 @@ Template.boardMenuPopup.events({
'click .js-board-info-on-my-boards': Popup.open('boardInfoOnMyBoards'),
'click .js-change-language': Popup.open('changeLanguage'),
'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
currentBoard.archive();
// XXX We should have some kind of notification on top of the page to
// confirm that the board was successfully archived.
FlowRouter.go('home');
}),
'click .js-delete-board': Popup.afterConfirm('deleteBoard', function() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
Popup.back();
Boards.remove(currentBoard._id);
FlowRouter.go('home');
@@ -251,7 +249,7 @@ Template.boardMenuPopup.onCreated(function() {
Template.boardMenuPopup.helpers({
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
withApi() {
return Template.instance().apiEnabled.get();
@@ -281,13 +279,13 @@ Template.memberPopup.events({
// This works from removing member from board, card members and assignees.
const boardId = Session.get('currentBoard');
const memberId = this.userId;
Cards.find({ boardId, members: memberId }).forEach(card => {
ReactiveCache.getCards({ boardId, members: memberId }).forEach(card => {
card.unassignMember(memberId);
});
Cards.find({ boardId, assignees: memberId }).forEach(card => {
ReactiveCache.getCards({ boardId, assignees: memberId }).forEach(card => {
card.unassignAssignee(memberId);
});
Boards.findOne(boardId).removeMember(memberId);
ReactiveCache.getBoard(boardId).removeMember(memberId);
Popup.back();
}),
'click .js-leave-member': Popup.afterConfirm('leaveBoard', () => {
@@ -301,16 +299,16 @@ Template.memberPopup.events({
Template.removeMemberPopup.helpers({
user() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
board() {
return Boards.findOne(Session.get('currentBoard'));
return Utils.getCurrentBoard();
},
});
Template.leaveBoardPopup.helpers({
board() {
return Boards.findOne(Session.get('currentBoard'));
return Utils.getCurrentBoard();
},
});
BlazeComponent.extendComponent({
@@ -335,7 +333,6 @@ BlazeComponent.extendComponent({
onRendered() {
this.setLoading(false);
Utils.setBackgroundImage();
},
setError(error) {
@@ -361,11 +358,11 @@ BlazeComponent.extendComponent({
Template.membersWidget.helpers({
isInvited() {
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
return user && user.isInvitedTo(Session.get('currentBoard'));
},
isWorker() {
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
if (user) {
return Meteor.call(Boards.hasWorker(user.memberId));
} else {
@@ -373,22 +370,22 @@ Template.membersWidget.helpers({
}
},
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
AtLeastOneOrgWasCreated(){
let orgs = Org.find({}, {sort: { createdAt: -1 }});
let orgs = ReactiveCache.getOrgs({}, {sort: { createdAt: -1 }});
if(orgs === undefined)
return false;
return orgs.count() > 0;
return orgs.length > 0;
},
AtLeastOneTeamWasCreated(){
let teams = Team.find({}, {sort: { createdAt: -1 }});
let teams = ReactiveCache.getTeams({}, {sort: { createdAt: -1 }});
if(teams === undefined)
return false;
return teams.count() > 0;
return teams.length > 0;
},
});
@@ -409,13 +406,13 @@ Template.membersWidget.events({
},
'click .js-member-invite-accept'() {
const boardId = Session.get('currentBoard');
Meteor.user().removeInvite(boardId);
ReactiveCache.getCurrentUser().removeInvite(boardId);
},
'click .js-member-invite-decline'() {
const boardId = Session.get('currentBoard');
Meteor.call('quitBoard', boardId, (err, ret) => {
if (!err && ret) {
Meteor.user().removeInvite(boardId);
ReactiveCache.getCurrentUser().removeInvite(boardId);
FlowRouter.go('home');
}
});
@@ -428,7 +425,8 @@ BlazeComponent.extendComponent({
},
integrations() {
const boardId = this.boardId();
return Integrations.find({ boardId: `${boardId}` }).fetch();
const ret = ReactiveCache.getIntegrations({ boardId });
return ret;
},
types() {
return Integrations.Const.WEBHOOK_TYPES;
@@ -439,7 +437,7 @@ BlazeComponent.extendComponent({
for (const k in condition) {
if (!condition[k]) delete condition[k];
}
return Integrations.findOne(condition);
return ReactiveCache.getIntegration(condition);
},
onCreated() {
this.disabled = new ReactiveVar(false);
@@ -607,7 +605,7 @@ Template.labelsWidget.events({
Template.labelsWidget.helpers({
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
});
@@ -621,7 +619,7 @@ function draggableMembersLabelsWidgets() {
const currentBoardId = Tracker.nonreactive(() => {
return Session.get('currentBoard');
});
Boards.findOne(currentBoardId, {
ReactiveCache.getBoard(currentBoardId, {
fields: {
members: 1,
labels: 1,
@@ -642,7 +640,7 @@ function draggableMembersLabelsWidgets() {
});
function userIsMember() {
return Meteor.user() && Meteor.user().isBoardMember();
return ReactiveCache.getCurrentUser()?.isBoardMember();
}
this.autorun(() => {
@@ -661,7 +659,7 @@ BlazeComponent.extendComponent({
},
isSelected() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return currentBoard.color === this.currentData().toString();
},
@@ -669,7 +667,7 @@ BlazeComponent.extendComponent({
return [
{
'click .js-select-background'(evt) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
const newColor = this.currentData().toString();
currentBoard.setColor(newColor);
evt.preventDefault();
@@ -684,7 +682,7 @@ BlazeComponent.extendComponent({
return [
{
submit(event) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
const backgroundImageURL = this.find('.js-board-background-image-url').value.trim();
currentBoard.setBackgroundImageURL(backgroundImageURL);
Utils.setBackgroundImage();
@@ -692,7 +690,7 @@ BlazeComponent.extendComponent({
event.preventDefault();
},
'click .js-remove-background-image'() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
currentBoard.setBackgroundImageURL("");
Popup.back();
Utils.reload();
@@ -705,14 +703,14 @@ BlazeComponent.extendComponent({
Template.boardChangeBackgroundImagePopup.helpers({
backgroundImageURL() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return currentBoard.backgroundImageURL;
},
});
BlazeComponent.extendComponent({
onCreated() {
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
this.currentBoard = Utils.getCurrentBoard();
},
allowsCardCounterList() {
@@ -765,7 +763,7 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
onCreated() {
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
this.currentBoard = Utils.getCurrentBoard();
},
allowsSubtasks() {
@@ -788,7 +786,7 @@ BlazeComponent.extendComponent({
},
boards() {
return Boards.find(
const ret = ReactiveCache.getBoards(
{
archived: false,
'members.userId': Meteor.userId(),
@@ -797,10 +795,11 @@ BlazeComponent.extendComponent({
sort: { sort: 1 /* boards default sorting */ },
},
);
return ret;
},
lists() {
return Lists.find(
return ReactiveCache.getLists(
{
boardId: this.currentBoard._id,
archived: false,
@@ -812,7 +811,7 @@ BlazeComponent.extendComponent({
},
hasLists() {
return this.lists().count() > 0;
return this.lists().length > 0;
},
isListSelected() {
@@ -891,7 +890,7 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
onCreated() {
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
this.currentBoard = Utils.getCurrentBoard();
},
allowsReceivedDate() {
@@ -986,7 +985,7 @@ BlazeComponent.extendComponent({
},
boards() {
return Boards.find(
const ret = ReactiveCache.getBoards(
{
archived: false,
'members.userId': Meteor.userId(),
@@ -995,10 +994,11 @@ BlazeComponent.extendComponent({
sort: { sort: 1 /* boards default sorting */ },
},
);
return ret;
},
lists() {
return Lists.find(
return ReactiveCache.getLists(
{
boardId: this.currentBoard._id,
archived: false,
@@ -1010,7 +1010,7 @@ BlazeComponent.extendComponent({
},
hasLists() {
return this.lists().count() > 0;
return this.lists().length > 0;
},
isListSelected() {
@@ -1326,7 +1326,7 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
onCreated() {
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
this.currentBoard = Utils.getCurrentBoard();
},
allowsDescriptionTextOnMinicard() {
@@ -1346,7 +1346,7 @@ BlazeComponent.extendComponent({
},
lists() {
return Lists.find(
return ReactiveCache.getLists(
{
boardId: this.currentBoard._id,
archived: false,
@@ -1358,7 +1358,7 @@ BlazeComponent.extendComponent({
},
hasLists() {
return this.lists().count() > 0;
return this.lists().length > 0;
},
isListSelected() {
@@ -1452,7 +1452,7 @@ BlazeComponent.extendComponent({
isBoardMember() {
const userId = this.currentData().__originalId;
const user = Users.findOne(userId);
const user = ReactiveCache.getUser(userId);
return user && user.isBoardMember();
},
@@ -1492,7 +1492,7 @@ BlazeComponent.extendComponent({
},
'click .js-select-member'() {
const userId = this.currentData().__originalId;
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
if (!currentBoard.hasMember(userId)) {
this.inviteUser(userId);
}
@@ -1548,7 +1548,7 @@ BlazeComponent.extendComponent({
this.setError('');
},
'change #jsBoardOrgs'() {
let currentBoard = Boards.findOne(Session.get('currentBoard'));
let currentBoard = Utils.getCurrentBoard();
let selectElt = document.getElementById("jsBoardOrgs");
let selectedOrgId = selectElt.options[selectElt.selectedIndex].value;
let selectedOrgDisplayName = selectElt.options[selectElt.selectedIndex].text;
@@ -1580,8 +1580,8 @@ BlazeComponent.extendComponent({
Template.addBoardOrgPopup.helpers({
orgsDatas() {
let orgs = Org.find({}, {sort: { orgDisplayName: 1 }});
return orgs;
let ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});
return ret;
},
});
@@ -1622,7 +1622,7 @@ BlazeComponent.extendComponent({
},
'click #leaveBoardBtn'(){
let stringOrgId = document.getElementById('hideOrgId').value;
let currentBoard = Boards.findOne(Session.get('currentBoard'));
let currentBoard = Utils.getCurrentBoard();
let boardOrganizations = [];
if(currentBoard.orgs !== undefined){
for(let i = 0; i < currentBoard.orgs.length; i++){
@@ -1646,7 +1646,7 @@ BlazeComponent.extendComponent({
Template.removeBoardOrgPopup.helpers({
org() {
return Org.findOne(this.orgId);
return ReactiveCache.getOrg(this.orgId);
},
});
@@ -1693,7 +1693,7 @@ BlazeComponent.extendComponent({
this.setError('');
},
'change #jsBoardTeams'() {
let currentBoard = Boards.findOne(Session.get('currentBoard'));
let currentBoard = Utils.getCurrentBoard();
let selectElt = document.getElementById("jsBoardTeams");
let selectedTeamId = selectElt.options[selectElt.selectedIndex].value;
let selectedTeamDisplayName = selectElt.options[selectElt.selectedIndex].text;
@@ -1718,13 +1718,13 @@ BlazeComponent.extendComponent({
"teams.teamId": { $in: boardTeams.map(t => t.teamId) },
};
const boardTeamUsers = Users.find(query, {
const boardTeamUsers = ReactiveCache.getUsers(query, {
sort: { sort: 1 },
});
if(boardTeams !== undefined && boardTeams.length > 0){
let index;
if(boardTeamUsers && boardTeamUsers.count() > 0){
if (boardTeamUsers && boardTeamUsers.length > 0) {
boardTeamUsers.forEach((u) => {
index = members.findIndex(function(m){ return m.userId == u._id});
if(index == -1){
@@ -1753,8 +1753,8 @@ BlazeComponent.extendComponent({
Template.addBoardTeamPopup.helpers({
teamsDatas() {
let teams = Team.find({}, {sort: { teamDisplayName: 1 }});
return teams;
let ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
return ret;
},
});
@@ -1802,7 +1802,7 @@ BlazeComponent.extendComponent({
},
'click #leaveBoardTeamBtn'(){
let stringTeamId = document.getElementById('hideTeamId').value;
let currentBoard = Boards.findOne(Session.get('currentBoard'));
let currentBoard = Utils.getCurrentBoard();
let boardTeams = [];
if(currentBoard.teams !== undefined){
for(let i = 0; i < currentBoard.teams.length; i++){
@@ -1817,13 +1817,13 @@ BlazeComponent.extendComponent({
"teams.teamId": stringTeamId
};
const boardTeamUsers = Users.find(query, {
const boardTeamUsers = ReactiveCache.getUsers(query, {
sort: { sort: 1 },
});
if(currentBoard.teams !== undefined && currentBoard.teams.length > 0){
let index;
if(boardTeamUsers && boardTeamUsers.count() > 0){
if (boardTeamUsers && boardTeamUsers.length > 0) {
boardTeamUsers.forEach((u) => {
index = members.findIndex(function(m){ return m.userId == u._id});
if(index !== -1 && (u.isAdmin === undefined || u.isAdmin == false)){
@@ -1847,7 +1847,7 @@ BlazeComponent.extendComponent({
Template.removeBoardTeamPopup.helpers({
team() {
return Team.findOne(this.teamId);
return ReactiveCache.getTeam(this.teamId);
},
});
@@ -1855,7 +1855,7 @@ Template.changePermissionsPopup.events({
'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only, click .js-set-worker'(
event,
) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
const memberId = this.userId;
const isAdmin = $(event.currentTarget).hasClass('js-set-admin');
const isCommentOnly = $(event.currentTarget).hasClass(
@@ -1876,12 +1876,12 @@ Template.changePermissionsPopup.events({
Template.changePermissionsPopup.helpers({
isAdmin() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return currentBoard.hasAdmin(this.userId);
},
isNormal() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return (
!currentBoard.hasAdmin(this.userId) &&
!currentBoard.hasNoComments(this.userId) &&
@@ -1891,7 +1891,7 @@ Template.changePermissionsPopup.helpers({
},
isNoComments() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return (
!currentBoard.hasAdmin(this.userId) &&
currentBoard.hasNoComments(this.userId)
@@ -1899,7 +1899,7 @@ Template.changePermissionsPopup.helpers({
},
isCommentOnly() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return (
!currentBoard.hasAdmin(this.userId) &&
currentBoard.hasCommentOnly(this.userId)
@@ -1907,14 +1907,14 @@ Template.changePermissionsPopup.helpers({
},
isWorker() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return (
!currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
);
},
isLastAdmin() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return (
currentBoard.hasAdmin(this.userId) && currentBoard.activeAdmins() === 1
);
+7 -5
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
//archivedRequested = false;
@@ -33,7 +34,7 @@ BlazeComponent.extendComponent({
},
archivedCards() {
return Cards.find(
const ret = ReactiveCache.getCards(
{
archived: true,
boardId: Session.get('currentBoard'),
@@ -42,10 +43,11 @@ BlazeComponent.extendComponent({
sort: { archivedAt: -1, modifiedAt: -1 },
},
);
return ret;
},
archivedLists() {
return Lists.find(
return ReactiveCache.getLists(
{
archived: true,
boardId: Session.get('currentBoard'),
@@ -57,7 +59,7 @@ BlazeComponent.extendComponent({
},
archivedSwimlanes() {
return Swimlanes.find(
return ReactiveCache.getSwimlanes(
{
archived: true,
boardId: Session.get('currentBoard'),
@@ -159,10 +161,10 @@ BlazeComponent.extendComponent({
Template.archivesSidebar.helpers({
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
isWorker() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return (
!currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
);
@@ -1,10 +1,12 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
BlazeComponent.extendComponent({
customFields() {
return CustomFields.find({
const ret = ReactiveCache.getCustomFields({
boardIds: { $in: [Session.get('currentBoard')] },
});
return ret;
},
events() {
@@ -275,7 +277,7 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
'click .js-delete-custom-field': Popup.afterConfirm(
'deleteCustomField',
function() {
const customField = CustomFields.findOne(this._id);
const customField = ReactiveCache.getCustomField(this._id);
if (customField.boardIds.length > 1) {
CustomFields.update(customField._id, {
$pull: {
+7 -5
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
const subManager = new SubsManager();
BlazeComponent.extendComponent({
@@ -93,7 +95,7 @@ BlazeComponent.extendComponent({
},
'click .js-filter-to-selection'(evt) {
evt.preventDefault();
const selectedCards = Cards.find(Filter.mongoSelector()).map(c => {
const selectedCards = ReactiveCache.getCards(Filter.mongoSelector()).map(c => {
return c._id;
});
MultiSelection.add(selectedCards);
@@ -104,14 +106,14 @@ BlazeComponent.extendComponent({
}).register('filterSidebar');
function mutateSelectedCards(mutationName, ...args) {
Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).forEach(card => {
ReactiveCache.getCards(MultiSelection.getMongoSelector(), {sort: ['sort']}).forEach(card => {
card[mutationName](...args);
});
}
BlazeComponent.extendComponent({
mapSelection(kind, _id) {
return Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).map(card => {
return ReactiveCache.getCards(MultiSelection.getMongoSelector(), {sort: ['sort']}).map(card => {
const methodName = kind === 'label' ? 'hasLabel' : 'isAssigned';
return card[methodName](_id);
});
@@ -171,10 +173,10 @@ BlazeComponent.extendComponent({
Template.multiselectionSidebar.helpers({
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
isCommentOnly() {
return Meteor.user().isCommentOnly();
return ReactiveCache.getCurrentUser().isCommentOnly();
},
});
+2 -2
View File
@@ -4,12 +4,12 @@ BlazeComponent.extendComponent({
},
cards() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return currentBoard.searchCards(this.term.get());
},
lists() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return currentBoard.searchLists(this.term.get());
},
@@ -44,6 +44,9 @@ template(name="swimlaneActionPopup")
li: a.js-set-swimlane-color
i.fa.fa-paint-brush
| {{_ 'select-color'}}
li: a.js-set-swimlane-height
i.fa.fa-arrows-v
| {{_ 'set-swimlane-height'}}
unless this.isTemplateContainer
hr
ul.pop-over-list
@@ -82,6 +85,19 @@ template(name="setSwimlaneColorPopup")
button.primary.confirm.js-submit {{_ 'save'}}
button.js-remove-color.negate.wide.right {{_ 'unset-color'}}
template(name="setSwimlaneHeightPopup")
#js-swimlane-height-edit
label {{_ 'set-swimlane-height-value'}}
p
input.swimlane-height-value(type="number" value="{{ swimlaneHeightValue }}" min="100")
input.swimlane-height-apply(type="submit" value="{{_ 'apply'}}")
input.swimlane-height-error
template(name="swimlaneHeightErrorPopup")
.swimlane-height-invalid
p {{_ 'swimlane-height-error-message'}} '&gt;=100'
button.full.js-back-view(type="submit") {{_ 'cancel'}}
template(name="swimlaneDeletePopup")
p {{_ "swimlane-delete-pop"}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
+47 -3
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
const { calculateIndexData } = Utils;
let swimlaneColors;
@@ -30,12 +31,13 @@ BlazeComponent.extendComponent({
Template.swimlaneFixedHeader.helpers({
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
});
Template.swimlaneActionPopup.events({
'click .js-set-swimlane-color': Popup.open('setSwimlaneColor'),
'click .js-set-swimlane-height': Popup.open('setSwimlaneHeight'),
'click .js-close-swimlane'(event) {
event.preventDefault();
this.archive();
@@ -47,7 +49,7 @@ Template.swimlaneActionPopup.events({
Template.swimlaneActionPopup.events({
isCommentOnly() {
return Meteor.user().isCommentOnly();
return ReactiveCache.getCurrentUser().isCommentOnly();
},
});
@@ -61,7 +63,7 @@ BlazeComponent.extendComponent({
{
submit(event) {
event.preventDefault();
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
const nextSwimlane = currentBoard.nextSwimlane(this.currentSwimlane);
const titleInput = this.find('.swimlane-name-input');
const title = titleInput.value.trim();
@@ -128,3 +130,45 @@ BlazeComponent.extendComponent({
];
},
}).register('setSwimlaneColorPopup');
BlazeComponent.extendComponent({
onCreated() {
this.currentSwimlane = this.currentData();
},
applySwimlaneHeight() {
const swimlane = this.currentData();
const board = swimlane.boardId;
const height = parseInt(
Template.instance()
.$('.swimlane-height-value')
.val(),
10,
);
// FIXME(mark-i-m): where do we put constants?
if (height < 100 || !height) {
Template.instance()
.$('.swimlane-height-error')
.click();
} else {
Meteor.call('applySwimlaneHeight', board, swimlane._id, height);
Popup.back();
}
},
swimlaneHeightValue() {
const swimlane = this.currentData();
const board = swimlane.boardId;
return Meteor.user().getSwimlaneHeight(board, swimlane._id);
},
events() {
return [
{
'click .swimlane-height-apply': this.applySwimlaneHeight,
'click .swimlane-height-error': Popup.open('swimlaneHeightError'),
},
];
},
}).register('setSwimlaneHeightPopup');
@@ -116,6 +116,9 @@
left: 87vw;
font-size: 24px;
}
#js-swimlane-height-edit .swimlane-height-error {
display: none;
}
.list-group {
height: 100%;
}
+7 -6
View File
@@ -2,7 +2,8 @@ template(name="swimlane")
.swimlane
+swimlaneHeader
unless collapseSwimlane
.swimlane.js-lists.js-swimlane(id="swimlane-{{_id}}")
.swimlane.js-lists.js-swimlane(id="swimlane-{{_id}}"
style="height:{{swimlaneHeight}}px;")
if isMiniScreen
if currentListIsInThisSwimlane _id
+list(currentList)
@@ -28,20 +29,20 @@ template(name="listsGroup")
if currentList
+list(currentList)
else
each lists
+miniList(this)
if currentUser.isBoardMember
unless currentUser.isCommentOnly
+addListForm
each lists
+miniList(this)
else
if currentUser.isBoardMember
unless currentUser.isCommentOnly
+addListForm
each lists
if visible this
+list(this)
if currentCardIsInThisList _id null
+cardDetails(currentCard)
if currentUser.isBoardMember
unless currentUser.isCommentOnly
+addListForm
template(name="addListForm")
unless currentUser.isWorker
+17 -29
View File
@@ -1,7 +1,8 @@
import { ReactiveCache } from '/imports/reactiveCache';
const { calculateIndex } = Utils;
function currentListIsInThisSwimlane(swimlaneId) {
const currentList = Lists.findOne(Session.get('currentList'));
const currentList = Utils.getCurrentList();
return (
currentList &&
(currentList.swimlaneId === swimlaneId || currentList.swimlaneId === '')
@@ -10,7 +11,7 @@ function currentListIsInThisSwimlane(swimlaneId) {
function currentCardIsInThisList(listId, swimlaneId) {
const currentCard = Utils.getCurrentCard();
//const currentUser = Meteor.user();
//const currentUser = ReactiveCache.getCurrentUser();
if (
//currentUser &&
//currentUser.profile &&
@@ -104,15 +105,6 @@ function initSortable(boardComponent, $listsDom) {
},
});
//function userIsMember() {
// return (
// Meteor.user() &&
// Meteor.user().isBoardMember() &&
// !Meteor.user().isCommentOnly() &&
// !Meteor.user().isWorker()
// );
//}
boardComponent.autorun(() => {
if (Utils.isTouchScreenOrShowDesktopDragHandles()) {
$listsDom.sortable({
@@ -129,11 +121,7 @@ function initSortable(boardComponent, $listsDom) {
$listsDom.sortable(
'option',
'disabled',
// Disable drag-dropping when user is not member/is worker
//!userIsMember() || Meteor.user().isWorker(),
!Meteor.user() || !Meteor.user().isBoardAdmin(),
// Not disable drag-dropping while in multi-selection mode
// MultiSelection.isActive() || !userIsMember(),
!ReactiveCache.getCurrentUser()?.isBoardAdmin(),
);
}
});
@@ -182,7 +170,7 @@ BlazeComponent.extendComponent({
.parentComponent()
.data()._id;
const cards = list.cards(swimlaneId);
if (cards.count() === 0) {
if (cards.length === 0) {
return false;
}
}
@@ -235,11 +223,17 @@ BlazeComponent.extendComponent({
},
];
},
swimlaneHeight() {
const user = Meteor.user();
const swimlane = Template.currentData();
return user.getSwimlaneHeight(swimlane.boardId, swimlane._id);
},
}).register('swimlane');
BlazeComponent.extendComponent({
onCreated() {
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
this.currentBoard = Utils.getCurrentBoard();
this.isListTemplatesSwimlane =
this.currentBoard.isTemplatesBoard() &&
this.currentData().isListTemplatesSwimlane();
@@ -263,7 +257,7 @@ BlazeComponent.extendComponent({
if (lastList) {
const positionInput = this.find('.list-position-input');
const position = positionInput.value.trim();
const ret = Lists.findOne({ boardId: Session.get('currentBoard'), _id: position, archived: false })
const ret = ReactiveCache.getList({ boardId: Utils.getCurrentBoardId(), _id: position, archived: false })
sortIndex = parseInt(JSON.stringify(ret['sort']))
sortIndex = sortIndex+1
} else {
@@ -294,12 +288,6 @@ BlazeComponent.extendComponent({
Template.swimlane.helpers({
canSeeAddList() {
return Meteor.user().isBoardAdmin();
/*
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
*/
},
});
@@ -324,7 +312,7 @@ BlazeComponent.extendComponent({
.parentComponent()
.data()._id;
const cards = list.cards(swimlaneId);
if (cards.count() === 0) {
if (cards.length === 0) {
return false;
}
}
@@ -350,7 +338,7 @@ class MoveSwimlaneComponent extends BlazeComponent {
}
board() {
return Boards.findOne(Session.get('currentBoard'));
return Utils.getCurrentBoard();
}
toBoardsSelector() {
@@ -363,14 +351,14 @@ class MoveSwimlaneComponent extends BlazeComponent {
}
toBoards() {
return Boards.find(this.toBoardsSelector(), { sort: { title: 1 } });
const ret = ReactiveCache.getBoards(this.toBoardsSelector(), { sort: { title: 1 } });
return ret;
}
events() {
return [
{
'click .js-done'() {
// const swimlane = Swimlanes.findOne(this.currentSwimlane._id);
const bSelect = $('.js-select-boards')[0];
let boardId;
if (bSelect) {
+20 -24
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import Cards from '/models/cards';
import Avatars from '/models/avatars';
import Users from '/models/users';
@@ -6,7 +7,7 @@ import Team from '/models/team';
Template.userAvatar.helpers({
userData() {
return Users.findOne(this.userId, {
return ReactiveCache.getUser(this.userId, {
fields: {
profile: 1,
username: 1,
@@ -15,13 +16,13 @@ Template.userAvatar.helpers({
},
memberType() {
const user = Users.findOne(this.userId);
const user = ReactiveCache.getUser(this.userId);
return user && user.isBoardAdmin() ? 'admin' : 'normal';
},
/*
presenceStatusClassName() {
const user = Users.findOne(this.userId);
const user = ReactiveCache.getUser(this.userId);
const userPresence = presences.findOne({ userId: this.userId });
if (user && user.isInvitedTo(Session.get('currentBoard'))) return 'pending';
else if (!userPresence) return 'disconnected';
@@ -35,12 +36,12 @@ Template.userAvatar.helpers({
Template.userAvatarInitials.helpers({
initials() {
const user = Users.findOne(this.userId);
const user = ReactiveCache.getUser(this.userId);
return user && user.getInitials();
},
viewPortWidth() {
const user = Users.findOne(this.userId);
const user = ReactiveCache.getUser(this.userId);
return ((user && user.getInitials().length) || 1) * 12;
},
});
@@ -88,21 +89,18 @@ BlazeComponent.extendComponent({
Template.boardOrgRow.helpers({
orgData() {
return Org.findOne(this.orgId);
},
currentUser(){
return Meteor.user();
return ReactiveCache.getOrg(this.orgId);
},
});
Template.boardOrgName.helpers({
orgName() {
const org = Org.findOne(this.orgId);
const org = ReactiveCache.getOrg(this.orgId);
return org && org.orgDisplayName;
},
orgViewPortWidth() {
const org = Org.findOne(this.orgId);
const org = ReactiveCache.getOrg(this.orgId);
return ((org && org.orgDisplayName.length) || 1) * 12;
},
});
@@ -150,21 +148,18 @@ BlazeComponent.extendComponent({
Template.boardTeamRow.helpers({
teamData() {
return Team.findOne(this.teamId);
},
currentUser(){
return Meteor.user();
return ReactiveCache.getTeam(this.teamId);
},
});
Template.boardTeamName.helpers({
teamName() {
const team = Team.findOne(this.teamId);
const team = ReactiveCache.getTeam(this.teamId);
return team && team.teamDisplayName;
},
teamViewPortWidth() {
const team = Team.findOne(this.teamId);
const team = ReactiveCache.getTeam(this.teamId);
return ((team && team.teamDisplayName.length) || 1) * 12;
},
});
@@ -177,24 +172,25 @@ BlazeComponent.extendComponent({
},
uploadedAvatars() {
return Avatars.find({ userId: Meteor.userId() }).each();
const ret = ReactiveCache.getAvatars({ userId: Meteor.userId() }, {}, true).each();
return ret;
},
isSelected() {
const userProfile = Meteor.user().profile;
const userProfile = ReactiveCache.getCurrentUser().profile;
const avatarUrl = userProfile && userProfile.avatarUrl;
const currentAvatarUrl = `${this.currentData().link()}?auth=false&brokenIsFine=true`;
return avatarUrl === currentAvatarUrl;
},
noAvatarUrl() {
const userProfile = Meteor.user().profile;
const userProfile = ReactiveCache.getCurrentUser().profile;
const avatarUrl = userProfile && userProfile.avatarUrl;
return !avatarUrl;
},
setAvatar(avatarUrl) {
Meteor.user().setAvatarUrl(avatarUrl);
ReactiveCache.getCurrentUser().setAvatarUrl(avatarUrl);
},
setError(error) {
@@ -248,7 +244,7 @@ Template.cardMembersPopup.helpers({
},
user() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
});
@@ -263,13 +259,13 @@ Template.cardMembersPopup.events({
Template.cardMemberPopup.helpers({
user() {
return Users.findOne(this.userId);
return ReactiveCache.getUser(this.userId);
},
});
Template.cardMemberPopup.events({
'click .js-remove-member'() {
Cards.findOne(this.cardId).unassignMember(this.userId);
ReactiveCache.getCard(this.cardId).unassignMember(this.userId);
Popup.back();
},
'click .js-edit-profile': Popup.open('editProfile'),
+14 -19
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
Template.headerUserBar.events({
@@ -13,27 +14,27 @@ BlazeComponent.extendComponent({
Template.memberMenuPopup.helpers({
templatesBoardId() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return Meteor.user().getTemplatesBoardId();
return currentUser.getTemplatesBoardId();
} else {
// No need to getTemplatesBoardId on public board
return false;
}
},
templatesBoardSlug() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return Meteor.user().getTemplatesBoardSlug();
return currentUser.getTemplatesBoardSlug();
} else {
// No need to getTemplatesBoardSlug() on public board
return false;
}
},
isSameDomainNameSettingValue(){
const currSett = Settings.findOne();
const currSett = ReactiveCache.getCurrentSetting();
if(currSett && currSett != undefined && currSett.disableRegistration && currSett.mailDomainName !== undefined && currSett.mailDomainName != ""){
currentUser = Meteor.user();
currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
let found = false;
for(let i = 0; i < currentUser.emails.length; i++) {
@@ -51,7 +52,7 @@ Template.memberMenuPopup.helpers({
return false;
},
isNotOAuth2AuthenticationMethod(){
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return currentUser.authenticationMethod.toLowerCase() != 'oauth2';
} else {
@@ -140,12 +141,6 @@ Template.invitePeoplePopup.events({
},
});
Template.invitePeoplePopup.helpers({
currentSetting() {
return Settings.findOne();
},
});
Template.editProfilePopup.helpers({
allowEmailChange() {
Meteor.call('AccountSettings.allowEmailChange', (_, result) => {
@@ -191,9 +186,9 @@ Template.editProfilePopup.events({
'profile.initials': initials,
},
});
isChangeUserName = username !== Meteor.user().username;
isChangeUserName = username !== ReactiveCache.getCurrentUser().username;
isChangeEmail =
email.toLowerCase() !== Meteor.user().emails[0].address.toLowerCase();
email.toLowerCase() !== ReactiveCache.getCurrentUser().emails[0].address.toLowerCase();
if (isChangeUserName && isChangeEmail) {
Meteor.call(
'setUsernameAndEmail',
@@ -288,7 +283,7 @@ Template.changeLanguagePopup.events({
Template.changeSettingsPopup.helpers({
hiddenSystemMessages() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).hasHiddenSystemMessages;
} else if (window.localStorage.getItem('hasHiddenSystemMessages')) {
@@ -298,7 +293,7 @@ Template.changeSettingsPopup.helpers({
}
},
rescueCardDescription() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).rescueCardDescription;
} else if (window.localStorage.getItem('rescueCardDescription')) {
@@ -308,9 +303,9 @@ Template.changeSettingsPopup.helpers({
}
},
showCardsCountAt() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return Meteor.user().getLimitToShowCardsCount();
return currentUser.getLimitToShowCardsCount();
} else {
return window.localStorage.getItem('limitToShowCardsCount');
}
+22 -7
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { Blaze } from 'meteor/blaze';
import { Session } from 'meteor/session';
import moment from 'moment/min/moment-with-locales';
@@ -13,15 +14,21 @@ Blaze.registerHelper('currentCard', () => {
});
Blaze.registerHelper('currentList', () => {
const listId = Session.get('currentList');
if (listId) {
return Lists.findOne(listId);
} else {
return null;
}
const ret = Utils.getCurrentList();
return ret;
});
Blaze.registerHelper('getUser', userId => Users.findOne(userId));
Blaze.registerHelper('currentSetting', () => {
const ret = ReactiveCache.getCurrentSetting();
return ret;
});
Blaze.registerHelper('currentUser', () => {
const ret = ReactiveCache.getCurrentUser();
return ret;
});
Blaze.registerHelper('getUser', userId => ReactiveCache.getUser(userId));
Blaze.registerHelper('concat', (...args) => args.slice(0, -1).join(''));
@@ -42,3 +49,11 @@ Blaze.registerHelper('moment', (...args) => {
const [date, format] = args;
return moment(date).format(format);
});
Blaze.registerHelper('canModifyCard', () =>
Utils.canModifyCard(),
);
Blaze.registerHelper('canModifyBoard', () =>
Utils.canModifyBoard(),
);
+5 -4
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
import Cards from '../../models/cards';
import SessionData from '../../models/usersessiondata';
@@ -61,8 +62,8 @@ export class CardSearchPagedComponent extends BlazeComponent {
}
getSessionData(sessionId) {
return SessionData.findOne({
sessionId: sessionId ? sessionId : SessionData.getSessionId(),
return ReactiveCache.getSessionData({
sessionId: sessionId || SessionData.getSessionId(),
});
}
@@ -74,7 +75,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
console.log('session data:', this.sessionData);
const cards = [];
this.sessionData.cards.forEach(cardId => {
cards.push(Cards.findOne({ _id: cardId }));
cards.push(ReactiveCache.getCard(cardId));
});
this.queryErrors = this.sessionData.errors;
if (this.queryErrors.length) {
@@ -168,7 +169,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
} else if (this.resultsCount === 1) {
return TAPi18n.__('one-card-found');
} else if (this.resultsCount === this.totalHits) {
return TAPi18n.__('n-cards-found').replace('%s', this.resultsCount);
return TAPi18n.__('n-cards-found', {sprintf: [this.resultsCount]});
}
return TAPi18n.__('n-n-of-n-cards-found', {
+2 -1
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
import moment from 'moment/min/moment-with-locales';
@@ -22,7 +23,7 @@ export class DatePicker extends BlazeComponent {
}
startDayOfWeek() {
const currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return currentUser.getStartDayOfWeek();
} else {
+12 -10
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
export class DialogWithBoardSwimlaneList extends BlazeComponent {
/** returns the card dialog options
* @return Object with properties { boardId, swimlaneId, listId }
@@ -52,26 +54,26 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
}
}
this.getBoardData(this.selectedBoardId.get());
if (!this.selectedSwimlaneId.get() || !Swimlanes.findOne({_id: this.selectedSwimlaneId.get(), boardId: this.selectedBoardId.get()})) {
if (!this.selectedSwimlaneId.get() || !ReactiveCache.getSwimlane({_id: this.selectedSwimlaneId.get(), boardId: this.selectedBoardId.get()})) {
this.setFirstSwimlaneId();
}
if (!this.selectedListId.get() || !Lists.findOne({_id: this.selectedListId.get(), boardId: this.selectedBoardId.get()})) {
if (!this.selectedListId.get() || !ReactiveCache.getList({_id: this.selectedListId.get(), boardId: this.selectedBoardId.get()})) {
this.setFirstListId();
}
}
/** sets the first swimlane id */
setFirstSwimlaneId() {
try {
const board = Boards.findOne(this.selectedBoardId.get());
const swimlaneId = board.swimlanes().fetch()[0]._id;
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
const swimlaneId = board.swimlanes()[0]._id;
this.selectedSwimlaneId.set(swimlaneId);
} catch (e) {}
}
/** sets the first list id */
setFirstListId() {
try {
const board = Boards.findOne(this.selectedBoardId.get());
const listId = board.lists().fetch()[0]._id;
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
const listId = board.lists()[0]._id;
this.selectedListId.set(listId);
} catch (e) {}
}
@@ -105,11 +107,11 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
/** returns all available board */
boards() {
const ret = Boards.find(
const ret = ReactiveCache.getBoards(
{
archived: false,
'members.userId': Meteor.userId(),
_id: { $ne: Meteor.user().getTemplatesBoardId() },
_id: { $ne: ReactiveCache.getCurrentUser().getTemplatesBoardId() },
},
{
sort: { sort: 1 },
@@ -120,14 +122,14 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
/** returns all available swimlanes of the current board */
swimlanes() {
const board = Boards.findOne(this.selectedBoardId.get());
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
const ret = board.swimlanes();
return ret;
}
/** returns all available lists of the current board */
lists() {
const board = Boards.findOne(this.selectedBoardId.get());
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
const ret = board.lists();
return ret;
}
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { DialogWithBoardSwimlaneList } from '/client/lib/dialogWithBoardSwimlaneList';
export class DialogWithBoardSwimlaneListCard extends DialogWithBoardSwimlaneList {
@@ -22,7 +23,7 @@ export class DialogWithBoardSwimlaneListCard extends DialogWithBoardSwimlaneList
/** returns all available cards of the current list */
cards() {
const list = Lists.findOne(this.selectedListId.get());
const list = ReactiveCache.getList(this.selectedListId.get());
let ret = [];
if (list) {
ret = list.cards(this.selectedSwimlaneId.get());
+4 -3
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import moment from 'moment/min/moment-with-locales';
// Filtered view manager
@@ -107,7 +108,7 @@ class DateFilter {
// preferred starting day of the week. This date should be added
// to the moment start of week to get the real start of week date.
// The default is 1, meaning Monday.
const currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
const weekStartDay = currentUser ? currentUser.getStartDayOfWeek() : 1;
if (week === 'this') {
@@ -371,14 +372,14 @@ class AdvancedFilter {
}
_fieldNameToId(field) {
const found = CustomFields.findOne({
const found = ReactiveCache.getCustomField({
name: field,
});
return found._id;
}
_fieldValueToId(field, value) {
const found = CustomFields.findOne({
const found = ReactiveCache.getCustomField({
name: field,
});
if (
+14 -2
View File
@@ -1,11 +1,23 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
// We save the user language preference in the user profile, and use that to set
// the language reactively. If the user is not connected we use the language
// information provided by the browser, and default to english.
Meteor.startup(() => {
const currentUser = Meteor.user();
Meteor.startup(async () => {
let currentUser = ReactiveCache.getCurrentUser();
// If we're still logging in, wait (#4967)
if (!currentUser && Meteor.loggingIn()) {
await new Promise((resolve) => {
Tracker.autorun(() => {
if (!Meteor.loggingIn()) {
resolve();
}
});
});
currentUser = ReactiveCache.getCurrentUser();
}
// Select first available language
const [language] = [
// User profile
+13 -15
View File
@@ -1,3 +1,5 @@
import { ReactiveCache } from '/imports/reactiveCache';
// XXX There is no reason to define these shortcuts globally, they should be
// attached to a template (most of them will go in the `board` template).
@@ -76,14 +78,14 @@ Mousetrap.bind(numbArray, (evt, key) => {
return;
}
const currentBoardId = Session.get('currentBoard');
board = Boards.findOne(currentBoardId);
board = ReactiveCache.getBoard(currentBoardId);
labels = board.labels;
if(MultiSelection.isActive())
{
const cardIds = MultiSelection.getSelectedCardIds();
for (const cardId of cardIds)
{
card = Cards.findOne(cardId);
card = ReactiveCache.getCard(cardId);
if(num <= board.labels.length)
{
card.removeLabel(labels[num-1]["_id"]);
@@ -100,14 +102,14 @@ Mousetrap.bind(numArray, (evt, key) => {
if (currentUserId === null) {
return;
}
board = Boards.findOne(currentBoardId);
board = ReactiveCache.getBoard(currentBoardId);
labels = board.labels;
if(MultiSelection.isActive() && Meteor.user().isBoardMember())
if(MultiSelection.isActive() && ReactiveCache.getCurrentUser().isBoardMember())
{
const cardIds = MultiSelection.getSelectedCardIds();
for (const cardId of cardIds)
{
card = Cards.findOne(cardId);
card = ReactiveCache.getCard(cardId);
if(num <= board.labels.length)
{
card.addLabel(labels[num-1]["_id"]);
@@ -120,8 +122,8 @@ Mousetrap.bind(numArray, (evt, key) => {
if (!cardId) {
return;
}
if (Meteor.user().isBoardMember()) {
const card = Cards.findOne(cardId);
if (ReactiveCache.getCurrentUser().isBoardMember()) {
const card = ReactiveCache.getCard(cardId);
if(num <= board.labels.length)
{
card.toggleLabel(labels[num-1]["_id"]);
@@ -140,8 +142,8 @@ Mousetrap.bind('space', evt => {
return;
}
if (Meteor.user().isBoardMember()) {
const card = Cards.findOne(cardId);
if (ReactiveCache.getCurrentUser().isBoardMember()) {
const card = ReactiveCache.getCard(cardId);
card.toggleMember(currentUserId);
// We should prevent scrolling in card when spacebar is clicked
// This should do it according to Mousetrap docs, but it doesn't
@@ -160,12 +162,8 @@ Mousetrap.bind('c', evt => {
return;
}
if (
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
) {
const card = Cards.findOne(cardId);
if (Utils.canModifyBoard()) {
const card = ReactiveCache.getCard(cardId);
card.archive();
// We should prevent scrolling in card when spacebar is clicked
// This should do it according to Mousetrap docs, but it doesn't
+8 -6
View File
@@ -1,19 +1,21 @@
import { ReactiveCache } from '/imports/reactiveCache';
function getCardsBetween(idA, idB) {
function pluckId(doc) {
return doc._id;
}
function getListsStrictlyBetween(id1, id2) {
return Lists.find({
return ReactiveCache.getLists({
$and: [
{ sort: { $gt: Lists.findOne(id1).sort } },
{ sort: { $lt: Lists.findOne(id2).sort } },
{ sort: { $gt: ReactiveCache.getList(id1).sort } },
{ sort: { $lt: ReactiveCache.getList(id2).sort } },
],
archived: false,
}).map(pluckId);
}
const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], c => {
const cards = _.sortBy([ReactiveCache.getCard(idA), ReactiveCache.getCard(idB)], c => {
return c.sort;
});
@@ -48,7 +50,7 @@ function getCardsBetween(idA, idB) {
};
}
return Cards.find(Filter.mongoSelector(selector)).map(pluckId);
return ReactiveCache.getCards(Filter.mongoSelector(selector)).map(pluckId);
}
MultiSelection = {
@@ -77,7 +79,7 @@ MultiSelection = {
},
count() {
return Cards.find(this.getMongoSelector()).count();
return ReactiveCache.getCards(this.getMongoSelector()).length;
},
isEmpty() {
+23
View File
@@ -76,6 +76,14 @@ window.Popup = new (class {
dataContext: (this && this.currentData && this.currentData()) || (options && options.dataContextIfCurrentDataIsUndefined) || this,
});
const $contentWrapper = $('.content-wrapper')
if ($contentWrapper.length > 0) {
const contentWrapper = $contentWrapper[0];
self._getTopStack().scrollTop = contentWrapper.scrollTop;
// scroll from e.g. delete comment to the top (where the confirm button is)
$contentWrapper.scrollTop(0);
}
// 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
@@ -129,6 +137,21 @@ window.Popup = new (class {
/// steps back is greater than the popup stack size, the popup will be closed.
back(n = 1) {
if (this._stack.length > n) {
const $contentWrapper = $('.content-wrapper')
if ($contentWrapper.length > 0) {
const contentWrapper = $contentWrapper[0];
const stack = this._stack[this._stack.length - n];
// scrollTopMax and scrollLeftMax only available at Firefox (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTopMax)
const scrollTopMax = contentWrapper.scrollTopMax || contentWrapper.scrollHeight - contentWrapper.clientHeight;
if (scrollTopMax && stack.scrollTop > scrollTopMax) {
// sometimes scrollTopMax is lower than scrollTop, so i need this dirty hack
setTimeout(() => {
$contentWrapper.scrollTop(stack.scrollTop);
}, 6);
}
// restore the old popup scroll position
$contentWrapper.scrollTop(stack.scrollTop);
}
_.times(n, () => this._stack.pop());
this._dep.changed();
} else {
+3 -5
View File
@@ -1,19 +1,17 @@
import { ReactiveCache } from '/imports/reactiveCache';
Meteor.subscribe('setting');
import { ALLOWED_WAIT_SPINNERS } from '/config/const';
export class Spinner extends BlazeComponent {
currentSettings() {
return Settings.findOne();
}
getSpinnerName() {
let ret = 'Bounce';
let defaultWaitSpinner = Meteor.settings.public.WAIT_SPINNER;
if (defaultWaitSpinner && ALLOWED_WAIT_SPINNERS.includes(defaultWaitSpinner)) {
ret = defaultWaitSpinner;
}
let settings = this.currentSettings();
let settings = ReactiveCache.getCurrentSetting();
if (settings && settings.spinnerName) {
ret = settings.spinnerName;
+97 -63
View File
@@ -1,20 +1,13 @@
import { ReactiveCache } from '/imports/reactiveCache';
Utils = {
setBackgroundImage(url) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
/*
if(url) {
if (url !== currentBoard.backgroundImageURL) {
currentBoard.setBackgroundImageURL(url);
} else {
currentBoard.setBackgroundImageURL("");
}
}
*/
if (currentBoard.backgroundImageURL) {
const currentBoard = Utils.getCurrentBoard();
if (currentBoard.backgroundImageURL !== undefined) {
$(".board-wrapper,.board-wrapper .board-canvas").css({"background":"url(" + currentBoard.backgroundImageURL + ")","background-size":"cover"});
$(".swimlane,.swimlane .list,.swimlane .list .list-body,.swimlane .list:first-child .list-body").css({"background-color":"transparent"});
} else {
$(".board-wrapper,.board-wrapper .board-canvas").css({"background": currentBoard.background-color});
} else if (currentBoard.color !== undefined) {
currentBoard.setColor(currentBoard.color);
}
},
/** returns the current board id
@@ -40,22 +33,53 @@ Utils = {
const ret = Session.get('popupCardId');
return ret;
},
getCurrentListId() {
const ret = Session.get('currentList');
return ret;
},
/** returns the current board
* <li> returns the current board or the board of the popup card if set
*/
getCurrentBoard() {
const boardId = Utils.getCurrentBoardId();
const ret = Boards.findOne(boardId);
const ret = ReactiveCache.getBoard(boardId);
return ret;
},
getCurrentCard(ignorePopupCard) {
const cardId = Utils.getCurrentCardId(ignorePopupCard);
const ret = Cards.findOne(cardId);
const ret = ReactiveCache.getCard(cardId);
return ret;
},
getCurrentList() {
const listId = this.getCurrentListId();
let ret = null;
if (listId) {
ret = ReactiveCache.getList(listId);
}
return ret;
},
getPopupCard() {
const cardId = Utils.getPopupCardId();
const ret = Cards.findOne(cardId);
const ret = ReactiveCache.getCard(cardId);
return ret;
},
canModifyCard() {
const currentUser = ReactiveCache.getCurrentUser();
const ret = (
currentUser &&
currentUser.isBoardMember() &&
!currentUser.isCommentOnly() &&
!currentUser.isWorker()
);
return ret;
},
canModifyBoard() {
const currentUser = ReactiveCache.getCurrentUser();
const ret = (
currentUser &&
currentUser.isBoardMember() &&
!currentUser.isCommentOnly()
);
return ret;
},
reload() {
@@ -66,9 +90,9 @@ Utils = {
window.location.reload();
},
setBoardView(view) {
currentUser = Meteor.user();
currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
Meteor.user().setBoardView(view);
ReactiveCache.getCurrentUser().setBoardView(view);
} else if (view === 'board-view-swimlanes') {
window.localStorage.setItem('boardView', 'board-view-swimlanes'); //true
Utils.reload();
@@ -90,7 +114,7 @@ Utils = {
},
boardView() {
currentUser = Meteor.user();
currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).boardView;
} else if (
@@ -134,11 +158,8 @@ Utils = {
},
archivedBoardIds() {
const archivedBoards = [];
Boards.find({ archived: false }).forEach(board => {
archivedBoards.push(board._id);
});
return archivedBoards;
const ret = ReactiveCache.getBoards({ archived: false }).map(board => board._id);
return ret;
},
dueCardsView() {
@@ -173,7 +194,7 @@ Utils = {
// XXX We should remove these two methods
goBoardId(_id) {
const board = Boards.findOne(_id);
const board = ReactiveCache.getBoard(_id);
return (
board &&
FlowRouter.go('board', {
@@ -184,8 +205,8 @@ Utils = {
},
goCardId(_id) {
const card = Cards.findOne(_id);
const board = Boards.findOne(card.boardId);
const card = ReactiveCache.getCard(_id);
const board = ReactiveCache.getBoard(card.boardId);
return (
board &&
FlowRouter.go('card', {
@@ -198,7 +219,7 @@ Utils = {
getCommonAttachmentMetaFrom(card) {
const meta = {};
if (card.isLinkedCard()) {
meta.boardId = Cards.findOne(card.linkedId).boardId;
meta.boardId = ReactiveCache.getCard(card.linkedId).boardId;
meta.cardId = card.linkedId;
} else {
meta.boardId = card.boardId;
@@ -306,7 +327,7 @@ Utils = {
// returns if desktop drag handles are enabled
isShowDesktopDragHandles() {
//const currentUser = Meteor.user();
//const currentUser = ReactiveCache.getCurrentUser();
//if (currentUser) {
// return (currentUser.profile || {}).showDesktopDragHandles;
//} else if (window.localStorage.getItem('showDesktopDragHandles')) {
@@ -331,20 +352,51 @@ Utils = {
increment = 1;
// If we drop the card in the first position
} else if (!prevData) {
base = nextData.sort - 1;
increment = -1;
const nextSortIndex = nextData.sort;
const ceil = Math.ceil(nextSortIndex - 1);
if (ceil < nextSortIndex) {
increment = nextSortIndex - ceil;
base = nextSortIndex - increment;
} else {
base = nextData.sort - 1;
increment = -1;
}
// If we drop the card in the last position
} else if (!nextData) {
base = prevData.sort + 1;
increment = 1;
const prevSortIndex = prevData.sort;
const floor = Math.floor(prevSortIndex + 1);
if (floor > prevSortIndex) {
increment = prevSortIndex - floor;
base = prevSortIndex - increment;
} else {
base = prevData.sort + 1;
increment = 1;
}
}
// In the general case take the average of the previous and next element
// sort indexes.
else {
const prevSortIndex = prevData.sort;
const nextSortIndex = nextData.sort;
increment = (nextSortIndex - prevSortIndex) / (nItems + 1);
base = prevSortIndex + increment;
if (nItems == 1 ) {
if (prevSortIndex < 0 ) {
const ceil = Math.ceil(nextSortIndex - 1);
if (ceil < nextSortIndex && ceil > prevSortIndex) {
increment = ceil - prevSortIndex;
}
} else {
const floor = Math.floor(nextSortIndex - 1);
if (floor < nextSortIndex && floor > prevSortIndex) {
increment = floor - prevSortIndex;
}
}
}
if (!increment) {
increment = (nextSortIndex - prevSortIndex) / (nItems + 1);
}
if (!base) {
base = prevSortIndex + increment;
}
}
// XXX Return a generator that yield values instead of a base with a
// increment number.
@@ -356,34 +408,16 @@ Utils = {
// Determine the new sort index
calculateIndex(prevCardDomElement, nextCardDomElement, nCards = 1) {
let base, increment;
// If we drop the card to an empty column
if (!prevCardDomElement && !nextCardDomElement) {
base = 0;
increment = 1;
// If we drop the card in the first position
} else if (!prevCardDomElement) {
base = Blaze.getData(nextCardDomElement).sort - 1;
increment = -1;
// If we drop the card in the last position
} else if (!nextCardDomElement) {
base = Blaze.getData(prevCardDomElement).sort + 1;
increment = 1;
let prevData = null;
let nextData = null;
if (prevCardDomElement) {
prevData = Blaze.getData(prevCardDomElement)
}
// In the general case take the average of the previous and next element
// sort indexes.
else {
const prevSortIndex = Blaze.getData(prevCardDomElement).sort;
const nextSortIndex = Blaze.getData(nextCardDomElement).sort;
increment = (nextSortIndex - prevSortIndex) / (nCards + 1);
base = prevSortIndex + increment;
if (nextCardDomElement) {
nextData = Blaze.getData(nextCardDomElement);
}
// XXX Return a generator that yield values instead of a base with a
// increment number.
return {
base,
increment,
};
const ret = Utils.calculateIndexData(prevData, nextData, nCards);
return ret;
},
manageCustomUI() {
@@ -398,7 +432,7 @@ Utils = {
},
setCustomUI(data) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
if (currentBoard) {
DocHead.setTitle(`${currentBoard.title} - ${data.productName}`);
} else {
@@ -410,7 +444,7 @@ Utils = {
window._paq = window._paq || [];
window._paq.push(['setDoNotTrack', data.doNotTrack]);
if (data.withUserName) {
window._paq.push(['setUserId', Meteor.user().username]);
window._paq.push(['setUserId', ReactiveCache.getCurrentUser().username]);
}
window._paq.push(['trackPageView']);
window._paq.push(['enableLinkTracking']);
+3 -5
View File
@@ -4,7 +4,7 @@ const passwordField = AccountsTemplates.removeField('password');
const emailField = AccountsTemplates.removeField('email');
let disableRegistration = false;
let disableForgotPassword = false;
let passwordLoginDisabled = false;
let passwordLoginEnabled = false;
let oidcRedirectionEnabled = false;
let oauthServerUrl = "home";
let oauthDashboardUrl = "";
@@ -16,11 +16,9 @@ Meteor.call('isOidcRedirectionEnabled', (_, result) => {
}
});
Meteor.call('isPasswordLoginDisabled', (_, result) => {
Meteor.call('isPasswordLoginEnabled', (_, result) => {
if (result) {
passwordLoginDisabled = true;
//console.log('passwordLoginDisabled');
//console.log(result);
passwordLoginEnabled = true;
}
});
+4 -1
View File
@@ -540,12 +540,15 @@ export class Query {
}
} else if (operator === OPERATOR_LIMIT) {
const limit = parseInt(value, 10);
if (isNaN(limit) || limit < 1) {
if (isNaN(limit) || limit < 0) {
this.addError(OPERATOR_LIMIT, {
tag: 'operator-limit-invalid',
value,
});
continue;
} else if (limit == 0) {
// no limit
continue;
} else {
value = limit;
}
+1 -1
View File
@@ -421,7 +421,7 @@ _.each(redirections, (newPath, oldPath) => {
//Meteor.isClient && Meteor.startup(() => {
// Tracker.autorun(() => {
// const currentBoard = Boards.findOne(Session.get('currentBoard'));
// const currentBoard = Utils.getCurrentBoard();
// const titleStack = [appTitle];
// if (currentBoard) {
// titleStack.push(currentBoard.title);
+11 -1
View File
@@ -85,6 +85,14 @@
"add-card": "Add Card",
"add-card-to-top-of-list": "Add Card to Top of List",
"add-card-to-bottom-of-list": "Add Card to Bottom of List",
"setListWidthPopup-title": "Set List Width",
"set-list-width": "Set List Width",
"set-list-width-value": "List Width (pixels)",
"list-width-error-message": "List width must be a positive integer",
"setSwimlaneHeightPopup-title": "Set Swimlane Height",
"set-swimlane-height": "Set Swimlane Height",
"set-swimlane-height-value": "Swimlane Height (pixels)",
"swimlane-height-error-message": "Swimlane height must be a positive integer",
"add-swimlane": "Add Swimlane",
"add-subtask": "Add Subtask",
"add-checklist": "Add Checklist",
@@ -1219,5 +1227,7 @@
"allowed-upload-filetypes": "Allowed upload filetypes:",
"max-avatar-filesize": "Max avatar filesize in bytes:",
"allowed-avatar-filetypes": "Allowed avatar filetypes:",
"invalid-file": "If filename is invalid, upload or rename is cancelled."
"invalid-file": "If filename is invalid, upload or rename is cancelled.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
Loaded 100 of 305 files, more files were not shown because too many files have changed in this diff. Show more