Compare commits

...
303 Commits
Author SHA1 Message Date
Lauri Ojansivu 998f3fe8a7 v7.06 2023-08-15 14:46:59 +03:00
Lauri Ojansivu 81ece7cec2 Merge pull request #5080 from VidVidex/5074-swiping
Add attachment swiping
2023-08-14 16:46:42 +03:00
Vid Smole 30073ce1d6 Add attachment swiping 2023-08-14 15:38:13 +02:00
Lauri Ojansivu fc9fb9132c Updated translations. 2023-08-13 02:48:42 +03:00
Lauri Ojansivu 2f8c01eccf Updated ChangeLog. 2023-08-13 02:45:54 +03:00
Lauri Ojansivu 6d1705af34 Update building Windows bundle.
Thanks to xet7 !
2023-08-13 02:44:17 +03:00
Lauri Ojansivu fa6db6118d Updated translations. 2023-08-12 16:27:48 +03:00
Lauri Ojansivu f555acee6f Updated ChangeLog. 2023-08-09 22:24:08 +03:00
Lauri Ojansivu 4bc5799b4f Merge pull request #5075 from mfilser/label_drag_drop_and_reorder
label drag/drop (reorder labels) works now again
2023-08-09 21:26:49 +03:00
Martin Filser b2b8a99899 label drag/drop (reorder labels) works now again 2023-08-09 20:11:16 +02:00
Lauri Ojansivu 9641ac7ee8 Updated ChangeLog. 2023-08-09 16:56:35 +03:00
Lauri Ojansivu f9823f67bd Updated exceljs and jszip.
Thanks to developers of dependencies !
2023-08-09 16:54:27 +03:00
Lauri Ojansivu af14ff6e89 Updated translations. 2023-08-09 16:54:10 +03:00
Lauri Ojansivu 323f1b1d87 Updated ChangeLog. 2023-08-09 02:49:27 +03:00
Lauri Ojansivu 3e23a5ddce Merge pull request #5071 from chrisi51/alphabetic-order
Alphabetic ordered member lists on assigne and member lists
2023-08-09 02:40:45 +03:00
Christian 037bba83d6 Alphabetic ordered member lists on assigne and member lists 2023-08-08 23:24:35 +00:00
Lauri Ojansivu a60acac51a Updated ChangeLog. 2023-08-08 15:45:32 +03:00
Lauri Ojansivu eea0b1afc4 v7.05 2023-08-08 12:08:01 +03:00
Lauri Ojansivu 9a6d0c4aad Updated ChangeLog. 2023-08-08 11:58:39 +03:00
Lauri Ojansivu 1c530632ac Merge branch 'master' of https://github.com/chrisi51/wekan 2023-08-08 11:49:55 +03:00
Christian 18c49695b1 Optimize member list popups 2023-08-08 08:31:23 +00:00
Christian c8a743bb8e Fixing positioning of opened cards 2023-08-08 00:05:19 +00:00
Lauri Ojansivu 7e92068955 Updated dependencies. 2023-08-07 22:42:13 +03:00
Lauri Ojansivu 8c84254392 Updated ChangeLog. 2023-08-07 17:43:01 +03:00
Lauri Ojansivu 6b1403984f Fixed Normal (non-admin) board users cannot adjust swimlane height.
Thanks to mgdbbrt and xet7 !

Fixes #5063
2023-08-07 17:41:33 +03:00
Lauri Ojansivu c965cc9b76 Updated ChangeLog. 2023-08-07 17:15:28 +03:00
Lauri Ojansivu ab40737211 Show option b) -1 for disabling swimlane height at swimlane height popup.
Thanks to xet7 !
2023-08-07 17:12:49 +03:00
Lauri Ojansivu 950b477d9d Updated ChangeLog. 2023-08-07 17:02:13 +03:00
Lauri Ojansivu 529a43fa0e Updated dependencies. 2023-08-07 16:59:17 +03:00
Lauri Ojansivu eb16cd19bb Merge branch 'swimlane-default' of https://github.com/mark-i-m/wekan 2023-08-07 16:30:59 +03:00
Lauri Ojansivu fbd64a6a9e Updated translations. 2023-08-07 16:23:02 +03:00
mark 7536c7b532 allow -1 as 'auto' 2023-08-03 22:03:30 -05:00
mark 406766a82b make default swimlane auto-height 2023-08-03 22:03:30 -05:00
Lauri Ojansivu 5bb794e3bb v7.04 2023-08-03 22:21:18 +03:00
Lauri Ojansivu ee73e04004 Updated ChangeLog. 2023-08-03 22:18:37 +03:00
Lauri Ojansivu 672be413f7 Updated translations. 2023-08-03 22:17:03 +03:00
Lauri Ojansivu b0ba57a165 Updated ChangeLog. 2023-08-03 22:15:50 +03:00
Lauri Ojansivu 79c2301ad5 Updated dependencies. 2023-08-03 22:15:25 +03:00
Lauri Ojansivu b2c7be244e Updated translations. 2023-08-03 21:37:09 +03:00
Lauri Ojansivu 8f8c045930 Merge pull request #5058 from VidVidex/master
Do not open preview for attachments that cannot be previewed
2023-08-03 20:12:05 +03:00
Vid Smole 21ffff3977 Do not open preview for attachments that cannot be previewed 2023-08-03 18:57:12 +02:00
Lauri Ojansivu 7d1bca3702 Merge pull request #5056 from cloudron-io/login-layout-fixes-2
Login layout fixes 2
2023-08-03 18:38:29 +03:00
Johannes Zellner d93a58d892 Do not show OAuth2 in auth method dropdown as it has its own button 2023-08-03 17:17:08 +02:00
Johannes Zellner 99d9291a28 Never show the login form OR separator
So many states for with password enabled/disabled treated async
separately. Might be easier to bring back once password login is treated
like saml/ldap/... while still using the very same form elements
regardless
2023-08-03 17:00:34 +02:00
Johannes Zellner bda166ba50 Ensure we subscribe to currentSettings in login view 2023-08-03 16:53:23 +02:00
Johannes Zellner f190a102f9 formAuthenticationMethods is an array
part of #5051
2023-08-03 16:41:27 +02:00
Lauri Ojansivu d0ba89d913 Updated translations. 2023-08-03 12:53:38 +02:00
Lauri Ojansivu cb4f3c8895 Updated ChangeLog. 2023-08-03 12:50:44 +02:00
Lauri Ojansivu fd003f4402 Merge pull request #5055 from Pandetthe/master
Fix edit_swimlane
2023-08-03 13:46:27 +03:00
Jakub Jurczyk 3a22d4efdc Fix edit_swimlane 2023-08-03 12:44:22 +02:00
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
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
293 changed files with 6198 additions and 7027 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} \
+83 -1
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
@@ -53,6 +53,88 @@ 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
ostrio:i18n
reactive-var@1.0.12
+1 -1
View File
@@ -1 +1 @@
METEOR@2.12
METEOR@2.13
+83 -3
View File
@@ -48,7 +48,7 @@ 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
@@ -83,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
@@ -101,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
@@ -135,6 +135,86 @@ percolate:synced-cron@1.3.2
promise@0.12.2
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
random@1.2.1
rate-limit@1.1.1
react-fast-refresh@0.2.7
+232 -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,240 @@ Note:
[How to upgrade WeKan](https://github.com/wekan/wekan/issues/4585)
# Upcoming v7.00 WeKan ® release
# v7.06 2023-08-15 WeKan ® release
This version number and and some before it is reserved for upcoming PR from mfilser.
This release adds the following updates:
- [Updated exceljs and jszip](https://github.com/wekan/wekan/commit/f9823f67bd7ded44982298b15487f945e8216b60).
Thanks to developers of dependencies.
- [Update building Windows bundle](https://github.com/wekan/wekan/commit/6d1705af344a36e1cd7846c3d41e486ae0200e2e).
Thanks to xet7.
and fixes the following bugs:
- [Alphabetic ordered member lists on assigne and member lists](https://github.com/wekan/wekan/pull/5071).
Thanks to chrisi51.
- [Label drag/drop (reorder labels) works now again](https://github.com/wekan/wekan/pull/5075).
Thanks to mfilser.
- [Add attachment swiping](https://github.com/wekan/wekan/pull/5080).
Thanks to VidVidex.
Thanks to above GitHub users for their contributions and translators for their translations.
# v7.05 2023-08-08 WeKan ® release
This release adds the following updates:
- [Updated dependencies](https://github.com/wekan/wekan/commit/529a43fa0e47ff478dd6b2e6f1c7b4513fe0bbbb).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Make default swimlane auto-height](https://github.com/wekan/wekan/pull/5059).
Thanks to mark-i-m.
- [Show option b) -1 for disabling swimlane height at swimlane height popup](https://github.com/wekan/wekan/commit/ab4073721151e1308b2e9ffd32a1ee765c7b7668).
Thanks to xet7.
- [Fixed Normal (non-admin) board users cannot adjust swimlane height](https://github.com/wekan/wekan/commit/6b1403984f3b11700f6b06b4eff64a062916381a).
Thanks to mgdbbrt and xet7.
- [Fixing positioning of opened cards](https://github.com/wekan/wekan/pull/5066).
Thanks to chrisi51.
- [Cleaner memberlist popups](https://github.com/wekan/wekan/issues/5068).
Thanks to chrisi51.
Thanks to above GitHub users for their contributions and translators for their translations.
# v7.04 2023-08-03 WeKan ® release
This release fixes the following bugs:
- [Fix edit_swimlane](https://github.com/wekan/wekan/pull/5055).
Thanks to Pandetthe.
. [Login layout fixes 2](https://github.com/wekan/wekan/pull/5056).
Thanks to nebulade.
- [Do not open preview for attachments that cannot be previewed](https://github.com/wekan/wekan/pull/5058).
Thanks to VidVidex.
Thanks to above GitHub users for their contributions and translators for their translations.
# v7.03 2023-08-02 WeKan ® release
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.
+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.99.0"
appVersion: "v7.06.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);
+20 -1
View File
@@ -19,6 +19,7 @@
.board-wrapper .board-canvas.is-sibling-sidebar-open {
margin-right: 248px;
}
.board-wrapper .board-canvas.overlayed {overflow:hidden}
.board-wrapper .board-canvas .board-overlay {
position: fixed;
left: 0;
@@ -168,11 +169,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 +221,5 @@
top: 5px;
right: 5px;
font-size: 25px;
cursor: pointer;
}
+2 -1
View File
@@ -21,7 +21,8 @@ template(name="boardBody")
.board-canvas.js-swimlanes(
class="{{#if Sidebar.isOpen}}is-sibling-sidebar-open{{/if}}"
class="{{#if MultiSelection.isActive}}is-multiselection-active{{/if}}"
class="{{#if draggingActive.get}}is-dragging-active{{/if}}")
class="{{#if draggingActive.get}}is-dragging-active{{/if}}"
class="{{#if showOverlay.get}}overlayed{{/if}}")
if showOverlay.get
.board-overlay
if currentBoard.isTemplatesBoard
+57 -43
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,25 +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(),
);
});
// 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 (Utils.canModifyBoard() && 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;
}
@@ -231,7 +233,7 @@ BlazeComponent.extendComponent({
},
isViewSwimlanes() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).boardView === 'board-view-swimlanes';
} else {
@@ -242,7 +244,7 @@ BlazeComponent.extendComponent({
},
isViewLists() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).boardView === 'board-view-lists';
} else {
@@ -251,7 +253,7 @@ BlazeComponent.extendComponent({
},
isViewCalendar() {
currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).boardView === 'board-view-cal';
} else {
@@ -342,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;
@@ -388,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());
@@ -400,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) {
@@ -415,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);
@@ -451,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 {
+18 -17
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'),
@@ -306,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'));
@@ -315,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();
@@ -337,7 +338,7 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
watchLevel() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const currentBoard = Utils.getCurrentBoard();
return currentBoard.getWatchLevel(Meteor.userId());
},
@@ -377,7 +378,7 @@ BlazeComponent.extendComponent({
allowedSortValues() {
const types = [];
const pushed = {};
Meteor.user()
ReactiveCache.getCurrentUser()
.getListSortTypes()
.forEach(type => {
const key = type.replace(/^-/, '');
@@ -393,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) {
+5 -6
View File
@@ -87,15 +87,14 @@ template(name="attachmentGallery")
.attachment-actions
a.js-download(href="{{link}}?download=true", download="{{name}}")
i.fa.fa-download.icon(title="{{_ 'download'}}")
if currentUser.isBoardAdmin
a.js-rename
i.fa.fa-pencil-square-o.icon(title="{{_ 'rename'}}")
a.js-confirm-delete
i.fa.fa-trash.icon(title="{{_ 'delete'}}")
if currentUser.isBoardMember
unless currentUser.isCommentOnly
unless currentUser.isWorker
a.fa.fa-navicon.icon.js-open-attachment-menu(title="{{_ 'attachmentActionsPopup-title'}}")
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")
+173 -78
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { ObjectID } from 'bson';
import DOMPurify from 'dompurify';
@@ -10,6 +11,13 @@ const prettyMilliseconds = require('pretty-ms');
let cardId = null;
let openAttachmentId = null;
// Used to store the start and end coordinates of a touch event for attachment swiping
let touchStartCoords = null;
let touchEndCoords = null;
// Stores link to the attachment for which attachment actions popup was opened
attachmentActionsLink = null;
Template.attachmentGallery.events({
'click .open-preview'(event) {
@@ -25,27 +33,18 @@ Template.attachmentGallery.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);
Attachments.remove(this._id);
Popup.back(2);
}),
});
function getNextAttachmentId(currentAttachmentId) {
const attachments = Attachments.find({'meta.cardId': cardId}).get();
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 = Attachments.find({'meta.cardId': cardId}).get();
function getNextAttachmentId(currentAttachmentId, offset = 0) {
const attachments = ReactiveCache.getAttachments({'meta.cardId': cardId});
let i = 0;
for (; i < attachments.length; i++) {
@@ -53,52 +52,82 @@ function getPrevAttachmentId(currentAttachmentId) {
break;
}
}
return attachments[(i - 1 + attachments.length) % attachments.length]._id;
return attachments[(i + offset + 1 + attachments.length) % attachments.length]._id;
}
function openAttachmentViewer(attachmentId){
function getPrevAttachmentId(currentAttachmentId, offset = 0) {
const attachments = ReactiveCache.getAttachments({'meta.cardId': cardId});
const attachment = Attachments.findOne({_id: 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;
let i = 0;
for (; i < attachments.length; i++) {
if (attachments[i]._id === currentAttachmentId) {
break;
}
}
return attachments[(i + offset - 1 + attachments.length) % attachments.length]._id;
}
$("#viewer-overlay").removeClass("hidden");
function attachmentCanBeOpened(attachment) {
return (
attachment.isImage ||
attachment.isPDF ||
attachment.isText ||
attachment.isJSON ||
attachment.isVideo ||
attachment.isAudio
);
}
function openAttachmentViewer(attachmentId) {
const attachment = ReactiveCache.getAttachment(attachmentId);
// Check if we can open the attachment (if we have a viewer for it) and exit if not
if (!attachmentCanBeOpened(attachment)) {
return;
}
/*
Instructions for adding a new viewer:
- add a new case to the switch statement below
- implement cleanup in the closeAttachmentViewer() function, if necessary
- mark attachment type as openable by adding a new condition to the attachmentCanBeOpened 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;
}
$('#attachment-name').text(attachment.name);
$('#viewer-overlay').removeClass('hidden');
}
function closeAttachmentViewer() {
@@ -125,7 +154,80 @@ function closeAttachmentViewer() {
$("#audio-viewer").addClass("hidden");
}
function openNextAttachment() {
closeAttachmentViewer();
let i = 0;
// Find an attachment that can be opened
while (true) {
const id = getNextAttachmentId(openAttachmentId, i);
const attachment = ReactiveCache.getAttachment(id);
if (attachmentCanBeOpened(attachment)) {
openAttachmentId = id;
openAttachmentViewer(id);
break;
}
i++;
}
}
function openPrevAttachment() {
closeAttachmentViewer();
let i = 0;
// Find an attachment that can be opened
while (true) {
const id = getPrevAttachmentId(openAttachmentId, i);
const attachment = ReactiveCache.getAttachment(id);
if (attachmentCanBeOpened(attachment)) {
openAttachmentId = id;
openAttachmentViewer(id);
break;
}
i--;
}
}
function processTouch(){
xDist = touchEndCoords.x - touchStartCoords.x;
yDist = touchEndCoords.y - touchStartCoords.y;
console.log("xDist: " + xDist);
// Left swipe
if (Math.abs(xDist) > Math.abs(yDist) && xDist < 0) {
openNextAttachment();
}
// Right swipe
if (Math.abs(xDist) > Math.abs(yDist) && xDist > 0) {
openPrevAttachment();
}
// Up swipe
if (Math.abs(yDist) > Math.abs(xDist) && yDist < 0) {
closeAttachmentViewer();
}
}
Template.attachmentViewer.events({
'touchstart #viewer-container'(event) {
console.log("touchstart")
touchStartCoords = {
x: event.changedTouches[0].screenX,
y: event.changedTouches[0].screenY
}
},
'touchend #viewer-container'(event) {
console.log("touchend")
touchEndCoords = {
x: event.changedTouches[0].screenX,
y: event.changedTouches[0].screenY
}
processTouch();
},
'click #viewer-container'(event) {
// Make sure the click was on #viewer-container and not on any of its children
@@ -143,23 +245,17 @@ Template.attachmentViewer.events({
'click #viewer-close'() {
closeAttachmentViewer();
},
'click #next-attachment'(event) {
closeAttachmentViewer()
const id = getNextAttachmentId(openAttachmentId);
openAttachmentId = id;
openAttachmentViewer(id);
'click #next-attachment'() {
openNextAttachment();
},
'click #prev-attachment'() {
openPrevAttachment();
},
'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);
@@ -315,11 +411,11 @@ 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;
},
@@ -327,23 +423,22 @@ BlazeComponent.extendComponent({
return [
{
'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();
+2 -7
View File
@@ -245,10 +245,10 @@
padding-top: 10px;
}
@media screen and (min-width: 801px) {
.card-details {
.card-details-maximized {
top: 97px;
left: 0;
width: 600px;
right:0;
bottom: 0;
position: fixed;
resize: both;
@@ -267,11 +267,6 @@
box-shadow: 0 0 7px 0 #b3b3b3;
transition: flex-basis 0.1s;
box-sizing: border-box;
position: absolute;
top: 0;
left: 0;
height: calc(100% - 20px);
width: calc(100% - 20px);
float: left;
}
.card-details-maximized .card-details-left {
+57 -89
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,30 +64,34 @@ 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();
return !Utils.getPopupCardId() && ReactiveCache.getCurrentUser().hasCardMaximized();
},
scrollParentContainer() {
const cardPanelWidth = 600;
const parentComponent = this.parentComponent();
/*
// Incomplete fix about bug where opening card scrolls to wrong place
// https://github.com/wekan/wekan/issues/4572#issuecomment-1184149395
// TODO sometimes parentComponent is not available, maybe because it's not
// yet created?!
if (!parentComponent) return;
const bodyBoardComponent = parentComponent.parentComponent();
//
// uncommented again by chrisi51
// only with that, the autoscroll feature is working properly
// after my fixes, all scrollings where correct
*/
if (!parentComponent) return;
const bodyBoardComponent = parentComponent.parentComponent();
//On Mobile View Parent is Board, Not Board Body. I cant see how this funciton should work then.
if (bodyBoardComponent === null) return;
@@ -143,7 +148,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,
@@ -192,15 +197,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) => {
@@ -216,6 +221,12 @@ BlazeComponent.extendComponent({
//-------------
}
if (!Utils.isMiniScreen()) {
Meteor.setTimeout(() => {
this.scrollParentContainer();
}, 500);
}
const $checklistsDom = this.$('.card-checklist-items');
$checklistsDom.sortable({
@@ -287,7 +298,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
@@ -441,11 +452,11 @@ BlazeComponent.extendComponent({
'click .js-maximize-card-details'() {
Meteor.call('toggleCardMaximized');
autosize($('.card-details'));
if (!Utils.isMiniScreen()) {
Meteor.setTimeout(() => {
this.scrollParentContainer();
}, 500);
}
// if (!Utils.isMiniScreen()) {
// Meteor.setTimeout(() => {
// this.scrollParentContainer();
// }, 500);
// }
},
'click .js-minimize-card-details'() {
Meteor.call('toggleCardMaximized');
@@ -651,7 +662,7 @@ Template.cardDetailsActionsPopup.helpers({
},
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
return ReactiveCache.getCurrentUser().isBoardAdmin();
},
});
@@ -727,19 +738,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);
});
@@ -752,29 +752,19 @@ Template.cardMembersPopup.events({
Template.cardMembersPopup.helpers({
members() {
return Template.instance().members.get();
return _.sortBy(Template.instance().members.get(),'fullname');
},
});
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)
@@ -813,11 +803,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);
@@ -827,11 +817,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');
@@ -854,11 +844,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');
@@ -872,7 +862,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);
@@ -884,11 +874,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');
@@ -960,27 +950,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 [];
}
@@ -1004,7 +994,7 @@ BlazeComponent.extendComponent({
setParentCardId(cardId) {
if (cardId) {
this.parentCard = Cards.findOne(cardId);
this.parentCard = ReactiveCache.getCard(cardId);
} else {
this.parentCard = null;
}
@@ -1023,7 +1013,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.
@@ -1562,8 +1552,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'))) {
@@ -1597,19 +1587,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);
});
@@ -1635,17 +1614,17 @@ Template.cardAssigneesPopup.helpers({
},
members() {
return Template.instance().members.get();
return _.sortBy(Template.instance().members.get(),'fullname');
},
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,
@@ -1654,21 +1633,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();
@@ -1677,13 +1645,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'),
+1 -1
View File
@@ -92,7 +92,7 @@ template(name="editChecklistItemForm")
| {{_ 'convertChecklistItemToCardPopup-title'}}
template(name="checklistItems")
if checklist.items.count
if checklist.items.length
if canModifyCard
+inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist position="top")
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true)
+18 -14
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
@@ -84,9 +85,11 @@ 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;
@@ -230,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();
},
@@ -266,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;
},
@@ -335,7 +339,7 @@ BlazeComponent.extendComponent({
Template.checklistItemDetail.helpers({
hideCheckedItems() {
const user = Meteor.user();
const user = ReactiveCache.getCurrentUser();
if (user) return user.hasHideCheckedItems();
return false;
},
@@ -361,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');
@@ -373,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');
+9 -6
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];
@@ -50,7 +52,8 @@ BlazeComponent.extendComponent({
appendTo: '.edit-labels-pop-over',
helper(element, currentItem) {
let ret = currentItem.clone();
if (currentItem.closest('.popup-container-depth-0').size() == 0) { // only set css transform at every sub-popup, not at the main popup
if (currentItem.closest('.popup-container-depth-0').length == 0)
{ // only set css transform at every sub-popup, not at the main popup
const content = currentItem.closest('.content')[0]
const offsetLeft = content.offsetLeft;
const offsetTop = $('.pop-over > .header').height() * -1;
@@ -117,7 +120,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 +133,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 +152,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);
},
});
+5 -6
View File
@@ -49,8 +49,7 @@ template(name="minicard")
if currentBoard.allowsCardNumber
span.card-number
| ##{getCardNumber}
b
= getTitle
= getTitle
if $eq 'subtext-with-full-path' currentBoard.presentParentTask
.parent-subtext
| {{ parentString ' > ' }}
@@ -130,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
@@ -157,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')) {
+6 -4
View File
@@ -1,22 +1,24 @@
import { ReactiveCache } from '/imports/reactiveCache';
BlazeComponent.extendComponent({
addSubtask(event) {
event.preventDefault();
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,
});
+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
+12 -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');
@@ -75,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;
@@ -97,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;
@@ -169,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(),
);
}
});
@@ -181,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;
@@ -202,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;
+3 -4
View File
@@ -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}}
+59 -62
View File
@@ -1,3 +1,4 @@
import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
BlazeLayout.setRoot('body');
@@ -19,80 +20,76 @@ 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.subscribe('setting', {
onReady() {
templateInstance.currentSetting.set(ReactiveCache.getCurrentSetting());
return this.stop();
},
});
}
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();
}
});
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 +161,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 +182,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;
+9 -1
View File
@@ -88,7 +88,7 @@
height: 20px;
}
.pop-over .quiet {
padding: 6px 6px 4px;
/* padding: 6px 6px 4px;*/
}
.pop-over.search-over {
background: #f0f0f0;
@@ -152,6 +152,14 @@
text-decoration: none;
overflow: hidden;
line-height: 33px;
display:flex;
/* flex-wrap:wrap;*/
gap:5px;
align-items: center;
}
.pop-over-list li > a > .member{
align-self: flex-start;
flex:0 0 auto;
}
.pop-over-list li > a .item-name {
display: block;
@@ -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;
+17 -20
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';
@@ -123,7 +124,7 @@ class AdminReport extends BlazeComponent {
}
abbreviate(text) {
if (text.length > 30) {
if (text?.length > 30) {
return `${text.substr(0, 29)}...`;
}
return text;
@@ -140,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,
@@ -161,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'));
@@ -179,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'));
+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() {
+8 -10
View File
@@ -3,23 +3,21 @@ Template.connectionMethod.onCreated(function() {
Meteor.call('getAuthenticationsEnabled', (_, result) => {
if (result) {
// Only enabled auth methods without OAuth2/OpenID which is a separate button
const tmp = Object.keys(result).filter((k) => result[k]).filter((k) => k !== 'oauth2');
// TODO : add a management of different languages
// (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')})
this.authenticationMethods.set([
{ value: 'password' },
// Gets only the authentication methods availables
...Object.entries(result)
.filter(e => e[1])
.map(e => ({ value: e[0] })),
]);
this.authenticationMethods.set([{ value: 'password' }].concat(tmp.map((k) => { return { value: k }; })));
}
// If only the default authentication available, hides the select boxe
const content = $('.at-form-authentication');
if (!(this.authenticationMethods.get().length > 1)) {
content.hide();
} else {
if (this.authenticationMethods.get().length > 1) {
content.show();
} else {
content.hide();
}
});
});
+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());
},
+38 -19
View File
@@ -24,7 +24,7 @@ template(name="swimlaneFixedHeader")
unless currentUser.isCommentOnly
if currentUser.isBoardAdmin
a.fa.fa-plus.js-open-add-swimlane-menu.swimlane-header-plus-icon(title="{{_ 'add-swimlane'}}")
a.fa.fa-navicon.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}")
a.fa.fa-navicon.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}")
unless isTouchScreen
if isShowDesktopDragHandles
a.swimlane-header-handle.handle.fa.fa-arrows.js-swimlane-header-handle
@@ -41,24 +41,29 @@ template(name="editSwimlaneTitleForm")
template(name="swimlaneActionPopup")
unless currentUser.isCommentOnly
ul.pop-over-list
li: a.js-set-swimlane-color
i.fa.fa-paint-brush
| {{_ 'select-color'}}
unless this.isTemplateContainer
hr
ul.pop-over-list
li: a.js-close-swimlane
i.fa.fa-arrow-right
i.fa.fa-archive
| {{_ 'archive-swimlane'}}
ul.pop-over-list
li: a.js-copy-swimlane
i.fa.fa-copy
| {{_ 'copy-swimlane'}}
ul.pop-over-list
li: a.js-move-swimlane
i.fa.fa-arrow-up
| {{_ 'move-swimlane'}}
if currentUser.isBoardAdmin
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'}}
if currentUser.isBoardAdmin
unless this.isTemplateContainer
hr
ul.pop-over-list
li: a.js-close-swimlane
i.fa.fa-arrow-right
i.fa.fa-archive
| {{_ 'archive-swimlane'}}
ul.pop-over-list
li: a.js-copy-swimlane
i.fa.fa-copy
| {{_ 'copy-swimlane'}}
ul.pop-over-list
li: a.js-move-swimlane
i.fa.fa-arrow-up
| {{_ 'move-swimlane'}}
template(name="swimlaneAddPopup")
unless currentUser.isCommentOnly
@@ -82,6 +87,20 @@ 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 a) {{_ 'set-swimlane-height-value'}}
label b) -1
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'}}
+48 -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,46 @@ 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?
// also in imports/i18n/data/en.i18n.json
if (height != -1 && (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}};")
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
+18 -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,18 @@ BlazeComponent.extendComponent({
},
];
},
swimlaneHeight() {
const user = Meteor.user();
const swimlane = Template.currentData();
const height = user.getSwimlaneHeight(swimlane.boardId, swimlane._id);
return height == -1 ? "auto" : (height + "px");
},
}).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 +258,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 +289,6 @@ BlazeComponent.extendComponent({
Template.swimlane.helpers({
canSeeAddList() {
return Meteor.user().isBoardAdmin();
/*
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
*/
},
});
@@ -324,7 +313,7 @@ BlazeComponent.extendComponent({
.parentComponent()
.data()._id;
const cards = list.cards(swimlaneId);
if (cards.count() === 0) {
if (cards.length === 0) {
return false;
}
}
@@ -350,7 +339,7 @@ class MoveSwimlaneComponent extends BlazeComponent {
}
board() {
return Boards.findOne(Session.get('currentBoard'));
return Utils.getCurrentBoard();
}
toBoardsSelector() {
@@ -363,14 +352,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');
}
+14 -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(''));
+4 -3
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) {
+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 (
+3 -2
View File
@@ -1,3 +1,4 @@
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
@@ -5,7 +6,7 @@ import { TAPi18n } from '/imports/i18n';
// information provided by the browser, and default to english.
Meteor.startup(async () => {
let currentUser = Meteor.user();
let currentUser = ReactiveCache.getCurrentUser();
// If we're still logging in, wait (#4967)
if (!currentUser && Meteor.loggingIn()) {
await new Promise((resolve) => {
@@ -15,7 +16,7 @@ Meteor.startup(async () => {
}
});
});
currentUser = Meteor.user();
currentUser = ReactiveCache.getCurrentUser();
}
// Select first available language
const [language] = [
+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() {
+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;
+32 -21
View File
@@ -1,6 +1,8 @@
import { ReactiveCache } from '/imports/reactiveCache';
Utils = {
setBackgroundImage(url) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
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"});
@@ -31,26 +33,38 @@ 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 = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
const ret = (
currentUser &&
currentUser.isBoardMember() &&
@@ -60,7 +74,7 @@ Utils = {
return ret;
},
canModifyBoard() {
const currentUser = Meteor.user();
const currentUser = ReactiveCache.getCurrentUser();
const ret = (
currentUser &&
currentUser.isBoardMember() &&
@@ -76,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();
@@ -100,7 +114,7 @@ Utils = {
},
boardView() {
currentUser = Meteor.user();
currentUser = ReactiveCache.getCurrentUser();
if (currentUser) {
return (currentUser.profile || {}).boardView;
} else if (
@@ -144,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() {
@@ -183,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', {
@@ -194,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', {
@@ -208,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;
@@ -316,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')) {
@@ -421,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 {
@@ -433,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;
}
});
+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);
+10 -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",
@@ -1220,5 +1228,6 @@
"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.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
+10 -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",
@@ -1220,5 +1228,6 @@
"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.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
+10 -1
View File
@@ -85,6 +85,14 @@
"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-checklist": "إضافة قائمة تدقيق",
@@ -1220,5 +1228,6 @@
"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.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
+10 -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",
@@ -1220,5 +1228,6 @@
"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.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
+10 -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",
@@ -1220,5 +1228,6 @@
"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.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
+10 -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",
@@ -1220,5 +1228,6 @@
"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.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
+10 -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",
@@ -1220,5 +1228,6 @@
"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.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
+10 -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",
@@ -1220,5 +1228,6 @@
"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.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
+10 -1
View File
@@ -85,6 +85,14 @@
"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-subtask": "Добави подзадача",
"add-checklist": "Добави списък със задачи",
@@ -1220,5 +1228,6 @@
"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.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
+10 -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",
@@ -1220,5 +1228,6 @@
"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.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
+10 -1
View File
@@ -85,6 +85,14 @@
"add-card": "Afegeix Fitxa",
"add-card-to-top-of-list": "Afegeix una fitxa al principi de la llista",
"add-card-to-bottom-of-list": "Afegeix una fitxa al final de la llista",
"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": "Afegeix carril",
"add-subtask": "Afegir Subtasca",
"add-checklist": "Llista de verificació d'Afegeix",
@@ -1220,5 +1228,6 @@
"max-avatar-filesize": "Tamany màxim del fitxer d'avatar en bytes:",
"allowed-avatar-filetypes": "Tipus de fitxer permesos per a l'avatar:",
"invalid-file": "Si el nom de fitxer és invàlid, actualitzar o renombrar es cancel·la.",
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead."
"preview-pdf-not-supported": "Your device does not support previewing PDF. Try downloading instead.",
"drag-board": "Drag board"
}
Loaded 100 of 293 files, more files were not shown because too many files have changed in this diff. Show more