Compare commits

...
401 Commits
Author SHA1 Message Date
Lauri Ojansivu b50dd68030 v3.00 2019-07-25 01:40:16 +03:00
Lauri Ojansivu 95698911f9 Now Docker works, fixed docker-compose.yml.
Thanks to xet7 !

Related #2533
2019-07-25 01:16:52 +03:00
Lauri Ojansivu 156c8aa75b Update ChangeLog. 2019-07-24 23:07:22 +03:00
Lauri Ojansivu 7df6f305c5 Try to fix Dockerfile. 2019-07-24 22:32:40 +03:00
Lauri Ojansivu f34197b8d2 Try libcurl3. 2019-07-24 21:33:17 +03:00
Lauri Ojansivu 2483b8dbe3 Snap: Add MongoDB dependencies libcurl4 and php-curl. 2019-07-24 21:20:20 +03:00
Lauri Ojansivu 0c8f13e1d9 Try MongoDB 4.0.10 deb with libcurl3-gnutls 2019-07-24 20:08:22 +03:00
Lauri Ojansivu 85084e1808 Update ChangeLog. 2019-07-24 19:16:09 +03:00
Lauri Ojansivu d87920f556 Update ChangeLog. 2019-07-24 18:26:40 +03:00
Lauri Ojansivu 4b5e6aa893 Update translations. 2019-07-24 18:07:43 +03:00
Lauri Ojansivu c48d5a73ca Added label text to labels on minicard.
Thanks to xet7 !

Closes #2561,
closes #2296,
closes #1466
2019-07-24 17:57:02 +03:00
Lauri Ojansivu a68c928896 Prevent isCommentOnly user adding attachments, editing list names, moving lists,
and seeing board settings menu. Show non-editable Custom Fields to isCommentOnly user.

Thanks to xet7 !

Closes wekan/wekan-snap#97,
closes #2416,
closes #2255
2019-07-24 15:01:05 +03:00
Lauri Ojansivu 62bfe1da21 Update translations. 2019-07-22 23:00:17 +03:00
Lauri Ojansivu ff23c54fd5 Merge branch 'pshunter-igbmc' 2019-07-22 00:12:09 +03:00
Lauri Ojansivu 4cc2f7411c Added meteor package percolate:synced-cron required by LDAP
backgound sync https://github.com/wekan/wekan/pull/2555

Thanks to xet7 !

Related #2354
2019-07-22 00:09:04 +03:00
Lauri Ojansivu 41e5478cb3 Merge branch 'igbmc' of https://github.com/pshunter/wekan into pshunter-igbmc 2019-07-22 00:02:00 +03:00
Lauri Ojansivu 14d7e4d20c Update translations. 2019-07-21 23:57:02 +03:00
Lauri Ojansivu e24925c27f Update translations. 2019-07-21 00:50:44 +03:00
Lauri Ojansivu 8ec98ef00c Try legacy MongoDB 4.0.10 without curl etc. 2019-07-21 00:48:39 +03:00
Jean-Christophe Haessig be44fb8aea Makes LDAP background sync work. If the sync interval is unspecified, falls back to a hourly default. 2019-07-19 09:30:35 +02:00
Lauri Ojansivu f06098f3dd Merge pull request #2553 from justinr1234/patch-5
More snap fixes
2019-07-19 00:23:38 +03:00
justinr1234 b30dc8d4f2 More snap fixes 2019-07-18 16:10:15 -05:00
Lauri Ojansivu 57f7af5f90 Merge pull request #2552 from justinr1234/patch-4
Fix snap build-pacakges
2019-07-18 22:32:08 +03:00
justinr1234 510a20133c Fix snap build-pacakges 2019-07-18 14:29:58 -05:00
Lauri Ojansivu 3bd0f6f911 Merge pull request #2549 from justinr1234/fix-invite
Fix invites
2019-07-18 22:24:52 +03:00
Justin Reynolds 66b45ed35c Fix invites 2019-07-18 13:06:25 -05:00
Lauri Ojansivu 34bd1e9c49 Update translations. 2019-07-18 19:10:21 +03:00
Lauri Ojansivu 007c4fc003 Remove python, docs generations etc from Dockerfile. 2019-07-18 04:57:28 +03:00
Lauri Ojansivu ec80acf36b Allow to shrink attached/pasted image: Add to Snap/Docker/Source.
Thanks to xet7 !
2019-07-18 04:52:19 +03:00
Lauri Ojansivu 26ebe6d63a Remove building OpenAPI with esprima-python etc.
Generated docs are included at repo.

Thanks to xet7 !
2019-07-18 04:33:04 +03:00
Lauri Ojansivu 132bf89677 Merge branch 'master' of github.com:wekan/wekan 2019-07-18 04:29:00 +03:00
Lauri Ojansivu 6d43e32f8c Merge branch 'whowillcare-master' 2019-07-18 04:28:42 +03:00
Lauri Ojansivu 9066bd1a0f Add env setting to image resizer, part 1.
Thanks to xet7 !
2019-07-18 04:27:03 +03:00
Lauri Ojansivu 73da3e122e Merge pull request #2546 from justinr1234/fix-snap
Fix snap
2019-07-18 04:19:01 +03:00
Justin Reynolds fbbcd47c4c Fix snap 2019-07-17 23:57:38 +00:00
Lauri Ojansivu 21e0e68a02 Merge branch 'master' of https://github.com/whowillcare/wekan into whowillcare-master 2019-07-17 17:58:57 +03:00
Lauri Ojansivu 21323b3755 Fix typo. 2019-07-17 17:12:46 +03:00
Lauri Ojansivu 6f2eb00c43 Add API docs to repo. 2019-07-17 17:06:25 +03:00
Lauri Ojansivu 797ea29113 v2.99 2019-07-17 16:18:30 +03:00
Lauri Ojansivu 3bf8af4840 Update ChangeLog. 2019-07-17 16:14:13 +03:00
Lauri Ojansivu 350807bc2d Update release scripts. 2019-07-17 16:13:53 +03:00
Lauri Ojansivu 0fb313aec7 Update translations. 2019-07-17 15:51:13 +03:00
Lauri Ojansivu fe42eb1d01 Add check for isActive.
Thanks to xet !
2019-07-17 03:11:37 +03:00
Lauri Ojansivu 1e9a481451 Update translations. 2019-07-16 19:09:56 +03:00
Lauri Ojansivu 7f2f407e2a Org tables already have created and modified fields, so they
[are not needed](https://github.com/wekan/wekan/commit/2cedbcb9b334cd497874736bbb740a1d5c5acb6c#r34310611)
for add-missing-created-and-modified migration, so removing not needed migration.

Thanks to justinr1234 and xet7 !

Related #802
2019-07-16 01:01:25 +03:00
Lauri Ojansivu 75c84e3b5d [Fix id to _id](https://github.com/wekan/wekan/commit/2cedbcb9b334cd497874736bbb740a1d5c5acb6c#r34310594).
Thanks to justinr1234 and xet7 !

Related #802
2019-07-15 23:50:30 +03:00
Lauri Ojansivu 74a4926e83 Use camelCase.
Thanks to xet7 !

Related #802
2019-07-15 23:36:29 +03:00
Lauri Ojansivu 41950ba4de Teams/Organizations part 3, in progress. Table: org_user, and indexes.
Thanks to xet7 !

Related #802
2019-07-15 23:23:09 +03:00
Lauri Ojansivu 583f32e5c5 Teams/Organizations part 2, in progress. Table: org, add index for name field.
Thanks to xet7 !

Related #802
2019-07-15 22:47:30 +03:00
Lauri Ojansivu 2cedbcb9b3 Teams/Organizations part 1, in progress. Add table: org
Thanks to xet7 !

Related  #802
2019-07-15 19:39:30 +03:00
Sam X. Chen 075f1b5df4 Add Feature: allow to shrink attached/pasted image if server has correponding settings 2019-07-15 10:25:16 -04:00
Lauri Ojansivu 2b1ba0b8f8 Update package-lock.json 2019-07-15 06:17:18 +03:00
Lauri Ojansivu 22319e8dfe Revert including local wekan-cfs-access-point, because it did not work. 2019-07-14 21:27:23 +03:00
Lauri Ojansivu 72604d5d73 Add cfs-access-point as local package included in Wekan repo,
to hopefully make Wekan all deps work directly with command `meteor`.

Thanks to xet7 !
2019-07-14 21:09:47 +03:00
Lauri Ojansivu 37ee7091f7 Update translations. 2019-07-14 16:16:30 +03:00
Lauri Ojansivu 3c938252a7 Update translations. 2019-07-12 23:51:47 +03:00
Lauri Ojansivu 09d0fb095f Fix typo. 2019-07-12 23:45:54 +03:00
Lauri Ojansivu 878b43ab31 Update translations. 2019-07-12 14:28:05 -04:00
Lauri Ojansivu b81193c41f Update ChangeLog. 2019-07-12 14:18:38 -04:00
Lauri Ojansivu 3ad6e554dc RELAX THEME: Use only in this theme the aggressive [red color and big bold serif font style
number](https://github.com/wekan/wekan/commit/bbc68309af0029f2bc4194db4c7e79689f888ea4#commitcomment-34216371) and
[card details text emphasis](https://github.com/wekan/wekan/commit/48ebc5f11745b125ce01d08d60e2d8e3a9419a5f#commitcomment-34268095).

Thanks to hever and xet7.
2019-07-12 14:14:50 -04:00
Lauri Ojansivu c9037f55bc Update ChangeLog. 2019-07-12 11:56:04 -04:00
Lauri Ojansivu 2c6b51857f Merge branch 'whowillcare-master' 2019-07-12 11:49:22 -04:00
Lauri Ojansivu 398ae568a0 Merge branch 'master' of https://github.com/whowillcare/wekan into whowillcare-master 2019-07-12 11:45:56 -04:00
Lauri Ojansivu e17d41a15e Update ChangeLog. 2019-07-12 11:35:20 -04:00
Lauri Ojansivu 8bf33a3fce Merge branch 'newhinton-fix/2529/hoverboardoverlay' 2019-07-12 11:14:17 -04:00
Lauri Ojansivu e9f6473a00 Merge branch 'fix/2529/hoverboardoverlay' of https://github.com/newhinton/wekan into newhinton-fix/2529/hoverboardoverlay 2019-07-12 11:07:24 -04:00
Lauri Ojansivu c0d44a9e69 Update translations. 2019-07-12 11:02:10 -04:00
Sam X. Chen 41cffc2418 Add Features: limit the board list to 2 or 1 for mobile clients 2019-07-11 17:32:24 -04:00
Lauri Ojansivu d7c09df7d2 Add BIGEVENTS_PATTERN to Source/Snap/Docker.
Thanks to xet7 !
2019-07-11 17:14:34 -04:00
Lauri Ojansivu 507f84df4c Update translations. 2019-07-11 16:43:52 -04:00
Lauri Ojansivu b39bbfc97a Merge pull request #2541 from whowillcare/master
Added new features: user will be notified when been @ and other feature
2019-07-11 22:47:48 +03:00
Lauri Ojansivu f85080ebd3 Update translations. 2019-07-11 15:39:00 -04:00
Lauri Ojansivu d14a96027a Add package-lock.json 2019-07-11 15:37:12 -04:00
Sam X. Chen 5fd86d29ba Add Features: notifications will be sent when user is being @, or activitytype matches env var BIGENVENTS 2019-07-11 14:32:39 -04:00
Lauri Ojansivu 2461836ae8 Update translations. 2019-07-11 12:35:15 -04:00
Lauri Ojansivu 15dbe227e8 Try to fix Dockerfile. 2019-07-11 12:33:11 -04:00
Sam X. Chen f2a0ae0a2c Merge remote-tracking branch 'upstream/master' 2019-07-11 10:47:08 -04:00
Lauri Ojansivu 46970ae424 Try to fix Dockerfile. 2019-07-10 20:22:27 -04:00
Lauri Ojansivu f7bfa5c112 Try to fix Dockerfile. 2019-07-10 20:05:24 -04:00
Lauri Ojansivu cad8ed89cc Try to fix Dockerfile. 2019-07-10 20:02:06 -04:00
Lauri Ojansivu bae8180385 Try to fix Dockerfile. 2019-07-10 19:55:09 -04:00
Lauri Ojansivu ea97d9dd02 Try to fix Dockerfile. 2019-07-10 19:44:42 -04:00
Lauri Ojansivu 27f73e692f Try to fix Dockerfile. 2019-07-10 19:41:54 -04:00
Lauri Ojansivu e4d1e0d4cb Try to fix Dockerfile. 2019-07-10 19:36:12 -04:00
Lauri Ojansivu 6f90a8d027 Try to fix Dockerfile. 2019-07-10 19:27:37 -04:00
Lauri Ojansivu 7a03e0ef12 Try to fix Dockerfile. 2019-07-10 19:20:38 -04:00
Lauri Ojansivu aa7ad516ee Try to fix Dockerfile. 2019-07-10 19:18:09 -04:00
Lauri Ojansivu d05c4ea9ef Try to fix Dockerfile. 2019-07-10 19:12:39 -04:00
Lauri Ojansivu 72921f04bb Try to fix Dockerfile.
Thanks to xet7 !
2019-07-10 19:11:28 -04:00
Lauri Ojansivu 9b4322c8c7 Try to fix Dockerfile.
Thanks to xet7 !
2019-07-10 18:58:11 -04:00
Lauri Ojansivu 5db7988066 Change compiler to g++
Thanks to xet7 !
2019-07-10 18:45:57 -04:00
Lauri Ojansivu 1634a14246 Try to fix Dockerfile: Create directory for node-gyp.
Thanks to xet7 !
2019-07-10 18:34:22 -04:00
Lauri Ojansivu b7dfd17cbb Try to fix Dockerfile.
Thanks to xet7 !
2019-07-10 18:28:31 -04:00
Lauri Ojansivu 7f16c55ff4 Add missing Python that is used during build.
Thanks to xet7 !
2019-07-10 18:17:09 -04:00
Lauri Ojansivu 15e4d89d20 Update ChangeLog. 2019-07-10 18:00:36 -04:00
Lauri Ojansivu a276fe13a6 Update translations. 2019-07-10 17:57:49 -04:00
Lauri Ojansivu 5042a1f853 Update ChangeLog. 2019-07-10 17:51:30 -04:00
Lauri Ojansivu 2003d90467 Outgoing Webhooks setCustomField: Add board name, card name, custom field name to be visible.
Still missing: custom field value, list name, swimlane name.

Thanks to xet7 !
2019-07-10 17:46:07 -04:00
Lauri Ojansivu 12795c5995 Update ChangeLog. 2019-07-10 13:47:59 -04:00
Lauri Ojansivu 5084cddf37 Notify Due Days: Add settings to Snap/Docker/Source.
Rename env variables to NOTIFY_DUE_DAYS_BEFORE_AND_AFTER and NOTIFY_DUE_AT_HOUR_OF_DAY.

Thanks to xet7 !
2019-07-10 13:45:37 -04:00
Felix Nüsse 064d3dd5f7 dont remove boardoverlay when mouse leaves carddetails 2019-07-10 19:26:43 +02:00
Lauri Ojansivu a3201f4d28 Update rebuild-wekan.sh . 2019-07-10 11:58:37 -04:00
Lauri Ojansivu bbefc67b54 Update rebuild-wekan.sh 2019-07-10 11:56:50 -04:00
Lauri Ojansivu bf24cf48fc Update translations. 2019-07-10 11:42:05 -04:00
Lauri Ojansivu 2ff27674d0 Add .eslintcache to .gitignore 2019-07-10 11:40:30 -04:00
Lauri Ojansivu c80cd9d0b0 Update ChangeLog. 2019-07-10 10:39:10 -04:00
Lauri Ojansivu c019a68fc5 Merge branch 'whowillcare-master' 2019-07-10 10:29:24 -04:00
Lauri Ojansivu 12051a5164 Update babel runtime. 2019-07-10 09:07:01 -04:00
Sam X. Chen 5ca09cdf09 Add Feature: system timelines will be showing any modification for duat startat endat receivedat, also notification to the watchers and if card is due, watchers will be notified 2019-07-09 16:47:48 -04:00
Sam X. Chen 2c44f83453 Add Feature: system timelines will be showing any modification for duat startat endat receivedat, also notification to the watchers and if card is due, watchers will be notified 2019-07-09 16:36:50 -04:00
Lauri Ojansivu a545f8c1a2 Update translations. 2019-07-08 12:44:31 -04:00
Lauri Ojansivu 561a24c481 Update changelog. 2019-07-08 12:42:55 -04:00
Lauri Ojansivu 1ea6552cd1 [Remove from minicard comment icon and number of comments
the aggressive red color and big bold serif font style
number](https://github.com/wekan/wekan/commit/bbc68309af0029f2bc4194db4c7e79689f888ea4#commitcomment-34216371).

Thanks to hever and xet7 !
2019-07-08 12:31:00 -04:00
Lauri Ojansivu 96065d11a5 Update Meteor mongo package version. 2019-07-08 12:30:31 -04:00
Lauri Ojansivu d82c72f1c1 Update dependencies. 2019-07-08 04:50:19 +03:00
Lauri Ojansivu 202cc5a797 Fix docker-compose.yml to use correct master branch that has meteor 1.8.1. 2019-07-06 06:58:12 -04:00
Lauri Ojansivu 289e78dbd2 Add Corteza theme. In progress.
Thanks to xet7 !
2019-07-06 04:59:17 -04:00
Lauri Ojansivu 6dd63db16c Update translations. 2019-07-06 01:56:44 -04:00
Lauri Ojansivu fa00564883 Fix lint error. 2019-07-03 16:04:18 -04:00
Lauri Ojansivu c65ef9bb31 Fix lint error. 2019-07-03 15:53:55 -04:00
Lauri Ojansivu a33cad0d13 v2.98 2019-07-01 17:31:51 -04:00
Lauri Ojansivu 979a439078 Update translations. 2019-07-01 17:27:56 -04:00
Lauri Ojansivu bdd958b24b Update ChangeLog. 2019-07-01 17:25:20 -04:00
Lauri Ojansivu 34b2168d0d Add Wekan v2.95-v2.97 master branch features and fixes to meteor-1.8 branch.
Thanks to xet7 !
2019-07-01 17:23:41 -04:00
Lauri Ojansivu 2c90e7c585 Remove snapcraft version. 2019-07-01 16:16:55 -04:00
Lauri Ojansivu 2105f4d805 Add version. 2019-06-29 11:13:44 -04:00
Lauri Ojansivu 6a05f4fb4e - Change start-wekan.sh use mongodb port 27018 because xet7 uses
RocketChat MongoDB at 27017 and Wekan Snap MongoDB at 27019.
  MongoDB 4.0.10 port is installed separately for Xubuntu 19.10
  from MongDB website and changed at /etc/mongod.conf to run
  on port 27018.

Thanks to xet7.
2019-06-29 11:02:19 -04:00
Lauri Ojansivu 0d10282dbe Update build scripts. 2019-06-29 10:40:03 -04:00
Lauri Ojansivu 8c23d12487 v2.94 2019-06-29 10:11:14 -04:00
Lauri Ojansivu 31e801cc39 - [LDAP: Check if email attribute is an array, that has many email addresses](https://github.com/wekan/wekan/pull/2519).
Thanks to tdemaret and xet7 !
2019-06-29 10:02:23 -04:00
Lauri Ojansivu a2587f94da Update translations. 2019-06-29 09:04:01 -04:00
Lauri Ojansivu 40b782788a Merge branch 'justinr1234-linting' into meteor-1.8 2019-06-29 08:38:52 -04:00
Lauri Ojansivu 45163e2d2d Fix rebuild-wekan.sh 2019-06-29 08:37:14 -04:00
Lauri Ojansivu b711cbae94 Fixes to rebuild-wekan.sh 2019-06-29 08:21:55 -04:00
Lauri Ojansivu b84dc20ded Merge branch 'linting' of https://github.com/justinr1234/wekan into justinr1234-linting 2019-06-29 07:47:57 -04:00
Lauri Ojansivu 100288b3e1 Update translations. 2019-06-29 07:46:25 -04:00
Justin Reynolds 3eb4d2c341 Prettier & eslint project style update 2019-06-28 12:56:51 -05:00
Lauri Ojansivu a0a482aa8e Merge branch 'justinr1234-created-modified' into meteor-1.8 2019-06-27 15:27:14 -04:00
Justin Reynolds 3d63b6006b Auto linting on commit 2019-06-27 09:19:29 -05:00
Justin Reynolds 7d86af2b00 Add prettier 2019-06-27 09:13:22 -05:00
Justin Reynolds c60e80d25b Add createdAt and modifiedAt to all collections 2019-06-27 09:13:20 -05:00
Lauri Ojansivu fb728baf0c Merge branch 'edge' into meteor-1.8 2019-06-27 05:04:23 +03:00
Lauri Ojansivu 436db99a5b v2.92 2019-06-27 05:02:50 +03:00
Lauri Ojansivu ac9b2f7c8f Update translations. 2019-06-27 04:28:16 +03:00
Lauri Ojansivu f0f0634e83 Update translation. 2019-06-27 04:24:38 +03:00
Lauri Ojansivu d6d4629b5a Update changelog. 2019-06-27 04:14:43 +03:00
Lauri Ojansivu 5283ba9ebb - Fix Outgoing Webhook messages for Checlists, Checklist Items, Card comments, Add/Remove CustomField to board.
Not yet fixed is Outgoing Webhook message about setting CustomField value.

Thanks to xet7 !

Related #1969
2019-06-27 04:06:21 +03:00
Lauri Ojansivu 0c352ab143 Merge branch 'edge' into meteor-1.8 2019-06-27 00:54:06 +03:00
Lauri Ojansivu 7c89336ea9 v2.91 2019-06-27 00:52:20 +03:00
Lauri Ojansivu bca1a2f95b Update changelog. 2019-06-26 23:14:16 +03:00
Lauri Ojansivu 6a2f120d00 Fix Attachment Outgoing Webhook missing list and swimlane name.
Thanks to xet7 !

Related #1969,
Closes #2170
2019-06-26 23:06:50 +03:00
Lauri Ojansivu e8ccfb6743 Update translations. 2019-06-26 22:14:51 +03:00
Lauri Ojansivu 69333ea64f Merge branch 'edge' into meteor-1.8 2019-06-21 21:30:15 +03:00
Lauri Ojansivu 8f5e2c4af3 v2.90 2019-06-21 21:28:30 +03:00
Lauri Ojansivu e5c0d0ea18 Revert v2.89 setting every Sandstorm Wekan user as admin.
Thanks to xet7.

Related #2405
2019-06-21 21:23:42 +03:00
Lauri Ojansivu a35712c708 Merge branch 'edge' into meteor-1.8 2019-06-21 21:00:06 +03:00
Lauri Ojansivu 47e64c269c v2.89 2019-06-21 20:58:30 +03:00
Lauri Ojansivu cd69b03ac1 Update translations. 2019-06-21 20:55:36 +03:00
Lauri Ojansivu 5afaa5bce6 Update changelog. 2019-06-21 20:53:58 +03:00
Lauri Ojansivu 60d62a6ae3 - Sandstorm Wekan: Set everyone as Admin. Please test does this help with
[Problem with the user management: can't add users or give wekan admin rights](https://github.com/wekan/wekan/issues/2405).

Thanks to xet7 !

Related #2405
2019-06-21 20:46:05 +03:00
Lauri Ojansivu 4f46adc389 - If board does not exist, redirect to All Boards page, at all Wekan platforms.
So now at Sandstorm when loading Wekan grain, if first Sandstorm board is found,
  it is opened. If first Sandstorm board is not found (it's deleted or archived),
  then redirect automatically to All Boards page.

Closes #3132
2019-06-21 20:09:18 +03:00
Lauri Ojansivu f2bc6f773b Merge branch 'edge' into meteor-1.8 2019-06-21 18:12:21 +03:00
Lauri Ojansivu d2dfcf36d9 v2.88 2019-06-21 18:11:19 +03:00
Lauri Ojansivu 353768b4b5 Update translations. 2019-06-21 18:07:45 +03:00
Lauri Ojansivu 11ad8c7b30 Merge branch 'edge' into meteor-1.8 2019-06-21 12:51:21 +03:00
Lauri Ojansivu 4f3e83b363 v2.87 2019-06-21 12:50:13 +03:00
Lauri Ojansivu 263ec64453 Update changelog. 2019-06-21 12:46:19 +03:00
Lauri Ojansivu 140dc6db25 Update translations. 2019-06-21 12:22:29 +03:00
Lauri Ojansivu 47a7097044 Merge pull request #2508 from road42/bug/card_move_to_top_bottom_fix
Inferface: Can move cardToTop/Bottom. Fixes #2289
2019-06-21 11:54:01 +03:00
Lauri Ojansivu b8e774107a Merge pull request #2507 from road42/bug/english_language_fix_card_trigger
English language update. Fixes #2456
2019-06-21 11:53:44 +03:00
Lauri Ojansivu 3d3c78260b Merge pull request #2506 from road42/feature/rule_card_action_setdate
Adds rule feature: cardAction - SetDate #2504
2019-06-21 11:53:20 +03:00
Christoph Jahn e8f4c4d8b8 Inferface: Can move cardToTop/Bottom. Fixes #2289 2019-06-21 10:11:40 +02:00
Christoph Jahn 2156b28445 English language fixed #2456 2019-06-21 09:11:42 +02:00
Christoph Jahn a9fc74a9b4 Adds rule feature: cardAction - SetDate #2504 2019-06-21 07:24:21 +02:00
Lauri Ojansivu e0a1651784 Merge branch 'edge' into meteor-1.8 2019-06-19 22:58:01 +03:00
Lauri Ojansivu 02de9164f0 v2.86 2019-06-19 22:56:46 +03:00
Lauri Ojansivu 140a2d7915 Update changelog. 2019-06-19 22:50:49 +03:00
Lauri Ojansivu 17c4c96c29 - [Fix Wekan unable to Select Text from Description edit box](https://github.com/wekan/wekan/issues/2451)
by removing feature of card description submit on click outside. This is because when selecting text
  and dragging up did trigger submit of description, so description was closed and selecting text failed.
  This did affect all Chromium-based browsers: Chrome, Chromium, Chromium Edge.

Thanks to xet7 !

Closes #2451
2019-06-19 22:39:29 +03:00
Lauri Ojansivu 2e1162ed73 Merge branch 'edge' into meteor-1.8 2019-06-19 11:43:23 +03:00
Lauri Ojansivu 56e5585730 v2.85 2019-06-19 11:41:59 +03:00
Lauri Ojansivu 51a0dd8861 [Fixed bug: rule doesn't move card to top/bottom](https://github.com/wekan/wekan/pull/2502).
Thanks to road42 !

Closes #2501
2019-06-19 11:36:13 +03:00
Lauri Ojansivu 8bfd94474a Merge pull request #2502 from road42/bug/rule_action_card_move_fix
Fixed bug (rule doesn't move card to top/bottom) #2501
2019-06-19 11:33:34 +03:00
Christoph Jahn 6789e8564a Fixed bug #2501
card.move needs boardId as first parameter
2019-06-19 06:57:58 +02:00
Lauri Ojansivu 8b6856fc89 Merge branch 'edge' into meteor-1.8 2019-06-18 23:45:33 +03:00
Lauri Ojansivu b48c6a5b9c v2.84 2019-06-18 23:43:49 +03:00
Lauri Ojansivu b39b9f5463 Update changelog. 2019-06-18 21:28:32 +03:00
Lauri Ojansivu e72f186a36 Merge branch 'road42-devel' into devel 2019-06-18 21:25:33 +03:00
Christoph Jahn c3d495e7c6 Show buttons for isBoardAdmin 2019-06-17 21:05:21 +02:00
Lauri Ojansivu 70e5b71bdd Merge branch 'meteor-1.8' of github.com:wekan/wekan into meteor-1.8 2019-06-17 21:58:58 +03:00
Lauri Ojansivu a84c8f518b Merge branch 'edge' into meteor-1.8 2019-06-17 21:58:38 +03:00
Lauri Ojansivu 98c6ea467a v2.83 2019-06-17 21:55:16 +03:00
Lauri Ojansivu 6e73abde50 Update changelog. 2019-06-17 21:51:59 +03:00
Lauri Ojansivu 7ff6f24a90 Fix Bug: Unable to click board submenu on mobile.
Thanks to xet7 !

Closes #2261
2019-06-17 21:47:02 +03:00
Lauri Ojansivu 6790c22794 Update dependencies. 2019-06-15 12:58:14 -04:00
Lauri Ojansivu 60a9b4b934 Merge branch 'edge' into meteor-1.8 2019-06-14 16:31:48 +03:00
Lauri Ojansivu 8368461b57 v2.82 2019-06-14 16:30:34 +03:00
Lauri Ojansivu 7dc8a2d659 [Fix OIDC Docker login. Empty string results to empty array at wekan/server/authentication.js](https://github.com/wekan/wekan/commit/bddbaa7bc2f3cfe8553a2265e168231ab51876f3).
Thanks to xet7 !

Closes #2206
2019-06-14 16:27:40 +03:00
Lauri Ojansivu bddbaa7bc2 - Fix OIDC Docker login. Empty string results to empty array at wekan/server/authentication.js
Thanks to xet7 !

Closes #2206
2019-06-14 16:23:18 +03:00
Lauri Ojansivu 434fa3226a Merge branch 'edge' into meteor-1.8 2019-06-13 19:31:02 +03:00
Lauri Ojansivu f9abfe5244 v2.81 2019-06-13 19:29:41 +03:00
Lauri Ojansivu 97d57b05ad Update changelog. 2019-06-13 19:28:08 +03:00
Lauri Ojansivu 4334fbbb9d - Change OAuth2 whitelist default to empty string at snap, so it would be used as array on wekan/server/authentication.js.
Thanks to xet7 !
2019-06-13 19:24:50 +03:00
Lauri Ojansivu e689feddcb Merge branch 'edge' into meteor-1.8 2019-06-13 19:01:30 +03:00
Lauri Ojansivu 595c657b57 Add missing text. 2019-06-13 19:00:18 +03:00
Lauri Ojansivu 375fda0eff Merge branch 'edge' into meteor-1.8 2019-06-13 18:23:24 +03:00
Lauri Ojansivu ed04769947 v2.80 2019-06-13 18:21:51 +03:00
Lauri Ojansivu 44dbd462b1 Default whitelist array, not string.
Thanks to xet7 !
2019-06-13 18:18:03 +03:00
Lauri Ojansivu 291797b238 v2.79 2019-06-13 18:14:43 +03:00
Lauri Ojansivu 1178a48e68 Add back [OAuth2 idTokenWhitelistFields default empty array](https://github.com/wekan/wekan/commit/8b31c0768c34fc4557b54cec936a0b4288a8e722#commitcomment-33921882).
Thanks to moserben16 !
2019-06-13 11:03:45 +03:00
Lauri Ojansivu 34b7bfd19c Update translations. 2019-06-12 19:07:31 +03:00
Lauri Ojansivu 02c418f4bb Update changelog. 2019-06-12 19:05:29 +03:00
Lauri Ojansivu ae3b061d4c Merge pull request #2488 from DominikPf/fix-dockerfile-oauth2-typo
fix oauth2 typos in dockerfile & compose
2019-06-12 18:44:50 +03:00
Dominik Pfeifer eb49bb5e10 fix oauth2 typos in dockerfile & compose 2019-06-12 13:41:10 +02:00
Lauri Ojansivu 38a238df80 Merge branch 'edge' into meteor-1.8 2019-06-12 06:37:34 +03:00
Lauri Ojansivu f154c03385 Merge branch 'edge' into meteor-1.8 2019-06-11 17:48:08 +03:00
Lauri Ojansivu 526e10865f Merge branch 'edge' into meteor-1.8 2019-05-22 21:48:52 +03:00
Lauri Ojansivu e38988126a Merge branch 'edge' into meteor-1.8 2019-05-14 21:34:30 +03:00
Lauri Ojansivu 4903f3a814 Merge branch 'edge' into meteor-1.8 2019-05-14 16:56:35 +03:00
Lauri Ojansivu 663384e62f Merge branch 'edge' into meteor-1.8 2019-05-13 10:51:44 +03:00
Lauri Ojansivu e246099794 Merge branch 'edge' into meteor-1.8 2019-05-12 20:52:49 +03:00
Lauri Ojansivu 0b3343674b Merge branch 'edge' into meteor-1.8 2019-05-11 23:53:39 +03:00
Lauri Ojansivu 1d33701af0 Merge branch 'edge' into meteor-1.8 2019-05-11 00:09:08 +03:00
Lauri Ojansivu df69ade422 Merge branch 'edge' into meteor-1.8 2019-05-10 23:20:17 +03:00
Lauri Ojansivu ac0f13ad18 Merge branch 'edge' into meteor-1.8 2019-05-10 21:03:03 +03:00
Lauri Ojansivu 34b1654077 Merge branch 'edge' into meteor-1.8 2019-05-09 16:37:18 +03:00
Lauri Ojansivu 5dcd1b630e Merge branch 'meteor-1.8' of github.com:wekan/wekan into meteor-1.8 2019-05-09 16:34:33 +03:00
Lauri Ojansivu 9fe4aedec1 Update packages. 2019-05-09 08:48:02 -04:00
Lauri Ojansivu b6d7c71cc8 Merge branch 'edge' into meteor-1.8 2019-05-09 14:27:34 +03:00
Lauri Ojansivu 778cd22e72 Merge pull request #2396 from justinr1234/wekan-profile-checks
Fix missing profile checks
2019-05-09 14:25:06 +03:00
Justin Reynolds daf314b037 Fix missing profile checks 2019-05-08 16:54:15 -05:00
Lauri Ojansivu 97ff2bd2fa Merge branch 'edge' into meteor-1.8 2019-04-24 16:13:29 +03:00
Lauri Ojansivu 4282906833 Merge branch 'edge' into meteor-1.8 2019-04-24 14:41:37 +03:00
Lauri Ojansivu b1cfd8229a Merge branch 'meteor-1.8' of github.com:wekan/wekan into meteor-1.8 2019-04-23 19:52:07 +03:00
Lauri Ojansivu 202f4235d7 Merge branch 'edge' into meteor-1.8 2019-04-23 19:51:53 +03:00
Lauri Ojansivu 1fff4e0eed Upgrade pip also. 2019-04-23 15:10:05 +03:00
Lauri Ojansivu 9d2227bffb Merge branch 'edge' into meteor-1.8 2019-04-23 14:42:58 +03:00
Lauri Ojansivu d9e361cf1b Merge branch 'edge' into meteor-1.8 2019-04-23 14:09:39 +03:00
Lauri Ojansivu 070de69ebe Fix build scripts. 2019-04-20 15:11:20 -04:00
Lauri Ojansivu a72d730373 Remove extra check. 2019-04-20 14:20:37 -04:00
Lauri Ojansivu a1efe50659 Fix repo url. 2019-04-20 14:17:55 -04:00
Lauri Ojansivu 30e3b448fd Update docker-compose.yml to use meteor-1.8 branch with MongoDB 4.0.9. 2019-04-20 13:56:32 -04:00
Lauri Ojansivu 29d895742c Fix snap npm permissions. 2019-04-20 13:45:23 -04:00
Lauri Ojansivu c23047a59f Update to MongoDB 4.0.9 on Snap. 2019-04-20 13:34:55 -04:00
Lauri Ojansivu 4aa26e292e Try to fix snap. 2019-04-20 13:31:36 -04:00
Lauri Ojansivu 0a20795ea4 Fix python3 pip and setuptools error. 2019-04-20 13:31:03 -04:00
Lauri Ojansivu c3a27f6d17 Fixes to get Dockerfile built on ubuntu:disco. 2019-04-20 13:13:00 -04:00
Lauri Ojansivu 4c9a90a461 Update version. 2019-04-20 12:09:42 -04:00
Lauri Ojansivu eb58d335c0 Merge branch 'edge' into meteor-1.8 2019-04-20 17:12:41 +03:00
Lauri Ojansivu 2f2c4723a6 Merge pull request #2347 from justinr1234/meteor18
Additional Meteor 1.8.1 changes
2019-04-20 16:52:33 +03:00
Lauri Ojansivu 02819ca169 Merge branch 'edge' into meteor-1.8 2019-04-20 16:51:57 +03:00
Justin Reynolds a1ae4d7ef0 Additional Meteor 1.8.1 changes 2019-04-19 10:16:37 -05:00
Lauri Ojansivu 53d42a17ff Update compatible mongodb version to 4.0.6 2019-04-12 19:26:24 +00:00
Lauri Ojansivu cc21da6266 Fix quotes. 2019-04-12 18:55:24 +00:00
Lauri Ojansivu ab05af79ec Update packages, and remove broken one about mousewheel. 2019-04-12 18:40:50 +00:00
Lauri Ojansivu c46c5e9c8f Fix rebuild script. 2019-04-12 18:03:07 +00:00
Lauri Ojansivu 9c50b81c70 Update packages. 2019-04-12 18:01:02 +00:00
Lauri Ojansivu 144771bebf Merge branch 'meteor-1.8' of github.com:wekan/wekan into meteor-1.8 2019-04-12 17:02:12 +00:00
Lauri Ojansivu 422aabd562 Update to Meteor 1.8.1 2019-04-12 17:01:44 +00:00
Lauri Ojansivu 076dda8bd3 Merge branch 'edge' into meteor-1.8 2019-04-08 10:33:24 +03:00
Lauri Ojansivu f2f13450b5 Merge branch 'edge' into meteor-1.8 2019-04-06 14:17:09 +03:00
Lauri Ojansivu 4356aaff23 Merge branch 'edge' into meteor-1.8 2019-04-06 13:56:09 +03:00
Lauri Ojansivu 0b9afcb443 Merge branch 'edge' into meteor-1.8 2019-04-02 15:28:30 +03:00
Lauri Ojansivu 5e7e9e8c0d Change to MongoDB 4.0.7 legacy versions without curl to get it working. 2019-03-27 19:02:57 +02:00
Lauri Ojansivu 5841a3abea Merge branch 'edge' into meteor-1.8 2019-03-27 17:53:06 +02:00
Lauri Ojansivu d753fc06c9 Use mongodb for Ubuntu 16.04 2019-03-26 00:25:40 +02:00
Lauri Ojansivu a85d652db4 Try to fix meteor-1.8 snap build. 2019-03-25 20:09:31 +02:00
Lauri Ojansivu a9e6bf62bd Merge branch 'edge' into meteor-1.8 2019-03-25 19:12:48 +02:00
Lauri Ojansivu 0674ce19fe Revert to original snapcraft.yaml. 2019-03-25 17:18:01 +02:00
Lauri Ojansivu 3fc251c1f6 Merge branch 'meteor-1.8' of github.com:wekan/wekan into meteor-1.8 2019-03-25 17:15:36 +02:00
Lauri Ojansivu 67c3f663a1 Merge branch 'edge' into meteor-1.8 2019-03-25 17:15:18 +02:00
Lauri Ojansivu 2050796a33 Try to build meteor-1.8 snap. 2019-03-25 08:59:52 +00:00
Lauri Ojansivu 7c4c467e46 Update packages. 2019-03-25 08:25:36 +00:00
Lauri Ojansivu 4f4f3e4593 Merge branch 'edge' into meteor-1.8 2019-03-23 21:35:55 +02:00
Lauri Ojansivu 5160d59d79 Merge branch 'edge' into meteor-1.8 2019-03-23 21:14:05 +02:00
Lauri Ojansivu ab4774a59a Merge branch 'edge' into meteor-1.8 2019-03-22 13:10:31 +02:00
Lauri Ojansivu b0d1ccc311 Merge branch 'edge' into meteor-1.8 2019-03-21 02:42:14 +02:00
Lauri Ojansivu 8c2ebde3d5 Merge branch 'edge' into meteor-1.8 2019-03-21 01:23:20 +02:00
Lauri Ojansivu 508e8c87be Merge branch 'edge' into meteor-1.8 2019-03-21 01:12:57 +02:00
Lauri Ojansivu 365e8455e6 Merge branch 'edge' into meteor-1.8 2019-03-21 00:40:46 +02:00
Lauri Ojansivu 393684fb19 Merge branch 'edge' into meteor-1.8 2019-03-15 11:09:21 +02:00
Lauri Ojansivu 909a23e529 Merge branch 'edge' into meteor-1.8 2019-03-14 00:41:55 +02:00
Lauri Ojansivu b68a2e2b41 Merge branch 'edge' into meteor-1.8 2019-03-13 15:56:54 +02:00
Lauri Ojansivu 33f09f0887 Merge branch 'edge' into meteor-1.8 2019-03-11 23:40:24 +02:00
Lauri Ojansivu aee05a549f v2.44
Merge branch 'edge' into meteor-1.8
2019-03-11 20:26:23 +02:00
Lauri Ojansivu 0155c7d8ce Merge branch 'edge' into meteor-1.8 2019-03-08 19:17:33 +02:00
Lauri Ojansivu 64fca5893e Merge branch 'edge' into meteor-1.8 2019-03-07 01:54:00 +02:00
Lauri Ojansivu 221831e4e5 Merge branch 'edge' into meteor-1.8 2019-03-07 00:05:46 +02:00
Lauri Ojansivu cb755af2ee Merge branch 'edge' into meteor-1.8 2019-03-06 20:58:01 +02:00
Lauri Ojansivu f71f3126db Merge branch 'edge' into meteor-1.8 2019-03-06 18:23:37 +02:00
Lauri Ojansivu 42a2767211 Merge branch 'edge' into meteor-1.8 2019-03-06 17:32:20 +02:00
Lauri Ojansivu e410205886 Merge branch 'edge' into meteor-1.8 2019-03-06 03:15:51 +02:00
Lauri Ojansivu 07433b8005 Merge branch 'edge' into meteor-1.8 2019-03-04 19:57:14 +00:00
Lauri Ojansivu 58575706fe Update stylus. 2019-03-04 19:56:22 +00:00
Lauri Ojansivu ebba71077e Fix escaping special character as advised at
https://github.com/jquery/jquery/issues/2885

Thanks to xet7 !
2019-03-04 10:31:05 +00:00
Lauri Ojansivu 6c0df108c7 Merge branch 'edge' into meteor-1.8 2019-03-04 12:10:11 +02:00
Lauri Ojansivu 5f3ffcb0eb Merge branch 'edge' into meteor-1.8 2019-03-04 10:17:14 +02:00
Lauri Ojansivu 265d57b9f4 Update packages.
Thanks to xet7 !
2019-03-04 10:02:54 +02:00
Lauri Ojansivu 42e85f693c Upgrade to Meteor 1.8.0.2.
Thanks to xet7 !
2019-03-04 09:56:12 +02:00
Lauri Ojansivu 30dacb0369 Change Dockerfile to use ubuntu:cosmic base.
Thanks to xet7 !
2019-03-04 09:48:59 +02:00
Lauri Ojansivu 304d5e6256 Merge branch 'edge' into meteor-1.8 2019-03-03 22:40:24 +02:00
Lauri Ojansivu 597de31116 Merge branch 'edge' into meteor-1.8 2019-03-02 17:33:01 +02:00
Lauri Ojansivu 425b3d98b3 Merge branch 'edge' into meteor-1.8 2019-03-01 15:44:16 +02:00
Lauri Ojansivu c2fb8b5be8 Merge branch 'edge' into meteor-1.8 2019-03-01 07:11:59 +02:00
Lauri Ojansivu 1ba299585c Merge branch 'edge' into meteor-1.8 2019-02-28 23:32:58 +02:00
Lauri Ojansivu 174ad1a987 Merge branch 'edge' into meteor-1.8 2019-02-28 23:03:16 +02:00
Lauri Ojansivu 199246ea6c Merge branch 'edge' into meteor-1.8 2019-02-28 12:42:49 +02:00
Lauri Ojansivu eeb8d4b3de Merge branch 'edge' into meteor-1.8 2019-02-28 00:54:29 +02:00
Lauri Ojansivu 82a728df71 Merge branch 'edge' into meteor-1.8 2019-02-27 21:03:54 +02:00
Lauri Ojansivu 3f067c793c Merge branch 'devel' into meteor-1.8 2019-02-27 17:29:39 +02:00
Lauri Ojansivu 2489cc5b91 Merge branch 'devel' into meteor-1.8 2019-02-27 16:27:15 +02:00
Lauri Ojansivu 1c832a24b7 Merge branch 'devel' into meteor-1.8 2019-02-27 06:21:23 +02:00
Lauri Ojansivu e40198cd26 Merge branch 'devel' into meteor-1.8 2019-02-25 20:04:47 +02:00
Lauri Ojansivu c81556b64c Merge branch 'edge' into meteor-1.8 2019-02-23 19:55:50 +02:00
Lauri Ojansivu 60546d2ce3 Merge branch 'edge' into meteor-1.8 2019-02-23 19:24:51 +02:00
Lauri Ojansivu fa0b4d7edd Merge branch 'edge' into meteor-1.8 2019-02-17 18:16:11 +02:00
Lauri Ojansivu d5593e059b Merge branch 'edge' into meteor-1.8 2019-02-13 03:17:04 +02:00
Lauri Ojansivu 93ae4e504e Merge branch 'edge' into meteor-1.8 2019-02-12 03:26:56 +02:00
Lauri Ojansivu fcac5d1033 Merge branch 'edge' into meteor-1.8 2019-02-11 16:46:12 +02:00
Lauri Ojansivu f69392566a Merge branch 'edge' into meteor-1.8 2019-02-09 00:06:05 +02:00
Lauri Ojansivu 8e3689a11d Merge branch 'edge' into meteor-1.8 2019-02-08 20:58:04 +02:00
Lauri Ojansivu 5804a204fe Merge branch 'edge' into meteor-1.8 2019-02-04 21:48:58 +02:00
Lauri Ojansivu 09682111d6 Merge branch 'edge' into meteor-1.8 2019-02-03 15:47:05 +02:00
Lauri Ojansivu 3a845d13f8 Merge branch 'edge' into meteor-1.8 2019-02-03 05:19:58 +02:00
Lauri Ojansivu 2cb4df9e0b Merge branch 'edge' into meteor-1.8 2019-02-03 03:09:02 +02:00
Lauri Ojansivu daa602ed9e Merge branch 'edge' into meteor-1.8 2019-02-03 02:33:03 +02:00
Lauri Ojansivu eabf24d750 Merge branch 'edge' into meteor-1.8 2019-02-03 02:26:23 +02:00
Lauri Ojansivu e2475ad73f Merge branch 'edge' into meteor-1.8 2019-02-02 21:56:40 +02:00
Lauri Ojansivu 4f79e84399 Merge branch 'devel' into meteor-1.8 2019-02-02 21:03:12 +02:00
Lauri Ojansivu e4c0638f72 Merge branch 'edge' into meteor-1.8 2019-02-01 17:16:22 +02:00
Lauri Ojansivu e774f71205 Merge branch 'edge' into meteor-1.8 2019-01-31 19:33:39 +02:00
Lauri Ojansivu b2986ca289 Merge branch 'edge' into meteor-1.8 2019-01-31 14:28:53 +02:00
Lauri Ojansivu 271853e155 Merge branch 'edge' into meteor-1.8 2019-01-30 18:53:02 +02:00
Lauri Ojansivu a2a3d316d5 Merge branch 'edge' into meteor-1.8 2019-01-30 18:19:07 +02:00
Lauri Ojansivu 33b75f2f23 Merge branch 'edge' into meteor-1.8 2019-01-30 16:07:41 +02:00
Lauri Ojansivu 929ca9cbd9 Merge branch 'edge' into meteor-1.8 2019-01-30 02:20:35 +02:00
Lauri Ojansivu ea3bcf4320 Merge branch 'edge' into meteor-1.8 2019-01-29 18:57:57 +02:00
Lauri Ojansivu 0b018bfad5 Merge branch 'edge' into meteor-1.8 2019-01-28 18:31:26 +02:00
Lauri Ojansivu c360afb341 Merge branch 'edge' into meteor-1.8 2019-01-28 17:27:50 +02:00
Lauri Ojansivu 2dba189830 Merge branch 'edge' into meteor-1.8 2019-01-28 02:59:32 +02:00
Lauri Ojansivu d40d5652ba Merge branch 'edge' into meteor-1.8 2019-01-27 19:13:01 +02:00
Lauri Ojansivu d40ad94384 Merge branch 'edge' into meteor-1.8 2019-01-27 18:29:02 +02:00
Lauri Ojansivu 8e2f44bbc0 Merge branch 'edge' into meteor-1.8 2019-01-26 20:22:17 +02:00
Lauri Ojansivu 87df11434b Merge branch 'edge' into meteor-1.8 2019-01-25 23:07:43 +02:00
Lauri Ojansivu 95c178cee3 Merge branch 'edge' into meteor-1.8 2019-01-25 22:20:00 +02:00
Lauri Ojansivu 46a468b06d Merge branch 'edge' into meteor-1.8 2019-01-22 17:33:27 +02:00
Lauri Ojansivu 8d4eef6649 Merge branch 'edge' into meteor-1.8 2019-01-13 20:14:23 +02:00
Lauri Ojansivu 9421c0ba05 Merge branch 'edge' into meteor-1.8 2019-01-06 13:30:19 +02:00
Lauri Ojansivu 1c827f9830 Merge branch 'edge' into meteor-1.8 2019-01-04 20:08:55 +02:00
Lauri Ojansivu 4114d08961 Merge branch 'edge' into meteor-1.8 2019-01-04 12:18:24 +02:00
Lauri Ojansivu 98917523fc Merge branch 'edge' into meteor-1.8 2019-01-01 14:10:10 +02:00
Lauri Ojansivu e9a3601d2e - Upgrade to Meteor 1.8.0.1.
Thanks to xet7 !
2018-12-29 19:47:59 +02:00
Lauri Ojansivu 3c53b3de15 - Change to meteor v1.8, finally got it working, at least it started.
Note that if MongoDB does not start, you could try fixing meteor's local database with
  command from https://github.com/meteor/meteor/issues/9591#issuecomment-367351465 that for
  Linux is `cd ~ && .meteor/packages/meteor-tool/1.8.0/mt-os.linux.x86_64/dev_bundle/mongodb/bin/mongod --dbpath ./repos/wekan/.meteor/local/db --repair`
  but that did not work for me, so I needed to move away (or delete) repos/wekan/.meteor/local/db file
  so that it was created again and with command `mongo` database could start correctly.

Thanks to xet7 !
2018-12-29 19:29:14 +02:00
Lauri Ojansivu 8becd9aad3 - Update some packages. Error about tap:i18n still exists.
Thanks to xet7 !
2018-12-29 16:41:20 +02:00
Lauri Ojansivu 5eadc0c850 Merge branch 'edge' into meteor-1.8 2018-12-28 17:33:28 +02:00
Lauri Ojansivu 89d0da5eee - Update dependencies. But this Meteor 1.8.x version still does not work
because of tap:18n bug.

Thanks to xet7 !
2018-12-28 17:20:34 +02:00
Lauri Ojansivu 03fbc1cd70 Merge branch 'edge' into meteor-1.8 2018-12-27 00:36:41 +02:00
Lauri Ojansivu 738e07c424 Merge branch 'edge' into meteor-1.8 2018-12-26 23:58:42 +02:00
Lauri Ojansivu 4fb81bd686 Merge branch 'edge' into meteor-1.8 2018-12-26 22:50:25 +02:00
Lauri Ojansivu aff8b562d6 Merge branch 'edge' into meteor-1.8 2018-12-24 23:56:54 +02:00
Lauri Ojansivu 236c99b39f Merge branch 'edge' into meteor-1.8 2018-12-24 18:27:49 +02:00
Lauri Ojansivu 5488b68b9b - Update meteor.
Thanks to xet7 !
2018-12-24 14:03:31 +02:00
Lauri Ojansivu 6d18fb689f - Update dependency package versions.
Thanks to xet7 !
2018-12-24 13:56:29 +02:00
Lauri Ojansivu 9d7e9e9869 Merge branch 'edge' into meteor-1.8 2018-12-22 21:42:11 +02:00
Lauri Ojansivu 6d15fd29ee Merge branch 'edge' into meteor-1.8 2018-12-22 19:05:33 +02:00
Lauri Ojansivu d78e067246 Merge branch 'edge' into meteor-1.8 2018-12-22 18:58:35 +02:00
Lauri Ojansivu 5b227b2b4f Merge branch 'edge' into meteor-1.8 2018-12-21 22:24:21 +02:00
Lauri Ojansivu 16fe2be04d Merge branch 'edge' into meteor-1.8 2018-12-19 19:59:11 +02:00
Lauri Ojansivu 61c0292089 Merge branch 'edge' into meteor-1.8 2018-12-18 20:23:43 +02:00
Lauri Ojansivu c8173fd9f9 Merge branch 'edge' into meteor-1.8 2018-12-16 19:11:05 +02:00
Lauri Ojansivu 72f8baf6b3 Merge branch 'edge' into meteor-1.8 2018-12-16 12:01:42 +02:00
Lauri Ojansivu e135af8c37 Merge branch 'edge' into meteor-1.8 2018-12-16 00:43:25 +02:00
Lauri Ojansivu 61eb0e7acd Merge branch 'edge' into meteor-1.8 2018-12-15 22:45:36 +02:00
Lauri Ojansivu 0b841f2e05 Merge branch 'edge' into meteor-1.8 2018-12-15 22:03:10 +02:00
Lauri Ojansivu 9662267628 Merge branch 'edge' into meteor-1.8 2018-12-15 20:53:47 +02:00
Lauri Ojansivu 34f2e4466e Merge branch 'edge' into meteor-1.8 2018-12-14 23:34:06 +02:00
Lauri Ojansivu 73f288cd9b Merge branch 'edge' into meteor-1.8 2018-12-13 20:15:16 +02:00
Lauri Ojansivu 622f1360bb Merge branch 'edge' into meteor-1.8 2018-12-13 14:41:42 +02:00
Lauri Ojansivu 4ecdf7558f Merge branch 'edge' into meteor-1.8 2018-12-09 01:45:24 +02:00
Lauri Ojansivu 25fac166cf Merge branch 'edge' into meteor-1.8 2018-12-09 00:51:50 +02:00
Lauri Ojansivu 66d1546081 Merge branch 'edge' into meteor-1.8 2018-12-07 05:23:00 +02:00
Lauri Ojansivu 181b564bf3 Upgrade to meteor 1.8.1-beta.8
Thanks to xet7 !
2018-12-07 04:14:34 +02:00
Lauri Ojansivu 872e503ff8 Merge branch 'edge' into meteor-1.8 2018-12-06 02:01:36 +02:00
Lauri Ojansivu 38012903b8 Merge branch 'edge' into meteor-1.8 2018-12-05 08:59:59 +02:00
Lauri Ojansivu 6ab699d650 Merge branch 'edge' into meteor-1.8 2018-12-04 22:34:22 +02:00
Lauri Ojansivu af6513ccc7 Merge branch 'edge' into meteor-1.8 2018-12-03 18:26:01 +02:00
Lauri Ojansivu 30fe263bfe Merge branch 'edge' into meteor-1.8 2018-12-03 16:32:05 +02:00
Lauri Ojansivu 51cf57025d Merge branch 'meteor-1.8' of github.com:wekan/wekan into meteor-1.8 2018-11-23 16:39:43 +02:00
Lauri Ojansivu 28884cb409 Merge branch 'devel' into meteor-1.8 2018-11-23 16:39:28 +02:00
Lauri Ojansivu 6e29152b76 Merge branch 'edge' into meteor-1.8 2018-11-20 22:52:24 +02:00
Lauri Ojansivu 0defff70af Merge branch 'edge' into meteor-1.8 2018-11-20 12:26:02 +02:00
Lauri Ojansivu d93efd9e9b Merge branch 'edge' into meteor-1.8 2018-11-20 02:46:35 +02:00
Lauri Ojansivu eab46523ee Merge branch 'edge' into meteor-1.8 2018-11-19 23:29:49 +02:00
Lauri Ojansivu c4473f3515 Merge branch 'edge' into meteor-1.8 2018-11-19 23:12:46 +02:00
Lauri Ojansivu 8b3f8ac501 Merge branch 'edge' into meteor-1.8 2018-11-19 15:09:10 +02:00
Lauri Ojansivu fb2e8b4a31 Merge branch 'devel' into meteor-1.8 2018-11-17 17:44:11 +02:00
Lauri Ojansivu 871e229fae Merge branch 'edge' into meteor-1.8 2018-11-17 16:58:27 +02:00
Lauri Ojansivu e1b3f38315 Merge branch 'edge' into meteor-1.8 2018-11-17 15:22:47 +02:00
Lauri Ojansivu b8b1512e26 Merge branch 'edge' into meteor-1.8 2018-11-17 14:51:22 +02:00
Lauri Ojansivu 3300c69a03 Merge branch 'edge' into meteor-1.8 2018-11-09 21:58:31 +02:00
Lauri Ojansivu 09a95dfef6 v1.69.2 2018-11-05 15:46:43 +02:00
Lauri Ojansivu ea141f62d7 Update meteor 2018-11-05 15:43:35 +02:00
222 changed files with 40195 additions and 11196 deletions

No files matched your search

+17
View File
@@ -8,3 +8,20 @@ end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
[*.{js,html}]
charset = utf-8
end_of_line = lf
indent_brace_style = 1TBS
indent_size = 2
indent_style = space
insert_final_newline = true
max_line_length = 80
quote_type = auto
spaces_around_operators = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
+1
View File
@@ -0,0 +1 @@
packages/*
+34 -12
View File
@@ -1,16 +1,19 @@
{
"extends": "eslint:recommended",
"extends": [
"eslint:recommended",
"plugin:meteor/recommended",
"prettier",
"prettier/standard"
],
"env": {
"es6": true,
"node": true,
"browser": true
"browser": true,
"meteor": true
},
"parserOptions": {
"ecmaVersion": 2017,
"sourceType": "module",
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
"strict": 0,
@@ -20,7 +23,7 @@
"consistent-return": 2,
"dot-notation": 2,
"eqeqeq": 2,
"indent": [2, 2],
"indent": 0,
"no-cond-assign": 2,
"no-constant-condition": 2,
"no-eval": 2,
@@ -28,11 +31,12 @@
"no-unneeded-ternary": 2,
"radix": 2,
"semi": [2, "always"],
"camelcase": [2, {"properties": "never"}],
"camelcase": [2, { "properties": "never" }],
"comma-spacing": 2,
"comma-style": 2,
"eol-last": 2,
"linebreak-style": [2, "unix"],
"meteor/audit-argument-checks": 0,
"new-parens": 2,
"no-lonely-if": 2,
"no-multiple-empty-lines": 2,
@@ -43,7 +47,6 @@
"quotes": [2, "single"],
"semi-spacing": 2,
"space-unary-ops": 2,
"arrow-parens": 2,
"arrow-spacing": 2,
"no-class-assign": 2,
"no-dupe-class-members": 2,
@@ -52,8 +55,27 @@
"prefer-const": 2,
"prefer-spread": 2,
"prefer-template": 2,
"no-unused-vars" : "warn"
"no-unused-vars": "warn",
"prettier/prettier": [
"error",
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"trailingComma": "all"
}
],
"meteor/no-session": 0
},
"settings": {
"import/resolver": {
"meteor": {
"extensions": [".js", ".jsx"]
}
}
},
"plugins": ["prettier", "meteor"],
"globals": {
"Meteor": false,
"Session": false,
@@ -100,7 +122,7 @@
"Attachments": true,
"Boards": true,
"CardComments": true,
"DatePicker" : true,
"DatePicker": true,
"Cards": true,
"CustomFields": true,
"Lists": true,
+1 -1
View File
@@ -8,7 +8,6 @@ npm-debug.log
.vscode/
.idea/
.build/*
package-lock.json
**/parts/
**/stage
**/prime
@@ -29,3 +28,4 @@ versions.json
.Trashes
Thumbs.db
ehthumbs.db
.eslintcache
+1
View File
@@ -16,3 +16,4 @@ notices-for-facebook-graph-api-2
1.4.1-add-shell-server-package
1.4.3-split-account-service-packages
1.5-add-dynamic-import-package
1.7-split-underscore-from-meteor-base
+24 -21
View File
@@ -3,17 +3,16 @@
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
meteor-base@1.2.0
meteor-base@1.4.0
# Build system
ecmascript
stylus@2.513.13
standard-minifier-css@1.3.5
standard-minifier-js@2.2.0
ecmascript@0.12.4
standard-minifier-css@1.5.3
standard-minifier-js@2.4.1
mquandalle:jade
# Polyfills
es5-shim@4.6.15
es5-shim@4.8.0
# Collections
aldeed:collection2
@@ -23,7 +22,7 @@ dburles:collection-helpers
idmontie:migrations
matb33:collection-hooks
matteodem:easy-search
mongo@1.3.1
mongo@1.6.2
mquandalle:collection-mutations
# Account system
@@ -36,12 +35,12 @@ wekan-accounts-cas
wekan-accounts-oidc
# Utilities
check@1.2.5
check@1.3.1
jquery@1.11.10
random@1.0.10
reactive-dict@1.2.0
session@1.1.7
tracker@1.1.3
random@1.1.0
reactive-dict@1.3.0
session@1.2.0
tracker@1.2.0
underscore@1.0.10
3stack:presence
alethes:pages
@@ -49,13 +48,11 @@ arillo:flow-router-helpers
audit-argument-checks@1.0.7
kadira:blaze-layout
kadira:dochead
meteorhacks:picker
meteorhacks:subs-manager
mquandalle:autofocus
ongoworks:speakingurl
raix:handlebar-helpers
tap:i18n
http@1.3.0
http@1.4.2
# UI components
blaze
@@ -70,25 +67,31 @@ templates:tabs
verron:autosize
simple:json-routes
rajit:bootstrap3-datepicker
shell-server@0.3.0
shell-server@0.4.0
simple:rest-accounts-password
useraccounts:core
email@1.2.3
horka:swipebox
dynamic-import@0.2.0
dynamic-import@0.5.1
staringatlights:fast-render
mixmax:smart-disconnect
accounts-password@1.5.0
accounts-password@1.5.1
cfs:gridfs
rzymek:fullcalendar
momentjs:moment@2.22.2
browser-policy-framing
browser-policy-framing@1.1.0
mquandalle:moment
msavin:usercache
wekan-scrollbar
mquandalle:perfect-scrollbar
mdg:meteor-apm-agent
meteorhacks:unblock
mdg:meteor-apm-agent@3.2.0-rc.0!
coagmano:stylus
lucasantoniassi:accounts-lockout
meteorhacks:subs-manager
meteorhacks:picker
lamhieu:unblock
meteorhacks:aggregate@1.3.0
wekan-markdown
konecty:mongo-counter
percolate:synced-cron
+1 -1
View File
@@ -1 +1 @@
METEOR@1.6.0.1
METEOR@1.8.1
+83 -76
View File
@@ -1,29 +1,29 @@
3stack:presence@1.1.2
accounts-base@1.4.0
accounts-oauth@1.1.15
accounts-password@1.5.0
accounts-base@1.4.4
accounts-oauth@1.1.16
accounts-password@1.5.1
aldeed:collection2@2.10.0
aldeed:collection2-core@1.2.0
aldeed:schema-deny@1.1.0
aldeed:schema-index@1.1.1
aldeed:simple-schema@1.5.3
aldeed:simple-schema@1.5.4
alethes:pages@1.8.6
allow-deny@1.1.0
arillo:flow-router-helpers@0.5.2
audit-argument-checks@1.0.7
autoupdate@1.3.12
babel-compiler@6.24.7
babel-runtime@1.1.1
base64@1.0.10
binary-heap@1.0.10
blaze@2.3.2
autoupdate@1.6.0
babel-compiler@7.3.4
babel-runtime@1.3.0
base64@1.0.11
binary-heap@1.0.11
blaze@2.3.3
blaze-tools@1.0.10
boilerplate-generator@1.3.1
boilerplate-generator@1.6.0
browser-policy-common@1.0.11
browser-policy-framing@1.1.0
caching-compiler@1.1.9
caching-html-compiler@1.1.2
callback-hook@1.0.10
caching-compiler@1.2.1
caching-html-compiler@1.1.3
callback-hook@1.1.0
cfs:access-point@0.1.49
cfs:base-package@0.0.30
cfs:collection@0.5.5
@@ -36,78 +36,83 @@ cfs:http-publish@0.0.13
cfs:power-queue@0.9.11
cfs:reactive-list@0.0.9
cfs:reactive-property@0.0.4
cfs:standard-packages@0.5.9
cfs:storage-adapter@0.2.3
cfs:tempstore@0.1.5
cfs:standard-packages@0.5.10
cfs:storage-adapter@0.2.4
cfs:tempstore@0.1.6
cfs:upload-http@0.0.20
cfs:worker@0.1.4
check@1.2.5
cfs:worker@0.1.5
check@1.3.1
chuangbo:cookie@1.1.0
coffeescript@1.12.7_3
coffeescript-compiler@1.12.7_3
coagmano:stylus@2.0.0
coffeescript@1.0.17
cottz:publish-relations@2.0.8
dburles:collection-helpers@1.1.0
ddp@1.4.0
ddp-client@2.2.0
ddp-common@1.3.0
ddp-client@2.3.3
ddp-common@1.4.0
ddp-rate-limiter@1.0.7
ddp-server@2.1.1
ddp-server@2.3.0
deps@1.0.12
diff-sequence@1.0.7
dynamic-import@0.2.1
ecmascript@0.9.0
ecmascript-runtime@0.5.0
ecmascript-runtime-client@0.5.0
ecmascript-runtime-server@0.5.0
diff-sequence@1.1.1
dynamic-import@0.5.1
ecmascript@0.12.7
ecmascript-runtime@0.7.0
ecmascript-runtime-client@0.8.0
ecmascript-runtime-server@0.7.1
ejson@1.1.0
email@1.2.3
es5-shim@4.6.15
es5-shim@4.8.0
fastclick@1.0.13
fetch@0.1.1
fortawesome:fontawesome@4.7.0
geojson-utils@1.0.10
horka:swipebox@1.0.2
hot-code-push@1.0.4
html-tools@1.0.11
htmljs@1.0.11
http@1.3.0
id-map@1.0.9
http@1.4.2
id-map@1.1.0
idmontie:migrations@1.0.3
jquery@1.11.10
inter-process-messaging@0.1.0
jquery@1.11.11
kadira:blaze-layout@2.3.0
kadira:dochead@1.5.0
kadira:flow-router@2.12.1
kenton:accounts-sandstorm@0.7.0
konecty:mongo-counter@0.0.5_3
lamhieu:meteorx@2.0.1
lamhieu:unblock@1.0.0
launch-screen@1.1.1
livedata@1.0.18
localstorage@1.2.0
logging@1.1.19
logging@1.1.20
lucasantoniassi:accounts-lockout@1.0.0
matb33:collection-hooks@0.8.4
matteodem:easy-search@1.6.4
mdg:meteor-apm-agent@3.1.2
mdg:meteor-apm-agent@3.2.3
mdg:validation-error@0.5.1
meteor@1.8.2
meteor-base@1.2.0
meteor@1.9.3
meteor-base@1.4.0
meteor-platform@1.2.6
meteorhacks:aggregate@1.3.0
meteorhacks:collection-utils@1.2.0
meteorhacks:meteorx@1.4.1
meteorhacks:picker@1.0.3
meteorhacks:subs-manager@1.6.4
meteorhacks:unblock@1.1.0
meteorspark:util@0.2.0
minifier-css@1.2.16
minifier-js@2.2.2
minifier-css@1.4.2
minifier-js@2.4.1
minifiers@1.1.8-faster-rebuild.0
minimongo@1.4.3
minimongo@1.4.5
mixmax:smart-disconnect@0.0.4
mobile-status-bar@1.0.14
modules@0.11.0
modules-runtime@0.9.1
momentjs:moment@2.22.2
mongo@1.3.1
modern-browsers@0.1.4
modules@0.13.0
modules-runtime@0.10.3
momentjs:moment@2.24.0
mongo@1.6.3
mongo-decimal@0.1.1
mongo-dev-server@1.1.0
mongo-id@1.0.6
mongo-id@1.0.7
mongo-livedata@1.0.12
mousetrap:mousetrap@1.4.6_1
mquandalle:autofocus@1.0.0
@@ -119,70 +124,72 @@ mquandalle:jquery-ui-drag-drop-sort@0.2.0
mquandalle:moment@1.0.1
mquandalle:mousetrap-bindglobal@0.0.1
mquandalle:perfect-scrollbar@0.6.5_2
msavin:usercache@1.0.0
msavin:usercache@1.8.0
npm-bcrypt@0.9.3
npm-mongo@2.2.33
oauth@1.2.1
oauth2@1.2.0
npm-mongo@3.1.2
oauth@1.2.8
oauth2@1.2.1
observe-sequence@1.0.16
ongoworks:speakingurl@1.1.0
ordered-dict@1.0.9
ordered-dict@1.1.0
peerlibrary:assert@0.2.5
peerlibrary:base-component@0.16.0
peerlibrary:blaze-components@0.15.1
peerlibrary:computed-field@0.7.0
peerlibrary:reactive-field@0.3.0
promise@0.10.0
peerlibrary:computed-field@0.9.0
peerlibrary:reactive-field@0.5.0
percolate:synced-cron@1.3.2
promise@0.11.2
raix:eventemitter@0.1.3
raix:handlebar-helpers@0.2.5
rajit:bootstrap3-datepicker@1.7.1
random@1.0.10
rate-limit@1.0.8
reactive-dict@1.2.0
rajit:bootstrap3-datepicker@1.7.1_1
random@1.1.0
rate-limit@1.0.9
reactive-dict@1.3.0
reactive-var@1.0.11
reload@1.1.11
retry@1.0.9
routepolicy@1.0.12
reload@1.3.0
retry@1.1.0
routepolicy@1.1.0
rzymek:fullcalendar@3.8.0
server-render@0.3.1
service-configuration@1.0.11
session@1.1.7
session@1.2.0
sha@1.0.9
shell-server@0.3.1
shell-server@0.4.0
simple:authenticate-user-by-token@1.0.1
simple:json-routes@2.1.0
simple:rest-accounts-password@1.1.2
simple:rest-bearer-token-parser@1.0.1
simple:rest-json-error-handler@1.0.1
socket-stream-client@0.2.2
softwarerero:accounts-t9n@1.3.11
spacebars@1.0.15
spacebars-compiler@1.1.3
srp@1.0.10
standard-minifier-css@1.3.5
standard-minifier-js@2.2.3
staringatlights:fast-render@2.16.5
staringatlights:inject-data@2.0.5
stylus@2.513.13
srp@1.0.12
standard-minifier-css@1.5.3
standard-minifier-js@2.4.1
staringatlights:fast-render@3.2.0
staringatlights:inject-data@2.3.0
tap:i18n@1.8.2
templates:tabs@2.3.0
templating@1.3.2
templating-compiler@1.3.3
templating-runtime@1.3.2
templating-tools@1.1.2
tracker@1.1.3
tracker@1.2.0
ui@1.0.13
underscore@1.0.10
url@1.1.0
url@1.2.0
useraccounts:core@1.14.2
useraccounts:flow-routing@1.14.2
useraccounts:unstyled@1.14.2
verron:autosize@3.0.8
webapp@1.4.0
webapp@1.7.4
webapp-hashing@1.0.9
wekan-accounts-cas@0.1.0
wekan-accounts-oidc@1.0.10
wekan-ldap@0.0.2
wekan-markdown@1.0.7
wekan-oidc@1.0.12
wekan-scrollbar@3.1.3
wekan-accounts-cas@0.1.0
wekan-ldap@0.0.2
yasaricli:slugify@0.0.7
zimme:active-route@2.3.2
+7
View File
@@ -0,0 +1,7 @@
packages/
node_modules/
.build/
.meteor/
.vscode/
.tx/
.github/
+8
View File
@@ -0,0 +1,8 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "all"
}
+310 -1
View File
@@ -1,3 +1,312 @@
# v3.00 2019-07-25 Wekan release
This release:
- works with source, and docker-compose.yml at master branch.
- Docker release uses Meteor 1.8.1 and MongoDB 4.0.10, so you need to backup your old MongoDB database and
restore with --noIndexRestore as described at https://github.com/wekan/wekan/wiki/Backup
- Snap and Sandstorm builds are not fixed yet, see progress at https://github.com/wekan/wekan/issues/2533
This release adds the following new features:
- [Added label text to labels on minicard](https://github.com/wekan/wekan/commit/c48d5a73cab04db1a1e113e4367dc88573110438).
Thanks to xet7.
- [Allow to shrink attached/pasted image](https://github.com/wekan/wekan/pull/2544).
Thanks to whowillcare.
and fixes the following bugs:
- [Fix invites](https://github.com/wekan/wekan/pull/2549).
Thanks to justinr1234.
- [Makes LDAP background sync work. If the sync interval is unspecified, falls back to a hourly default](https://github.com/wekan/wekan/pull/2555).
Thanks to pshunter.
- [Prevent isCommentOnly user adding attachments, editing list names, moving lists,
and seeing board settings menu. Show non-editable Custom Fields to isCommentOnly user](https://github.com/wekan/wekan/commit/a68c928896a94c377134f29a7183aa0b5a423720).
Thanks to xet7.
- [Many](https://github.com/wekan/wekan/pull/2546) [Snap](https://github.com/wekan/wekan/pull/2552) [fixes](https://github.com/wekan/wekan/pull/2553).
In Progress. Thanks to justrinr1234.
- [Fixed Dockerfile](https://github.com/wekan/wekan/commit/7df6f305c5cf41ac213623aeffaa7e48c981e0b6) and
[docker-compose.yml](https://github.com/wekan/wekan/commit/95698911f92ca728dbaab69406fd09bcbf81339d).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.99 2019-07-17 Wekan release
This release adds the following new features:
- [Add Corteza theme. In progress](https://github.com/wekan/wekan/commit/289e78dbd29cca9d97d3b5787c3368583d43b40f).
Thanks to xet7.
- [Notify Due Days: System timelines will be showing any user modification for duat startat endat receivedat,
also notification to the watchers and if any card is due, about due or past due](https://github.com/wekan/wekan/pull/2536).
ENV variables: NOTIFY_DUE_DAYS_BEFORE_AND_AFTER (default is 2, if 0, will turn off notification for and dued cards),
NOTIFY_DUE_AT_HOUR_OF_DAY (any number between 0 - 23, standing for at what hour of a day that the notification will
be sent to the watchers). Also [bug fix for this, timeOldValue needs to set to "" in params when it's
not set](https://github.com/wekan/wekan/pull/2541).
Thanks to whowillcare.
- [Notify Due Days: Add settings to Snap/Docker/Source. Rename env variables to NOTIFY_DUE_DAYS_BEFORE_AND_AFTER and
NOTIFY_DUE_AT_HOUR_OF_DAY](https://github.com/wekan/wekan/commit/5084cddf37ba16ce0855f8575c39f5e62d1b7f67).
Thanks to xet7.
- [BIGEVENTS_PATTERN: When user being @ in comment, as long as it's not himself, a notification will be
sent out no matter this user is watching the board or not](https://github.com/wekan/wekan/pull/2541).
Introduced a system env var BIGEVENTS_PATTERN default as "due", so any activityType matches the pattern,
system will send out notifications to all board members no matter they are watching or tracking
the board or not. Owner of the Wekan server can disable the feature by setting this variable to "NONE"
or change the pattern to any valid regex. i.e. '|' delimited activityType names.
Thanks to whowillcare.
- [Add BIGEVENTS_PATTERN to Source/Snap/Docker](https://github.com/wekan/wekan/commit/d7c09df7d2649bf2d2b61772c251f81793a6ed77).
Thanks to xet7.
and adds the following updates:
- [Update Meteor mongo package version](https://github.com/wekan/wekan/commit/96065d11a543852c1069cbab528bd08508b4a27c).
Thanks to xet7.
- [Update dependencies](https://github.com/wekan/wekan/commit/d82c72f1c1df908e92045e5034fa12b33fc7f70c).
Thanks to xet7.
and fixes the following bugs:
- RELAX THEME: Use [only in this theme](https://github.com/wekan/wekan/commit/3ad6e554dceea822dee7390872260e872a792dcd)
the aggressive [red color and big bold serif font style
number](https://github.com/wekan/wekan/commit/bbc68309af0029f2bc4194db4c7e79689f888ea4#commitcomment-34216371) and
[card details text emphasis](https://github.com/wekan/wekan/commit/48ebc5f11745b125ce01d08d60e2d8e3a9419a5f#commitcomment-34268095)
Thanks to hever and xet7.
- [Try to fix docker-compose.yml to use correct master branch that has
meteor 1.8.1](https://github.com/wekan/wekan/commit/202cc5a797b6269ec422c6f2e532a49f09d4e30a).
Thanks to xet7.
- [Outgoing Webhooks setCustomField: Add board name, card name, custom field name to be
visible](https://github.com/wekan/wekan/commit/2003d90467debeadf51b69630c80ee6040524f52).
Still missing: custom field value, list name, swimlane name.
Thanks to xet7.
- [Don't remove boardoverlay when mouse leaves carddetails](https://github.com/wekan/wekan/pull/2540).
This reduces Wekan board flashiness.
Thanks to newhinton.
- [Limit the board list to 2 or 1 for mobile clients](https://github.com/wekan/wekan/pull/2542).
As a mobile user, the board size of in the home page too small, so the user is easily to
click on archive or copy button by accident. Increase the board size to 50% for pixel
greater than 360 and lesser than 800 and height to 8rem, 100% for any screen is even smaller.
This will reduce the accident much more.
Thanks to whowillcare.
- [Add check for board member isActive](https://github.com/wekan/wekan/commit fe42eb1d014c06dfed8114a00b29eac9b08baec6).
Thanks to xet7.
and has the following features in progress, not anything visible yet:
- [Teams/Organizations: Add beginnings of database structure](https://github.com/wekan/wekan/issues/802#issuecomment-505986270).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.98 2019-07-02 Wekan release
This release adds the following new features, thanks to xet7:
- [Add Wekan v2.95-v2.97 master branch features and fixes to meteor-1.8 branch](https://github.com/wekan/wekan/commit/34b2168d0dda253dedabbee47031873efa4ae446).
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.97 2019-07-01 Wekan release
This release [adds the following new features](https://github.com/wekan/wekan/commit/3e8cb8c6e1617ef03ebce045d3b93aeb2cf91228), thanks to xet7:
- Add background color names to background colors.
- Add new background colors: moderatepink, strongcyan, limegreen.
- Add new background colors with themes: dark, relax.
Note: Due Date etc on cards is visible on all background colors and themes. Hiding is not implemented yet.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.96 2019-07-01 Wekan release
This release removes the following features, that were added at Wekan v2.95:
- [Remove RELAX MODE and DARK MODE](https://github.com/wekan/wekan/commit/8477e94f3b8f531a4209f49758200009d274c1cf),
because [they changed look of all existing boards](https://github.com/wekan/wekan/issues/1149#issuecomment-507255114).
At some later Wekan release they will be added back as separate themes
that can be selected, without changing existing boards.
Thanks to chirrut2 and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.95 2019-07-01 Wekan release
This release adds the following new features, thanks to xet7:
- [Make list header add card + button more black, to make it more visible](https://github.com/wekan/wekan/commit/b260d05a8b2f87c29dd998d42103d1220b20cc08).
- [On minicard, make comment icon and number of comments have red color
on white rounded background, so it is more visible when there is comments on card](https://github.com/wekan/wekan/commit/bbc68309af0029f2bc4194db4c7e79689f888ea4).
- [Make card description text more visible with black borders and more white text area](https://github.com/wekan/wekan/commit/48ebc5f11745b125ce01d08d60e2d8e3a9419a5f).
and adds the following [themes to board background colors](https://github.com/wekan/wekan/commit/c04292e98832e3aa7952e8a7858d47a853f40aad), thanks to xet7:
- RELAX MODE, so when green background selected, list background is light green.
- [DARK MODE](https://github.com/wekan/wekan/issues/1149), when dark backgroud color selected. Please test and send color visibility fixes as pull requests.
- In RELAX MODE and DARK MODE, [hide card fields: received, start, due, end, members, requested, assigned](https://github.com/wekan/wekan/commit/b42ecb7948ad194433dc4460305174965106a751).
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.94 2019-06-29 Wekan release
This release adds the following updates:
- [Prettier & eslint project style update](https://github.com/wekan/wekan/pull/2520).
Thanks to justinr1234.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.93 2019-06-28 Wekan release
This release fixes the following bugs:
- [LDAP: Check if email attribute is an array, that has many email addresses](https://github.com/wekan/wekan/pull/2519).
Thanks to tdemaret and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.92 2019-06-27 Wekan release
This release fixes the following bugs:
- [Fix Outgoing Webhook messages for Checlists, Checklist Items, Card comments, Add/Remove CustomField to board](https://github.com/wekan/wekan/commit/5283ba9ebbedf11540ffef1d4d87891c5ce9efc7).
Not yet fixed is Outgoing Webhook message about setting CustomField value.
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.91 2019-06-27 Wekan release
This release fixes the following bugs:
- [Fix Attachment Outgoing Webhook missing list and swimlane name](https://github.com/wekan/wekan/commit/6a2f120d00b5ce9089ad2e12d01edb1ed9f94800).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.90 2019-06-21 Wekan release
This release reverts the following Sandstorm changes:
- [Revert v2.89 setting every Sandstorm Wekan user as admin](https://github.com/wekan/wekan/commit/e5c0d0ea18fe74a47afdfe101160280854e2c74f).
Thanks to xet7. [Related #2405](https://github.com/wekan/wekan/issues/2405).
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.89 2019-06-21 Wekan release
This release adds the following Sandstorm features:
- [Sandstorm Wekan: Set everyone as Admin](https://github.com/wekan/wekan/commit/60d62a6ae3a79059e68b2cd1d554d67b7d50b6aa).
Please test does this help with [Problem with the user management: can't add users or give wekan admin rights](https://github.com/wekan/wekan/issues/2405).
Thanks to xet7.
- [If board does not exist, redirect to All Boards page, at all Wekan platforms](https://github.com/wekan/wekan/commit/4f46adc389126597266d71110f9754841f86857c).
So now at Sandstorm when loading Wekan grain, if first Sandstorm board is found,
it is opened. If first Sandstorm board is not found (it's deleted or archived),
then redirect automatically to All Boards page. [Closes #3132](https://github.com/wekan/wekan/issues/3132).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.88 2019-06-21 Wekan release
This release adds the following updates:
- Update translations.
Thanks to translators for their translations.
# v2.87 2019-06-21 Wekan release
This release adds the following new features:
- [Rule cardAction - SetDate](https://github.com/wekan/wekan/pull/2506).
Thanks to road42.
and fixes the following bugs:
- [Fix Move card to top/bottom of list](https://github.com/wekan/wekan/pull/2508).
Thanks to road42.
- [Translation fixes](https://github.com/wekan/wekan/pull/2507).
Thanks to road42.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.86 2019-06-19 Wekan release
This release fixes the following bugs:
- [Fix Wekan unable to Select Text from Description edit box](https://github.com/wekan/wekan/issues/2451)
by removing feature of card description submit on click outside. This is because when selecting text
and dragging up did trigger submit of description, so description was closed and selecting text failed.
This did affect all Chromium-based browsers: Chrome, Chromium, Chromium Edge.
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.85 2019-06-19 Wekan release
This release fixes the following bugs:
- [Fixed bug: rule doesn't move card to top/bottom](https://github.com/wekan/wekan/pull/2502).
Thanks to road42.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.84 2019-06-18 Wekan release
This release fixes the following bugs:
- [Buttons for adding rules to a board where missing for isBoardAdmin](https://github.com/wekan/wekan/pull/2500).
Thanks to road42.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.83 2019-06-17 Wekan release
This release fixes the following bugs:
- [Fix Bug: Unable to click board submenu on mobile](https://github.com/wekan/wekan/commit/7ff6f24a90374ae95edbb87b37e0c235e7aee434).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.82 2019-06-14 Wekan release
This release fixes the following bugs:
- [Fix OIDC Docker login. Empty string results to empty array at wekan/server/authentication.js](https://github.com/wekan/wekan/commit/bddbaa7bc2f3cfe8553a2265e168231ab51876f3).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.81 2019-06-13 Wekan release
This release fixes the following bugs:
- [Change OAuth2 whitelist default to empty string at snap, so it would be used as array on
wekan/server/authentication.js](https://github.com/wekan/wekan/commit/4334fbbb9dacf45b0262019526a9697b015049a1).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.80 2019-06-13 Wekan release
This release fixes the following bugs:
- [Fix OAuth2 typos in snap-src/bin/config](https://github.com/wekan/wekan/commit/44dbd462b19e613fcb47161d44e4046d5d91a319).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.79 2019-06-13 Wekan release
This release fixes the following bugs:
- [Fix OAuth2 typos in Dockerfile and docker-compose.yml](https://github.com/wekan/wekan/pull/2488).
Thanks to DominikPf.
Thanks to above GitHub users for their contributions and translators for their translations.
# v2.78 2019-06-12 Wekan release
This release fixes the following bugs:
@@ -230,7 +539,7 @@ and adds the following updates:
because [it was found old version was in use](https://github.com/wekan/wekan/issues/2334).
Thanks to shaygover and xet7.
- [Upgrade to Node 8.16.0](https://github.com/wekan/wekan/commit/6117097a93bfb11c8bd4c87a23c44a50e22ceb87).
Thanks to Node developers and xet7.
Thanks to Node developers and xet7.
- [Upgrade Docker base image to ubuntu:disco](https://github.com/wekan/wekan/commit/bd14ee3b1f450ddc6dec26ccc8da702b839942e5).
Thanks to Ubuntu developers and xet7.
+52 -38
View File
@@ -4,14 +4,14 @@ LABEL maintainer="wekan"
# Set the environment variables (defaults where required)
# DOES NOT WORK: paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
# ENV BUILD_DEPS="paxctl"
ENV BUILD_DEPS="apt-utils bsdtar gnupg gosu wget curl bzip2 build-essential python3 python3-pip git ca-certificates gcc-8" \
ENV BUILD_DEPS="apt-utils bsdtar gnupg gosu wget curl bzip2 g++ build-essential git ca-certificates" \
DEBUG=false \
NODE_VERSION=v8.16.0 \
METEOR_RELEASE=1.6.0.1 \
METEOR_RELEASE=1.8.1 \
USE_EDGE=false \
METEOR_EDGE=1.5-beta.17 \
NPM_VERSION=latest \
FIBERS_VERSION=2.0.0 \
FIBERS_VERSION=4.0.1 \
ARCHITECTURE=linux-x64 \
SRC_PATH=./ \
WITH_API=true \
@@ -21,6 +21,11 @@ ENV BUILD_DEPS="apt-utils bsdtar gnupg gosu wget curl bzip2 build-essential pyth
ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE=3 \
ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD=60 \
ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW=15 \
MAX_IMAGE_PIXEL="" \
IMAGE_COMPRESS_RATIO="" \
BIGEVENTS_PATTERN="" \
NOTIFY_DUE_DAYS_BEFORE_AND_AFTER="" \
NOTIFY_DUE_AT_HOUR_OF_DAY="" \
EMAIL_NOTIFICATION_TIMEOUT=30000 \
MATOMO_ADDRESS="" \
MATOMO_SITE_ID="" \
@@ -40,8 +45,8 @@ ENV BUILD_DEPS="apt-utils bsdtar gnupg gosu wget curl bzip2 build-essential pyth
OAUTH2_ID_MAP="" \
OAUTH2_USERNAME_MAP="" \
OAUTH2_FULLNAME_MAP="" \
OAUTH2_ID_TOKEN_WHITELIST_FIELDS=[] \
OAUTH2_REQUEST_PERMISSIONS='openid profiles email' \
OAUTH2_ID_TOKEN_WHITELIST_FIELDS="" \
OAUTH2_REQUEST_PERMISSIONS='openid profile email' \
OAUTH2_EMAIL_MAP="" \
LDAP_ENABLE=false \
LDAP_PORT=389 \
@@ -113,7 +118,7 @@ RUN \
\
# OS dependencies
apt-get update -y && apt-get install -y --no-install-recommends ${BUILD_DEPS} && \
pip3 install -U pip setuptools wheel && \
#pip3 install -U pip setuptools wheel && \
\
# Meteor installer doesn't work with the default tar binary, so using bsdtar while installing.
# https://github.com/coreos/bugs/issues/1095#issuecomment-350574389
@@ -169,33 +174,39 @@ RUN \
mv node-${NODE_VERSION}-${ARCHITECTURE} /opt/nodejs && \
ln -s /opt/nodejs/bin/node /usr/bin/node && \
ln -s /opt/nodejs/bin/npm /usr/bin/npm && \
mkdir -p /opt/nodejs/lib/node_modules/fibers/.node-gyp /root/.node-gyp/8.16.0 /home/wekan/.config && \
chown wekan --recursive /home/wekan/.config && \
\
#DOES NOT WORK: paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
#paxctl -mC `which node` && \
\
# Install Node dependencies
# Install Node dependencies. Python path for node-gyp.
npm install -g npm@${NPM_VERSION} && \
npm install -g node-gyp && \
npm install -g fibers@${FIBERS_VERSION} && \
#npm config set python python2.7 && \
#npm install -g node-gyp && \
#npm install -g fibers@${FIBERS_VERSION} && \
\
# Change user to wekan and install meteor
cd /home/wekan/ && \
chown wekan:wekan --recursive /home/wekan && \
curl "https://install.meteor.com" -o /home/wekan/install_meteor.sh && \
chown wekan --recursive /home/wekan && \
#curl "https://install.meteor.com" -o /home/wekan/install_meteor.sh && \
#curl "https://install.meteor.com/?release=${METEOR_RELEASE}" -o /home/wekan/install_meteor.sh && \
# OLD: sed -i "s|RELEASE=.*|RELEASE=${METEOR_RELEASE}\"\"|g" ./install_meteor.sh && \
# Install Meteor forcing its progress
sed -i 's/VERBOSITY="--silent"/VERBOSITY="--progress-bar"/' ./install_meteor.sh && \
#sed -i 's/VERBOSITY="--silent"/VERBOSITY="--progress-bar"/' ./install_meteor.sh && \
echo "Starting meteor ${METEOR_RELEASE} installation... \n" && \
chown wekan:wekan /home/wekan/install_meteor.sh && \
gosu wekan:wekan curl https://install.meteor.com/ | /bin/sh && \
mv /root/.meteor /home/wekan/ && \
chown wekan --recursive /home/wekan/.meteor && \
\
# Check if opting for a release candidate instead of major release
if [ "$USE_EDGE" = false ]; then \
gosu wekan:wekan sh /home/wekan/install_meteor.sh; \
else \
gosu wekan:wekan git clone --recursive --depth 1 -b release/METEOR@${METEOR_EDGE} git://github.com/meteor/meteor.git /home/wekan/.meteor; \
fi; \
\
#if [ "$USE_EDGE" = false ]; then \
#gosu wekan:wekan sh /home/wekan/install_meteor.sh; \
# gosu wekan:wekan curl https://install.meteor.com/ | sh; \
#else \
# gosu wekan:wekan git clone --recursive --depth 1 -b release/METEOR@${METEOR_EDGE} https://github.com/meteor/meteor.git /home/wekan/.meteor; \
#fi; \
#\
# Get additional packages
#mkdir -p /home/wekan/app/packages && \
#chown wekan:wekan --recursive /home/wekan && \
@@ -216,25 +227,28 @@ RUN \
gosu wekan:wekan /home/wekan/.meteor/meteor -- help; \
\
# extract the OpenAPI specification
npm install -g api2html@0.3.3 && \
mkdir -p /home/wekan/python && \
chown wekan:wekan --recursive /home/wekan/python && \
cd /home/wekan/python && \
gosu wekan:wekan git clone --depth 1 -b master https://github.com/Kronuz/esprima-python && \
cd /home/wekan/python/esprima-python && \
python3 setup.py install --record files.txt && \
cd /home/wekan/app &&\
gosu wekan:wekan mkdir -p ./public/api && \
gosu wekan:wekan python3 ./openapi/generate_openapi.py --release $(git describe --tags --abbrev=0) > ./public/api/wekan.yml && \
gosu wekan:wekan /opt/nodejs/bin/api2html -c ./public/logo-header.png -o ./public/api/wekan.html ./public/api/wekan.yml; \
#npm install -g api2html@0.3.3 && \
#mkdir -p /home/wekan/python && \
#chown wekan --recursive /home/wekan/python && \
#cd /home/wekan/python && \
#gosu wekan:wekan git clone --depth 1 -b master https://github.com/Kronuz/esprima-python && \
#cd /home/wekan/python/esprima-python && \
#python3 setup.py install --record files.txt && \
#cd /home/wekan/app && \
#mkdir -p /home/wekan/app/public/api && \
#chown wekan --recursive /home/wekan/app && \
#gosu wekan:wekan python3 ./openapi/generate_openapi.py --release $(git describe --tags --abbrev=0) > ./public/api/wekan.yml && \
#gosu wekan:wekan /opt/nodejs/bin/api2html -c ./public/logo-header.png -o ./public/api/wekan.html ./public/api/wekan.yml; \
# Build app
cd /home/wekan/app && \
gosu wekan:wekan /home/wekan/.meteor/meteor add standard-minifier-js && \
gosu wekan:wekan /home/wekan/.meteor/meteor npm install && \
mkdir -p /home/wekan/.npm && \
chown wekan --recursive /home/wekan/.npm /home/wekan/.config /home/wekan/.meteor && \
#gosu wekan:wekan /home/wekan/.meteor/meteor add standard-minifier-js && \
gosu wekan:wekan npm install && \
gosu wekan:wekan /home/wekan/.meteor/meteor build --directory /home/wekan/app_build && \
cp /home/wekan/app/fix-download-unicode/cfs_access-point.txt /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
rm /home/wekan/app_build/bundle/programs/server/npm/node_modules/meteor/rajit_bootstrap3-datepicker/lib/bootstrap-datepicker/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs && \
chown wekan:wekan /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
#rm /home/wekan/app_build/bundle/programs/server/npm/node_modules/meteor/rajit_bootstrap3-datepicker/lib/bootstrap-datepicker/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs && \
chown wekan /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
#Removed binary version of bcrypt because of security vulnerability that is not fixed yet.
#https://github.com/wekan/wekan/commit/4b2010213907c61b0e0482ab55abb06f6a668eac
#https://github.com/wekan/wekan/commit/7eeabf14be3c63fae2226e561ef8a0c1390c8d3c
@@ -256,10 +270,10 @@ RUN \
rm -R /var/lib/apt/lists/* && \
rm -R /home/wekan/.meteor && \
rm -R /home/wekan/app && \
rm -R /home/wekan/app_build && \
cat /home/wekan/python/esprima-python/files.txt | xargs rm -R && \
rm -R /home/wekan/python && \
rm /home/wekan/install_meteor.sh
rm -R /home/wekan/app_build
#cat /home/wekan/python/esprima-python/files.txt | xargs rm -R && \
#rm -R /home/wekan/python
#rm /home/wekan/install_meteor.sh
ENV PORT=8080
EXPOSE $PORT
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v2.78.0"
appVersion: "v3.00.0"
files:
userUploads:
- README.md
@@ -201,6 +201,19 @@ template(name="cardActivities")
.activity-checklist(href="{{ card.absoluteUrl }}")
+viewer
= checklistItem.title
if(currentData.timeKey)
| {{{_ activityType }}}
= ' '
i(title=currentData.timeValue).activity-meta {{ moment currentData.timeValue 'LLL' }}
if (currentData.timeOldValue)
= ' '
| {{{_ "previous_as" }}}
= ' '
i(title=currentData.timeOldValue).activity-meta {{ moment currentData.timeOldValue 'LLL' }}
= ' @'
else if(currentData.timeValue)
| {{{_ activityType currentData.timeValue}}}
if($eq activityType 'addComment')
+inlinedForm(classNames='js-edit-comment')
+90 -58
View File
@@ -13,7 +13,7 @@ BlazeComponent.extendComponent({
let thisId, searchId;
if (mode === 'linkedcard' || mode === 'linkedboard') {
thisId = Session.get('currentCard');
searchId = Cards.findOne({_id: thisId}).linkedId;
searchId = Cards.findOne({ _id: thisId }).linkedId;
mode = mode.replace('linked', '');
} else {
thisId = Session.get(`current${capitalizedMode}`);
@@ -22,8 +22,7 @@ BlazeComponent.extendComponent({
const limit = this.page.get() * activitiesPerPage;
const user = Meteor.user();
const hideSystem = user ? user.hasHiddenSystemMessages() : false;
if (searchId === null)
return;
if (searchId === null) return;
this.subscribe('activities', mode, searchId, limit, hideSystem, () => {
this.loadNextPageLocked = false;
@@ -50,9 +49,9 @@ BlazeComponent.extendComponent({
}
},
checkItem(){
checkItem() {
const checkItemId = this.currentData().checklistItemId;
const checkItem = ChecklistItems.findOne({_id:checkItemId});
const checkItem = ChecklistItems.findOne({ _id: checkItemId });
return checkItem.title;
},
@@ -66,42 +65,58 @@ BlazeComponent.extendComponent({
cardLink() {
const card = this.currentData().card();
return card && Blaze.toHTML(HTML.A({
href: card.absoluteUrl(),
'class': 'action-card',
}, card.title));
return (
card &&
Blaze.toHTML(
HTML.A(
{
href: card.absoluteUrl(),
class: 'action-card',
},
card.title,
),
)
);
},
lastLabel(){
lastLabel() {
const lastLabelId = this.currentData().labelId;
if (!lastLabelId)
return null;
const lastLabel = Boards.findOne(Session.get('currentBoard')).getLabelById(lastLabelId);
if(lastLabel.name === undefined || lastLabel.name === ''){
if (!lastLabelId) return null;
const lastLabel = Boards.findOne(Session.get('currentBoard')).getLabelById(
lastLabelId,
);
if (lastLabel.name === undefined || lastLabel.name === '') {
return lastLabel.color;
}else{
} else {
return lastLabel.name;
}
},
lastCustomField(){
const lastCustomField = CustomFields.findOne(this.currentData().customFieldId);
if (!lastCustomField)
return null;
lastCustomField() {
const lastCustomField = CustomFields.findOne(
this.currentData().customFieldId,
);
if (!lastCustomField) return null;
return lastCustomField.name;
},
lastCustomFieldValue(){
const lastCustomField = CustomFields.findOne(this.currentData().customFieldId);
if (!lastCustomField)
return null;
lastCustomFieldValue() {
const lastCustomField = CustomFields.findOne(
this.currentData().customFieldId,
);
if (!lastCustomField) return null;
const value = this.currentData().value;
if (lastCustomField.settings.dropdownItems && lastCustomField.settings.dropdownItems.length > 0) {
const dropDownValue = _.find(lastCustomField.settings.dropdownItems, (item) => {
return item._id === value;
});
if (dropDownValue)
return dropDownValue.name;
if (
lastCustomField.settings.dropdownItems &&
lastCustomField.settings.dropdownItems.length > 0
) {
const dropDownValue = _.find(
lastCustomField.settings.dropdownItems,
item => {
return item._id === value;
},
);
if (dropDownValue) return dropDownValue.name;
}
return value;
},
@@ -112,11 +127,16 @@ BlazeComponent.extendComponent({
sourceLink() {
const source = this.currentData().source;
if(source) {
if(source.url) {
return Blaze.toHTML(HTML.A({
href: source.url,
}, source.system));
if (source) {
if (source.url) {
return Blaze.toHTML(
HTML.A(
{
href: source.url,
},
source.system,
),
);
} else {
return source.system;
}
@@ -133,38 +153,50 @@ BlazeComponent.extendComponent({
attachmentLink() {
const attachment = this.currentData().attachment();
// trying to display url before file is stored generates js errors
return attachment && attachment.url({ download: true }) && Blaze.toHTML(HTML.A({
href: attachment.url({ download: true }),
target: '_blank',
}, attachment.name()));
return (
attachment &&
attachment.url({ download: true }) &&
Blaze.toHTML(
HTML.A(
{
href: attachment.url({ download: true }),
target: '_blank',
},
attachment.name(),
),
)
);
},
customField() {
const customField = this.currentData().customField();
if (!customField)
return null;
if (!customField) return null;
return customField.name;
},
events() {
return [{
// XXX We should use Popup.afterConfirmation here
'click .js-delete-comment'() {
const commentId = this.currentData().commentId;
CardComments.remove(commentId);
return [
{
// XXX We should use Popup.afterConfirmation here
'click .js-delete-comment'() {
const commentId = this.currentData().commentId;
CardComments.remove(commentId);
},
'submit .js-edit-comment'(evt) {
evt.preventDefault();
const commentText = this.currentComponent()
.getValue()
.trim();
const commentId = Template.parentData().commentId;
if (commentText) {
CardComments.update(commentId, {
$set: {
text: commentText,
},
});
}
},
},
'submit .js-edit-comment'(evt) {
evt.preventDefault();
const commentText = this.currentComponent().getValue().trim();
const commentId = Template.parentData().commentId;
if (commentText) {
CardComments.update(commentId, {
$set: {
text: commentText,
},
});
}
},
}];
];
},
}).register('activities');
+41 -35
View File
@@ -14,39 +14,41 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-new-comment:not(.focus)'() {
commentFormIsOpen.set(true);
return [
{
'click .js-new-comment:not(.focus)'() {
commentFormIsOpen.set(true);
},
'submit .js-new-comment-form'(evt) {
const input = this.getInput();
const text = input.val().trim();
const card = this.currentData();
let boardId = card.boardId;
let cardId = card._id;
if (card.isLinkedCard()) {
boardId = Cards.findOne(card.linkedId).boardId;
cardId = card.linkedId;
}
if (text) {
CardComments.insert({
text,
boardId,
cardId,
});
resetCommentInput(input);
Tracker.flush();
autosize.update(input);
}
evt.preventDefault();
},
// Pressing Ctrl+Enter should submit the form
'keydown form textarea'(evt) {
if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) {
this.find('button[type=submit]').click();
}
},
},
'submit .js-new-comment-form'(evt) {
const input = this.getInput();
const text = input.val().trim();
const card = this.currentData();
let boardId = card.boardId;
let cardId = card._id;
if (card.isLinkedCard()) {
boardId = Cards.findOne(card.linkedId).boardId;
cardId = card.linkedId;
}
if (text) {
CardComments.insert({
text,
boardId,
cardId,
});
resetCommentInput(input);
Tracker.flush();
autosize.update(input);
}
evt.preventDefault();
},
// Pressing Ctrl+Enter should submit the form
'keydown form textarea'(evt) {
if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) {
this.find('button[type=submit]').click();
}
},
}];
];
},
}).register('commentForm');
@@ -69,7 +71,8 @@ Tracker.autorun(() => {
});
});
EscapeActions.register('inlinedForm',
EscapeActions.register(
'inlinedForm',
() => {
const draftKey = {
fieldName: 'cardComment',
@@ -84,7 +87,10 @@ EscapeActions.register('inlinedForm',
}
resetCommentInput(commentInput);
},
() => { return commentFormIsOpen.get(); }, {
() => {
return commentFormIsOpen.get();
},
{
noClickEscapeOn: '.js-new-comment',
}
},
);
+36 -27
View File
@@ -4,36 +4,45 @@ BlazeComponent.extendComponent({
},
archivedBoards() {
return Boards.find({ archived: true }, {
sort: ['title'],
});
return Boards.find(
{ archived: true },
{
sort: ['title'],
},
);
},
events() {
return [{
'click .js-restore-board'() {
// TODO : Make isSandstorm variable global
const isSandstorm = Meteor.settings && Meteor.settings.public &&
Meteor.settings.public.sandstorm;
if (isSandstorm && Session.get('currentBoard')) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
currentBoard.archive();
}
const board = this.currentData();
board.restore();
Utils.goBoardId(board._id);
return [
{
'click .js-restore-board'() {
// TODO : Make isSandstorm variable global
const isSandstorm =
Meteor.settings &&
Meteor.settings.public &&
Meteor.settings.public.sandstorm;
if (isSandstorm && Session.get('currentBoard')) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
currentBoard.archive();
}
const board = this.currentData();
board.restore();
Utils.goBoardId(board._id);
},
'click .js-delete-board': Popup.afterConfirm('boardDelete', function() {
Popup.close();
const isSandstorm =
Meteor.settings &&
Meteor.settings.public &&
Meteor.settings.public.sandstorm;
if (isSandstorm && Session.get('currentBoard')) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
Boards.remove(currentBoard._id);
}
Boards.remove(this._id);
FlowRouter.go('home');
}),
},
'click .js-delete-board': Popup.afterConfirm('boardDelete', function() {
Popup.close();
const isSandstorm = Meteor.settings && Meteor.settings.public &&
Meteor.settings.public.sandstorm;
if (isSandstorm && Session.get('currentBoard')) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
Boards.remove(currentBoard._id);
}
Boards.remove(this._id);
FlowRouter.go('home');
}),
}];
];
},
}).register('archivedBoards');
+3 -2
View File
@@ -6,8 +6,9 @@ template(name="board")
else
+boardBody
else
//- XXX We need a better error message in case the board has been archived
+message(label="board-not-found")
//-- XXX We need a better error message in case the board has been archived
//-- +message(label="board-not-found")
| {{goHome}}
else
+spinner
+81 -54
View File
@@ -12,8 +12,7 @@ BlazeComponent.extendComponent({
// unfortunatly, Blaze doesn't have this notion.
this.autorun(() => {
const currentBoardId = Session.get('currentBoard');
if (!currentBoardId)
return;
if (!currentBoardId) return;
const handle = subManager.subscribe('board', currentBoardId, false);
Tracker.nonreactive(() => {
Tracker.autorun(() => {
@@ -27,6 +26,9 @@ BlazeComponent.extendComponent({
return Utils.isMiniScreen() && Session.get('currentCard');
},
goHome() {
FlowRouter.go('home');
},
}).register('board');
BlazeComponent.extendComponent({
@@ -43,7 +45,7 @@ BlazeComponent.extendComponent({
if (nullSortSwimlanes.count() > 0) {
const swimlanes = currentBoardData.swimlanes();
let count = 0;
swimlanes.forEach((s) => {
swimlanes.forEach(s => {
Swimlanes.update(s._id, {
$set: {
sort: count,
@@ -58,7 +60,7 @@ BlazeComponent.extendComponent({
if (nullSortLists.count() > 0) {
const lists = currentBoardData.lists();
let count = 0;
lists.forEach((l) => {
lists.forEach(l => {
Lists.update(l._id, {
$set: {
sort: count,
@@ -106,12 +108,15 @@ BlazeComponent.extendComponent({
// resize all swimlanes + headers to be a total of 150 px per row
// this could be achieved by setIsDragging(true) but we want immediate
// result
ui.item.siblings('.js-swimlane').css('height', `${swimlaneWhileSortingHeight - 26}px`);
ui.item
.siblings('.js-swimlane')
.css('height', `${swimlaneWhileSortingHeight - 26}px`);
// set the new scroll height after the resize and insertion of
// the placeholder. We want the element under the cursor to stay
// at the same place on the screen
ui.item.parent().get(0).scrollTop = ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY;
ui.item.parent().get(0).scrollTop =
ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY;
},
beforeStop(evt, ui) {
const parentOffset = ui.item.parent().offset();
@@ -120,7 +125,8 @@ BlazeComponent.extendComponent({
// compute the new scroll height after the resize and removal of
// the placeholder
const scrollTop = ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY;
const scrollTop =
ui.placeholder.get(0).offsetTop + parentOffset.top - evt.pageY;
// then reset the original view of the swimlane
siblings.removeClass('moving-swimlane');
@@ -150,11 +156,14 @@ BlazeComponent.extendComponent({
sort(evt, ui) {
// get the mouse position in the sortable
const parentOffset = ui.item.parent().offset();
const cursorY = evt.pageY - parentOffset.top + ui.item.parent().scrollTop();
const cursorY =
evt.pageY - parentOffset.top + ui.item.parent().scrollTop();
// compute the intended index of the placeholder (we need to skip the
// slots between the headers and the list of cards)
const newplaceholderIndex = Math.floor(cursorY / swimlaneWhileSortingHeight);
const newplaceholderIndex = Math.floor(
cursorY / swimlaneWhileSortingHeight,
);
let destPlaceholderIndex = (newplaceholderIndex + 1) * 2;
// if we are scrolling far away from the bottom of the list
@@ -165,9 +174,17 @@ BlazeComponent.extendComponent({
// update the placeholder position in the DOM tree
if (destPlaceholderIndex !== ui.placeholder.index()) {
if (destPlaceholderIndex < boardComponent.origPlaceholderIndex) {
ui.placeholder.insertBefore(ui.placeholder.siblings().slice(destPlaceholderIndex - 2, destPlaceholderIndex - 1));
ui.placeholder.insertBefore(
ui.placeholder
.siblings()
.slice(destPlaceholderIndex - 2, destPlaceholderIndex - 1),
);
} else {
ui.placeholder.insertAfter(ui.placeholder.siblings().slice(destPlaceholderIndex - 1, destPlaceholderIndex));
ui.placeholder.insertAfter(
ui.placeholder
.siblings()
.slice(destPlaceholderIndex - 1, destPlaceholderIndex),
);
}
}
},
@@ -177,7 +194,11 @@ BlazeComponent.extendComponent({
enableClickOnTouch('.js-swimlane:not(.placeholder)');
function userIsMember() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
}
// If there is no data in the board (ie, no lists) we autofocus the list
@@ -191,45 +212,44 @@ BlazeComponent.extendComponent({
isViewSwimlanes() {
const currentUser = Meteor.user();
if (!currentUser) return false;
return ((currentUser.profile || {}).boardView === 'board-view-swimlanes');
return (currentUser.profile || {}).boardView === 'board-view-swimlanes';
},
isViewLists() {
const currentUser = Meteor.user();
if (!currentUser) return true;
return ((currentUser.profile || {}).boardView === 'board-view-lists');
return (currentUser.profile || {}).boardView === 'board-view-lists';
},
isViewCalendar() {
const currentUser = Meteor.user();
if (!currentUser) return false;
return ((currentUser.profile || {}).boardView === 'board-view-cal');
return (currentUser.profile || {}).boardView === 'board-view-cal';
},
openNewListForm() {
if (this.isViewSwimlanes()) {
this.childComponents('swimlane')[0]
.childComponents('addListAndSwimlaneForm')[0].open();
.childComponents('addListAndSwimlaneForm')[0]
.open();
} else if (this.isViewLists()) {
this.childComponents('listsGroup')[0]
.childComponents('addListForm')[0].open();
.childComponents('addListForm')[0]
.open();
}
},
events() {
return [{
// XXX The board-overlay div should probably be moved to the parent
// component.
'mouseenter .board-overlay'() {
if (this.mouseHasEnterCardDetails) {
this.showOverlay.set(false);
}
return [
{
// XXX The board-overlay div should probably be moved to the parent
// component.
mouseup() {
if (this._isDragging) {
this._isDragging = false;
}
},
},
'mouseup'() {
if (this._isDragging) {
this._isDragging = false;
}
},
}];
];
},
// XXX Flow components allow us to avoid creating these two setter methods by
@@ -241,23 +261,24 @@ BlazeComponent.extendComponent({
scrollLeft(position = 0) {
const swimlanes = this.$('.js-swimlanes');
swimlanes && swimlanes.animate({
scrollLeft: position,
});
swimlanes &&
swimlanes.animate({
scrollLeft: position,
});
},
scrollTop(position = 0) {
const swimlanes = this.$('.js-swimlanes');
swimlanes && swimlanes.animate({
scrollTop: position,
});
swimlanes &&
swimlanes.animate({
scrollTop: position,
});
},
}).register('boardBody');
BlazeComponent.extendComponent({
onRendered() {
this.autorun(function(){
this.autorun(function() {
$('#calendar-view').fullCalendar('refetchEvents');
});
},
@@ -269,7 +290,8 @@ BlazeComponent.extendComponent({
timezone: 'local',
header: {
left: 'title today prev,next',
center: 'agendaDay,listDay,timelineDay agendaWeek,listWeek,timelineWeek month,timelineMonth timelineYear',
center:
'agendaDay,listDay,timelineDay agendaWeek,listWeek,timelineWeek month,timelineMonth timelineYear',
right: '',
},
// height: 'parent', nope, doesn't work as the parent might be small
@@ -279,7 +301,7 @@ BlazeComponent.extendComponent({
nowIndicator: true,
businessHours: {
// days of week. an array of zero-based day of week integers (0=Sunday)
dow: [ 1, 2, 3, 4, 5 ], // Monday - Friday
dow: [1, 2, 3, 4, 5], // Monday - Friday
start: '8:00',
end: '18:00',
},
@@ -287,20 +309,25 @@ BlazeComponent.extendComponent({
events(start, end, timezone, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const events = [];
currentBoard.cardsInInterval(start.toDate(), end.toDate()).forEach(function(card){
events.push({
id: card._id,
title: card.title,
start: card.startAt,
end: card.endAt,
allDay: Math.abs(card.endAt.getTime() - card.startAt.getTime()) / 1000 === 24*3600,
url: FlowRouter.url('card', {
boardId: currentBoard._id,
slug: currentBoard.slug,
cardId: card._id,
}),
currentBoard
.cardsInInterval(start.toDate(), end.toDate())
.forEach(function(card) {
events.push({
id: card._id,
title: card.title,
start: card.startAt,
end: card.endAt,
allDay:
Math.abs(card.endAt.getTime() - card.startAt.getTime()) /
1000 ===
24 * 3600,
url: FlowRouter.url('card', {
boardId: currentBoard._id,
slug: currentBoard.slug,
cardId: card._id,
}),
});
});
});
callback(events);
},
eventResize(event, delta, revertFunc) {
@@ -335,6 +362,6 @@ BlazeComponent.extendComponent({
isViewCalendar() {
const currentUser = Meteor.user();
if (!currentUser) return false;
return ((currentUser.profile || {}).boardView === 'board-view-cal');
return (currentUser.profile || {}).boardView === 'board-view-cal';
},
}).register('calendarView');
+205
View File
@@ -87,3 +87,208 @@ setBoardColor(color)
.board-color-pumpkin
setBoardColor(#E67E22)
.board-color-moderatepink
setBoardColor(#CD5A91)
.board-color-strongcyan
setBoardColor(#00AECC)
.board-color-limegreen
setBoardColor(#4BBF6B)
.board-color-dark
setBoardColor(#2C3E51)
/* Not hidden in dark mode.
card fields: received, start, due, end, members, requested, assigned
.card-details-item.card-details-item-received,
.card-details-item.card-details-item-start,
.card-details-item.card-details-item-due,
.card-details-item.card-details-item-end,
.card-details-item.card-details-item-members,
.card-details-item.card-details-item-name { display:none; }
.card-details-items:empty { display:none; }
*/
// DARK MODE, when dark background mode selected.
// Modified version from https://github.com/wekan/wekan/wiki/Custom-CSS-themes#dark-theme
// In progress, please send pull requests to fix remaining visibility issues.
.ui-sortable,
.swimlane,
.swimlane >.swimlane-header-wrap,
.swimlane >.list.js-list,
.swimlane >.list-composer.js-list-composer,
.list-body,
.list,
.list-composer,
.sidebar-content,
.card-details
background-color:#2C3E50
.card-details h3,
.card-details-items,
.card-checklist-items .ui-sortable,
.card-subtasks-items,
.activities,
.material-toggle-switch
color:#bbbbbb
.list-header
background-color: #888888
.board-widget,
.board-widget-labels,
.board-widget-members
color: #aaaaaa
/* popup menu titles (boards, swimlanes, lists, cards, labels) */
.pop-over >.header
display:none;
/* HIDE UNTIL HOVER -------------------------------------------------- */
/* header "+" button */
#header-quick-access .fa-plus
display:none
#header-quick-access:hover .fa-plus
display:inherit
/* "add card" links (use visibility rather than display so items don't jump) */
.open-minicard-composer
visibility:hidden
.list.js-list:hover .open-minicard-composer
visibility:visible
.list-header-menu
visibility:hidden
.list.js-list:hover .list-header-menu
visibility:visible
/* "add list/swimlane" links (use visibility rather than display so items don't jump) */
.list.js-list-composer >.list-header
visibility:hidden
.list.js-list-composer:hover >.list-header
visibility:visible
/* headers */
#header-quick-access, #header
background-color:rgba(0,0,0,.75) !important
#header .board-header-btn:hover
background-color:rgba(255,255,255,0.3) !important
/* foregrounds: swimlanes, lists */
.list >.list-header, .swimlane-header
color:rgba(255,255,255,.7)
/* minicards */
.minicard
background-color:rgba(255,255,255,.4)
.minicard-wrapper.is-selected .minicard,
.minicard:hover,
.minicard-composer.js-composer,
.open-minicard-composer:hover
background-color:rgba(255,255,255,.8) !important
color:#000
.minicard, .minicard .badge
color:#fff
.minicard:hover .badge, .minicard-wrapper.is-selected .badge
color:#000
/* cards */
.card-details .card-details-header
background-color:#ccc
/* sidebar */
.sidebar-tongue, .sidebar-shadow
background-color:#666 !important
.sidebar-content h3, .sidebar-content h2, .sidebar-content
color:rgba(255,255,255,.7) !important
.board-color-relax
setBoardColor(#27AE61)
// RELAX MODE: light green background, with green background color,
// to help this theme users to relax.
// Colors and emphasis are specific to this Wekan theme contributor's company.
.ui-sortable
background-color:#a7e366
.list-header
background-color:#a7e366
border-bottom: 6px solid #a7e366
.list-body
background-color:#a7e366
.list
border-left: 1px dotted #000000
// Card details text emphasis: black border and white background
// to make it details text field easier to find for RELAX MODE users,
// and focus attention.
.card-details .card-details-items
& ~ .js-open-inlined-form
.viewer
background-color #ffffff !important
padding 15px !important
border 1px solid #000000 !important
// When card has comment, emphasis on minicard:
// bigger red comment icon and number of comments,
// to make it easier notice card comments and focus attention.
.minicard .badges .badge
.badge-icon,
.badge-text
&.badge-comment
display: block
border-radius: 4px
padding: 1px 3px
margin-bottom: 0.3rem
color: #ff0000
background-color: #ffffff
font-weight: bold
font-size: 11pt
.board-color-corteza
setBoardColor(#568BA2)
/*
Wekan for Corteza https://cortezaproject.org
Theme to match Corteza colors from:
https://github.com/cortezaproject/corteza-webapp-messaging/blob/master/src/assets/sass/variables.scss
// Paths
$fonts_dir : './assets/fonts/';
$icomoon-font-path: $fonts_dir + 'icomoon' !default;
$icomoon-font-family: "icomoon" !default;
// Typography
$regular: 'nunito_sansregular';
$bold: 'nunito_sansbold';
$semibold: 'nunito_sanssemibold';
// Color system
$white: #fff !default;
$black: #000 !default;
$primary: #568ba2;
$secondary: #90A3B1;
$success: #719430;
$warning: #F5D380;
$danger: #E85568;
$light: #F3F3F5;
$dark: #1e2224;
$currentmymessagebgcolor : #a7d0e3;
*/
//.header-quick-access
// backgroud-color: #568ba2
+119 -87
View File
@@ -45,15 +45,21 @@ Template.boardMenuPopup.helpers({
});
Template.boardChangeTitlePopup.events({
submit(evt, tpl) {
const newTitle = tpl.$('.js-board-name').val().trim();
const newDesc = tpl.$('.js-board-desc').val().trim();
submit(event, templateInstance) {
const newTitle = templateInstance
.$('.js-board-name')
.val()
.trim();
const newDesc = templateInstance
.$('.js-board-desc')
.val()
.trim();
if (newTitle) {
this.rename(newTitle);
this.setDescription(newDesc);
Popup.close();
}
evt.preventDefault();
event.preventDefault();
},
});
@@ -76,67 +82,79 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-edit-board-title': Popup.open('boardChangeTitle'),
'click .js-star-board'() {
Meteor.user().toggleBoardStar(Session.get('currentBoard'));
return [
{
'click .js-edit-board-title': Popup.open('boardChangeTitle'),
'click .js-star-board'() {
Meteor.user().toggleBoardStar(Session.get('currentBoard'));
},
'click .js-open-board-menu': Popup.open('boardMenu'),
'click .js-change-visibility': Popup.open('boardChangeVisibility'),
'click .js-watch-board': Popup.open('boardChangeWatch'),
'click .js-open-archived-board'() {
Modal.open('archivedBoards');
},
'click .js-toggle-board-view'() {
const currentUser = Meteor.user();
if (
(currentUser.profile || {}).boardView === 'board-view-swimlanes'
) {
currentUser.setBoardView('board-view-cal');
} else if (
(currentUser.profile || {}).boardView === 'board-view-lists'
) {
currentUser.setBoardView('board-view-swimlanes');
} else if (
(currentUser.profile || {}).boardView === 'board-view-cal'
) {
currentUser.setBoardView('board-view-lists');
} else {
currentUser.setBoardView('board-view-swimlanes');
}
},
'click .js-toggle-sidebar'() {
Sidebar.toggle();
},
'click .js-open-filter-view'() {
Sidebar.setView('filter');
},
'click .js-filter-reset'(event) {
event.stopPropagation();
Sidebar.setView();
Filter.reset();
},
'click .js-open-search-view'() {
Sidebar.setView('search');
},
'click .js-open-rules-view'() {
Modal.openWide('rulesMain');
},
'click .js-multiselection-activate'() {
const currentCard = Session.get('currentCard');
MultiSelection.activate();
if (currentCard) {
MultiSelection.add(currentCard);
}
},
'click .js-multiselection-reset'(event) {
event.stopPropagation();
MultiSelection.disable();
},
'click .js-log-in'() {
FlowRouter.go('atSignIn');
},
},
'click .js-open-board-menu': Popup.open('boardMenu'),
'click .js-change-visibility': Popup.open('boardChangeVisibility'),
'click .js-watch-board': Popup.open('boardChangeWatch'),
'click .js-open-archived-board'() {
Modal.open('archivedBoards');
},
'click .js-toggle-board-view'() {
const currentUser = Meteor.user();
if ((currentUser.profile || {}).boardView === 'board-view-swimlanes') {
currentUser.setBoardView('board-view-cal');
} else if ((currentUser.profile || {}).boardView === 'board-view-lists') {
currentUser.setBoardView('board-view-swimlanes');
} else if ((currentUser.profile || {}).boardView === 'board-view-cal') {
currentUser.setBoardView('board-view-lists');
} else {
currentUser.setBoardView('board-view-swimlanes');
}
},
'click .js-toggle-sidebar'() {
Sidebar.toggle();
},
'click .js-open-filter-view'() {
Sidebar.setView('filter');
},
'click .js-filter-reset'(evt) {
evt.stopPropagation();
Sidebar.setView();
Filter.reset();
},
'click .js-open-search-view'() {
Sidebar.setView('search');
},
'click .js-open-rules-view'() {
Modal.openWide('rulesMain');
},
'click .js-multiselection-activate'() {
const currentCard = Session.get('currentCard');
MultiSelection.activate();
if (currentCard) {
MultiSelection.add(currentCard);
}
},
'click .js-multiselection-reset'(evt) {
evt.stopPropagation();
MultiSelection.disable();
},
'click .js-log-in'() {
FlowRouter.go('atSignIn');
},
}];
];
},
}).register('boardHeaderBar');
Template.boardHeaderBar.helpers({
canModifyBoard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
});
@@ -164,15 +182,17 @@ const CreateBoard = BlazeComponent.extendComponent({
this.visibilityMenuIsOpen.set(!this.visibilityMenuIsOpen.get());
},
onSubmit(evt) {
evt.preventDefault();
onSubmit(event) {
event.preventDefault();
const title = this.find('.js-new-board-title').value;
const visibility = this.visibility.get();
this.boardId.set(Boards.insert({
title,
permission: visibility,
}));
this.boardId.set(
Boards.insert({
title,
permission: visibility,
}),
);
Swimlanes.insert({
title: 'Default',
@@ -183,26 +203,28 @@ const CreateBoard = BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-select-visibility'() {
this.setVisibility(this.currentData());
return [
{
'click .js-select-visibility'() {
this.setVisibility(this.currentData());
},
'click .js-change-visibility': this.toggleVisibilityMenu,
'click .js-import': Popup.open('boardImportBoard'),
submit: this.onSubmit,
'click .js-import-board': Popup.open('chooseBoardSource'),
'click .js-board-template': Popup.open('searchElement'),
},
'click .js-change-visibility': this.toggleVisibilityMenu,
'click .js-import': Popup.open('boardImportBoard'),
submit: this.onSubmit,
'click .js-import-board': Popup.open('chooseBoardSource'),
'click .js-board-template': Popup.open('searchElement'),
}];
];
},
}).register('createBoardPopup');
(class HeaderBarCreateBoard extends CreateBoard {
onSubmit(evt) {
super.onSubmit(evt);
onSubmit(event) {
super.onSubmit(event);
// Immediately star boards crated with the headerbar popup.
Meteor.user().toggleBoardStar(this.boardId.get());
}
}).register('headerBarCreateBoardPopup');
}.register('headerBarCreateBoardPopup'));
BlazeComponent.extendComponent({
visibilityCheck() {
@@ -218,9 +240,11 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-select-visibility': this.selectBoardVisibility,
}];
return [
{
'click .js-select-visibility': this.selectBoardVisibility,
},
];
},
}).register('boardChangeVisibilityPopup');
@@ -235,13 +259,21 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-select-watch'() {
const level = this.currentData();
Meteor.call('watch', 'board', Session.get('currentBoard'), level, (err, ret) => {
if (!err && ret) Popup.close();
});
return [
{
'click .js-select-watch'() {
const level = this.currentData();
Meteor.call(
'watch',
'board',
Session.get('currentBoard'),
level,
(err, ret) => {
if (!err && ret) Popup.close();
},
);
},
},
}];
];
},
}).register('boardChangeWatchPopup');
+50 -44
View File
@@ -21,11 +21,14 @@ BlazeComponent.extendComponent({
},
boards() {
return Boards.find({
archived: false,
'members.userId': Meteor.userId(),
type: 'board',
}, { sort: ['title'] });
return Boards.find(
{
archived: false,
'members.userId': Meteor.userId(),
type: 'board',
},
{ sort: ['title'] },
);
},
isStarred() {
const user = Meteor.user();
@@ -48,46 +51,49 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-add-board': Popup.open('createBoard'),
'click .js-star-board'(evt) {
const boardId = this.currentData()._id;
Meteor.user().toggleBoardStar(boardId);
evt.preventDefault();
},
'click .js-clone-board'(evt) {
Meteor.call('cloneBoard',
this.currentData()._id,
Session.get('fromBoard'),
(err, res) => {
if (err) {
this.setError(err.error);
} else {
Session.set('fromBoard', null);
Utils.goBoardId(res);
return [
{
'click .js-add-board': Popup.open('createBoard'),
'click .js-star-board'(evt) {
const boardId = this.currentData()._id;
Meteor.user().toggleBoardStar(boardId);
evt.preventDefault();
},
'click .js-clone-board'(evt) {
Meteor.call(
'cloneBoard',
this.currentData()._id,
Session.get('fromBoard'),
(err, res) => {
if (err) {
this.setError(err.error);
} else {
Session.set('fromBoard', null);
Utils.goBoardId(res);
}
},
);
evt.preventDefault();
},
'click .js-archive-board'(evt) {
const boardId = this.currentData()._id;
Meteor.call('archiveBoard', boardId);
evt.preventDefault();
},
'click .js-accept-invite'() {
const boardId = this.currentData()._id;
Meteor.call('acceptInvite', boardId);
},
'click .js-decline-invite'() {
const boardId = this.currentData()._id;
Meteor.call('quitBoard', boardId, (err, ret) => {
if (!err && ret) {
Meteor.call('acceptInvite', boardId);
FlowRouter.go('home');
}
}
);
evt.preventDefault();
});
},
},
'click .js-archive-board'(evt) {
const boardId = this.currentData()._id;
Meteor.call('archiveBoard', boardId);
evt.preventDefault();
},
'click .js-accept-invite'() {
const boardId = this.currentData()._id;
Meteor.user().removeInvite(boardId);
},
'click .js-decline-invite'() {
const boardId = this.currentData()._id;
Meteor.call('quitBoard', boardId, (err, ret) => {
if (!err && ret) {
Meteor.user().removeInvite(boardId);
FlowRouter.go('home');
}
});
},
}];
];
},
}).register('boardList');
+4 -2
View File
@@ -161,6 +161,7 @@ $spaceBetweenTiles = 16px
padding-right: 6px
.background-box
color: white
border-radius: 3px
background-size: cover
display: block
@@ -182,10 +183,11 @@ $spaceBetweenTiles = 16px
overflow: scroll
li
width: 33.3%
width: 50%
.board-list-item
overflow: hidden
height: 8rem
.board-list-item-sub-name
position: relative
@@ -194,4 +196,4 @@ $spaceBetweenTiles = 16px
@media screen and (max-width: 360px)
li
width: 50%
width: 100%
+14 -12
View File
@@ -37,17 +37,19 @@ template(name="attachmentsGalery")
i.fa.fa-download
| {{_ 'download'}}
if currentUser.isBoardMember
if isImage
a(class="{{#if $eq ../coverId _id}}js-remove-cover{{else}}js-add-cover{{/if}}")
i.fa.fa-thumb-tack
if($eq ../coverId _id)
| {{_ 'remove-cover'}}
else
| {{_ 'add-cover'}}
a.js-confirm-delete
i.fa.fa-close
| {{_ 'delete'}}
unless currentUser.isCommentOnly
if isImage
a(class="{{#if $eq ../coverId _id}}js-remove-cover{{else}}js-add-cover{{/if}}")
i.fa.fa-thumb-tack
if($eq ../coverId _id)
| {{_ 'remove-cover'}}
else
| {{_ 'add-cover'}}
a.js-confirm-delete
i.fa.fa-close
| {{_ 'delete'}}
if currentUser.isBoardMember
li.attachment-item.add-attachment
a.js-add-attachment {{_ 'add-attachment' }}
unless currentUser.isCommentOnly
li.attachment-item.add-attachment
a.js-add-attachment {{_ 'add-attachment' }}
+131 -29
View File
@@ -1,10 +1,11 @@
Template.attachmentsGalery.events({
'click .js-add-attachment': Popup.open('cardAttachments'),
'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete',
'click .js-confirm-delete': Popup.afterConfirm(
'attachmentDelete',
function() {
Attachments.remove(this._id);
Popup.close();
}
},
),
// If we let this event bubble, FlowRouter will handle it and empty the page
// content, see #101.
@@ -17,8 +18,8 @@ Template.attachmentsGalery.events({
'click .js-remove-cover'() {
Cards.findOne(this.cardId).unsetCover();
},
'click .js-preview-image'(evt) {
Popup.open('previewAttachedImage').call(this, evt);
'click .js-preview-image'(event) {
Popup.open('previewAttachedImage').call(this, event);
// when multiple thumbnails, if click one then another very fast,
// we might get a wrong width from previous img.
// when popup reused, onRendered() won't be called, so we cannot get there.
@@ -31,41 +32,40 @@ Template.attachmentsGalery.events({
// if the image is too large, we resize & center the popup.
if (w > 300) {
$('div.pop-over').css({
width: (w + 20),
width: w + 20,
position: 'absolute',
left: (window.innerWidth - w)/2,
top: (window.innerHeight - h)/2,
left: (window.innerWidth - w) / 2,
top: (window.innerHeight - h) / 2,
});
}
};
const url = $(evt.currentTarget).attr('src');
if (img.src === url && img.complete)
rePosPopup();
else
img.onload = rePosPopup;
const url = $(event.currentTarget).attr('src');
if (img.src === url && img.complete) rePosPopup();
else img.onload = rePosPopup;
},
});
Template.previewAttachedImagePopup.events({
'click .js-large-image-clicked'(){
'click .js-large-image-clicked'() {
Popup.close();
},
});
Template.cardAttachmentsPopup.events({
'change .js-attach-file'(evt) {
'change .js-attach-file'(event) {
const card = this;
FS.Utility.eachFile(evt, (f) => {
const processFile = f => {
const file = new FS.File(f);
if (card.isLinkedCard()) {
file.boardId = Cards.findOne(card.linkedId).boardId;
file.cardId = card.linkedId;
} else {
file.boardId = card.boardId;
file.swimlaneId = card.swimlaneId;
file.listId = card.listId;
file.cardId = card._id;
}
file.userId = Meteor.userId();
const attachment = Attachments.insert(file);
if (attachment && attachment._id && attachment.isImage()) {
@@ -73,39 +73,141 @@ Template.cardAttachmentsPopup.events({
}
Popup.close();
};
FS.Utility.eachFile(event, f => {
if (
MAX_IMAGE_PIXEL > 0 &&
typeof f.type === 'string' &&
f.type.match(/^image/)
) {
// is image
const reader = new FileReader();
reader.onload = function(e) {
const dataurl = e && e.target && e.target.result;
if (dataurl !== undefined) {
shrinkImage({
dataurl,
maxSize: MAX_IMAGE_PIXEL,
ratio: COMPRESS_RATIO,
toBlob: true,
callback(blob) {
if (blob === false) {
processFile(f);
} else {
blob.name = f.name;
processFile(blob);
}
},
});
} else {
// couldn't process it let other function handle it?
processFile(f);
}
};
reader.readAsDataURL(f);
} else {
processFile(f);
}
});
},
'click .js-computer-upload'(evt, tpl) {
tpl.find('.js-attach-file').click();
evt.preventDefault();
'click .js-computer-upload'(event, templateInstance) {
templateInstance.find('.js-attach-file').click();
event.preventDefault();
},
'click .js-upload-clipboard-image': Popup.open('previewClipboardImage'),
});
const MAX_IMAGE_PIXEL = Meteor.settings.public.MAX_IMAGE_PIXEL;
const COMPRESS_RATIO = Meteor.settings.public.IMAGE_COMPRESS_RATIO;
let pastedResults = null;
const shrinkImage = function(options) {
// shrink image to certain size
const dataurl = options.dataurl,
callback = options.callback,
toBlob = options.toBlob;
let canvas = document.createElement('canvas'),
image = document.createElement('img');
const maxSize = options.maxSize || 1024;
const ratio = options.ratio || 1.0;
const next = function(result) {
image = null;
canvas = null;
if (typeof callback === 'function') {
callback(result);
}
};
image.onload = function() {
let width = this.width,
height = this.height;
let changed = false;
if (width > height) {
if (width > maxSize) {
height *= maxSize / width;
width = maxSize;
changed = true;
}
} else if (height > maxSize) {
width *= maxSize / height;
height = maxSize;
changed = true;
}
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(this, 0, 0, width, height);
if (changed === true) {
const type = 'image/jpeg';
if (toBlob) {
canvas.toBlob(next, type, ratio);
} else {
next(canvas.toDataURL(type, ratio));
}
} else {
next(changed);
}
};
image.onerror = function() {
next(false);
};
image.src = dataurl;
};
Template.previewClipboardImagePopup.onRendered(() => {
// we can paste image from clipboard
$(document.body).pasteImageReader((results) => {
const handle = results => {
if (results.dataURL.startsWith('data:image/')) {
$('img.preview-clipboard-image').attr('src', results.dataURL);
pastedResults = results;
const direct = results => {
$('img.preview-clipboard-image').attr('src', results.dataURL);
pastedResults = results;
};
if (MAX_IMAGE_PIXEL) {
// if has size limitation on image we shrink it before uploading
shrinkImage({
dataurl: results.dataURL,
maxSize: MAX_IMAGE_PIXEL,
ratio: COMPRESS_RATIO,
callback(changed) {
if (changed !== false && !!changed) {
results.dataURL = changed;
}
direct(results);
},
});
}
}
});
};
$(document.body).pasteImageReader(handle);
// we can also drag & drop image file to it
$(document.body).dropImageReader((results) => {
if (results.dataURL.startsWith('data:image/')) {
$('img.preview-clipboard-image').attr('src', results.dataURL);
pastedResults = results;
}
});
$(document.body).dropImageReader(handle);
});
Template.previewClipboardImagePopup.events({
'click .js-upload-pasted-image'() {
const results = pastedResults;
if (results && results.file) {
window.oPasted = pastedResults;
const card = this;
const file = new FS.File(results.file);
if (!results.name) {
@@ -31,6 +31,10 @@ template(name="cardCustomField-text")
= value
else
| {{_ 'edit'}}
else
+viewer
= value
template(name="cardCustomField-number")
if canModifyCard
@@ -45,6 +49,9 @@ template(name="cardCustomField-number")
= value
else
| {{_ 'edit'}}
else
if value
= value
template(name="cardCustomField-date")
if canModifyCard
@@ -55,6 +62,11 @@ template(name="cardCustomField-date")
| {{showDate}}
else
| {{_ 'edit'}}
else
if value
div.card-date
time(datetime="{{showISODate}}")
| {{showDate}}
template(name="cardCustomField-dropdown")
if canModifyCard
@@ -79,3 +91,7 @@ template(name="cardCustomField-dropdown")
= selectedItem
else
| {{_ 'edit'}}
else
if value
+viewer
= selectedItem
+51 -44
View File
@@ -7,22 +7,21 @@ Template.cardCustomFieldsPopup.helpers({
});
Template.cardCustomFieldsPopup.events({
'click .js-select-field'(evt) {
'click .js-select-field'(event) {
const card = Cards.findOne(Session.get('currentCard'));
const customFieldId = this._id;
card.toggleCustomField(customFieldId);
evt.preventDefault();
event.preventDefault();
},
'click .js-settings'(evt) {
'click .js-settings'(event) {
EscapeActions.executeUpTo('detailsPane');
Sidebar.setView('customFields');
evt.preventDefault();
event.preventDefault();
},
});
// cardCustomField
const CardCustomField = BlazeComponent.extendComponent({
getTemplate() {
return `cardCustomField-${this.data().definition.type}`;
},
@@ -34,52 +33,55 @@ const CardCustomField = BlazeComponent.extendComponent({
},
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
});
CardCustomField.register('cardCustomField');
// cardCustomField-text
(class extends CardCustomField {
onCreated() {
super.onCreated();
}
events() {
return [{
'submit .js-card-customfield-text'(evt) {
evt.preventDefault();
const value = this.currentComponent().getValue();
this.card.setCustomField(this.customFieldId, value);
return [
{
'submit .js-card-customfield-text'(event) {
event.preventDefault();
const value = this.currentComponent().getValue();
this.card.setCustomField(this.customFieldId, value);
},
},
}];
];
}
}).register('cardCustomField-text');
}.register('cardCustomField-text'));
// cardCustomField-number
(class extends CardCustomField {
onCreated() {
super.onCreated();
}
events() {
return [{
'submit .js-card-customfield-number'(evt) {
evt.preventDefault();
const value = parseInt(this.find('input').value, 10);
this.card.setCustomField(this.customFieldId, value);
return [
{
'submit .js-card-customfield-number'(event) {
event.preventDefault();
const value = parseInt(this.find('input').value, 10);
this.card.setCustomField(this.customFieldId, value);
},
},
}];
];
}
}).register('cardCustomField-number');
}.register('cardCustomField-number'));
// cardCustomField-date
(class extends CardCustomField {
onCreated() {
super.onCreated();
const self = this;
@@ -108,8 +110,10 @@ CardCustomField.register('cardCustomField');
}
classes() {
if (this.date.get().isBefore(this.now.get(), 'minute') &&
this.now.get().isBefore(this.data().value)) {
if (
this.date.get().isBefore(this.now.get(), 'minute') &&
this.now.get().isBefore(this.data().value)
) {
return 'current';
}
return '';
@@ -120,12 +124,13 @@ CardCustomField.register('cardCustomField');
}
events() {
return [{
'click .js-edit-date': Popup.open('cardCustomField-date'),
}];
return [
{
'click .js-edit-date': Popup.open('cardCustomField-date'),
},
];
}
}).register('cardCustomField-date');
}.register('cardCustomField-date'));
// cardCustomField-datePopup
(class extends DatePicker {
@@ -144,11 +149,10 @@ CardCustomField.register('cardCustomField');
_deleteDate() {
this.card.setCustomField(this.customFieldId, '');
}
}).register('cardCustomField-datePopup');
}.register('cardCustomField-datePopup'));
// cardCustomField-dropdown
(class extends CardCustomField {
onCreated() {
super.onCreated();
this._items = this.data().definition.settings.dropdownItems;
@@ -160,20 +164,23 @@ CardCustomField.register('cardCustomField');
}
selectedItem() {
const selected = this._items.find((item) => {
const selected = this._items.find(item => {
return item._id === this.data().value;
});
return (selected) ? selected.name : TAPi18n.__('custom-field-dropdown-unknown');
return selected
? selected.name
: TAPi18n.__('custom-field-dropdown-unknown');
}
events() {
return [{
'submit .js-card-customfield-dropdown'(evt) {
evt.preventDefault();
const value = this.find('select').value;
this.card.setCustomField(this.customFieldId, value);
return [
{
'submit .js-card-customfield-dropdown'(event) {
event.preventDefault();
const value = this.find('select').value;
this.card.setCustomField(this.customFieldId, value);
},
},
}];
];
}
}).register('cardCustomField-dropdown');
}.register('cardCustomField-dropdown'));
+93 -89
View File
@@ -11,15 +11,20 @@ BlazeComponent.extendComponent({
},
onRendered() {
const $picker = this.$('.js-datepicker').datepicker({
todayHighlight: true,
todayBtn: 'linked',
language: TAPi18n.getLanguage(),
}).on('changeDate', function(evt) {
this.find('#date').value = moment(evt.date).format('L');
this.error.set('');
this.find('#time').focus();
}.bind(this));
const $picker = this.$('.js-datepicker')
.datepicker({
todayHighlight: true,
todayBtn: 'linked',
language: TAPi18n.getLanguage(),
})
.on(
'changeDate',
function(evt) {
this.find('#date').value = moment(evt.date).format('L');
this.error.set('');
this.find('#time').focus();
}.bind(this),
);
if (this.date.get().isValid()) {
$picker.datepicker('update', this.date.get().toDate());
@@ -27,13 +32,11 @@ BlazeComponent.extendComponent({
},
showDate() {
if (this.date.get().isValid())
return this.date.get().format('L');
if (this.date.get().isValid()) return this.date.get().format('L');
return '';
},
showTime() {
if (this.date.get().isValid())
return this.date.get().format('LT');
if (this.date.get().isValid()) return this.date.get().format('LT');
return '';
},
dateFormat() {
@@ -44,51 +47,58 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'keyup .js-date-field'() {
// parse for localized date format in strict mode
const dateMoment = moment(this.find('#date').value, 'L', true);
if (dateMoment.isValid()) {
this.error.set('');
this.$('.js-datepicker').datepicker('update', dateMoment.toDate());
}
},
'keyup .js-time-field'() {
// parse for localized time format in strict mode
const dateMoment = moment(this.find('#time').value, 'LT', true);
if (dateMoment.isValid()) {
this.error.set('');
}
},
'submit .edit-date'(evt) {
evt.preventDefault();
return [
{
'keyup .js-date-field'() {
// parse for localized date format in strict mode
const dateMoment = moment(this.find('#date').value, 'L', true);
if (dateMoment.isValid()) {
this.error.set('');
this.$('.js-datepicker').datepicker('update', dateMoment.toDate());
}
},
'keyup .js-time-field'() {
// parse for localized time format in strict mode
const dateMoment = moment(this.find('#time').value, 'LT', true);
if (dateMoment.isValid()) {
this.error.set('');
}
},
'submit .edit-date'(evt) {
evt.preventDefault();
// if no time was given, init with 12:00
const time = evt.target.time.value || moment(new Date().setHours(12, 0, 0)).format('LT');
// if no time was given, init with 12:00
const time =
evt.target.time.value ||
moment(new Date().setHours(12, 0, 0)).format('LT');
const dateString = `${evt.target.date.value} ${time}`;
const newDate = moment(dateString, 'L LT', true);
if (newDate.isValid()) {
this._storeDate(newDate.toDate());
const dateString = `${evt.target.date.value} ${time}`;
const newDate = moment(dateString, 'L LT', true);
if (newDate.isValid()) {
this._storeDate(newDate.toDate());
Popup.close();
} else {
this.error.set('invalid-date');
evt.target.date.focus();
}
},
'click .js-delete-date'(evt) {
evt.preventDefault();
this._deleteDate();
Popup.close();
}
else {
this.error.set('invalid-date');
evt.target.date.focus();
}
},
},
'click .js-delete-date'(evt) {
evt.preventDefault();
this._deleteDate();
Popup.close();
},
}];
];
},
});
Template.dateBadge.helpers({
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
});
@@ -96,7 +106,8 @@ Template.dateBadge.helpers({
(class extends DatePicker {
onCreated() {
super.onCreated();
this.data().getReceived() && this.date.set(moment(this.data().getReceived()));
this.data().getReceived() &&
this.date.set(moment(this.data().getReceived()));
}
_storeDate(date) {
@@ -106,8 +117,7 @@ Template.dateBadge.helpers({
_deleteDate() {
this.card.setReceived(null);
}
}).register('editCardReceivedDatePopup');
}.register('editCardReceivedDatePopup'));
// editCardStartDatePopup
(class extends DatePicker {
@@ -119,7 +129,10 @@ Template.dateBadge.helpers({
onRendered() {
super.onRendered();
if (moment.isDate(this.card.getReceived())) {
this.$('.js-datepicker').datepicker('setStartDate', this.card.getReceived());
this.$('.js-datepicker').datepicker(
'setStartDate',
this.card.getReceived(),
);
}
}
@@ -130,7 +143,7 @@ Template.dateBadge.helpers({
_deleteDate() {
this.card.setStart(null);
}
}).register('editCardStartDatePopup');
}.register('editCardStartDatePopup'));
// editCardDueDatePopup
(class extends DatePicker {
@@ -153,7 +166,7 @@ Template.dateBadge.helpers({
_deleteDate() {
this.card.setDue(null);
}
}).register('editCardDueDatePopup');
}.register('editCardDueDatePopup'));
// editCardEndDatePopup
(class extends DatePicker {
@@ -176,8 +189,7 @@ Template.dateBadge.helpers({
_deleteDate() {
this.card.setEnd(null);
}
}).register('editCardEndDatePopup');
}.register('editCardEndDatePopup'));
// Display received, start, due & end dates
const CardDate = BlazeComponent.extendComponent({
@@ -224,17 +236,20 @@ class CardReceivedDate extends CardDate {
const startAt = this.data().getStart();
const theDate = this.date.get();
// if dueAt, endAt and startAt exist & are > receivedAt, receivedAt doesn't need to be flagged
if (((startAt) && (theDate.isAfter(dueAt))) ||
((endAt) && (theDate.isAfter(endAt))) ||
((dueAt) && (theDate.isAfter(dueAt))))
if (
(startAt && theDate.isAfter(dueAt)) ||
(endAt && theDate.isAfter(endAt)) ||
(dueAt && theDate.isAfter(dueAt))
)
classes += 'long-overdue';
else
classes += 'current';
else classes += 'current';
return classes;
}
showTitle() {
return `${TAPi18n.__('card-received-on')} ${this.date.get().format('LLLL')}`;
return `${TAPi18n.__('card-received-on')} ${this.date
.get()
.format('LLLL')}`;
}
events() {
@@ -261,13 +276,10 @@ class CardStartDate extends CardDate {
const theDate = this.date.get();
const now = this.now.get();
// if dueAt or endAt exist & are > startAt, startAt doesn't need to be flagged
if (((endAt) && (theDate.isAfter(endAt))) ||
((dueAt) && (theDate.isAfter(dueAt))))
if ((endAt && theDate.isAfter(endAt)) || (dueAt && theDate.isAfter(dueAt)))
classes += 'long-overdue';
else if (theDate.isBefore(now, 'minute'))
classes += 'almost-due';
else
classes += 'current';
else if (theDate.isBefore(now, 'minute')) classes += 'almost-due';
else classes += 'current';
return classes;
}
@@ -298,17 +310,12 @@ class CardDueDate extends CardDate {
const theDate = this.date.get();
const now = this.now.get();
// if the due date is after the end date, green - done early
if ((endAt) && (theDate.isAfter(endAt)))
classes += 'current';
if (endAt && theDate.isAfter(endAt)) classes += 'current';
// if there is an end date, don't need to flag the due date
else if (endAt)
classes += '';
else if (now.diff(theDate, 'days') >= 2)
classes += 'long-overdue';
else if (now.diff(theDate, 'minute') >= 0)
classes += 'due';
else if (now.diff(theDate, 'days') >= -1)
classes += 'almost-due';
else if (endAt) classes += '';
else if (now.diff(theDate, 'days') >= 2) classes += 'long-overdue';
else if (now.diff(theDate, 'minute') >= 0) classes += 'due';
else if (now.diff(theDate, 'days') >= -1) classes += 'almost-due';
return classes;
}
@@ -337,12 +344,9 @@ class CardEndDate extends CardDate {
let classes = 'end-date' + ' ';
const dueAt = this.data().getDue();
const theDate = this.date.get();
if (theDate.diff(dueAt, 'days') >= 2)
classes += 'long-overdue';
else if (theDate.diff(dueAt, 'days') >= 0)
classes += 'due';
else if (theDate.diff(dueAt, 'days') >= -2)
classes += 'almost-due';
if (theDate.diff(dueAt, 'days') >= 2) classes += 'long-overdue';
else if (theDate.diff(dueAt, 'days') >= 0) classes += 'due';
else if (theDate.diff(dueAt, 'days') >= -2) classes += 'almost-due';
return classes;
}
@@ -362,22 +366,22 @@ CardEndDate.register('cardEndDate');
showDate() {
return this.date.get().format('l');
}
}).register('minicardReceivedDate');
}.register('minicardReceivedDate'));
(class extends CardStartDate {
showDate() {
return this.date.get().format('l');
}
}).register('minicardStartDate');
}.register('minicardStartDate'));
(class extends CardDueDate {
showDate() {
return this.date.get().format('l');
}
}).register('minicardDueDate');
}.register('minicardDueDate'));
(class extends CardEndDate {
showDate() {
return this.date.get().format('l');
}
}).register('minicardEndDate');
}.register('minicardEndDate'));
+223 -170
View File
@@ -27,7 +27,7 @@ BlazeComponent.extendComponent({
onCreated() {
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
this.isLoaded = new ReactiveVar(false);
const boardBody = this.parentComponent().parentComponent();
const boardBody = this.parentComponent().parentComponent();
//in Miniview parent is Board, not BoardBody.
if (boardBody !== null) {
boardBody.showOverlay.set(true);
@@ -48,7 +48,11 @@ BlazeComponent.extendComponent({
},
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
scrollParentContainer() {
@@ -80,18 +84,17 @@ BlazeComponent.extendComponent({
const cardContainerScrollTop = $cardContainer.scrollTop();
let topOffset = false;
if(cardViewStartTop !== 100){
if (cardViewStartTop !== 100) {
topOffset = cardViewStartTop - 100;
}
if(topOffset !== false) {
if (topOffset !== false) {
bodyBoardComponent.scrollTop(cardContainerScrollTop + topOffset);
}
},
presentParentTask() {
let result = this.currentBoard.presentParentTask;
if ((result === null) || (result === undefined)) {
if (result === null || result === undefined) {
result = 'no-parent';
}
return result;
@@ -116,7 +119,13 @@ BlazeComponent.extendComponent({
onRendered() {
if (!Utils.isMiniScreen()) {
Meteor.setTimeout(() => {
$('.card-details').mCustomScrollbar({theme:'minimal-dark', setWidth: false, setLeft: 0, scrollbarPosition: 'outside', mouseWheel: true });
$('.card-details').mCustomScrollbar({
theme: 'minimal-dark',
setWidth: false,
setLeft: 0,
scrollbarPosition: 'outside',
mouseWheel: true,
});
this.scrollParentContainer();
}, 500);
}
@@ -212,7 +221,7 @@ BlazeComponent.extendComponent({
},
onDestroyed() {
const parentComponent = this.parentComponent().parentComponent();
const parentComponent = this.parentComponent().parentComponent();
//on mobile view parent is Board, not board body.
if (parentComponent === null) return;
parentComponent.showOverlay.set(false);
@@ -228,56 +237,64 @@ BlazeComponent.extendComponent({
},
};
return [{
...events,
'click .js-close-card-details' () {
Utils.goBoardId(this.data().boardId);
return [
{
...events,
'click .js-close-card-details'() {
Utils.goBoardId(this.data().boardId);
},
'click .js-open-card-details-menu': Popup.open('cardDetailsActions'),
'submit .js-card-description'(event) {
event.preventDefault();
const description = this.currentComponent().getValue();
this.data().setDescription(description);
},
'submit .js-card-details-title'(event) {
event.preventDefault();
const title = this.currentComponent()
.getValue()
.trim();
if (title) {
this.data().setTitle(title);
}
},
'submit .js-card-details-assigner'(event) {
event.preventDefault();
const assigner = this.currentComponent()
.getValue()
.trim();
if (assigner) {
this.data().setAssignedBy(assigner);
}
},
'submit .js-card-details-requester'(event) {
event.preventDefault();
const requester = this.currentComponent()
.getValue()
.trim();
if (requester) {
this.data().setRequestedBy(requester);
}
},
'click .js-member': Popup.open('cardMember'),
'click .js-add-members': Popup.open('cardMembers'),
'click .js-add-labels': Popup.open('cardLabels'),
'click .js-received-date': Popup.open('editCardReceivedDate'),
'click .js-start-date': Popup.open('editCardStartDate'),
'click .js-due-date': Popup.open('editCardDueDate'),
'click .js-end-date': Popup.open('editCardEndDate'),
'mouseenter .js-card-details'() {
const parentComponent = this.parentComponent().parentComponent();
//on mobile view parent is Board, not BoardBody.
if (parentComponent === null) return;
parentComponent.showOverlay.set(true);
parentComponent.mouseHasEnterCardDetails = true;
},
'click #toggleButton'() {
Meteor.call('toggleSystemMessages');
},
},
'click .js-open-card-details-menu': Popup.open('cardDetailsActions'),
'submit .js-card-description' (evt) {
evt.preventDefault();
const description = this.currentComponent().getValue();
this.data().setDescription(description);
},
'submit .js-card-details-title' (evt) {
evt.preventDefault();
const title = this.currentComponent().getValue().trim();
if (title) {
this.data().setTitle(title);
}
},
'submit .js-card-details-assigner'(evt) {
evt.preventDefault();
const assigner = this.currentComponent().getValue().trim();
if (assigner) {
this.data().setAssignedBy(assigner);
}
},
'submit .js-card-details-requester'(evt) {
evt.preventDefault();
const requester = this.currentComponent().getValue().trim();
if (requester) {
this.data().setRequestedBy(requester);
}
},
'click .js-member': Popup.open('cardMember'),
'click .js-add-members': Popup.open('cardMembers'),
'click .js-add-labels': Popup.open('cardLabels'),
'click .js-received-date': Popup.open('editCardReceivedDate'),
'click .js-start-date': Popup.open('editCardStartDate'),
'click .js-due-date': Popup.open('editCardDueDate'),
'click .js-end-date': Popup.open('editCardEndDate'),
'mouseenter .js-card-details' () {
const parentComponent = this.parentComponent().parentComponent();
//on mobile view parent is Board, not BoardBody.
if (parentComponent === null) return;
parentComponent.showOverlay.set(true);
parentComponent.mouseHasEnterCardDetails = true;
},
'click #toggleButton'() {
Meteor.call('toggleSystemMessages');
},
}];
];
},
}).register('cardDetails');
@@ -297,7 +314,9 @@ BlazeComponent.extendComponent({
close(isReset = false) {
if (this.isOpen.get() && !isReset) {
const draft = this.getValue().trim();
if (draft !== Cards.findOne(Session.get('currentCard')).getDescription()) {
if (
draft !== Cards.findOne(Session.get('currentCard')).getDescription()
) {
UnsavedEdits.set(this._getUnsavedEditKey(), this.getValue());
}
}
@@ -311,12 +330,14 @@ BlazeComponent.extendComponent({
events() {
const parentEvents = InlinedForm.prototype.events()[0];
return [{
...parentEvents,
'click .js-close-inlined-form': this.reset,
}];
return [
{
...parentEvents,
'click .js-close-inlined-form': this.reset,
},
];
}
}).register('inlinedCardDescription');
}.register('inlinedCardDescription'));
Template.cardDetailsActionsPopup.helpers({
isWatching() {
@@ -324,7 +345,11 @@ Template.cardDetailsActionsPopup.helpers({
},
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
});
@@ -342,23 +367,31 @@ Template.cardDetailsActionsPopup.events({
'click .js-copy-card': Popup.open('copyCard'),
'click .js-copy-checklist-cards': Popup.open('copyChecklistToManyCards'),
'click .js-set-card-color': Popup.open('setCardColor'),
'click .js-move-card-to-top' (evt) {
evt.preventDefault();
const minOrder = _.min(this.list().cards(this.swimlaneId).map((c) => c.sort));
this.move(this.swimlaneId, this.listId, minOrder - 1);
'click .js-move-card-to-top'(event) {
event.preventDefault();
const minOrder = _.min(
this.list()
.cards(this.swimlaneId)
.map(c => c.sort),
);
this.move(this.boardId, this.swimlaneId, this.listId, minOrder - 1);
},
'click .js-move-card-to-bottom' (evt) {
evt.preventDefault();
const maxOrder = _.max(this.list().cards(this.swimlaneId).map((c) => c.sort));
this.move(this.swimlaneId, this.listId, maxOrder + 1);
'click .js-move-card-to-bottom'(event) {
event.preventDefault();
const maxOrder = _.max(
this.list()
.cards(this.swimlaneId)
.map(c => c.sort),
);
this.move(this.boardId, this.swimlaneId, this.listId, maxOrder + 1);
},
'click .js-archive' (evt) {
evt.preventDefault();
'click .js-archive'(event) {
event.preventDefault();
this.archive();
Popup.close();
},
'click .js-more': Popup.open('cardMore'),
'click .js-toggle-watch-card' () {
'click .js-toggle-watch-card'() {
const currentCard = this;
const level = currentCard.findWatcher(Meteor.userId()) ? null : 'watching';
Meteor.call('watch', 'card', currentCard._id, level, (err, ret) => {
@@ -367,15 +400,15 @@ Template.cardDetailsActionsPopup.events({
},
});
Template.editCardTitleForm.onRendered(function () {
Template.editCardTitleForm.onRendered(function() {
autosize(this.$('.js-edit-card-title'));
});
Template.editCardTitleForm.events({
'keydown .js-edit-card-title' (evt) {
'keydown .js-edit-card-title'(event) {
// If enter key was pressed, submit the data
// Unless the shift key is also being pressed
if (evt.keyCode === 13 && !evt.shiftKey) {
if (event.keyCode === 13 && !event.shiftKey) {
$('.js-submit-edit-card-title-form').click();
}
},
@@ -386,9 +419,9 @@ Template.editCardRequesterForm.onRendered(function() {
});
Template.editCardRequesterForm.events({
'keydown .js-edit-card-requester'(evt) {
'keydown .js-edit-card-requester'(event) {
// If enter key was pressed, submit the data
if (evt.keyCode === 13) {
if (event.keyCode === 13) {
$('.js-submit-edit-card-requester-form').click();
}
},
@@ -399,16 +432,16 @@ Template.editCardAssignerForm.onRendered(function() {
});
Template.editCardAssignerForm.events({
'keydown .js-edit-card-assigner'(evt) {
'keydown .js-edit-card-assigner'(event) {
// If enter key was pressed, submit the data
if (evt.keyCode === 13) {
if (event.keyCode === 13) {
$('.js-submit-edit-card-assigner-form').click();
}
},
});
Template.moveCardPopup.events({
'click .js-done' () {
'click .js-done'() {
// XXX We should *not* get the currentCard from the global state, but
// instead from a “component” state.
const card = Cards.findOne(Session.get('currentCard'));
@@ -429,13 +462,16 @@ BlazeComponent.extendComponent({
},
boards() {
const boards = Boards.find({
archived: false,
'members.userId': Meteor.userId(),
_id: {$ne: Meteor.user().getTemplatesBoardId()},
}, {
sort: ['title'],
});
const boards = Boards.find(
{
archived: false,
'members.userId': Meteor.userId(),
_id: { $ne: Meteor.user().getTemplatesBoardId() },
},
{
sort: ['title'],
},
);
return boards;
},
@@ -450,12 +486,14 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'change .js-select-boards'(evt) {
this.selectedBoardId.set($(evt.currentTarget).val());
subManager.subscribe('board', this.selectedBoardId.get(), false);
return [
{
'change .js-select-boards'(event) {
this.selectedBoardId.set($(event.currentTarget).val());
subManager.subscribe('board', this.selectedBoardId.get(), false);
},
},
}];
];
},
}).register('boardsAndLists');
@@ -471,7 +509,9 @@ Template.copyCardPopup.events({
const textarea = $('#copy-card-title');
const title = textarea.val().trim();
// insert new card to the bottom of new list
card.sort = Lists.findOne(card.listId).cards().count();
card.sort = Lists.findOne(card.listId)
.cards()
.count();
if (title) {
card.title = title;
@@ -489,7 +529,7 @@ Template.copyCardPopup.events({
});
Template.copyChecklistToManyCardsPopup.events({
'click .js-done' () {
'click .js-done'() {
const card = Cards.findOne(Session.get('currentCard'));
const oldId = card._id;
card._id = null;
@@ -502,11 +542,13 @@ Template.copyChecklistToManyCardsPopup.events({
const textarea = $('#copy-card-title');
const titleEntry = textarea.val().trim();
// insert new card to the bottom of new list
card.sort = Lists.findOne(card.listId).cards().count();
card.sort = Lists.findOne(card.listId)
.cards()
.count();
if (titleEntry) {
const titleList = JSON.parse(titleEntry);
for (let i = 0; i < titleList.length; i++){
for (let i = 0; i < titleList.length; i++) {
const obj = titleList[i];
card.title = obj.title;
card.description = obj.description;
@@ -519,12 +561,12 @@ Template.copyChecklistToManyCardsPopup.events({
Filter.addException(_id);
// copy checklists
Checklists.find({cardId: oldId}).forEach((ch) => {
Checklists.find({ cardId: oldId }).forEach(ch => {
ch.copy(_id);
});
// copy subtasks
cursor = Cards.find({parentId: oldId});
cursor = Cards.find({ parentId: oldId });
cursor.forEach(function() {
'use strict';
const subtask = arguments[0];
@@ -534,7 +576,7 @@ Template.copyChecklistToManyCardsPopup.events({
});
// copy card comments
CardComments.find({cardId: oldId}).forEach((cmt) => {
CardComments.find({ cardId: oldId }).forEach(cmt => {
cmt.copy(_id);
});
}
@@ -550,7 +592,7 @@ BlazeComponent.extendComponent({
},
colors() {
return cardColors.map((color) => ({ color, name: '' }));
return cardColors.map(color => ({ color, name: '' }));
},
isSelected(color) {
@@ -561,19 +603,21 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
return [
{
'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
},
'click .js-submit'() {
this.currentCard.setColor(this.currentColor.get());
Popup.close();
},
'click .js-remove-color'() {
this.currentCard.setColor(null);
Popup.close();
},
},
'click .js-submit' () {
this.currentCard.setColor(this.currentColor.get());
Popup.close();
},
'click .js-remove-color'() {
this.currentCard.setColor(null);
Popup.close();
},
}];
];
},
}).register('setCardColorPopup');
@@ -592,15 +636,18 @@ BlazeComponent.extendComponent({
},
boards() {
const boards = Boards.find({
archived: false,
'members.userId': Meteor.userId(),
_id: {
$ne: Meteor.user().getTemplatesBoardId(),
const boards = Boards.find(
{
archived: false,
'members.userId': Meteor.userId(),
_id: {
$ne: Meteor.user().getTemplatesBoardId(),
},
},
}, {
sort: ['title'],
});
{
sort: ['title'],
},
);
return boards;
},
@@ -609,7 +656,7 @@ BlazeComponent.extendComponent({
if (this.parentBoard.get()) {
return Cards.find({
boardId: this.parentBoard.get(),
_id: {$ne: currentId},
_id: { $ne: currentId },
});
} else {
return [];
@@ -642,63 +689,69 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-copy-card-link-to-clipboard' () {
// Clipboard code from:
// https://stackoverflow.com/questions/6300213/copy-selected-text-to-the-clipboard-without-using-flash-must-be-cross-browser
const StringToCopyElement = document.getElementById('cardURL');
StringToCopyElement.select();
if (document.execCommand('copy')) {
StringToCopyElement.blur();
} else {
document.getElementById('cardURL').selectionStart = 0;
document.getElementById('cardURL').selectionEnd = 999;
document.execCommand('copy');
if (window.getSelection) {
if (window.getSelection().empty) { // Chrome
window.getSelection().empty();
} else if (window.getSelection().removeAllRanges) { // Firefox
window.getSelection().removeAllRanges();
return [
{
'click .js-copy-card-link-to-clipboard'() {
// Clipboard code from:
// https://stackoverflow.com/questions/6300213/copy-selected-text-to-the-clipboard-without-using-flash-must-be-cross-browser
const StringToCopyElement = document.getElementById('cardURL');
StringToCopyElement.select();
if (document.execCommand('copy')) {
StringToCopyElement.blur();
} else {
document.getElementById('cardURL').selectionStart = 0;
document.getElementById('cardURL').selectionEnd = 999;
document.execCommand('copy');
if (window.getSelection) {
if (window.getSelection().empty) {
// Chrome
window.getSelection().empty();
} else if (window.getSelection().removeAllRanges) {
// Firefox
window.getSelection().removeAllRanges();
}
} else if (document.selection) {
// IE?
document.selection.empty();
}
} else if (document.selection) { // IE?
document.selection.empty();
}
}
},
'click .js-delete': Popup.afterConfirm('cardDelete', function() {
Popup.close();
Cards.remove(this._id);
Utils.goBoardId(this.boardId);
}),
'change .js-field-parent-board'(event) {
const selection = $(event.currentTarget).val();
const list = $('.js-field-parent-card');
if (selection === 'none') {
this.parentBoard.set(null);
} else {
subManager.subscribe('board', $(event.currentTarget).val(), false);
this.parentBoard.set(selection);
list.prop('disabled', false);
}
this.setParentCardId(null);
},
'change .js-field-parent-card'(event) {
const selection = $(event.currentTarget).val();
this.setParentCardId(selection);
},
},
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
Popup.close();
Cards.remove(this._id);
Utils.goBoardId(this.boardId);
}),
'change .js-field-parent-board'(evt) {
const selection = $(evt.currentTarget).val();
const list = $('.js-field-parent-card');
if (selection === 'none') {
this.parentBoard.set(null);
} else {
subManager.subscribe('board', $(evt.currentTarget).val(), false);
this.parentBoard.set(selection);
list.prop('disabled', false);
}
this.setParentCardId(null);
},
'change .js-field-parent-card'(evt) {
const selection = $(evt.currentTarget).val();
this.setParentCardId(selection);
},
}];
];
},
}).register('cardMorePopup');
// Close the card details pane by pressing escape
EscapeActions.register('detailsPane',
EscapeActions.register(
'detailsPane',
() => {
Utils.goBoardId(Session.get('currentBoard'));
},
() => {
return !Session.equals('currentCard', null);
}, {
},
{
noClickEscapeOn: '.js-card-details,.board-sidebar,#header',
}
},
);
+1 -1
View File
@@ -134,7 +134,7 @@ input[type="submit"].attachment-add-link-submit
.card-details-canvas
width: 100%
padding-left: 0px;
.card-details-header
.close-card-details
margin-right: 0px
+37 -25
View File
@@ -20,29 +20,31 @@ BlazeComponent.extendComponent({
this.card.setSpentTime(null);
},
events() {
return [{
//TODO : need checking this portion
'submit .edit-time'(evt) {
evt.preventDefault();
return [
{
//TODO : need checking this portion
'submit .edit-time'(evt) {
evt.preventDefault();
const spentTime = parseFloat(evt.target.time.value);
const isOvertime = this.card.getIsOvertime();
const spentTime = parseFloat(evt.target.time.value);
const isOvertime = this.card.getIsOvertime();
if (spentTime >= 0) {
this.storeTime(spentTime, isOvertime);
if (spentTime >= 0) {
this.storeTime(spentTime, isOvertime);
Popup.close();
} else {
this.error.set('invalid-time');
evt.target.time.focus();
}
},
'click .js-delete-time'(evt) {
evt.preventDefault();
this.deleteTime();
Popup.close();
} else {
this.error.set('invalid-time');
evt.target.time.focus();
}
},
'click a.js-toggle-overtime': this.toggleOvertime,
},
'click .js-delete-time'(evt) {
evt.preventDefault();
this.deleteTime();
Popup.close();
},
'click a.js-toggle-overtime': this.toggleOvertime,
}];
];
},
}).register('editCardSpentTimePopup');
@@ -56,23 +58,33 @@ BlazeComponent.extendComponent({
},
showTitle() {
if (this.data().getIsOvertime()) {
return `${TAPi18n.__('overtime')} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`;
return `${TAPi18n.__(
'overtime',
)} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`;
} else {
return `${TAPi18n.__('card-spent')} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`;
return `${TAPi18n.__(
'card-spent',
)} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`;
}
},
showTime() {
return this.data().getSpentTime();
},
events() {
return [{
'click .js-edit-time': Popup.open('editCardSpentTime'),
}];
return [
{
'click .js-edit-time': Popup.open('editCardSpentTime'),
},
];
},
}).register('cardSpentTime');
Template.timeBadge.helpers({
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
});
+45 -25
View File
@@ -64,20 +64,22 @@ BlazeComponent.extendComponent({
},
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
}).register('checklistDetail');
BlazeComponent.extendComponent({
addChecklist(event) {
event.preventDefault();
const textarea = this.find('textarea.js-add-checklist-item');
const title = textarea.value.trim();
let cardId = this.currentData().cardId;
const card = Cards.findOne(cardId);
if (card.isLinked())
cardId = card.linkedId;
if (card.isLinked()) cardId = card.linkedId;
if (title) {
Checklists.insert({
@@ -86,7 +88,9 @@ BlazeComponent.extendComponent({
sort: card.checklists().count(),
});
setTimeout(() => {
this.$('.add-checklist-item').last().click();
this.$('.add-checklist-item')
.last()
.click();
}, 100);
}
textarea.value = '';
@@ -113,7 +117,11 @@ BlazeComponent.extendComponent({
},
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
deleteChecklist() {
@@ -167,37 +175,43 @@ BlazeComponent.extendComponent({
events() {
const events = {
'click .toggle-delete-checklist-dialog'(event) {
if($(event.target).hasClass('js-delete-checklist')){
if ($(event.target).hasClass('js-delete-checklist')) {
this.checklistToDelete = this.currentData().checklist; //Store data context
}
this.toggleDeleteDialog.set(!this.toggleDeleteDialog.get());
},
};
return [{
...events,
'submit .js-add-checklist': this.addChecklist,
'submit .js-edit-checklist-title': this.editChecklist,
'submit .js-add-checklist-item': this.addChecklistItem,
'submit .js-edit-checklist-item': this.editChecklistItem,
'click .js-delete-checklist-item': this.deleteItem,
'click .confirm-checklist-delete': this.deleteChecklist,
keydown: this.pressKey,
}];
return [
{
...events,
'submit .js-add-checklist': this.addChecklist,
'submit .js-edit-checklist-title': this.editChecklist,
'submit .js-add-checklist-item': this.addChecklistItem,
'submit .js-edit-checklist-item': this.editChecklistItem,
'click .js-delete-checklist-item': this.deleteItem,
'click .confirm-checklist-delete': this.deleteChecklist,
keydown: this.pressKey,
},
];
},
}).register('checklists');
Template.checklistDeleteDialog.onCreated(() => {
const $cardDetails = this.$('.card-details');
this.scrollState = { position: $cardDetails.scrollTop(), //save current scroll position
this.scrollState = {
position: $cardDetails.scrollTop(), //save current scroll position
top: false, //required for smooth scroll animation
};
//Callback's purpose is to only prevent scrolling after animation is complete
$cardDetails.animate({ scrollTop: 0 }, 500, () => { this.scrollState.top = true; });
$cardDetails.animate({ scrollTop: 0 }, 500, () => {
this.scrollState.top = true;
});
//Prevent scrolling while dialog is open
$cardDetails.on('scroll', () => {
if(this.scrollState.top) { //If it's already in position, keep it there. Otherwise let animation scroll
if (this.scrollState.top) {
//If it's already in position, keep it there. Otherwise let animation scroll
$cardDetails.scrollTop(0);
}
});
@@ -206,12 +220,16 @@ Template.checklistDeleteDialog.onCreated(() => {
Template.checklistDeleteDialog.onDestroyed(() => {
const $cardDetails = this.$('.card-details');
$cardDetails.off('scroll'); //Reactivate scrolling
$cardDetails.animate( { scrollTop: this.scrollState.position });
$cardDetails.animate({ scrollTop: this.scrollState.position });
});
Template.checklistItemDetail.helpers({
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
});
@@ -224,8 +242,10 @@ BlazeComponent.extendComponent({
}
},
events() {
return [{
'click .js-checklist-item .check-box': this.toggleItem,
}];
return [
{
'click .js-checklist-item .check-box': this.toggleItem,
},
];
},
}).register('checklistItemDetail');
+25 -17
View File
@@ -9,7 +9,7 @@ BlazeComponent.extendComponent({
},
labels() {
return labelColors.map((color) => ({ color, name: '' }));
return labelColors.map(color => ({ color, name: '' }));
},
isSelected(color) {
@@ -17,11 +17,13 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
return [
{
'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
},
},
}];
];
},
}).register('formLabel');
@@ -38,19 +40,19 @@ Template.createLabelPopup.helpers({
});
Template.cardLabelsPopup.events({
'click .js-select-label'(evt) {
'click .js-select-label'(event) {
const card = Cards.findOne(Session.get('currentCard'));
const labelId = this._id;
card.toggleLabel(labelId);
evt.preventDefault();
event.preventDefault();
},
'click .js-edit-label': Popup.open('editLabel'),
'click .js-add-label': Popup.open('createLabel'),
});
Template.formLabel.events({
'click .js-palette-color'(evt) {
const $this = $(evt.currentTarget);
'click .js-palette-color'(event) {
const $this = $(event.currentTarget);
// hide selected ll colors
$('.js-palette-select').addClass('hide');
@@ -62,11 +64,14 @@ Template.formLabel.events({
Template.createLabelPopup.events({
// Create the new label
'submit .create-label'(evt, tpl) {
evt.preventDefault();
'submit .create-label'(event, templateInstance) {
event.preventDefault();
const board = Boards.findOne(Session.get('currentBoard'));
const name = tpl.$('#labelName').val().trim();
const color = Blaze.getData(tpl.find('.fa-check')).color;
const name = templateInstance
.$('#labelName')
.val()
.trim();
const color = Blaze.getData(templateInstance.find('.fa-check')).color;
board.addLabel(name, color);
Popup.back();
},
@@ -78,11 +83,14 @@ Template.editLabelPopup.events({
board.removeLabel(this._id);
Popup.back(2);
}),
'submit .edit-label'(evt, tpl) {
evt.preventDefault();
'submit .edit-label'(event, templateInstance) {
event.preventDefault();
const board = Boards.findOne(Session.get('currentBoard'));
const name = tpl.$('#labelName').val().trim();
const color = Blaze.getData(tpl.find('.fa-check')).color;
const name = templateInstance
.$('#labelName')
.val()
.trim();
const color = Blaze.getData(templateInstance.find('.fa-check')).color;
board.editLabel(this._id, name, color);
Popup.back();
},
+7 -2
View File
@@ -8,7 +8,9 @@ template(name="minicard")
if labels
.minicard-labels
each labels
.minicard-label(class="card-label-{{color}}" title="{{name}}")
span.card-label(class="card-label-{{color}}" title=name)
+viewer
= name
.minicard-title
.handle
.fa.fa-arrows
@@ -74,7 +76,10 @@ template(name="minicard")
if comments.count
.badge(title="{{_ 'card-comments-title' comments.count }}")
span.badge-icon.fa.fa-comment-o.badge-comment
span.badge-text= comments.count
= ' '
= comments.count
//span.badge-comment.badge-text
//| {{_ 'comment'}}
if getDescription
.badge.badge-state-image-only(title=getDescription)
span.badge-icon.fa.fa-align-left
+8 -7
View File
@@ -8,13 +8,14 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-linked-link' () {
if (this.data().isLinkedCard())
Utils.goCardId(this.data().linkedId);
else if (this.data().isLinkedBoard())
Utils.goBoardId(this.data().linkedId);
return [
{
'click .js-linked-link'() {
if (this.data().isLinkedCard()) Utils.goCardId(this.data().linkedId);
else if (this.data().isLinkedBoard())
Utils.goBoardId(this.data().linkedId);
},
},
}];
];
},
}).register('minicard');
+1 -1
View File
@@ -144,7 +144,7 @@
.badge-text
vertical-align: middle
&.badge-comment
margin-bottom: 0.1rem
margin-bottom: 0.1rem
.badge-text
font-size: 0.9em
+37 -19
View File
@@ -1,11 +1,14 @@
BlazeComponent.extendComponent({
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
}).register('subtaskDetail');
BlazeComponent.extendComponent({
addSubtask(event) {
event.preventDefault();
const textarea = this.find('textarea.js-add-subtask-item');
@@ -38,9 +41,10 @@ BlazeComponent.extendComponent({
// See https://github.com/wekan/wekan/issues/80
Filter.addException(_id);
setTimeout(() => {
this.$('.add-subtask-item').last().click();
this.$('.add-subtask-item')
.last()
.click();
}, 100);
}
textarea.value = '';
@@ -48,7 +52,11 @@ BlazeComponent.extendComponent({
},
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
deleteSubtask() {
@@ -85,13 +93,13 @@ BlazeComponent.extendComponent({
events() {
const events = {
'click .toggle-delete-subtask-dialog'(event) {
if($(event.target).hasClass('js-delete-subtask')){
if ($(event.target).hasClass('js-delete-subtask')) {
this.subtaskToDelete = this.currentData().subtask; //Store data context
}
this.toggleDeleteDialog.set(!this.toggleDeleteDialog.get());
},
'click .js-view-subtask'(event) {
if($(event.target).hasClass('js-view-subtask')){
if ($(event.target).hasClass('js-view-subtask')) {
const subtask = this.currentData().subtask;
const board = subtask.board();
FlowRouter.go('card', {
@@ -103,27 +111,33 @@ BlazeComponent.extendComponent({
},
};
return [{
...events,
'submit .js-add-subtask': this.addSubtask,
'submit .js-edit-subtask-title': this.editSubtask,
'click .confirm-subtask-delete': this.deleteSubtask,
keydown: this.pressKey,
}];
return [
{
...events,
'submit .js-add-subtask': this.addSubtask,
'submit .js-edit-subtask-title': this.editSubtask,
'click .confirm-subtask-delete': this.deleteSubtask,
keydown: this.pressKey,
},
];
},
}).register('subtasks');
Template.subtaskDeleteDialog.onCreated(() => {
const $cardDetails = this.$('.card-details');
this.scrollState = { position: $cardDetails.scrollTop(), //save current scroll position
this.scrollState = {
position: $cardDetails.scrollTop(), //save current scroll position
top: false, //required for smooth scroll animation
};
//Callback's purpose is to only prevent scrolling after animation is complete
$cardDetails.animate({ scrollTop: 0 }, 500, () => { this.scrollState.top = true; });
$cardDetails.animate({ scrollTop: 0 }, 500, () => {
this.scrollState.top = true;
});
//Prevent scrolling while dialog is open
$cardDetails.on('scroll', () => {
if(this.scrollState.top) { //If it's already in position, keep it there. Otherwise let animation scroll
if (this.scrollState.top) {
//If it's already in position, keep it there. Otherwise let animation scroll
$cardDetails.scrollTop(0);
}
});
@@ -132,12 +146,16 @@ Template.subtaskDeleteDialog.onCreated(() => {
Template.subtaskDeleteDialog.onDestroyed(() => {
const $cardDetails = this.$('.card-details');
$cardDetails.off('scroll'); //Reactivate scrolling
$cardDetails.animate( { scrollTop: this.scrollState.position });
$cardDetails.animate({ scrollTop: this.scrollState.position });
});
Template.subtaskItemDetail.helpers({
canModifyCard() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
});
+47 -38
View File
@@ -56,7 +56,7 @@ BlazeComponent.extendComponent({
const membersMapping = this.membersToMap.get();
if (membersMapping) {
const mappingById = {};
membersMapping.forEach((member) => {
membersMapping.forEach(member => {
if (member.wekanId) {
mappingById[member.id] = member.wekanId;
}
@@ -64,7 +64,8 @@ BlazeComponent.extendComponent({
additionalData.membersMapping = mappingById;
}
this.membersToMap.set([]);
Meteor.call('importBoard',
Meteor.call(
'importBoard',
this.importedData.get(),
additionalData,
this.importSource,
@@ -76,7 +77,7 @@ BlazeComponent.extendComponent({
Session.set('fromBoard', null);
Utils.goBoardId(res);
}
}
},
);
},
@@ -84,12 +85,12 @@ BlazeComponent.extendComponent({
const importSource = Session.get('importSource');
let membersToMap;
switch (importSource) {
case 'trello':
membersToMap = trelloMembersMapper.getMembersToMap(dataObject);
break;
case 'wekan':
membersToMap = wekanMembersMapper.getMembersToMap(dataObject);
break;
case 'trello':
membersToMap = trelloMembersMapper.getMembersToMap(dataObject);
break;
case 'wekan':
membersToMap = wekanMembersMapper.getMembersToMap(dataObject);
break;
}
return membersToMap;
},
@@ -109,22 +110,26 @@ BlazeComponent.extendComponent({
},
events() {
return [{
submit(evt) {
return this.parentComponent().importData(evt);
return [
{
submit(evt) {
return this.parentComponent().importData(evt);
},
},
}];
];
},
}).register('importTextarea');
BlazeComponent.extendComponent({
onCreated() {
this.autorun(() => {
this.parentComponent().membersToMap.get().forEach(({ wekanId }) => {
if (wekanId) {
this.subscribe('user-miniprofile', wekanId);
}
});
this.parentComponent()
.membersToMap.get()
.forEach(({ wekanId }) => {
if (wekanId) {
this.subscribe('user-miniprofile', wekanId);
}
});
});
},
@@ -149,23 +154,23 @@ BlazeComponent.extendComponent({
_setPropertyForMember(property, value, memberId, unset = false) {
const listOfMembers = this.members();
let finder = null;
if(memberId) {
finder = (member) => member.id === memberId;
if (memberId) {
finder = member => member.id === memberId;
} else {
finder = (member) => member.selected;
finder = member => member.selected;
}
listOfMembers.forEach((member) => {
if(finder(member)) {
if(value !== null) {
listOfMembers.forEach(member => {
if (finder(member)) {
if (value !== null) {
member[property] = value;
} else {
delete member[property];
}
if(!unset) {
if (!unset) {
// we shortcut if we don't care about unsetting the others
return false;
}
} else if(unset) {
} else if (unset) {
delete member[property];
}
return true;
@@ -186,9 +191,9 @@ BlazeComponent.extendComponent({
const allMembers = this.members();
let finder = null;
if (memberId) {
finder = (user) => user.id === memberId;
finder = user => user.id === memberId;
} else {
finder = (user) => user.selected;
finder = user => user.selected;
}
return allMembers.find(finder);
},
@@ -197,7 +202,7 @@ BlazeComponent.extendComponent({
return this._setPropertyForMember('wekanId', wekanId, null);
},
unmapMember(memberId){
unmapMember(memberId) {
return this._setPropertyForMember('wekanId', null, memberId);
},
@@ -208,7 +213,7 @@ BlazeComponent.extendComponent({
onMapMember(evt) {
const memberToMap = this.currentData();
if(memberToMap.wekan) {
if (memberToMap.wekan) {
// todo xxx ask for confirmation?
this.unmapMember(memberToMap.id);
} else {
@@ -218,10 +223,12 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'submit': this.onSubmit,
'click .js-select-member': this.onMapMember,
}];
return [
{
submit: this.onSubmit,
'click .js-select-member': this.onMapMember,
},
];
},
}).register('importMapMembers');
@@ -230,14 +237,16 @@ BlazeComponent.extendComponent({
this.find('.js-map-member input').focus();
},
onSelectUser(){
onSelectUser() {
Popup.getOpenerComponent().mapSelectedMember(this.currentData()._id);
Popup.back();
},
events() {
return [{
'click .js-select-import': this.onSelectUser,
}];
return [
{
'click .js-select-import': this.onSelectUser,
},
];
},
}).register('importMapMembersAddPopup');
@@ -4,7 +4,7 @@ export function getMembersToMap(data) {
// imported member
const membersToMap = data.members;
// auto-map based on username
membersToMap.forEach((importedMember) => {
membersToMap.forEach(importedMember => {
const wekanUser = Users.findOne({ username: importedMember.username });
if (wekanUser) {
importedMember.wekanId = wekanUser._id;
@@ -5,10 +5,10 @@ export function getMembersToMap(data) {
const membersToMap = data.members;
const users = data.users;
// auto-map based on username
membersToMap.forEach((importedMember) => {
membersToMap.forEach(importedMember => {
importedMember.id = importedMember.userId;
delete importedMember.userId;
const user = users.filter((user) => {
const user = users.filter(user => {
return user._id === importedMember.id;
})[0];
if (user.profile && user.profile.fullname) {
+32 -10
View File
@@ -21,14 +21,18 @@ BlazeComponent.extendComponent({
const boardComponent = this.parentComponent().parentComponent();
function userIsMember() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
}
const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
const $cards = this.$('.js-minicards');
if(window.matchMedia('(max-width: 1199px)').matches) {
$( '.js-minicards' ).sortable({
if (window.matchMedia('(max-width: 1199px)').matches) {
$('.js-minicards').sortable({
handle: '.handle',
});
}
@@ -42,10 +46,16 @@ BlazeComponent.extendComponent({
if (MultiSelection.isActive()) {
const andNOthers = $cards.find('.js-minicard.is-checked').length - 1;
if (andNOthers > 0) {
helper.append($(Blaze.toHTML(HTML.DIV(
{ 'class': 'and-n-other' },
TAPi18n.__('and-n-other-card', { count: andNOthers })
))));
helper.append(
$(
Blaze.toHTML(
HTML.DIV(
{ class: 'and-n-other' },
TAPi18n.__('and-n-other-card', { count: andNOthers }),
),
),
),
);
}
}
return helper;
@@ -70,9 +80,16 @@ BlazeComponent.extendComponent({
const currentBoard = Boards.findOne(Session.get('currentBoard'));
let swimlaneId = '';
const boardView = (Meteor.user().profile || {}).boardView;
if (boardView === 'board-view-swimlanes' || currentBoard.isTemplatesBoard())
if (
boardView === 'board-view-swimlanes' ||
currentBoard.isTemplatesBoard()
)
swimlaneId = Blaze.getData(ui.item.parents('.swimlane').get(0))._id;
else if ((boardView === 'board-view-lists') || (boardView === 'board-view-cal') || !boardView)
else if (
boardView === 'board-view-lists' ||
boardView === 'board-view-cal' ||
!boardView
)
swimlaneId = currentBoard.getDefaultSwimline()._id;
// Normally the jquery-ui sortable library moves the dragged DOM element
@@ -86,7 +103,12 @@ BlazeComponent.extendComponent({
if (MultiSelection.isActive()) {
Cards.find(MultiSelection.getMongoSelector()).forEach((card, i) => {
card.move(currentBoard._id, swimlaneId, listId, sortIndex.base + i * sortIndex.increment);
card.move(
currentBoard._id,
swimlaneId,
listId,
sortIndex.base + i * sortIndex.increment,
);
});
} else {
const cardDomElement = ui.item.get(0);
+4
View File
@@ -103,6 +103,10 @@
color: #8c8c8c
font-size: 0.8em
.list-header .list-header-plus-icon, .js-open-list-menu, .list-header-menu a
color #4d4d4d
padding-left 4px
.list-body
flex: 1 1 auto
flex-direction: column
+317 -229
View File
@@ -16,7 +16,7 @@ BlazeComponent.extendComponent({
options.position = options.position || 'top';
const forms = this.childComponents('inlinedForm');
let form = forms.find((component) => {
let form = forms.find(component => {
return component.data().position === options.position;
});
if (!form && forms.length > 0) {
@@ -52,11 +52,12 @@ BlazeComponent.extendComponent({
let cardType = 'cardType-card';
if (title) {
if (board.isTemplatesBoard()) {
swimlaneId = this.parentComponent().parentComponent().data()._id; // Always swimlanes view
swimlaneId = this.parentComponent()
.parentComponent()
.data()._id; // Always swimlanes view
const swimlane = Swimlanes.findOne(swimlaneId);
// If this is the card templates swimlane, insert a card template
if (swimlane.isCardTemplatesSwimlane())
cardType = 'template-card';
if (swimlane.isCardTemplatesSwimlane()) cardType = 'template-card';
// If this is the board templates swimlane, insert a board template and a linked card
else if (swimlane.isBoardTemplatesSwimlane()) {
linkedId = Boards.insert({
@@ -71,8 +72,14 @@ BlazeComponent.extendComponent({
cardType = 'cardType-linkedBoard';
}
} else if (boardView === 'board-view-swimlanes')
swimlaneId = this.parentComponent().parentComponent().data()._id;
else if ((boardView === 'board-view-lists') || (boardView === 'board-view-cal') || !boardView)
swimlaneId = this.parentComponent()
.parentComponent()
.data()._id;
else if (
boardView === 'board-view-lists' ||
boardView === 'board-view-cal' ||
!boardView
)
swimlaneId = board.getDefaultSwimline()._id;
const _id = Cards.insert({
@@ -91,7 +98,9 @@ BlazeComponent.extendComponent({
// if the displayed card count is less than the total cards in the list,
// we need to increment the displayed card count to prevent the spinner
// to appear
const cardCount = this.data().cards(this.idOrNull(swimlaneId)).count();
const cardCount = this.data()
.cards(this.idOrNull(swimlaneId))
.count();
if (this.cardlimit.get() < cardCount) {
this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter);
}
@@ -149,8 +158,12 @@ BlazeComponent.extendComponent({
idOrNull(swimlaneId) {
const currentUser = Meteor.user();
if ((currentUser.profile || {}).boardView === 'board-view-swimlanes' ||
this.data().board().isTemplatesBoard())
if (
(currentUser.profile || {}).boardView === 'board-view-swimlanes' ||
this.data()
.board()
.isTemplatesBoard()
)
return swimlaneId;
return undefined;
},
@@ -161,8 +174,7 @@ BlazeComponent.extendComponent({
listId: this.currentData()._id,
archived: false,
};
if (swimlaneId)
selector.swimlaneId = swimlaneId;
if (swimlaneId) selector.swimlaneId = swimlaneId;
return Cards.find(Filter.mongoSelector(selector), {
sort: ['sort'],
limit,
@@ -175,21 +187,32 @@ BlazeComponent.extendComponent({
},
canSeeAddCard() {
return !this.reachedWipLimit() && Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
!this.reachedWipLimit() &&
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
reachedWipLimit() {
const list = Template.currentData();
return !list.getWipLimit('soft') && list.getWipLimit('enabled') && list.getWipLimit('value') <= list.cards().count();
return (
!list.getWipLimit('soft') &&
list.getWipLimit('enabled') &&
list.getWipLimit('value') <= list.cards().count()
);
},
events() {
return [{
'click .js-minicard': this.clickOnMiniCard,
'click .js-toggle-multi-selection': this.toggleMultiSelection,
'click .open-minicard-composer': this.scrollToBottom,
submit: this.addCard,
}];
return [
{
'click .js-minicard': this.clickOnMiniCard,
'click .js-toggle-multi-selection': this.toggleMultiSelection,
'click .open-minicard-composer': this.scrollToBottom,
submit: this.addCard,
},
];
},
}).register('listBody');
@@ -212,10 +235,15 @@ BlazeComponent.extendComponent({
const currentBoardId = Session.get('currentBoard');
arr = [];
_.forEach(Boards.findOne(currentBoardId).customFields().fetch(), function(field){
if(field.automaticallyOnCard)
arr.push({_id: field._id, value: null});
});
_.forEach(
Boards.findOne(currentBoardId)
.customFields()
.fetch(),
function(field) {
if (field.automaticallyOnCard)
arr.push({ _id: field._id, value: null });
},
);
this.customFields.set(arr);
},
@@ -227,7 +255,7 @@ BlazeComponent.extendComponent({
getLabels() {
const currentBoardId = Session.get('currentBoard');
return Boards.findOne(currentBoardId).labels.filter((label) => {
return Boards.findOne(currentBoardId).labels.filter(label => {
return this.labels.get().indexOf(label._id) > -1;
});
},
@@ -257,18 +285,20 @@ BlazeComponent.extendComponent({
}
BlazeComponent.getComponentForElement(nextList).openForm({
position:this.data().position,
position: this.data().position,
});
}
},
events() {
return [{
keydown: this.pressKey,
'click .js-link': Popup.open('linkCard'),
'click .js-search': Popup.open('searchElement'),
'click .js-card-template': Popup.open('searchElement'),
}];
return [
{
keydown: this.pressKey,
'click .js-link': Popup.open('linkCard'),
'click .js-search': Popup.open('searchElement'),
'click .js-card-template': Popup.open('searchElement'),
},
];
},
onRendered() {
@@ -277,66 +307,75 @@ BlazeComponent.extendComponent({
autosize($textarea);
$textarea.escapeableTextComplete([
// User mentions
{
match: /\B@([\w.]*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
callback($.map(currentBoard.activeMembers(), (member) => {
const user = Users.findOne(member.userId);
return user.username.indexOf(term) === 0 ? user : null;
}));
$textarea.escapeableTextComplete(
[
// User mentions
{
match: /\B@([\w.]*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
callback(
$.map(currentBoard.activeMembers(), member => {
const user = Users.findOne(member.userId);
return user.username.indexOf(term) === 0 ? user : null;
}),
);
},
template(user) {
return user.username;
},
replace(user) {
toggleValueInReactiveArray(editor.members, user._id);
return '';
},
index: 1,
},
template(user) {
return user.username;
},
replace(user) {
toggleValueInReactiveArray(editor.members, user._id);
return '';
},
index: 1,
},
// Labels
// Labels
{
match: /\B#(\w*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
callback(
$.map(currentBoard.labels, label => {
if (
label.name.indexOf(term) > -1 ||
label.color.indexOf(term) > -1
) {
return label;
}
return null;
}),
);
},
template(label) {
return Blaze.toHTMLWithData(Template.autocompleteLabelLine, {
hasNoName: !label.name,
colorName: label.color,
labelName: label.name || label.color,
});
},
replace(label) {
toggleValueInReactiveArray(editor.labels, label._id);
return '';
},
index: 1,
},
],
{
match: /\B#(\w*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
callback($.map(currentBoard.labels, (label) => {
if (label.name.indexOf(term) > -1 ||
label.color.indexOf(term) > -1) {
return label;
}
return null;
}));
// When the autocomplete menu is shown we want both a press of both `Tab`
// or `Enter` to validation the auto-completion. We also need to stop the
// event propagation to prevent the card from submitting (on `Enter`) or
// going on the next column (on `Tab`).
onKeydown(evt, commands) {
if (evt.keyCode === 9 || evt.keyCode === 13) {
evt.stopPropagation();
return commands.KEY_ENTER;
}
return null;
},
template(label) {
return Blaze.toHTMLWithData(Template.autocompleteLabelLine, {
hasNoName: !label.name,
colorName: label.color,
labelName: label.name || label.color,
});
},
replace(label) {
toggleValueInReactiveArray(editor.labels, label._id);
return '';
},
index: 1,
},
], {
// When the autocomplete menu is shown we want both a press of both `Tab`
// or `Enter` to validation the auto-completion. We also need to stop the
// event propagation to prevent the card from submitting (on `Enter`) or
// going on the next column (on `Tab`).
onKeydown(evt, commands) {
if (evt.keyCode === 9 || evt.keyCode === 13) {
evt.stopPropagation();
return commands.KEY_ENTER;
}
return null;
},
});
);
},
}).register('addCardForm');
@@ -354,24 +393,29 @@ BlazeComponent.extendComponent({
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
this.listId = Blaze.getData(list[0])._id;
// Swimlane where to insert card
const swimlane = $(Popup._getTopStack().openerElement).closest('.js-swimlane');
const swimlane = $(Popup._getTopStack().openerElement).closest(
'.js-swimlane',
);
this.swimlaneId = '';
const boardView = (Meteor.user().profile || {}).boardView;
if (boardView === 'board-view-swimlanes')
this.swimlaneId = Blaze.getData(swimlane[0])._id;
else if (boardView === 'board-view-lists' || !boardView)
this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id;
},
boards() {
const boards = Boards.find({
archived: false,
'members.userId': Meteor.userId(),
_id: {$ne: Session.get('currentBoard')},
type: 'board',
}, {
sort: ['title'],
});
const boards = Boards.find(
{
archived: false,
'members.userId': Meteor.userId(),
_id: { $ne: Session.get('currentBoard') },
type: 'board',
},
{
sort: ['title'],
},
);
return boards;
},
@@ -379,7 +423,7 @@ BlazeComponent.extendComponent({
if (!this.selectedBoardId.get()) {
return [];
}
const swimlanes = Swimlanes.find({boardId: this.selectedBoardId.get()});
const swimlanes = Swimlanes.find({ boardId: this.selectedBoardId.get() });
if (swimlanes.count())
this.selectedSwimlaneId.set(swimlanes.fetch()[0]._id);
return swimlanes;
@@ -389,9 +433,8 @@ 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 = Lists.find({ boardId: this.selectedBoardId.get() });
if (lists.count()) this.selectedListId.set(lists.fetch()[0]._id);
return lists;
},
@@ -399,73 +442,84 @@ BlazeComponent.extendComponent({
if (!this.board) {
return [];
}
const ownCardsIds = this.board.cards().map((card) => { return card.linkedId || card._id; });
const ownCardsIds = this.board.cards().map(card => {
return card.linkedId || card._id;
});
return Cards.find({
boardId: this.selectedBoardId.get(),
swimlaneId: this.selectedSwimlaneId.get(),
listId: this.selectedListId.get(),
archived: false,
linkedId: {$nin: ownCardsIds},
_id: {$nin: ownCardsIds},
type: {$nin: ['template-card']},
linkedId: { $nin: ownCardsIds },
_id: { $nin: ownCardsIds },
type: { $nin: ['template-card'] },
});
},
events() {
return [{
'change .js-select-boards'(evt) {
subManager.subscribe('board', $(evt.currentTarget).val(), false);
this.selectedBoardId.set($(evt.currentTarget).val());
},
'change .js-select-swimlanes'(evt) {
this.selectedSwimlaneId.set($(evt.currentTarget).val());
},
'change .js-select-lists'(evt) {
this.selectedListId.set($(evt.currentTarget).val());
},
'click .js-done' (evt) {
// LINK CARD
evt.stopPropagation();
evt.preventDefault();
const linkedId = $('.js-select-cards option:selected').val();
if (!linkedId) {
return [
{
'change .js-select-boards'(evt) {
subManager.subscribe('board', $(evt.currentTarget).val(), false);
this.selectedBoardId.set($(evt.currentTarget).val());
},
'change .js-select-swimlanes'(evt) {
this.selectedSwimlaneId.set($(evt.currentTarget).val());
},
'change .js-select-lists'(evt) {
this.selectedListId.set($(evt.currentTarget).val());
},
'click .js-done'(evt) {
// LINK CARD
evt.stopPropagation();
evt.preventDefault();
const linkedId = $('.js-select-cards option:selected').val();
if (!linkedId) {
Popup.close();
return;
}
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(),
type: 'cardType-linkedCard',
linkedId,
});
Filter.addException(_id);
Popup.close();
return;
}
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(),
type: 'cardType-linkedCard',
linkedId,
});
Filter.addException(_id);
Popup.close();
},
'click .js-link-board' (evt) {
//LINK BOARD
evt.stopPropagation();
evt.preventDefault();
const impBoardId = $('.js-select-boards option:selected').val();
if (!impBoardId || Cards.findOne({linkedId: impBoardId, archived: false})) {
},
'click .js-link-board'(evt) {
//LINK BOARD
evt.stopPropagation();
evt.preventDefault();
const impBoardId = $('.js-select-boards option:selected').val();
if (
!impBoardId ||
Cards.findOne({ linkedId: impBoardId, archived: false })
) {
Popup.close();
return;
}
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(),
type: 'cardType-linkedBoard',
linkedId: impBoardId,
});
Filter.addException(_id);
Popup.close();
return;
}
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(),
type: 'cardType-linkedBoard',
linkedId: impBoardId,
});
Filter.addException(_id);
Popup.close();
},
},
}];
];
},
}).register('linkCardPopup');
@@ -475,11 +529,20 @@ BlazeComponent.extendComponent({
},
onCreated() {
this.isCardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-card-template');
this.isListTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-list-template');
this.isSwimlaneTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-open-add-swimlane-menu');
this.isBoardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass('js-add-board');
this.isTemplateSearch = this.isCardTemplateSearch ||
this.isCardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass(
'js-card-template',
);
this.isListTemplateSearch = $(Popup._getTopStack().openerElement).hasClass(
'js-list-template',
);
this.isSwimlaneTemplateSearch = $(
Popup._getTopStack().openerElement,
).hasClass('js-open-add-swimlane-menu');
this.isBoardTemplateSearch = $(Popup._getTopStack().openerElement).hasClass(
'js-add-board',
);
this.isTemplateSearch =
this.isCardTemplateSearch ||
this.isListTemplateSearch ||
this.isSwimlaneTemplateSearch ||
this.isBoardTemplateSearch;
@@ -491,7 +554,12 @@ BlazeComponent.extendComponent({
board = Boards.findOne({
archived: false,
'members.userId': Meteor.userId(),
_id: {$nin: [Session.get('currentBoard'), (Meteor.user().profile || {}).templatesBoardId]},
_id: {
$nin: [
Session.get('currentBoard'),
(Meteor.user().profile || {}).templatesBoardId,
],
},
});
}
if (!board) {
@@ -509,11 +577,12 @@ BlazeComponent.extendComponent({
subManager.subscribe('board', this.boardId, false);
this.swimlaneId = '';
// Swimlane where to insert card
const swimlane = $(Popup._getTopStack().openerElement).parents('.js-swimlane');
const swimlane = $(Popup._getTopStack().openerElement).parents(
'.js-swimlane',
);
if ((Meteor.user().profile || {}).boardView === 'board-view-swimlanes')
this.swimlaneId = Blaze.getData(swimlane[0])._id;
else
this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
else this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id;
// List where to insert card
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
this.listId = Blaze.getData(list[0])._id;
@@ -522,14 +591,17 @@ BlazeComponent.extendComponent({
},
boards() {
const boards = Boards.find({
archived: false,
'members.userId': Meteor.userId(),
_id: {$ne: Session.get('currentBoard')},
type: 'board',
}, {
sort: ['title'],
});
const boards = Boards.find(
{
archived: false,
'members.userId': Meteor.userId(),
_id: { $ne: Session.get('currentBoard') },
type: 'board',
},
{
sort: ['title'],
},
);
return boards;
},
@@ -546,7 +618,7 @@ BlazeComponent.extendComponent({
return board.searchSwimlanes(this.term.get());
} else if (this.isBoardTemplateSearch) {
const boards = board.searchBoards(this.term.get());
boards.forEach((board) => {
boards.forEach(board => {
subManager.subscribe('board', board.linkedId, false);
});
return boards;
@@ -556,60 +628,69 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'change .js-select-boards'(evt) {
subManager.subscribe('board', $(evt.currentTarget).val(), false);
this.selectedBoardId.set($(evt.currentTarget).val());
},
'submit .js-search-term-form'(evt) {
evt.preventDefault();
this.term.set(evt.target.searchTerm.value);
},
'click .js-minicard'(evt) {
// 0. Common
const title = $('.js-element-title').val().trim();
if (!title)
return;
const element = Blaze.getData(evt.currentTarget);
element.title = title;
let _id = '';
if (!this.isTemplateSearch || this.isCardTemplateSearch) {
// Card insertion
// 1. Common
element.sort = Lists.findOne(this.listId).cards().count();
// 1.A From template
if (this.isTemplateSearch) {
element.type = 'cardType-card';
element.linkedId = '';
_id = element.copy(this.boardId, this.swimlaneId, this.listId);
// 1.B Linked card
} else {
delete element._id;
element.type = 'cardType-linkedCard';
element.linkedId = element.linkedId || element._id;
_id = Cards.insert(element);
return [
{
'change .js-select-boards'(evt) {
subManager.subscribe('board', $(evt.currentTarget).val(), false);
this.selectedBoardId.set($(evt.currentTarget).val());
},
'submit .js-search-term-form'(evt) {
evt.preventDefault();
this.term.set(evt.target.searchTerm.value);
},
'click .js-minicard'(evt) {
// 0. Common
const title = $('.js-element-title')
.val()
.trim();
if (!title) return;
const element = Blaze.getData(evt.currentTarget);
element.title = title;
let _id = '';
if (!this.isTemplateSearch || this.isCardTemplateSearch) {
// Card insertion
// 1. Common
element.sort = Lists.findOne(this.listId)
.cards()
.count();
// 1.A From template
if (this.isTemplateSearch) {
element.type = 'cardType-card';
element.linkedId = '';
_id = element.copy(this.boardId, this.swimlaneId, this.listId);
// 1.B Linked card
} else {
delete element._id;
element.type = 'cardType-linkedCard';
element.linkedId = element.linkedId || element._id;
_id = Cards.insert(element);
}
Filter.addException(_id);
// List insertion
} else if (this.isListTemplateSearch) {
element.sort = Swimlanes.findOne(this.swimlaneId)
.lists()
.count();
element.type = 'list';
_id = element.copy(this.boardId, this.swimlaneId);
} else if (this.isSwimlaneTemplateSearch) {
element.sort = Boards.findOne(this.boardId)
.swimlanes()
.count();
element.type = 'swimlalne';
_id = element.copy(this.boardId);
} else if (this.isBoardTemplateSearch) {
board = Boards.findOne(element.linkedId);
board.sort = Boards.find({ archived: false }).count();
board.type = 'board';
board.title = element.title;
delete board.slug;
_id = board.copy();
}
Filter.addException(_id);
// List insertion
} else if (this.isListTemplateSearch) {
element.sort = Swimlanes.findOne(this.swimlaneId).lists().count();
element.type = 'list';
_id = element.copy(this.boardId, this.swimlaneId);
} else if (this.isSwimlaneTemplateSearch) {
element.sort = Boards.findOne(this.boardId).swimlanes().count();
element.type = 'swimlalne';
_id = element.copy(this.boardId);
} else if (this.isBoardTemplateSearch) {
board = Boards.findOne(element.linkedId);
board.sort = Boards.find({archived: false}).count();
board.type = 'board';
board.title = element.title;
delete board.slug;
_id = board.copy();
}
Popup.close();
Popup.close();
},
},
}];
];
},
}).register('searchElementPopup');
@@ -622,15 +703,23 @@ BlazeComponent.extendComponent({
const boardView = (Meteor.user().profile || {}).boardView;
if (boardView === 'board-view-swimlanes')
this.swimlaneId = this.parentComponent().parentComponent().parentComponent().data()._id;
this.swimlaneId = this.parentComponent()
.parentComponent()
.parentComponent()
.data()._id;
},
onRendered() {
this.spinner = this.find('.sk-spinner-list');
this.container = this.$(this.spinner).parents('.js-perfect-scrollbar')[0];
$(this.container).on(`scroll.spinner_${this.swimlaneId}_${this.listId}`, () => this.updateList());
$(window).on(`resize.spinner_${this.swimlaneId}_${this.listId}`, () => this.updateList());
$(this.container).on(
`scroll.spinner_${this.swimlaneId}_${this.listId}`,
() => this.updateList(),
);
$(window).on(`resize.spinner_${this.swimlaneId}_${this.listId}`, () =>
this.updateList(),
);
this.updateList();
},
@@ -660,5 +749,4 @@ BlazeComponent.extendComponent({
return bottomViewPosition > threshold;
},
}).register('spinnerList');
+1 -1
View File
@@ -9,7 +9,7 @@ template(name="listHeader")
if currentList
a.list-header-left-icon.fa.fa-angle-left.js-unselect-list
h2.list-header-name(
class="{{#if currentUser.isBoardMember}}js-open-inlined-form is-editable{{/if}}")
class="{{#if currentUser.isBoardMember}}{{#unless currentUser.isCommentOnly}}js-open-inlined-form is-editable{{/unless}}{{/if}}")
+viewer
= title
if wipLimit.enabled
+84 -52
View File
@@ -6,12 +6,18 @@ Meteor.startup(() => {
BlazeComponent.extendComponent({
canSeeAddCard() {
const list = Template.currentData();
return !list.getWipLimit('enabled') || list.getWipLimit('soft') || !this.reachedWipLimit();
return (
!list.getWipLimit('enabled') ||
list.getWipLimit('soft') ||
!this.reachedWipLimit()
);
},
editTitle(evt) {
evt.preventDefault();
const newTitle = this.childComponents('inlinedForm')[0].getValue().trim();
editTitle(event) {
event.preventDefault();
const newTitle = this.childComponents('inlinedForm')[0]
.getValue()
.trim();
const list = this.currentData();
if (newTitle) {
list.rename(newTitle.trim());
@@ -32,14 +38,19 @@ BlazeComponent.extendComponent({
let swimlaneId = '';
const boardView = (Meteor.user().profile || {}).boardView;
if (boardView === 'board-view-swimlanes')
swimlaneId = this.parentComponent().parentComponent().data()._id;
swimlaneId = this.parentComponent()
.parentComponent()
.data()._id;
return list.cards(swimlaneId).count();
},
reachedWipLimit() {
const list = Template.currentData();
return list.getWipLimit('enabled') && list.getWipLimit('value') <= list.cards().count();
return (
list.getWipLimit('enabled') &&
list.getWipLimit('value') <= list.cards().count()
);
},
showCardsCountForList(count) {
@@ -48,20 +59,24 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-open-list-menu': Popup.open('listAction'),
'click .js-add-card' (evt) {
const listDom = $(evt.target).parents(`#js-list-${this.currentData()._id}`)[0];
const listComponent = BlazeComponent.getComponentForElement(listDom);
listComponent.openForm({
position: 'top',
});
return [
{
'click .js-open-list-menu': Popup.open('listAction'),
'click .js-add-card'(event) {
const listDom = $(event.target).parents(
`#js-list-${this.currentData()._id}`,
)[0];
const listComponent = BlazeComponent.getComponentForElement(listDom);
listComponent.openForm({
position: 'top',
});
},
'click .js-unselect-list'() {
Session.set('currentList', null);
},
submit: this.editTitle,
},
'click .js-unselect-list'() {
Session.set('currentList', null);
},
submit: this.editTitle,
}];
];
},
}).register('listHeader');
@@ -76,22 +91,22 @@ Template.listActionPopup.helpers({
});
Template.listActionPopup.events({
'click .js-list-subscribe' () {},
'click .js-list-subscribe'() {},
'click .js-set-color-list': Popup.open('setListColor'),
'click .js-select-cards' () {
const cardIds = this.allCards().map((card) => card._id);
'click .js-select-cards'() {
const cardIds = this.allCards().map(card => card._id);
MultiSelection.add(cardIds);
Popup.close();
},
'click .js-toggle-watch-list' () {
'click .js-toggle-watch-list'() {
const currentList = this;
const level = currentList.findWatcher(Meteor.userId()) ? null : 'watching';
Meteor.call('watch', 'list', currentList._id, level, (err, ret) => {
if (!err && ret) Popup.close();
});
},
'click .js-close-list' (evt) {
evt.preventDefault();
'click .js-close-list'(event) {
event.preventDefault();
this.archive();
Popup.close();
},
@@ -102,10 +117,17 @@ Template.listActionPopup.events({
BlazeComponent.extendComponent({
applyWipLimit() {
const list = Template.currentData();
const limit = parseInt(Template.instance().$('.wip-limit-value').val(), 10);
const limit = parseInt(
Template.instance()
.$('.wip-limit-value')
.val(),
10,
);
if(limit < list.cards().count() && !list.getWipLimit('soft')){
Template.instance().$('.wip-limit-error').click();
if (limit < list.cards().count() && !list.getWipLimit('soft')) {
Template.instance()
.$('.wip-limit-error')
.click();
} else {
Meteor.call('applyWipLimit', list._id, limit);
Popup.back();
@@ -115,7 +137,10 @@ BlazeComponent.extendComponent({
enableSoftLimit() {
const list = Template.currentData();
if(list.getWipLimit('soft') && list.getWipLimit('value') < list.cards().count()){
if (
list.getWipLimit('soft') &&
list.getWipLimit('value') < list.cards().count()
) {
list.setWipLimit(list.cards().count());
}
Meteor.call('enableSoftLimit', Template.currentData()._id);
@@ -124,7 +149,10 @@ BlazeComponent.extendComponent({
enableWipLimit() {
const list = Template.currentData();
// 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()){
if (
!list.getWipLimit('enabled') &&
list.getWipLimit('value') < list.cards().count()
) {
list.setWipLimit(list.cards().count());
}
Meteor.call('enableWipLimit', list._id);
@@ -138,24 +166,26 @@ BlazeComponent.extendComponent({
return Template.currentData().getWipLimit('enabled');
},
wipLimitValue(){
wipLimitValue() {
return Template.currentData().getWipLimit('value');
},
events() {
return [{
'click .js-enable-wip-limit': this.enableWipLimit,
'click .wip-limit-apply': this.applyWipLimit,
'click .wip-limit-error': Popup.open('wipLimitError'),
'click .materialCheckBox': this.enableSoftLimit,
}];
return [
{
'click .js-enable-wip-limit': this.enableWipLimit,
'click .wip-limit-apply': this.applyWipLimit,
'click .wip-limit-error': Popup.open('wipLimitError'),
'click .materialCheckBox': this.enableSoftLimit,
},
];
},
}).register('setWipLimitPopup');
Template.listMorePopup.events({
'click .js-delete': Popup.afterConfirm('listDelete', function () {
'click .js-delete': Popup.afterConfirm('listDelete', function() {
Popup.close();
this.allCards().map((card) => Cards.remove(card._id));
this.allCards().map(card => Cards.remove(card._id));
Lists.remove(this._id);
Utils.goBoardId(this.boardId);
}),
@@ -168,7 +198,7 @@ BlazeComponent.extendComponent({
},
colors() {
return listsColors.map((color) => ({ color, name: '' }));
return listsColors.map(color => ({ color, name: '' }));
},
isSelected(color) {
@@ -176,18 +206,20 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
return [
{
'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
},
'click .js-submit'() {
this.currentList.setColor(this.currentColor.get());
Popup.close();
},
'click .js-remove-color'() {
this.currentList.setColor(null);
Popup.close();
},
},
'click .js-submit' () {
this.currentList.setColor(this.currentColor.get());
Popup.close();
},
'click .js-remove-color'() {
this.currentList.setColor(null);
Popup.close();
},
}];
];
},
}).register('setListColorPopup');
+63 -54
View File
@@ -9,10 +9,15 @@ Template.editor.onRendered(() => {
match: /\B@([\w.]*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
callback(currentBoard.activeMembers().map((member) => {
const username = Users.findOne(member.userId).username;
return username.includes(term) ? username : null;
}).filter(Boolean));
callback(
currentBoard
.activeMembers()
.map(member => {
const username = Users.findOne(member.userId).username;
return username.includes(term) ? username : null;
})
.filter(Boolean),
);
},
template(value) {
return value;
@@ -33,69 +38,73 @@ import sanitizeXss from 'xss';
// compiled version to most users -- who don't need to edit.
// In the meantime, all the transformation are done on the client using the
// Blaze API.
const at = HTML.CharRef({html: '&commat;', str: '@'});
Blaze.Template.registerHelper('mentions', new Template('mentions', function() {
const view = this;
let content = Blaze.toHTML(view.templateContentBlock);
const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (!currentBoard)
const at = HTML.CharRef({ html: '&commat;', str: '@' });
Blaze.Template.registerHelper(
'mentions',
new Template('mentions', function() {
const view = this;
let content = Blaze.toHTML(view.templateContentBlock);
const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (!currentBoard) return HTML.Raw(sanitizeXss(content));
const knowedUsers = currentBoard.members.map(member => {
const u = Users.findOne(member.userId);
if (u) {
member.username = u.username;
}
return member;
});
const mentionRegex = /\B@([\w.]*)/gi;
let currentMention;
while ((currentMention = mentionRegex.exec(content)) !== null) {
const [fullMention, username] = currentMention;
const knowedUser = _.findWhere(knowedUsers, { username });
if (!knowedUser) {
continue;
}
const linkValue = [' ', at, knowedUser.username];
let linkClass = 'atMention js-open-member';
if (knowedUser.userId === Meteor.userId()) {
linkClass += ' me';
}
const link = HTML.A(
{
class: linkClass,
// XXX Hack. Since we stringify this render function result below with
// `Blaze.toHTML` we can't rely on blaze data contexts to pass the
// `userId` to the popup as usual, and we need to store it in the DOM
// using a data attribute.
'data-userId': knowedUser.userId,
},
linkValue,
);
content = content.replace(fullMention, Blaze.toHTML(link));
}
return HTML.Raw(sanitizeXss(content));
const knowedUsers = currentBoard.members.map((member) => {
const u = Users.findOne(member.userId);
if(u){
member.username = u.username;
}
return member;
});
const mentionRegex = /\B@([\w.]*)/gi;
let currentMention;
while ((currentMention = mentionRegex.exec(content)) !== null) {
const [fullMention, username] = currentMention;
const knowedUser = _.findWhere(knowedUsers, { username });
if (!knowedUser) {
continue;
}
const linkValue = [' ', at, knowedUser.username];
let linkClass = 'atMention js-open-member';
if (knowedUser.userId === Meteor.userId()) {
linkClass += ' me';
}
const link = HTML.A({
'class': linkClass,
// XXX Hack. Since we stringify this render function result below with
// `Blaze.toHTML` we can't rely on blaze data contexts to pass the
// `userId` to the popup as usual, and we need to store it in the DOM
// using a data attribute.
'data-userId': knowedUser.userId,
}, linkValue);
content = content.replace(fullMention, Blaze.toHTML(link));
}
return HTML.Raw(sanitizeXss(content));
}));
}),
);
Template.viewer.events({
// Viewer sometimes have click-able wrapper around them (for instance to edit
// the corresponding text). Clicking a link shouldn't fire these actions, stop
// we stop these event at the viewer component level.
'click a'(evt, tpl) {
evt.stopPropagation();
'click a'(event, templateInstance) {
event.stopPropagation();
// XXX We hijack the build-in browser action because we currently don't have
// `_blank` attributes in viewer links, and the transformer function is
// handled by a third party package that we can't configure easily. Fix that
// by using directly `_blank` attribute in the rendered HTML.
evt.preventDefault();
event.preventDefault();
const userId = evt.currentTarget.dataset.userid;
const userId = event.currentTarget.dataset.userid;
if (userId) {
Popup.open('member').call({ userId }, evt, tpl);
}
else {
const href = evt.currentTarget.href;
Popup.open('member').call({ userId }, event, templateInstance);
} else {
const href = event.currentTarget.href;
if (href) {
window.open(href, '_blank');
}
+2 -2
View File
@@ -20,13 +20,13 @@ Template.header.helpers({
},
hasAnnouncement() {
const announcements = Announcements.findOne();
const announcements = Announcements.findOne();
return announcements && announcements.enabled;
},
announcement() {
$('.announcement').show();
const announcements = Announcements.findOne();
const announcements = Announcements.findOne();
return announcements && announcements.body;
},
});
+40 -32
View File
@@ -1,6 +1,6 @@
BlazeLayout.setRoot('body');
const i18nTagToT9n = (i18nTag) => {
const i18nTagToT9n = i18nTag => {
// t9n/i18n tags are same now, see: https://github.com/softwarerero/meteor-accounts-t9n/pull/129
// but we keep this conversion function here, to be aware that that they are different system.
return i18nTag;
@@ -21,20 +21,23 @@ const validator = {
};
Template.userFormsLayout.onCreated(function() {
const instance = this;
instance.currentSetting = new ReactiveVar();
instance.isLoading = new ReactiveVar(false);
const templateInstance = this;
templateInstance.currentSetting = new ReactiveVar();
templateInstance.isLoading = new ReactiveVar(false);
Meteor.subscribe('setting', {
onReady() {
instance.currentSetting.set(Settings.findOne());
templateInstance.currentSetting.set(Settings.findOne());
return this.stop();
},
});
});
Template.userFormsLayout.onRendered(() => {
AccountsTemplates.state.form.keys = new Proxy(AccountsTemplates.state.form.keys, validator);
AccountsTemplates.state.form.keys = new Proxy(
AccountsTemplates.state.form.keys,
validator,
);
const i18nTag = navigator.language;
if (i18nTag) {
@@ -89,18 +92,17 @@ Template.userFormsLayout.helpers({
});
Template.userFormsLayout.events({
'change .js-userform-set-language'(evt) {
const i18nTag = $(evt.currentTarget).val();
'change .js-userform-set-language'(event) {
const i18nTag = $(event.currentTarget).val();
T9n.setLanguage(i18nTagToT9n(i18nTag));
evt.preventDefault();
event.preventDefault();
},
'click #at-btn'(event, instance) {
'click #at-btn'(event, templateInstance) {
if (FlowRouter.getRouteName() === 'atSignIn') {
instance.isLoading.set(true);
authentication(event, instance)
.then(() => {
instance.isLoading.set(false);
});
templateInstance.isLoading.set(true);
authentication(event, templateInstance).then(() => {
templateInstance.isLoading.set(false);
});
}
},
});
@@ -111,13 +113,16 @@ Template.defaultLayout.events({
},
});
async function authentication(event, instance) {
async function authentication(event, templateInstance) {
const match = $('#at-field-username_and_email').val();
const password = $('#at-field-password').val();
if (!match || !password) return undefined;
const result = await getAuthenticationMethod(instance.currentSetting.get(), match);
const result = await getAuthenticationMethod(
templateInstance.currentSetting.get(),
match,
);
if (result === 'password') return undefined;
@@ -126,26 +131,29 @@ async function authentication(event, instance) {
event.stopImmediatePropagation();
switch (result) {
case 'ldap':
return new Promise((resolve) => {
Meteor.loginWithLDAP(match, password, function() {
resolve(FlowRouter.go('/'));
case 'ldap':
return new Promise(resolve => {
Meteor.loginWithLDAP(match, password, function() {
resolve(FlowRouter.go('/'));
});
});
});
case 'cas':
return new Promise((resolve) => {
Meteor.loginWithCas(match, password, function() {
resolve(FlowRouter.go('/'));
case 'cas':
return new Promise(resolve => {
Meteor.loginWithCas(match, password, function() {
resolve(FlowRouter.go('/'));
});
});
});
default:
return undefined;
default:
return undefined;
}
}
function getAuthenticationMethod({displayAuthenticationMethod, defaultAuthenticationMethod}, match) {
function getAuthenticationMethod(
{ displayAuthenticationMethod, defaultAuthenticationMethod },
match,
) {
if (displayAuthenticationMethod) {
return $('.select-authentication').val();
}
@@ -153,7 +161,7 @@ function getAuthenticationMethod({displayAuthenticationMethod, defaultAuthentica
}
function getUserAuthenticationMethod(defaultAuthenticationMethod, match) {
return new Promise((resolve) => {
return new Promise(resolve => {
try {
Meteor.subscribe('user-authenticationMethod', match, {
onReady() {
@@ -166,7 +174,7 @@ function getUserAuthenticationMethod(defaultAuthenticationMethod, match) {
resolve(authenticationMethod);
},
});
} catch(error) {
} catch (error) {
resolve(defaultAuthenticationMethod);
}
});
+11 -9
View File
@@ -18,15 +18,17 @@ Mixins.InfiniteScrolling = BlazeComponent.extendComponent({
},
events() {
return [{
scroll(evt) {
const domElement = evt.currentTarget;
let altitude = domElement.scrollTop + domElement.offsetHeight;
altitude += peakAnticipation;
if (altitude >= this.callFirstWith(null, 'getNextPeak')) {
this.mixinParent().callFirstWith(null, 'reachNextPeak');
}
return [
{
scroll(evt) {
const domElement = evt.currentTarget;
let altitude = domElement.scrollTop + domElement.offsetHeight;
altitude += peakAnticipation;
if (altitude >= this.callFirstWith(null, 'getNextPeak')) {
this.mixinParent().callFirstWith(null, 'reachNextPeak');
}
},
},
}];
];
},
});
+158 -161
View File
@@ -1,168 +1,165 @@
BlazeComponent.extendComponent({
onCreated() {
},
onCreated() {},
events() {
return [{
'click .js-create-card-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const cardName = this.find('#card-name').value;
const listName = this.find('#list-name').value;
const swimlaneName = this.find('#swimlane-name2').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'createCard',
swimlaneName,
cardName,
listName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
return [
{
'click .js-create-card-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const cardName = this.find('#card-name').value;
const listName = this.find('#list-name').value;
const swimlaneName = this.find('#swimlane-name2').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'createCard',
swimlaneName,
cardName,
listName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
},
'click .js-add-swimlane-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const swimlaneName = this.find('#swimlane-name').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'addSwimlane',
swimlaneName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
},
'click .js-add-spec-move-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#move-spec-action').value;
const listTitle = this.find('#listName').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'top') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'moveCardToTop',
listTitle,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'bottom') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'moveCardToBottom',
listTitle,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
'click .js-add-gen-move-action'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const boardId = Session.get('currentBoard');
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#move-gen-action').value;
if (actionSelected === 'top') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'moveCardToTop',
listTitle: '*',
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'bottom') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'moveCardToBottom',
listTitle: '*',
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
'click .js-add-arch-action'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const boardId = Session.get('currentBoard');
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#arch-action').value;
if (actionSelected === 'archive') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'archive',
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'unarchive') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'unarchive',
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
},
'click .js-add-swimlane-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const swimlaneName = this.find('#swimlane-name').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'addSwimlane',
swimlaneName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
},
'click .js-add-spec-move-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#move-spec-action').value;
const listTitle = this.find('#listName').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'top') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'moveCardToTop',
listTitle,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'bottom') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'moveCardToBottom',
listTitle,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
'click .js-add-gen-move-action' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const boardId = Session.get('currentBoard');
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#move-gen-action').value;
if (actionSelected === 'top') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'moveCardToTop',
'listTitle': '*',
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'bottom') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'moveCardToBottom',
'listTitle': '*',
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
'click .js-add-arch-action' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const boardId = Session.get('currentBoard');
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#arch-action').value;
if (actionSelected === 'archive') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'archive',
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'unarchive') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'unarchive',
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
}];
];
},
}).register('boardActions');
/* eslint-no-undef */
@@ -1,11 +1,44 @@
template(name="cardActions")
div.trigger-item
div.trigger-content
div.trigger-dropdown
select(id="setdate-action")
option(value="setDate") {{{_'r-set'}}}
option(value="updateDate") {{{_'r-update'}}}
div.trigger-text
| {{{_'r-datefield'}}}
div.trigger-dropdown
select(id="setdate-datefield")
option(value="startAt") {{{_'r-df-start-at'}}}
option(value="dueAt") {{{_'r-df-due-at'}}}
option(value="endAt") {{{_'r-df-end-at'}}}
option(value="receivedAt") {{{_'r-df-received-at'}}}
div.trigger-text
| {{{_'r-to-current-datetime'}}}
div.trigger-button.js-set-date-action.js-goto-rules
i.fa.fa-plus
div.trigger-item
div.trigger-content
div.trigger-text
| {{{_'r-remove-value-from'}}}
| {{{_'r-datefield'}}}
div.trigger-dropdown
select(id="setdate-removedatefieldvalue")
option(value="startAt") {{{_'r-df-start-at'}}}
option(value="dueAt") {{{_'r-df-due-at'}}}
option(value="endAt") {{{_'r-df-end-at'}}}
option(value="receivedAt") {{{_'r-df-received-at'}}}
div.trigger-button.js-remove-datevalue-action.js-goto-rules
i.fa.fa-plus
div.trigger-item
div.trigger-content
div.trigger-dropdown
select(id="label-action")
option(value="add") {{{_'r-add'}}}
option(value="remove") {{{_'r-remove'}}}
div.trigger-text
div.trigger-text
| {{{_'r-label'}}}
div.trigger-dropdown
select(id="label-id")
@@ -21,16 +54,16 @@ template(name="cardActions")
select(id="member-action")
option(value="add") {{{_'r-add'}}}
option(value="remove") {{{_'r-remove'}}}
div.trigger-text
div.trigger-text
| {{{_'r-member'}}}
div.trigger-dropdown
input(id="member-name",type=text,placeholder="{{{_'r-name'}}}")
input(id="member-name",type=text,placeholder="{{{_'r-name'}}}")
div.trigger-button.js-add-member-action.js-goto-rules
i.fa.fa-plus
div.trigger-item
div.trigger-content
div.trigger-text
div.trigger-text
| {{{_'r-remove-all'}}}
div.trigger-button.js-add-removeall-action.js-goto-rules
i.fa.fa-plus
+163 -112
View File
@@ -14,7 +14,7 @@ BlazeComponent.extendComponent({
},
cardColorButtonText() {
return `color-${ this.cardColorButtonValue.get() }`;
return `color-${this.cardColorButtonValue.get()}`;
},
labels() {
@@ -28,61 +28,24 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-add-label-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#label-action').value;
const labelId = this.find('#label-id').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'add') {
return [
{
'click .js-set-date-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'addLabel',
labelId,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'remove') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'removeLabel',
labelId,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
const actionSelected = this.find('#setdate-action').value;
const dateFieldSelected = this.find('#setdate-datefield').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
},
'click .js-add-member-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#member-action').value;
const username = this.find('#member-name').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'add') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'addMember',
username,
actionType: actionSelected,
dateField: dateFieldSelected,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
@@ -90,12 +53,118 @@ BlazeComponent.extendComponent({
boardId,
desc,
});
}
if (actionSelected === 'remove') {
},
'click .js-remove-datevalue-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const triggerId = Triggers.insert(trigger);
const dateFieldSelected = this.find('#setdate-removedatefieldvalue')
.value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const actionId = Actions.insert({
actionType: 'removeDate',
dateField: dateFieldSelected,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
desc,
});
},
'click .js-add-label-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#label-action').value;
const labelId = this.find('#label-id').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'add') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'addLabel',
labelId,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'remove') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'removeLabel',
labelId,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
'click .js-add-member-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#member-action').value;
const username = this.find('#member-name').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'add') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'addMember',
username,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
desc,
});
}
if (actionSelected === 'remove') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'removeMember',
username,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
'click .js-add-removeall-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const triggerId = Triggers.insert(trigger);
const desc = Utils.getTriggerActionDesc(event, this);
const boardId = Session.get('currentBoard');
const actionId = Actions.insert({
actionType: 'removeMember',
username,
username: '*',
boardId,
desc,
});
@@ -105,58 +174,38 @@ BlazeComponent.extendComponent({
actionId,
boardId,
});
}
},
'click .js-show-color-palette'(event) {
const funct = Popup.open('setCardActionsColor');
const colorButton = this.find('#color-action');
if (colorButton.value === '') {
colorButton.value = 'green';
}
funct.call(this, event);
},
'click .js-set-color-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const selectedColor = this.cardColorButtonValue.get();
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'setColor',
selectedColor,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
},
},
'click .js-add-removeall-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const triggerId = Triggers.insert(trigger);
const desc = Utils.getTriggerActionDesc(event, this);
const boardId = Session.get('currentBoard');
const actionId = Actions.insert({
actionType: 'removeMember',
'username': '*',
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
},
'click .js-show-color-palette'(event){
const funct = Popup.open('setCardActionsColor');
const colorButton = this.find('#color-action');
if (colorButton.value === '') {
colorButton.value = 'green';
}
funct.call(this, event);
},
'click .js-set-color-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const selectedColor = this.cardColorButtonValue.get();
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'setColor',
selectedColor,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
},
}];
];
},
}).register('cardActions');
BlazeComponent.extendComponent({
@@ -167,7 +216,7 @@ BlazeComponent.extendComponent({
},
colors() {
return cardColors.map((color) => ({ color, name: '' }));
return cardColors.map(color => ({ color, name: '' }));
},
isSelected(color) {
@@ -175,14 +224,16 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
return [
{
'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
},
'click .js-submit'() {
this.colorButtonValue.set(this.currentColor.get());
Popup.close();
},
},
'click .js-submit' () {
this.colorButtonValue.set(this.currentColor.get());
Popup.close();
},
}];
];
},
}).register('setCardActionsColorPopup');
@@ -3,149 +3,148 @@ BlazeComponent.extendComponent({
this.subscribe('allRules');
},
events() {
return [{
'click .js-add-checklist-items-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const checklistName = this.find('#checklist-name-3').value;
const checklistItems = this.find('#checklist-items').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'addChecklistWithItems',
checklistName,
checklistItems,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
return [
{
'click .js-add-checklist-items-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const checklistName = this.find('#checklist-name-3').value;
const checklistItems = this.find('#checklist-items').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'addChecklistWithItems',
checklistName,
checklistItems,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
},
'click .js-add-checklist-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#check-action').value;
const checklistName = this.find('#checklist-name').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'add') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'addChecklist',
checklistName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'remove') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'removeChecklist',
checklistName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
'click .js-add-checkall-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#checkall-action').value;
const checklistName = this.find('#checklist-name2').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'check') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'checkAll',
checklistName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'uncheck') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'uncheckAll',
checklistName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
'click .js-add-check-item-action'(event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const checkItemName = this.find('#checkitem-name');
const checklistName = this.find('#checklist-name3');
const actionSelected = this.find('#check-item-action').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'check') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'checkItem',
checklistName,
checkItemName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'uncheck') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'uncheckItem',
checklistName,
checkItemName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
},
'click .js-add-checklist-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#check-action').value;
const checklistName = this.find('#checklist-name').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'add') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'addChecklist',
checklistName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'remove') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'removeChecklist',
checklistName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
'click .js-add-checkall-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const actionSelected = this.find('#checkall-action').value;
const checklistName = this.find('#checklist-name2').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'check') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'checkAll',
checklistName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'uncheck') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'uncheckAll',
checklistName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
'click .js-add-check-item-action' (event) {
const ruleName = this.data().ruleName.get();
const trigger = this.data().triggerVar.get();
const checkItemName = this.find('#checkitem-name');
const checklistName = this.find('#checklist-name3');
const actionSelected = this.find('#check-item-action').value;
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
if (actionSelected === 'check') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'checkItem',
checklistName,
checkItemName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
if (actionSelected === 'uncheck') {
const triggerId = Triggers.insert(trigger);
const actionId = Actions.insert({
actionType: 'uncheckItem',
checklistName,
checkItemName,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
}
},
}];
];
},
}).register('checklistActions');
+28 -29
View File
@@ -1,35 +1,34 @@
BlazeComponent.extendComponent({
onCreated() {
},
onCreated() {},
events() {
return [{
'click .js-mail-action' (event) {
const emailTo = this.find('#email-to').value;
const emailSubject = this.find('#email-subject').value;
const emailMsg = this.find('#email-msg').value;
const trigger = this.data().triggerVar.get();
const ruleName = this.data().ruleName.get();
const triggerId = Triggers.insert(trigger);
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const actionId = Actions.insert({
actionType: 'sendEmail',
emailTo,
emailSubject,
emailMsg,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
return [
{
'click .js-mail-action'(event) {
const emailTo = this.find('#email-to').value;
const emailSubject = this.find('#email-subject').value;
const emailMsg = this.find('#email-msg').value;
const trigger = this.data().triggerVar.get();
const ruleName = this.data().ruleName.get();
const triggerId = Triggers.insert(trigger);
const boardId = Session.get('currentBoard');
const desc = Utils.getTriggerActionDesc(event, this);
const actionId = Actions.insert({
actionType: 'sendEmail',
emailTo,
emailSubject,
emailMsg,
boardId,
desc,
});
Rules.insert({
title: ruleName,
triggerId,
actionId,
boardId,
});
},
},
}];
];
},
}).register('mailActions');
-2
View File
@@ -3,7 +3,6 @@ BlazeComponent.extendComponent({
this.subscribe('allRules');
this.subscribe('allTriggers');
this.subscribe('allActions');
},
trigger() {
@@ -34,5 +33,4 @@ BlazeComponent.extendComponent({
events() {
return [{}];
},
}).register('ruleDetails');
+15 -13
View File
@@ -40,19 +40,21 @@ BlazeComponent.extendComponent({
// console.log(this.data());
},
events() {
return [{
'click .js-set-board-actions'(){
this.setBoardActions();
return [
{
'click .js-set-board-actions'() {
this.setBoardActions();
},
'click .js-set-card-actions'() {
this.setCardActions();
},
'click .js-set-mail-actions'() {
this.setMailActions();
},
'click .js-set-checklist-actions'() {
this.setChecklistActions();
},
},
'click .js-set-card-actions'() {
this.setCardActions();
},
'click .js-set-mail-actions'() {
this.setMailActions();
},
'click .js-set-checklist-actions'() {
this.setChecklistActions();
},
}];
];
},
}).register('rulesActions');
+11 -1
View File
@@ -17,6 +17,10 @@ template(name="rulesList")
button.js-delete-rule
i.fa.fa-trash-o
| {{{_ 'r-delete-rule'}}}
else if currentUser.isBoardAdmin
button.js-delete-rule
i.fa.fa-trash-o
| {{{_ 'r-delete-rule'}}}
else
li.no-items-message {{{_ 'r-no-rules' }}}
if currentUser.isAdmin
@@ -24,4 +28,10 @@ template(name="rulesList")
button.js-goto-trigger
i.fa.fa-plus
| {{{_ 'r-add-rule'}}}
input(type=text,placeholder="{{{_ 'r-new-rule-name' }}}",id="ruleTitle")
input(type=text,placeholder="{{{_ 'r-new-rule-name' }}}",id="ruleTitle")
else if currentUser.isBoardAdmin
div.rules-add
button.js-goto-trigger
i.fa.fa-plus
| {{{_ 'r-add-rule'}}}
input(type=text,placeholder="{{{_ 'r-new-rule-name' }}}",id="ruleTitle")
+70 -66
View File
@@ -9,12 +9,12 @@ BlazeComponent.extendComponent({
setTrigger() {
this.rulesCurrentTab.set('trigger');
},
sanitizeObject(obj){
Object.keys(obj).forEach((key) => {
if(obj[key] === '' || obj[key] === undefined){
sanitizeObject(obj) {
Object.keys(obj).forEach(key => {
if (obj[key] === '' || obj[key] === undefined) {
obj[key] = '*';
}}
);
}
});
},
setRulesList() {
this.rulesCurrentTab.set('rulesList');
@@ -29,69 +29,73 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-delete-rule' () {
const rule = this.currentData();
Rules.remove(rule._id);
Actions.remove(rule.actionId);
Triggers.remove(rule.triggerId);
},
'click .js-goto-trigger' (event) {
event.preventDefault();
const ruleTitle = this.find('#ruleTitle').value;
if(ruleTitle !== undefined && ruleTitle !== ''){
this.find('#ruleTitle').value = '';
this.ruleName.set(ruleTitle);
this.setTrigger();
}
},
'click .js-goto-action' (event) {
event.preventDefault();
// Add user to the trigger
const username = $(event.currentTarget.offsetParent).find('.user-name').val();
let trigger = this.triggerVar.get();
trigger.userId = '*';
if(username !== undefined ){
const userFound = Users.findOne({username});
if(userFound !== undefined){
trigger.userId = userFound._id;
this.triggerVar.set(trigger);
return [
{
'click .js-delete-rule'() {
const rule = this.currentData();
Rules.remove(rule._id);
Actions.remove(rule.actionId);
Triggers.remove(rule.triggerId);
},
'click .js-goto-trigger'(event) {
event.preventDefault();
const ruleTitle = this.find('#ruleTitle').value;
if (ruleTitle !== undefined && ruleTitle !== '') {
this.find('#ruleTitle').value = '';
this.ruleName.set(ruleTitle);
this.setTrigger();
}
}
// Sanitize trigger
trigger = this.triggerVar.get();
this.sanitizeObject(trigger);
this.triggerVar.set(trigger);
this.setAction();
},
'click .js-show-user-field' (event) {
event.preventDefault();
$(event.currentTarget.offsetParent).find('.user-details').removeClass('hide-element');
},
'click .js-goto-rules' (event) {
event.preventDefault();
this.setRulesList();
},
'click .js-goback' (event) {
event.preventDefault();
if(this.rulesCurrentTab.get() === 'trigger' || this.rulesCurrentTab.get() === 'ruleDetails' ){
},
'click .js-goto-action'(event) {
event.preventDefault();
// Add user to the trigger
const username = $(event.currentTarget.offsetParent)
.find('.user-name')
.val();
let trigger = this.triggerVar.get();
trigger.userId = '*';
if (username !== undefined) {
const userFound = Users.findOne({ username });
if (userFound !== undefined) {
trigger.userId = userFound._id;
this.triggerVar.set(trigger);
}
}
// Sanitize trigger
trigger = this.triggerVar.get();
this.sanitizeObject(trigger);
this.triggerVar.set(trigger);
this.setAction();
},
'click .js-show-user-field'(event) {
event.preventDefault();
$(event.currentTarget.offsetParent)
.find('.user-details')
.removeClass('hide-element');
},
'click .js-goto-rules'(event) {
event.preventDefault();
this.setRulesList();
}
if(this.rulesCurrentTab.get() === 'action'){
this.setTrigger();
}
},
'click .js-goback'(event) {
event.preventDefault();
if (
this.rulesCurrentTab.get() === 'trigger' ||
this.rulesCurrentTab.get() === 'ruleDetails'
) {
this.setRulesList();
}
if (this.rulesCurrentTab.get() === 'action') {
this.setTrigger();
}
},
'click .js-goto-details'(event) {
event.preventDefault();
const rule = this.currentData();
this.ruleId.set(rule._id);
this.setRuleDetails();
},
},
'click .js-goto-details' (event) {
event.preventDefault();
const rule = this.currentData();
this.ruleId.set(rule._id);
this.setRuleDetails();
},
}];
];
},
}).register('rulesMain');
+12 -10
View File
@@ -38,16 +38,18 @@ BlazeComponent.extendComponent({
// console.log(this.data());
},
events() {
return [{
'click .js-set-board-triggers' () {
this.setBoardTriggers();
return [
{
'click .js-set-board-triggers'() {
this.setBoardTriggers();
},
'click .js-set-card-triggers'() {
this.setCardTriggers();
},
'click .js-set-checklist-triggers'() {
this.setChecklistTriggers();
},
},
'click .js-set-card-triggers' () {
this.setCardTriggers();
},
'click .js-set-checklist-triggers' () {
this.setChecklistTriggers();
},
}];
];
},
}).register('rulesTriggers');
@@ -4,116 +4,118 @@ BlazeComponent.extendComponent({
this.currentPopupTriggerId = 'def';
this.cardTitleFilters = {};
},
setNameFilter(name){
this.cardTitleFilters[this.currentPopupTriggerId] = name;
setNameFilter(name) {
this.cardTitleFilters[this.currentPopupTriggerId] = name;
},
events() {
return [{
'click .js-open-card-title-popup'(event){
const funct = Popup.open('boardCardTitle');
const divId = $(event.currentTarget.parentNode.parentNode).attr('id');
//console.log('current popup');
//console.log(this.currentPopupTriggerId);
this.currentPopupTriggerId = divId;
funct.call(this, event);
},
'click .js-add-create-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const listName = this.find('#create-list-name').value;
const swimlaneName = this.find('#create-swimlane-name').value;
const boardId = Session.get('currentBoard');
const divId = $(event.currentTarget.parentNode).attr('id');
const cardTitle = this.cardTitleFilters[divId];
// move to generic funciont
datas.triggerVar.set({
activityType: 'createCard',
boardId,
cardTitle,
swimlaneName,
listName,
desc,
});
},
'click .js-add-moved-trigger' (event) {
const datas = this.data();
const desc = Utils.getTriggerActionDesc(event, this);
const swimlaneName = this.find('#create-swimlane-name-2').value;
const actionSelected = this.find('#move-action').value;
const listName = this.find('#move-list-name').value;
const boardId = Session.get('currentBoard');
const divId = $(event.currentTarget.parentNode).attr('id');
const cardTitle = this.cardTitleFilters[divId];
if (actionSelected === 'moved-to') {
return [
{
'click .js-open-card-title-popup'(event) {
const funct = Popup.open('boardCardTitle');
const divId = $(event.currentTarget.parentNode.parentNode).attr('id');
//console.log('current popup');
//console.log(this.currentPopupTriggerId);
this.currentPopupTriggerId = divId;
funct.call(this, event);
},
'click .js-add-create-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const listName = this.find('#create-list-name').value;
const swimlaneName = this.find('#create-swimlane-name').value;
const boardId = Session.get('currentBoard');
const divId = $(event.currentTarget.parentNode).attr('id');
const cardTitle = this.cardTitleFilters[divId];
// move to generic funciont
datas.triggerVar.set({
activityType: 'moveCard',
activityType: 'createCard',
boardId,
cardTitle,
swimlaneName,
listName,
cardTitle,
swimlaneName,
'oldListName': '*',
desc,
});
}
if (actionSelected === 'moved-from') {
},
'click .js-add-moved-trigger'(event) {
const datas = this.data();
const desc = Utils.getTriggerActionDesc(event, this);
const swimlaneName = this.find('#create-swimlane-name-2').value;
const actionSelected = this.find('#move-action').value;
const listName = this.find('#move-list-name').value;
const boardId = Session.get('currentBoard');
const divId = $(event.currentTarget.parentNode).attr('id');
const cardTitle = this.cardTitleFilters[divId];
if (actionSelected === 'moved-to') {
datas.triggerVar.set({
activityType: 'moveCard',
boardId,
listName,
cardTitle,
swimlaneName,
oldListName: '*',
desc,
});
}
if (actionSelected === 'moved-from') {
datas.triggerVar.set({
activityType: 'moveCard',
boardId,
cardTitle,
swimlaneName,
listName: '*',
oldListName: listName,
desc,
});
}
},
'click .js-add-gen-moved-trigger'(event) {
const datas = this.data();
const desc = Utils.getTriggerActionDesc(event, this);
const boardId = Session.get('currentBoard');
datas.triggerVar.set({
activityType: 'moveCard',
boardId,
cardTitle,
swimlaneName,
'listName': '*',
'oldListName': listName,
swimlaneName: '*',
listName: '*',
oldListName: '*',
desc,
});
}
},
'click .js-add-arc-trigger'(event) {
const datas = this.data();
const desc = Utils.getTriggerActionDesc(event, this);
const actionSelected = this.find('#arch-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'archived') {
datas.triggerVar.set({
activityType: 'archivedCard',
boardId,
desc,
});
}
if (actionSelected === 'unarchived') {
datas.triggerVar.set({
activityType: 'restoredCard',
boardId,
desc,
});
}
},
},
'click .js-add-gen-moved-trigger' (event){
const datas = this.data();
const desc = Utils.getTriggerActionDesc(event, this);
const boardId = Session.get('currentBoard');
datas.triggerVar.set({
'activityType': 'moveCard',
boardId,
'swimlaneName': '*',
'listName':'*',
'oldListName': '*',
desc,
});
},
'click .js-add-arc-trigger' (event) {
const datas = this.data();
const desc = Utils.getTriggerActionDesc(event, this);
const actionSelected = this.find('#arch-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'archived') {
datas.triggerVar.set({
activityType: 'archivedCard',
boardId,
desc,
});
}
if (actionSelected === 'unarchived') {
datas.triggerVar.set({
activityType: 'restoredCard',
boardId,
desc,
});
}
},
}];
];
},
}).register('boardTriggers');
Template.boardCardTitlePopup.events({
submit(evt, tpl) {
const title = tpl.$('.js-card-filter-name').val().trim();
submit(event, templateInstance) {
const title = templateInstance
.$('.js-card-filter-name')
.val()
.trim();
Popup.getOpenerComponent().setNameFilter(title);
evt.preventDefault();
event.preventDefault();
Popup.close();
},
});
@@ -22,7 +22,7 @@ template(name="cardTriggers")
div.trigger-item
div.trigger-content
div.trigger-text
| {{_'r-when-the-label-is'}}
| {{_'r-when-the-label'}}
div.trigger-dropdown
select(id="spec-label")
each labels
+114 -112
View File
@@ -7,7 +7,7 @@ BlazeComponent.extendComponent({
for (let i = 0; i < labels.length; i++) {
if (labels[i].name === '' || labels[i].name === undefined) {
labels[i].name = labels[i].color;
labels[i].translatedname = `${TAPi18n.__(`color-${ labels[i].color}`)}`;
labels[i].translatedname = `${TAPi18n.__(`color-${labels[i].color}`)}`;
} else {
labels[i].translatedname = labels[i].name;
}
@@ -15,117 +15,119 @@ BlazeComponent.extendComponent({
return labels;
},
events() {
return [{
'click .js-add-gen-label-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#label-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'added') {
datas.triggerVar.set({
activityType: 'addedLabel',
boardId,
'labelId': '*',
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'removedLabel',
boardId,
'labelId': '*',
desc,
});
}
return [
{
'click .js-add-gen-label-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#label-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'added') {
datas.triggerVar.set({
activityType: 'addedLabel',
boardId,
labelId: '*',
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'removedLabel',
boardId,
labelId: '*',
desc,
});
}
},
'click .js-add-spec-label-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#spec-label-action').value;
const labelId = this.find('#spec-label').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'added') {
datas.triggerVar.set({
activityType: 'addedLabel',
boardId,
labelId,
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'removedLabel',
boardId,
labelId,
desc,
});
}
},
'click .js-add-gen-member-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#gen-member-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'added') {
datas.triggerVar.set({
activityType: 'joinMember',
boardId,
username: '*',
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'unjoinMember',
boardId,
username: '*',
desc,
});
}
},
'click .js-add-spec-member-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#spec-member-action').value;
const username = this.find('#spec-member').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'added') {
datas.triggerVar.set({
activityType: 'joinMember',
boardId,
username,
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'unjoinMember',
boardId,
username,
desc,
});
}
},
'click .js-add-attachment-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#attach-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'added') {
datas.triggerVar.set({
activityType: 'addAttachment',
boardId,
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'deleteAttachment',
boardId,
desc,
});
}
},
},
'click .js-add-spec-label-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#spec-label-action').value;
const labelId = this.find('#spec-label').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'added') {
datas.triggerVar.set({
activityType: 'addedLabel',
boardId,
labelId,
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'removedLabel',
boardId,
labelId,
desc,
});
}
},
'click .js-add-gen-member-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#gen-member-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'added') {
datas.triggerVar.set({
activityType: 'joinMember',
boardId,
'username': '*',
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'unjoinMember',
boardId,
'username': '*',
desc,
});
}
},
'click .js-add-spec-member-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#spec-member-action').value;
const username = this.find('#spec-member').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'added') {
datas.triggerVar.set({
activityType: 'joinMember',
boardId,
username,
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'unjoinMember',
boardId,
username,
desc,
});
}
},
'click .js-add-attachment-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#attach-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'added') {
datas.triggerVar.set({
activityType: 'addAttachment',
boardId,
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'deleteAttachment',
boardId,
desc,
});
}
},
}];
];
},
}).register('cardTriggers');
@@ -3,144 +3,145 @@ BlazeComponent.extendComponent({
this.subscribe('allRules');
},
events() {
return [{
'click .js-add-gen-check-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#gen-check-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'created') {
datas.triggerVar.set({
activityType: 'addChecklist',
boardId,
'checklistName': '*',
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'removeChecklist',
boardId,
'checklistName': '*',
desc,
});
}
},
'click .js-add-spec-check-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#spec-check-action').value;
const checklistId = this.find('#check-name').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'created') {
datas.triggerVar.set({
activityType: 'addChecklist',
boardId,
'checklistName': checklistId,
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'removeChecklist',
boardId,
'checklistName': checklistId,
desc,
});
}
},
'click .js-add-gen-comp-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
return [
{
'click .js-add-gen-check-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#gen-check-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'created') {
datas.triggerVar.set({
activityType: 'addChecklist',
boardId,
checklistName: '*',
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'removeChecklist',
boardId,
checklistName: '*',
desc,
});
}
},
'click .js-add-spec-check-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#spec-check-action').value;
const checklistId = this.find('#check-name').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'created') {
datas.triggerVar.set({
activityType: 'addChecklist',
boardId,
checklistName: checklistId,
desc,
});
}
if (actionSelected === 'removed') {
datas.triggerVar.set({
activityType: 'removeChecklist',
boardId,
checklistName: checklistId,
desc,
});
}
},
'click .js-add-gen-comp-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#gen-comp-check-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'completed') {
datas.triggerVar.set({
activityType: 'completeChecklist',
boardId,
'checklistName': '*',
desc,
});
}
if (actionSelected === 'uncompleted') {
datas.triggerVar.set({
activityType: 'uncompleteChecklist',
boardId,
'checklistName': '*',
desc,
});
}
const datas = this.data();
const actionSelected = this.find('#gen-comp-check-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'completed') {
datas.triggerVar.set({
activityType: 'completeChecklist',
boardId,
checklistName: '*',
desc,
});
}
if (actionSelected === 'uncompleted') {
datas.triggerVar.set({
activityType: 'uncompleteChecklist',
boardId,
checklistName: '*',
desc,
});
}
},
'click .js-add-spec-comp-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#spec-comp-check-action').value;
const checklistId = this.find('#spec-comp-check-name').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'completed') {
datas.triggerVar.set({
activityType: 'completeChecklist',
boardId,
checklistName: checklistId,
desc,
});
}
if (actionSelected === 'uncompleted') {
datas.triggerVar.set({
activityType: 'uncompleteChecklist',
boardId,
checklistName: checklistId,
desc,
});
}
},
'click .js-add-gen-check-item-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#check-item-gen-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'checked') {
datas.triggerVar.set({
activityType: 'checkedItem',
boardId,
checklistItemName: '*',
desc,
});
}
if (actionSelected === 'unchecked') {
datas.triggerVar.set({
activityType: 'uncheckedItem',
boardId,
checklistItemName: '*',
desc,
});
}
},
'click .js-add-spec-check-item-trigger'(event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#check-item-spec-action').value;
const checklistItemId = this.find('#check-item-name').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'checked') {
datas.triggerVar.set({
activityType: 'checkedItem',
boardId,
checklistItemName: checklistItemId,
desc,
});
}
if (actionSelected === 'unchecked') {
datas.triggerVar.set({
activityType: 'uncheckedItem',
boardId,
checklistItemName: checklistItemId,
desc,
});
}
},
},
'click .js-add-spec-comp-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#spec-comp-check-action').value;
const checklistId = this.find('#spec-comp-check-name').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'completed') {
datas.triggerVar.set({
activityType: 'completeChecklist',
boardId,
'checklistName': checklistId,
desc,
});
}
if (actionSelected === 'uncompleted') {
datas.triggerVar.set({
activityType: 'uncompleteChecklist',
boardId,
'checklistName': checklistId,
desc,
});
}
},
'click .js-add-gen-check-item-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#check-item-gen-action').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'checked') {
datas.triggerVar.set({
activityType: 'checkedItem',
boardId,
'checklistItemName': '*',
desc,
});
}
if (actionSelected === 'unchecked') {
datas.triggerVar.set({
activityType: 'uncheckedItem',
boardId,
'checklistItemName': '*',
desc,
});
}
},
'click .js-add-spec-check-item-trigger' (event) {
const desc = Utils.getTriggerActionDesc(event, this);
const datas = this.data();
const actionSelected = this.find('#check-item-spec-action').value;
const checklistItemId = this.find('#check-item-name').value;
const boardId = Session.get('currentBoard');
if (actionSelected === 'checked') {
datas.triggerVar.set({
activityType: 'checkedItem',
boardId,
'checklistItemName': checklistItemId,
desc,
});
}
if (actionSelected === 'unchecked') {
datas.triggerVar.set({
activityType: 'uncheckedItem',
boardId,
'checklistItemName': checklistItemId,
desc,
});
}
},
}];
];
},
}).register('checklistTriggers');
@@ -6,9 +6,11 @@ Template.connectionMethod.onCreated(function() {
// TODO : add a management of different languages
// (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')})
this.authenticationMethods.set([
{value: 'password'},
{ value: 'password' },
// Gets only the authentication methods availables
...Object.entries(result).filter((e) => e[1]).map((e) => ({value: e[0]})),
...Object.entries(result)
.filter(e => e[1])
.map(e => ({ value: e[0] })),
]);
}
@@ -24,7 +26,9 @@ Template.connectionMethod.onCreated(function() {
Template.connectionMethod.onRendered(() => {
// Moves the select boxe in the first place of the at-pwd-form div
$('.at-form-authentication').detach().prependTo('.at-pwd-form');
$('.at-form-authentication')
.detach()
.prependTo('.at-pwd-form');
});
Template.connectionMethod.helpers({
+69 -51
View File
@@ -29,19 +29,23 @@ BlazeComponent.extendComponent({
});
},
events() {
return [{
'click #searchButton'() {
this.filterPeople();
},
'keydown #searchInput'(event) {
if (event.keyCode === 13 && !event.shiftKey) {
return [
{
'click #searchButton'() {
this.filterPeople();
}
},
'keydown #searchInput'(event) {
if (event.keyCode === 13 && !event.shiftKey) {
this.filterPeople();
}
},
},
}];
];
},
filterPeople() {
const value = $('#searchInput').first().val();
const value = $('#searchInput')
.first()
.val();
if (value === '') {
this.findUsersOptions.set({});
} else {
@@ -79,7 +83,7 @@ BlazeComponent.extendComponent({
},
peopleList() {
const users = Users.find(this.findUsersOptions.get(), {
fields: {_id: true},
fields: { _id: true },
});
this.number.set(users.count());
return users;
@@ -105,9 +109,11 @@ Template.editUserPopup.onCreated(function() {
// TODO : add a management of different languages
// (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')})
this.authenticationMethods.set([
{value: 'password'},
{ value: 'password' },
// Gets only the authentication methods availables
...Object.entries(result).filter((e) => e[1]).map((e) => ({value: e[0]})),
...Object.entries(result)
.filter(e => e[1])
.map(e => ({ value: e[0] })),
]);
}
});
@@ -136,69 +142,79 @@ Template.editUserPopup.helpers({
});
BlazeComponent.extendComponent({
onCreated() {
},
onCreated() {},
user() {
return Users.findOne(this.userId);
},
events() {
return [{
'click a.edit-user': Popup.open('editUser'),
}];
return [
{
'click a.edit-user': Popup.open('editUser'),
},
];
},
}).register('peopleRow');
Template.editUserPopup.events({
submit(evt, tpl) {
evt.preventDefault();
submit(event, templateInstance) {
event.preventDefault();
const user = Users.findOne(this.userId);
const fullname = tpl.find('.js-profile-fullname').value.trim();
const username = tpl.find('.js-profile-username').value.trim();
const password = tpl.find('.js-profile-password').value;
const isAdmin = tpl.find('.js-profile-isadmin').value.trim();
const isActive = tpl.find('.js-profile-isactive').value.trim();
const email = tpl.find('.js-profile-email').value.trim();
const authentication = tpl.find('.js-authenticationMethod').value.trim();
const fullname = templateInstance.find('.js-profile-fullname').value.trim();
const username = templateInstance.find('.js-profile-username').value.trim();
const password = templateInstance.find('.js-profile-password').value;
const isAdmin = templateInstance.find('.js-profile-isadmin').value.trim();
const isActive = templateInstance.find('.js-profile-isactive').value.trim();
const email = templateInstance.find('.js-profile-email').value.trim();
const authentication = templateInstance
.find('.js-authenticationMethod')
.value.trim();
const isChangePassword = password.length > 0;
const isChangeUserName = username !== user.username;
const isChangeEmail = email.toLowerCase() !== user.emails[0].address.toLowerCase();
const isChangeEmail =
email.toLowerCase() !== user.emails[0].address.toLowerCase();
Users.update(this.userId, {
$set: {
'profile.fullname': fullname,
'isAdmin': isAdmin === 'true',
'loginDisabled': isActive === 'true',
'authenticationMethod': authentication,
isAdmin: isAdmin === 'true',
loginDisabled: isActive === 'true',
authenticationMethod: authentication,
},
});
if(isChangePassword){
if (isChangePassword) {
Meteor.call('setPassword', password, this.userId);
}
if (isChangeUserName && isChangeEmail) {
Meteor.call('setUsernameAndEmail', username, email.toLowerCase(), this.userId, function (error) {
const usernameMessageElement = tpl.$('.username-taken');
const emailMessageElement = tpl.$('.email-taken');
if (error) {
const errorElement = error.error;
if (errorElement === 'username-already-taken') {
usernameMessageElement.show();
emailMessageElement.hide();
} else if (errorElement === 'email-already-taken') {
Meteor.call(
'setUsernameAndEmail',
username,
email.toLowerCase(),
this.userId,
function(error) {
const usernameMessageElement = templateInstance.$('.username-taken');
const emailMessageElement = templateInstance.$('.email-taken');
if (error) {
const errorElement = error.error;
if (errorElement === 'username-already-taken') {
usernameMessageElement.show();
emailMessageElement.hide();
} else if (errorElement === 'email-already-taken') {
usernameMessageElement.hide();
emailMessageElement.show();
}
} else {
usernameMessageElement.hide();
emailMessageElement.show();
emailMessageElement.hide();
Popup.close();
}
} else {
usernameMessageElement.hide();
emailMessageElement.hide();
Popup.close();
}
});
},
);
} else if (isChangeUserName) {
Meteor.call('setUsername', username, this.userId, function (error) {
const usernameMessageElement = tpl.$('.username-taken');
Meteor.call('setUsername', username, this.userId, function(error) {
const usernameMessageElement = templateInstance.$('.username-taken');
if (error) {
const errorElement = error.error;
if (errorElement === 'username-already-taken') {
@@ -210,8 +226,10 @@ Template.editUserPopup.events({
}
});
} else if (isChangeEmail) {
Meteor.call('setEmail', email.toLowerCase(), this.userId, function (error) {
const emailMessageElement = tpl.$('.email-taken');
Meteor.call('setEmail', email.toLowerCase(), this.userId, function(
error,
) {
const emailMessageElement = templateInstance.$('.email-taken');
if (error) {
const errorElement = error.error;
if (errorElement === 'email-already-taken') {
+90 -53
View File
@@ -25,7 +25,9 @@ BlazeComponent.extendComponent({
checkField(selector) {
const value = $(selector).val();
if (!value || value.trim() === '') {
$(selector).parents('li.smtp-form').addClass('has-error');
$(selector)
.parents('li.smtp-form')
.addClass('has-error');
throw Error('blank field');
} else {
return value;
@@ -37,18 +39,23 @@ BlazeComponent.extendComponent({
},
boards() {
return Boards.find({
archived: false,
'members.userId': Meteor.userId(),
'members.isAdmin': true,
}, {
sort: ['title'],
});
return Boards.find(
{
archived: false,
'members.userId': Meteor.userId(),
'members.isAdmin': true,
},
{
sort: ['title'],
},
);
},
toggleRegistration() {
this.setLoading(true);
const registrationClosed = this.currentSetting().disableRegistration;
Settings.update(Settings.findOne()._id, {$set: {disableRegistration: !registrationClosed}});
Settings.update(Settings.findOne()._id, {
$set: { disableRegistration: !registrationClosed },
});
this.setLoading(false);
if (registrationClosed) {
$('.invite-people').slideUp();
@@ -90,13 +97,19 @@ BlazeComponent.extendComponent({
},
inviteThroughEmail() {
const emails = $('#email-to-invite').val().toLowerCase().trim().split('\n').join(',').split(',');
const emails = $('#email-to-invite')
.val()
.toLowerCase()
.trim()
.split('\n')
.join(',')
.split(',');
const boardsToInvite = [];
$('.js-toggle-board-choose .materialCheckBox.is-checked').each(function () {
$('.js-toggle-board-choose .materialCheckBox.is-checked').each(function() {
boardsToInvite.push($(this).data('id'));
});
const validEmails = [];
emails.forEach((email) => {
emails.forEach(email => {
if (email && SimpleSchema.RegEx.Email.test(email.trim())) {
validEmails.push(email.trim());
}
@@ -119,14 +132,22 @@ BlazeComponent.extendComponent({
try {
const host = this.checkField('#mail-server-host');
const port = this.checkField('#mail-server-port');
const username = $('#mail-server-username').val().trim();
const password = $('#mail-server-password').val().trim();
const username = $('#mail-server-username')
.val()
.trim();
const password = $('#mail-server-password')
.val()
.trim();
const from = this.checkField('#mail-server-from');
const tls = $('#mail-server-tls.is-checked').length > 0;
Settings.update(Settings.findOne()._id, {
$set: {
'mailServer.host': host, 'mailServer.port': port, 'mailServer.username': username,
'mailServer.password': password, 'mailServer.enableTLS': tls, 'mailServer.from': from,
'mailServer.host': host,
'mailServer.port': port,
'mailServer.username': username,
'mailServer.password': password,
'mailServer.enableTLS': tls,
'mailServer.from': from,
},
});
} catch (e) {
@@ -134,19 +155,25 @@ BlazeComponent.extendComponent({
} finally {
this.setLoading(false);
}
},
saveLayout() {
this.setLoading(true);
$('li').removeClass('has-error');
const productName = $('#product-name').val().trim();
const hideLogoChange = ($('input[name=hideLogo]:checked').val() === 'true');
const displayAuthenticationMethod = ($('input[name=displayAuthenticationMethod]:checked').val() === 'true');
const productName = $('#product-name')
.val()
.trim();
const hideLogoChange = $('input[name=hideLogo]:checked').val() === 'true';
const displayAuthenticationMethod =
$('input[name=displayAuthenticationMethod]:checked').val() === 'true';
const defaultAuthenticationMethod = $('#defaultAuthenticationMethod').val();
const customHTMLafterBodyStart = $('#customHTMLafterBodyStart').val().trim();
const customHTMLbeforeBodyEnd = $('#customHTMLbeforeBodyEnd').val().trim();
const customHTMLafterBodyStart = $('#customHTMLafterBodyStart')
.val()
.trim();
const customHTMLbeforeBodyEnd = $('#customHTMLbeforeBodyEnd')
.val()
.trim();
try {
Settings.update(Settings.findOne()._id, {
@@ -166,7 +193,6 @@ BlazeComponent.extendComponent({
}
DocHead.setTitle(productName);
},
sendSMTPTestEmail() {
@@ -183,31 +209,35 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click a.js-toggle-registration': this.toggleRegistration,
'click a.js-toggle-tls': this.toggleTLS,
'click a.js-setting-menu': this.switchMenu,
'click a.js-toggle-board-choose': this.checkBoard,
'click button.js-email-invite': this.inviteThroughEmail,
'click button.js-save': this.saveMailServerInfo,
'click button.js-send-smtp-test-email': this.sendSMTPTestEmail,
'click a.js-toggle-hide-logo': this.toggleHideLogo,
'click button.js-save-layout': this.saveLayout,
'click a.js-toggle-display-authentication-method': this.toggleDisplayAuthenticationMethod,
}];
return [
{
'click a.js-toggle-registration': this.toggleRegistration,
'click a.js-toggle-tls': this.toggleTLS,
'click a.js-setting-menu': this.switchMenu,
'click a.js-toggle-board-choose': this.checkBoard,
'click button.js-email-invite': this.inviteThroughEmail,
'click button.js-save': this.saveMailServerInfo,
'click button.js-send-smtp-test-email': this.sendSMTPTestEmail,
'click a.js-toggle-hide-logo': this.toggleHideLogo,
'click button.js-save-layout': this.saveLayout,
'click a.js-toggle-display-authentication-method': this
.toggleDisplayAuthenticationMethod,
},
];
},
}).register('setting');
BlazeComponent.extendComponent({
saveAccountsChange() {
const allowEmailChange = ($('input[name=allowEmailChange]:checked').val() === 'true');
const allowUserNameChange = ($('input[name=allowUserNameChange]:checked').val() === 'true');
const allowEmailChange =
$('input[name=allowEmailChange]:checked').val() === 'true';
const allowUserNameChange =
$('input[name=allowUserNameChange]:checked').val() === 'true';
AccountSettings.update('accounts-allowEmailChange', {
$set: {'booleanValue': allowEmailChange},
$set: { booleanValue: allowEmailChange },
});
AccountSettings.update('accounts-allowUserNameChange', {
$set: {'booleanValue': allowUserNameChange},
$set: { booleanValue: allowUserNameChange },
});
},
@@ -219,9 +249,11 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click button.js-accounts-save': this.saveAccountsChange,
}];
return [
{
'click button.js-accounts-save': this.saveAccountsChange,
},
];
},
}).register('accountSettings');
@@ -239,9 +271,11 @@ BlazeComponent.extendComponent({
},
saveMessage() {
const message = $('#admin-announcement').val().trim();
const message = $('#admin-announcement')
.val()
.trim();
Announcements.update(Announcements.findOne()._id, {
$set: {'body': message},
$set: { body: message },
});
},
@@ -249,7 +283,7 @@ BlazeComponent.extendComponent({
this.setLoading(true);
const isActive = this.currentSetting().enabled;
Announcements.update(Announcements.findOne()._id, {
$set: {'enabled': !isActive},
$set: { enabled: !isActive },
});
this.setLoading(false);
if (isActive) {
@@ -260,14 +294,15 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click a.js-toggle-activemessage': this.toggleActive,
'click button.js-announcement-save': this.saveMessage,
}];
return [
{
'click a.js-toggle-activemessage': this.toggleActive,
'click button.js-announcement-save': this.saveMessage,
},
];
},
}).register('announcementSettings');
Template.selectAuthenticationMethod.onCreated(function() {
this.authenticationMethods = new ReactiveVar([]);
@@ -276,9 +311,11 @@ Template.selectAuthenticationMethod.onCreated(function() {
// TODO : add a management of different languages
// (ex {value: ldap, text: TAPi18n.__('ldap', {}, T9n.getLanguage() || 'en')})
this.authenticationMethods.set([
{value: 'password'},
{ value: 'password' },
// Gets only the authentication methods availables
...Object.entries(result).filter((e) => e[1]).map((e) => ({value: e[0]})),
...Object.entries(result)
.filter(e => e[1])
.map(e => ({ value: e[0] })),
]);
}
});
+6 -4
View File
@@ -10,8 +10,8 @@ template(name="sidebar")
i.fa.fa-keyboard-o
span {{_ 'keyboard-shortcuts' }}
.sidebar-content.js-board-sidebar-content.js-perfect-scrollbar
a.hide-btn.js-hide-sidebar
i.fa.fa-navicon
//a.hide-btn.js-hide-sidebar
// i.fa.fa-navicon
unless isDefaultView
h2
a.fa.fa-chevron-left.js-back-home
@@ -34,8 +34,9 @@ template(name="membersWidget")
h3
i.fa.fa-user
| {{_ 'members'}}
a.board-header-btn.js-open-board-menu(title="{{_ 'boardMenuPopup-title'}}").right
i.board-header-btn-icon.fa.fa-cog
unless currentUser.isCommentOnly
a.board-header-btn.js-open-board-menu(title="{{_ 'boardMenuPopup-title'}}").right
i.board-header-btn-icon.fa.fa-cog
.board-widget-content
each currentBoard.activeMembers
@@ -61,6 +62,7 @@ template(name="boardChangeColorPopup")
each backgroundColors
.board-background-select.js-select-background
span.background-box(class="board-color-{{this}}")
span {{this}}
if isSelected
i.fa.fa-check
+192 -131
View File
@@ -91,29 +91,34 @@ BlazeComponent.extendComponent({
},
showTongueTitle() {
if (this.isOpen())
return `${TAPi18n.__('sidebar-close')}`;
else
return `${TAPi18n.__('sidebar-open')}`;
if (this.isOpen()) return `${TAPi18n.__('sidebar-close')}`;
else return `${TAPi18n.__('sidebar-open')}`;
},
events() {
return [{
'click .js-hide-sidebar': this.hide,
'click .js-toggle-sidebar': this.toggle,
'click .js-back-home': this.setView,
'click .js-shortcuts'() {
FlowRouter.go('shortcuts');
return [
{
'click .js-hide-sidebar': this.hide,
'click .js-toggle-sidebar': this.toggle,
'click .js-back-home': this.setView,
'click .js-shortcuts'() {
FlowRouter.go('shortcuts');
},
},
}];
];
},
}).register('sidebar');
Blaze.registerHelper('Sidebar', () => Sidebar);
EscapeActions.register('sidebarView',
() => { Sidebar.setView(defaultView); },
() => { return Sidebar && Sidebar.getView() !== defaultView; }
EscapeActions.register(
'sidebarView',
() => {
Sidebar.setView(defaultView);
},
() => {
return Sidebar && Sidebar.getView() !== defaultView;
},
);
Template.memberPopup.helpers({
@@ -122,13 +127,13 @@ Template.memberPopup.helpers({
},
memberType() {
const type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal';
if(type === 'normal'){
if (type === 'normal') {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const commentOnly = currentBoard.hasCommentOnly(this.userId);
const noComments = currentBoard.hasNoComments(this.userId);
if(commentOnly){
if (commentOnly) {
return TAPi18n.__('comment-only').toLowerCase();
} else if(noComments) {
} else if (noComments) {
return TAPi18n.__('no-comments').toLowerCase();
} else {
return TAPi18n.__(type).toLowerCase();
@@ -197,7 +202,7 @@ Template.memberPopup.events({
'click .js-remove-member': Popup.afterConfirm('removeMember', function() {
const boardId = Session.get('currentBoard');
const memberId = this.userId;
Cards.find({ boardId, members: memberId }).forEach((card) => {
Cards.find({ boardId, members: memberId }).forEach(card => {
card.unassignMember(memberId);
});
Boards.findOne(boardId).removeMember(memberId);
@@ -274,38 +279,40 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'submit'(evt) {
evt.preventDefault();
const url = evt.target.url.value;
const boardId = Session.get('currentBoard');
let id = null;
let integration = null;
if (evt.target.id) {
id = evt.target.id.value;
integration = this.integration(id);
if (url) {
Integrations.update(integration._id, {
$set: {
url: `${url}`,
},
return [
{
submit(evt) {
evt.preventDefault();
const url = evt.target.url.value;
const boardId = Session.get('currentBoard');
let id = null;
let integration = null;
if (evt.target.id) {
id = evt.target.id.value;
integration = this.integration(id);
if (url) {
Integrations.update(integration._id, {
$set: {
url: `${url}`,
},
});
} else {
Integrations.remove(integration._id);
}
} else if (url) {
Integrations.insert({
userId: Meteor.userId(),
enabled: true,
type: 'outgoing-webhooks',
url: `${url}`,
boardId: `${boardId}`,
activities: ['all'],
});
} else {
Integrations.remove(integration._id);
}
} else if (url) {
Integrations.insert({
userId: Meteor.userId(),
enabled: true,
type: 'outgoing-webhooks',
url: `${url}`,
boardId: `${boardId}`,
activities: ['all'],
});
}
Popup.close();
Popup.close();
},
},
}];
];
},
}).register('outgoingWebhooksPopup');
@@ -375,14 +382,16 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-select-background'(evt) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const newColor = this.currentData().toString();
currentBoard.setColor(newColor);
evt.preventDefault();
return [
{
'click .js-select-background'(evt) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const newColor = this.currentData().toString();
currentBoard.setColor(newColor);
evt.preventDefault();
},
},
}];
];
},
}).register('boardChangeColorPopup');
@@ -400,25 +409,34 @@ BlazeComponent.extendComponent({
},
isNullBoardSelected() {
return (this.currentBoard.subtasksDefaultBoardId === null) || (this.currentBoard.subtasksDefaultBoardId === undefined);
return (
this.currentBoard.subtasksDefaultBoardId === null ||
this.currentBoard.subtasksDefaultBoardId === undefined
);
},
boards() {
return Boards.find({
archived: false,
'members.userId': Meteor.userId(),
}, {
sort: ['title'],
});
return Boards.find(
{
archived: false,
'members.userId': Meteor.userId(),
},
{
sort: ['title'],
},
);
},
lists() {
return Lists.find({
boardId: this.currentBoard._id,
archived: false,
}, {
sort: ['title'],
});
return Lists.find(
{
boardId: this.currentBoard._id,
archived: false,
},
{
sort: ['title'],
},
);
},
hasLists() {
@@ -431,54 +449,74 @@ BlazeComponent.extendComponent({
presentParentTask() {
let result = this.currentBoard.presentParentTask;
if ((result === null) || (result === undefined)) {
if (result === null || result === undefined) {
result = 'no-parent';
}
return result;
},
events() {
return [{
'click .js-field-has-subtasks'(evt) {
evt.preventDefault();
this.currentBoard.allowsSubtasks = !this.currentBoard.allowsSubtasks;
this.currentBoard.setAllowsSubtasks(this.currentBoard.allowsSubtasks);
$('.js-field-has-subtasks .materialCheckBox').toggleClass('is-checked', this.currentBoard.allowsSubtasks);
$('.js-field-has-subtasks').toggleClass('is-checked', this.currentBoard.allowsSubtasks);
$('.js-field-deposit-board').prop('disabled', !this.currentBoard.allowsSubtasks);
},
'change .js-field-deposit-board'(evt) {
let value = evt.target.value;
if (value === 'null') {
value = null;
}
this.currentBoard.setSubtasksDefaultBoardId(value);
evt.preventDefault();
},
'change .js-field-deposit-list'(evt) {
this.currentBoard.setSubtasksDefaultListId(evt.target.value);
evt.preventDefault();
},
'click .js-field-show-parent-in-minicard'(evt) {
const value = evt.target.id || $(evt.target).parent()[0].id || $(evt.target).parent()[0].parent()[0].id;
const options = [
'prefix-with-full-path',
'prefix-with-parent',
'subtext-with-full-path',
'subtext-with-parent',
'no-parent'];
options.forEach(function(element) {
if (element !== value) {
$(`#${element} .materialCheckBox`).toggleClass('is-checked', false);
$(`#${element}`).toggleClass('is-checked', false);
return [
{
'click .js-field-has-subtasks'(evt) {
evt.preventDefault();
this.currentBoard.allowsSubtasks = !this.currentBoard.allowsSubtasks;
this.currentBoard.setAllowsSubtasks(this.currentBoard.allowsSubtasks);
$('.js-field-has-subtasks .materialCheckBox').toggleClass(
'is-checked',
this.currentBoard.allowsSubtasks,
);
$('.js-field-has-subtasks').toggleClass(
'is-checked',
this.currentBoard.allowsSubtasks,
);
$('.js-field-deposit-board').prop(
'disabled',
!this.currentBoard.allowsSubtasks,
);
},
'change .js-field-deposit-board'(evt) {
let value = evt.target.value;
if (value === 'null') {
value = null;
}
});
$(`#${value} .materialCheckBox`).toggleClass('is-checked', true);
$(`#${value}`).toggleClass('is-checked', true);
this.currentBoard.setPresentParentTask(value);
evt.preventDefault();
this.currentBoard.setSubtasksDefaultBoardId(value);
evt.preventDefault();
},
'change .js-field-deposit-list'(evt) {
this.currentBoard.setSubtasksDefaultListId(evt.target.value);
evt.preventDefault();
},
'click .js-field-show-parent-in-minicard'(evt) {
const value =
evt.target.id ||
$(evt.target).parent()[0].id ||
$(evt.target)
.parent()[0]
.parent()[0].id;
const options = [
'prefix-with-full-path',
'prefix-with-parent',
'subtext-with-full-path',
'subtext-with-parent',
'no-parent',
];
options.forEach(function(element) {
if (element !== value) {
$(`#${element} .materialCheckBox`).toggleClass(
'is-checked',
false,
);
$(`#${element}`).toggleClass('is-checked', false);
}
});
$(`#${value} .materialCheckBox`).toggleClass('is-checked', true);
$(`#${value}`).toggleClass('is-checked', true);
this.currentBoard.setPresentParentTask(value);
evt.preventDefault();
},
},
}];
];
},
}).register('boardSubtaskSettingsPopup');
@@ -528,35 +566,46 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'keyup input'() {
this.setError('');
return [
{
'keyup input'() {
this.setError('');
},
'click .js-select-member'() {
const userId = this.currentData()._id;
const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (!currentBoard.hasMember(userId)) {
this.inviteUser(userId);
}
},
'click .js-email-invite'() {
const idNameEmail = $('.js-search-member input').val();
if (idNameEmail.indexOf('@') < 0 || this.isValidEmail(idNameEmail)) {
this.inviteUser(idNameEmail);
} else this.setError('email-invalid');
},
},
'click .js-select-member'() {
const userId = this.currentData()._id;
const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (!currentBoard.hasMember(userId)) {
this.inviteUser(userId);
}
},
'click .js-email-invite'() {
const idNameEmail = $('.js-search-member input').val();
if (idNameEmail.indexOf('@')<0 || this.isValidEmail(idNameEmail)) {
this.inviteUser(idNameEmail);
} else this.setError('email-invalid');
},
}];
];
},
}).register('addMemberPopup');
Template.changePermissionsPopup.events({
'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only'(event) {
'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only'(
event,
) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const memberId = this.userId;
const isAdmin = $(event.currentTarget).hasClass('js-set-admin');
const isCommentOnly = $(event.currentTarget).hasClass('js-set-comment-only');
const isCommentOnly = $(event.currentTarget).hasClass(
'js-set-comment-only',
);
const isNoComments = $(event.currentTarget).hasClass('js-set-no-comments');
currentBoard.setMemberPermission(memberId, isAdmin, isNoComments, isCommentOnly);
currentBoard.setMemberPermission(
memberId,
isAdmin,
isNoComments,
isCommentOnly,
);
Popup.back(1);
},
});
@@ -569,21 +618,33 @@ Template.changePermissionsPopup.helpers({
isNormal() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
return !currentBoard.hasAdmin(this.userId) && !currentBoard.hasNoComments(this.userId) && !currentBoard.hasCommentOnly(this.userId);
return (
!currentBoard.hasAdmin(this.userId) &&
!currentBoard.hasNoComments(this.userId) &&
!currentBoard.hasCommentOnly(this.userId)
);
},
isNoComments() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
return !currentBoard.hasAdmin(this.userId) && currentBoard.hasNoComments(this.userId);
return (
!currentBoard.hasAdmin(this.userId) &&
currentBoard.hasNoComments(this.userId)
);
},
isCommentOnly() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
return !currentBoard.hasAdmin(this.userId) && currentBoard.hasCommentOnly(this.userId);
return (
!currentBoard.hasAdmin(this.userId) &&
currentBoard.hasCommentOnly(this.userId)
);
},
isLastAdmin() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
return currentBoard.hasAdmin(this.userId) && (currentBoard.activeAdmins() === 1);
return (
currentBoard.hasAdmin(this.userId) && currentBoard.activeAdmins() === 1
);
},
});
+70 -63
View File
@@ -10,12 +10,11 @@ BlazeComponent.extendComponent({
// unfortunatly, Blaze doesn't have this notion.
this.autorun(() => {
const currentBoardId = Session.get('currentBoard');
if (!currentBoardId)
return;
if (!currentBoardId) return;
const handle = subManager.subscribe('board', currentBoardId, true);
Tracker.nonreactive(() => {
Tracker.autorun(() => {
this.isArchiveReady.set( handle.ready() );
this.isArchiveReady.set(handle.ready());
});
});
});
@@ -59,74 +58,82 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-restore-card'() {
const card = this.currentData();
if(card.canBeRestored()){
card.restore();
}
},
'click .js-restore-all-cards'() {
this.archivedCards().forEach((card) => {
if(card.canBeRestored()){
return [
{
'click .js-restore-card'() {
const card = this.currentData();
if (card.canBeRestored()) {
card.restore();
}
});
},
},
'click .js-restore-all-cards'() {
this.archivedCards().forEach(card => {
if (card.canBeRestored()) {
card.restore();
}
});
},
'click .js-delete-card': Popup.afterConfirm('cardDelete', function() {
const cardId = this._id;
Cards.remove(cardId);
Popup.close();
}),
'click .js-delete-all-cards': Popup.afterConfirm('cardDelete', () => {
this.archivedCards().forEach((card) => {
Cards.remove(card._id);
});
Popup.close();
}),
'click .js-delete-card': Popup.afterConfirm('cardDelete', function() {
const cardId = this._id;
Cards.remove(cardId);
Popup.close();
}),
'click .js-delete-all-cards': Popup.afterConfirm('cardDelete', () => {
this.archivedCards().forEach(card => {
Cards.remove(card._id);
});
Popup.close();
}),
'click .js-restore-list'() {
const list = this.currentData();
list.restore();
},
'click .js-restore-all-lists'() {
this.archivedLists().forEach((list) => {
'click .js-restore-list'() {
const list = this.currentData();
list.restore();
});
},
},
'click .js-restore-all-lists'() {
this.archivedLists().forEach(list => {
list.restore();
});
},
'click .js-delete-list': Popup.afterConfirm('listDelete', function() {
this.remove();
Popup.close();
}),
'click .js-delete-all-lists': Popup.afterConfirm('listDelete', () => {
this.archivedLists().forEach((list) => {
list.remove();
});
Popup.close();
}),
'click .js-delete-list': Popup.afterConfirm('listDelete', function() {
this.remove();
Popup.close();
}),
'click .js-delete-all-lists': Popup.afterConfirm('listDelete', () => {
this.archivedLists().forEach(list => {
list.remove();
});
Popup.close();
}),
'click .js-restore-swimlane'() {
const swimlane = this.currentData();
swimlane.restore();
},
'click .js-restore-all-swimlanes'() {
this.archivedSwimlanes().forEach((swimlane) => {
'click .js-restore-swimlane'() {
const swimlane = this.currentData();
swimlane.restore();
});
},
},
'click .js-restore-all-swimlanes'() {
this.archivedSwimlanes().forEach(swimlane => {
swimlane.restore();
});
},
'click .js-delete-swimlane': Popup.afterConfirm('swimlaneDelete', function() {
this.remove();
Popup.close();
}),
'click .js-delete-all-swimlanes': Popup.afterConfirm('swimlaneDelete', () => {
this.archivedSwimlanes().forEach((swimlane) => {
swimlane.remove();
});
Popup.close();
}),
}];
'click .js-delete-swimlane': Popup.afterConfirm(
'swimlaneDelete',
function() {
this.remove();
Popup.close();
},
),
'click .js-delete-all-swimlanes': Popup.afterConfirm(
'swimlaneDelete',
() => {
this.archivedSwimlanes().forEach(swimlane => {
swimlane.remove();
});
Popup.close();
},
),
},
];
},
}).register('archivesSidebar');
+112 -97
View File
@@ -1,37 +1,43 @@
BlazeComponent.extendComponent({
customFields() {
return CustomFields.find({
boardIds: {$in: [Session.get('currentBoard')]},
boardIds: { $in: [Session.get('currentBoard')] },
});
},
events() {
return [{
'click .js-open-create-custom-field': Popup.open('createCustomField'),
'click .js-edit-custom-field': Popup.open('editCustomField'),
}];
return [
{
'click .js-open-create-custom-field': Popup.open('createCustomField'),
'click .js-edit-custom-field': Popup.open('editCustomField'),
},
];
},
}).register('customFieldsSidebar');
const CreateCustomFieldPopup = BlazeComponent.extendComponent({
_types: ['text', 'number', 'date', 'dropdown'],
onCreated() {
this.type = new ReactiveVar((this.data().type) ? this.data().type : this._types[0]);
this.dropdownItems = new ReactiveVar((this.data().settings && this.data().settings.dropdownItems) ? this.data().settings.dropdownItems : []);
this.type = new ReactiveVar(
this.data().type ? this.data().type : this._types[0],
);
this.dropdownItems = new ReactiveVar(
this.data().settings && this.data().settings.dropdownItems
? this.data().settings.dropdownItems
: [],
);
},
types() {
const currentType = this.data().type;
return this._types.
map((type) => {return {
return this._types.map(type => {
return {
value: type,
name: TAPi18n.__(`custom-field-${type}`),
selected: type === currentType,
};});
};
});
},
isTypeNotSelected(type) {
@@ -40,113 +46,122 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
getDropdownItems() {
const items = this.dropdownItems.get();
Array.from(this.findAll('.js-field-settings-dropdown input')).forEach((el, index) => {
//console.log('each item!', index, el.value);
if (!items[index]) items[index] = {
_id: Random.id(6),
};
items[index].name = el.value.trim();
});
Array.from(this.findAll('.js-field-settings-dropdown input')).forEach(
(el, index) => {
//console.log('each item!', index, el.value);
if (!items[index])
items[index] = {
_id: Random.id(6),
};
items[index].name = el.value.trim();
},
);
return items;
},
getSettings() {
const settings = {};
switch (this.type.get()) {
case 'dropdown': {
const dropdownItems = this.getDropdownItems().filter((item) => !!item.name.trim());
settings.dropdownItems = dropdownItems;
break;
}
case 'dropdown': {
const dropdownItems = this.getDropdownItems().filter(
item => !!item.name.trim(),
);
settings.dropdownItems = dropdownItems;
break;
}
}
return settings;
},
events() {
return [{
'change .js-field-type'(evt) {
const value = evt.target.value;
this.type.set(value);
},
'keydown .js-dropdown-item.last'(evt) {
if (evt.target.value.trim() && evt.keyCode === 13) {
const items = this.getDropdownItems();
this.dropdownItems.set(items);
evt.target.value = '';
}
},
'click .js-field-show-on-card'(evt) {
let $target = $(evt.target);
if(!$target.hasClass('js-field-show-on-card')){
$target = $target.parent();
}
$target.find('.materialCheckBox').toggleClass('is-checked');
$target.toggleClass('is-checked');
},
'click .js-field-automatically-on-card'(evt) {
let $target = $(evt.target);
if(!$target.hasClass('js-field-automatically-on-card')){
$target = $target.parent();
}
$target.find('.materialCheckBox').toggleClass('is-checked');
$target.toggleClass('is-checked');
},
'click .js-field-showLabel-on-card'(evt) {
let $target = $(evt.target);
if(!$target.hasClass('js-field-showLabel-on-card')){
$target = $target.parent();
}
$target.find('.materialCheckBox').toggleClass('is-checked');
$target.toggleClass('is-checked');
},
'click .primary'(evt) {
evt.preventDefault();
return [
{
'change .js-field-type'(evt) {
const value = evt.target.value;
this.type.set(value);
},
'keydown .js-dropdown-item.last'(evt) {
if (evt.target.value.trim() && evt.keyCode === 13) {
const items = this.getDropdownItems();
this.dropdownItems.set(items);
evt.target.value = '';
}
},
'click .js-field-show-on-card'(evt) {
let $target = $(evt.target);
if (!$target.hasClass('js-field-show-on-card')) {
$target = $target.parent();
}
$target.find('.materialCheckBox').toggleClass('is-checked');
$target.toggleClass('is-checked');
},
'click .js-field-automatically-on-card'(evt) {
let $target = $(evt.target);
if (!$target.hasClass('js-field-automatically-on-card')) {
$target = $target.parent();
}
$target.find('.materialCheckBox').toggleClass('is-checked');
$target.toggleClass('is-checked');
},
'click .js-field-showLabel-on-card'(evt) {
let $target = $(evt.target);
if (!$target.hasClass('js-field-showLabel-on-card')) {
$target = $target.parent();
}
$target.find('.materialCheckBox').toggleClass('is-checked');
$target.toggleClass('is-checked');
},
'click .primary'(evt) {
evt.preventDefault();
const data = {
name: this.find('.js-field-name').value.trim(),
type: this.type.get(),
settings: this.getSettings(),
showOnCard: this.find('.js-field-show-on-card.is-checked') !== null,
showLabelOnMiniCard: this.find('.js-field-showLabel-on-card.is-checked') !== null,
automaticallyOnCard: this.find('.js-field-automatically-on-card.is-checked') !== null,
};
const data = {
name: this.find('.js-field-name').value.trim(),
type: this.type.get(),
settings: this.getSettings(),
showOnCard: this.find('.js-field-show-on-card.is-checked') !== null,
showLabelOnMiniCard:
this.find('.js-field-showLabel-on-card.is-checked') !== null,
automaticallyOnCard:
this.find('.js-field-automatically-on-card.is-checked') !== null,
};
// insert or update
if (!this.data()._id) {
data.boardIds = [Session.get('currentBoard')];
CustomFields.insert(data);
} else {
CustomFields.update(this.data()._id, {$set: data});
}
// insert or update
if (!this.data()._id) {
data.boardIds = [Session.get('currentBoard')];
CustomFields.insert(data);
} else {
CustomFields.update(this.data()._id, { $set: data });
}
Popup.back();
Popup.back();
},
'click .js-delete-custom-field': Popup.afterConfirm(
'deleteCustomField',
function() {
const customField = CustomFields.findOne(this._id);
if (customField.boardIds.length > 1) {
CustomFields.update(customField._id, {
$pull: {
boardIds: Session.get('currentBoard'),
},
});
} else {
CustomFields.remove(customField._id);
}
Popup.close();
},
),
},
'click .js-delete-custom-field': Popup.afterConfirm('deleteCustomField', function() {
const customField = CustomFields.findOne(this._id);
if (customField.boardIds.length > 1) {
CustomFields.update(customField._id, {
$pull: {
boardIds: Session.get('currentBoard'),
},
});
} else {
CustomFields.remove(customField._id);
}
Popup.close();
}),
}];
];
},
});
CreateCustomFieldPopup.register('createCustomFieldPopup');
(class extends CreateCustomFieldPopup {
template() {
return 'createCustomFieldPopup';
}
}).register('editCustomFieldPopup');
}.register('editCustomFieldPopup'));
/*Template.deleteCustomFieldPopup.events({
'submit'(evt) {
+78 -76
View File
@@ -1,106 +1,108 @@
BlazeComponent.extendComponent({
events() {
return [{
'click .js-toggle-label-filter'(evt) {
evt.preventDefault();
Filter.labelIds.toggle(this.currentData()._id);
Filter.resetExceptions();
return [
{
'click .js-toggle-label-filter'(evt) {
evt.preventDefault();
Filter.labelIds.toggle(this.currentData()._id);
Filter.resetExceptions();
},
'click .js-toggle-member-filter'(evt) {
evt.preventDefault();
Filter.members.toggle(this.currentData()._id);
Filter.resetExceptions();
},
'click .js-toggle-custom-fields-filter'(evt) {
evt.preventDefault();
Filter.customFields.toggle(this.currentData()._id);
Filter.resetExceptions();
},
'change .js-field-advanced-filter'(evt) {
evt.preventDefault();
Filter.advanced.set(
this.find('.js-field-advanced-filter').value.trim(),
);
Filter.resetExceptions();
},
'click .js-clear-all'(evt) {
evt.preventDefault();
Filter.reset();
},
'click .js-filter-to-selection'(evt) {
evt.preventDefault();
const selectedCards = Cards.find(Filter.mongoSelector()).map(c => {
return c._id;
});
MultiSelection.add(selectedCards);
},
},
'click .js-toggle-member-filter'(evt) {
evt.preventDefault();
Filter.members.toggle(this.currentData()._id);
Filter.resetExceptions();
},
'click .js-toggle-custom-fields-filter'(evt) {
evt.preventDefault();
Filter.customFields.toggle(this.currentData()._id);
Filter.resetExceptions();
},
'change .js-field-advanced-filter'(evt) {
evt.preventDefault();
Filter.advanced.set(this.find('.js-field-advanced-filter').value.trim());
Filter.resetExceptions();
},
'click .js-clear-all'(evt) {
evt.preventDefault();
Filter.reset();
},
'click .js-filter-to-selection'(evt) {
evt.preventDefault();
const selectedCards = Cards.find(Filter.mongoSelector()).map((c) => {
return c._id;
});
MultiSelection.add(selectedCards);
},
}];
];
},
}).register('filterSidebar');
function mutateSelectedCards(mutationName, ...args) {
Cards.find(MultiSelection.getMongoSelector()).forEach((card) => {
Cards.find(MultiSelection.getMongoSelector()).forEach(card => {
card[mutationName](...args);
});
}
BlazeComponent.extendComponent({
mapSelection(kind, _id) {
return Cards.find(MultiSelection.getMongoSelector()).map((card) => {
return Cards.find(MultiSelection.getMongoSelector()).map(card => {
const methodName = kind === 'label' ? 'hasLabel' : 'isAssigned';
return card[methodName](_id);
});
},
allSelectedElementHave(kind, _id) {
if (MultiSelection.isEmpty())
return false;
else
return _.every(this.mapSelection(kind, _id));
if (MultiSelection.isEmpty()) return false;
else return _.every(this.mapSelection(kind, _id));
},
someSelectedElementHave(kind, _id) {
if (MultiSelection.isEmpty())
return false;
else
return _.some(this.mapSelection(kind, _id));
if (MultiSelection.isEmpty()) return false;
else return _.some(this.mapSelection(kind, _id));
},
events() {
return [{
'click .js-toggle-label-multiselection'(evt) {
const labelId = this.currentData()._id;
const mappedSelection = this.mapSelection('label', labelId);
return [
{
'click .js-toggle-label-multiselection'(evt) {
const labelId = this.currentData()._id;
const mappedSelection = this.mapSelection('label', labelId);
if (_.every(mappedSelection)) {
mutateSelectedCards('removeLabel', labelId);
} else if (_.every(mappedSelection, (bool) => !bool)) {
mutateSelectedCards('addLabel', labelId);
} else {
const popup = Popup.open('disambiguateMultiLabel');
// XXX We need to have a better integration between the popup and the
// UI components systems.
popup.call(this.currentData(), evt);
}
if (_.every(mappedSelection)) {
mutateSelectedCards('removeLabel', labelId);
} else if (_.every(mappedSelection, bool => !bool)) {
mutateSelectedCards('addLabel', labelId);
} else {
const popup = Popup.open('disambiguateMultiLabel');
// XXX We need to have a better integration between the popup and the
// UI components systems.
popup.call(this.currentData(), evt);
}
},
'click .js-toggle-member-multiselection'(evt) {
const memberId = this.currentData()._id;
const mappedSelection = this.mapSelection('member', memberId);
if (_.every(mappedSelection)) {
mutateSelectedCards('unassignMember', memberId);
} else if (_.every(mappedSelection, bool => !bool)) {
mutateSelectedCards('assignMember', memberId);
} else {
const popup = Popup.open('disambiguateMultiMember');
// XXX We need to have a better integration between the popup and the
// UI components systems.
popup.call(this.currentData(), evt);
}
},
'click .js-move-selection': Popup.open('moveSelection'),
'click .js-archive-selection'() {
mutateSelectedCards('archive');
EscapeActions.executeUpTo('multiselection');
},
},
'click .js-toggle-member-multiselection'(evt) {
const memberId = this.currentData()._id;
const mappedSelection = this.mapSelection('member', memberId);
if (_.every(mappedSelection)) {
mutateSelectedCards('unassignMember', memberId);
} else if (_.every(mappedSelection, (bool) => !bool)) {
mutateSelectedCards('assignMember', memberId);
} else {
const popup = Popup.open('disambiguateMultiMember');
// XXX We need to have a better integration between the popup and the
// UI components systems.
popup.call(this.currentData(), evt);
}
},
'click .js-move-selection': Popup.open('moveSelection'),
'click .js-archive-selection'() {
mutateSelectedCards('archive');
EscapeActions.executeUpTo('multiselection');
},
}];
];
},
}).register('multiselectionSidebar');
+7 -5
View File
@@ -9,11 +9,13 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'submit .js-search-term-form'(evt) {
evt.preventDefault();
this.term.set(evt.target.searchTerm.value);
return [
{
'submit .js-search-term-form'(evt) {
evt.preventDefault();
this.term.set(evt.target.searchTerm.value);
},
},
}];
];
},
}).register('searchSidebar');
+62 -48
View File
@@ -6,9 +6,11 @@ Meteor.startup(() => {
});
BlazeComponent.extendComponent({
editTitle(evt) {
evt.preventDefault();
const newTitle = this.childComponents('inlinedForm')[0].getValue().trim();
editTitle(event) {
event.preventDefault();
const newTitle = this.childComponents('inlinedForm')[0]
.getValue()
.trim();
const swimlane = this.currentData();
if (newTitle) {
swimlane.rename(newTitle.trim());
@@ -16,18 +18,20 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-open-swimlane-menu': Popup.open('swimlaneAction'),
'click .js-open-add-swimlane-menu': Popup.open('swimlaneAdd'),
submit: this.editTitle,
}];
return [
{
'click .js-open-swimlane-menu': Popup.open('swimlaneAction'),
'click .js-open-add-swimlane-menu': Popup.open('swimlaneAdd'),
submit: this.editTitle,
},
];
},
}).register('swimlaneHeader');
Template.swimlaneActionPopup.events({
'click .js-set-swimlane-color': Popup.open('setSwimlaneColor'),
'click .js-close-swimlane' (evt) {
evt.preventDefault();
'click .js-close-swimlane'(event) {
event.preventDefault();
this.archive();
Popup.close();
},
@@ -39,34 +43,42 @@ BlazeComponent.extendComponent({
},
events() {
return [{
submit(evt) {
evt.preventDefault();
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const nextSwimlane = currentBoard.nextSwimlane(this.currentSwimlane);
const titleInput = this.find('.swimlane-name-input');
const title = titleInput.value.trim();
const sortValue = calculateIndexData(this.currentSwimlane, nextSwimlane, 1);
const swimlaneType = (currentBoard.isTemplatesBoard())?'template-swimlane':'swimlane';
return [
{
submit(event) {
event.preventDefault();
const currentBoard = Boards.findOne(Session.get('currentBoard'));
const nextSwimlane = currentBoard.nextSwimlane(this.currentSwimlane);
const titleInput = this.find('.swimlane-name-input');
const title = titleInput.value.trim();
const sortValue = calculateIndexData(
this.currentSwimlane,
nextSwimlane,
1,
);
const swimlaneType = currentBoard.isTemplatesBoard()
? 'template-swimlane'
: 'swimlane';
if (title) {
Swimlanes.insert({
title,
boardId: Session.get('currentBoard'),
sort: sortValue.base,
type: swimlaneType,
});
if (title) {
Swimlanes.insert({
title,
boardId: Session.get('currentBoard'),
sort: sortValue.base,
type: swimlaneType,
});
titleInput.value = '';
titleInput.focus();
}
// XXX ideally, we should move the popup to the newly
// created swimlane so a user can add more than one swimlane
// with a minimum of interactions
Popup.close();
titleInput.value = '';
titleInput.focus();
}
// XXX ideally, we should move the popup to the newly
// created swimlane so a user can add more than one swimlane
// with a minimum of interactions
Popup.close();
},
'click .js-swimlane-template': Popup.open('searchElement'),
},
'click .js-swimlane-template': Popup.open('searchElement'),
}];
];
},
}).register('swimlaneAddPopup');
@@ -77,7 +89,7 @@ BlazeComponent.extendComponent({
},
colors() {
return swimlaneColors.map((color) => ({ color, name: '' }));
return swimlaneColors.map(color => ({ color, name: '' }));
},
isSelected(color) {
@@ -85,18 +97,20 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
return [
{
'click .js-palette-color'() {
this.currentColor.set(this.currentData().color);
},
'click .js-submit'() {
this.currentSwimlane.setColor(this.currentColor.get());
Popup.close();
},
'click .js-remove-color'() {
this.currentSwimlane.setColor(null);
Popup.close();
},
},
'click .js-submit' () {
this.currentSwimlane.setColor(this.currentColor.get());
Popup.close();
},
'click .js-remove-color'() {
this.currentSwimlane.setColor(null);
Popup.close();
},
}];
];
},
}).register('setSwimlaneColorPopup');
+8 -4
View File
@@ -9,14 +9,16 @@ template(name="swimlane")
each lists
+miniList(this)
if currentUser.isBoardMember
+addListForm
unless currentUser.isCommentOnly
+addListForm
else
each lists
+list(this)
if currentCardIsInThisList _id ../_id
+cardDetails(currentCard)
if currentUser.isBoardMember
+addListForm
unless currentUser.isCommentOnly
+addListForm
template(name="listsGroup")
.swimlane.list-group.js-lists
@@ -27,14 +29,16 @@ template(name="listsGroup")
each lists
+miniList(this)
if currentUser.isBoardMember
+addListForm
unless currentUser.isCommentOnly
+addListForm
else
each lists
+list(this)
if currentCardIsInThisList _id null
+cardDetails(currentCard)
if currentUser.isBoardMember
+addListForm
unless currentUser.isCommentOnly
+addListForm
template(name="addListForm")
.list.list-composer.js-list-composer
+100 -61
View File
@@ -2,16 +2,27 @@ const { calculateIndex, enableClickOnTouch } = Utils;
function currentListIsInThisSwimlane(swimlaneId) {
const currentList = Lists.findOne(Session.get('currentList'));
return currentList && (currentList.swimlaneId === swimlaneId || currentList.swimlaneId === '');
return (
currentList &&
(currentList.swimlaneId === swimlaneId || currentList.swimlaneId === '')
);
}
function currentCardIsInThisList(listId, swimlaneId) {
const currentCard = Cards.findOne(Session.get('currentCard'));
const currentUser = Meteor.user();
if (currentUser && currentUser.profile && currentUser.profile.boardView === 'board-view-swimlanes')
return currentCard && currentCard.listId === listId && currentCard.swimlaneId === swimlaneId;
else // Default view: board-view-lists
return currentCard && currentCard.listId === listId;
if (
currentUser &&
currentUser.profile &&
currentUser.profile.boardView === 'board-view-swimlanes'
)
return (
currentCard &&
currentCard.listId === listId &&
currentCard.swimlaneId === swimlaneId
);
// Default view: board-view-lists
else return currentCard && currentCard.listId === listId;
// https://github.com/wekan/wekan/issues/1623
// https://github.com/ChronikEwok/wekan/commit/cad9b20451bb6149bfb527a99b5001873b06c3de
// TODO: In public board, if you would like to switch between List/Swimlane view, you could
@@ -79,7 +90,11 @@ function initSortable(boardComponent, $listsDom) {
enableClickOnTouch('.js-list:not(.js-list-composer)');
function userIsMember() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
}
// Disable drag-dropping while in multi-selection mode, or if the current user
@@ -87,8 +102,11 @@ function initSortable(boardComponent, $listsDom) {
boardComponent.autorun(() => {
const $listDom = $listsDom;
if ($listDom.data('sortable')) {
$listsDom.sortable('option', 'disabled',
MultiSelection.isActive() || !userIsMember());
$listsDom.sortable(
'option',
'disabled',
MultiSelection.isActive() || !userIsMember(),
);
}
});
}
@@ -124,47 +142,60 @@ BlazeComponent.extendComponent({
},
events() {
return [{
// Click-and-drag action
'mousedown .board-canvas'(evt) {
// Translating the board canvas using the click-and-drag action can
// conflict with the build-in browser mechanism to select text. We
// define a list of elements in which we disable the dragging because
// the user will legitimately expect to be able to select some text with
// his mouse.
const noDragInside = ['a', 'input', 'textarea', 'p', '.js-list-header'];
if ($(evt.target).closest(noDragInside.join(',')).length === 0 && this.$('.swimlane').prop('clientHeight') > evt.offsetY) {
this._isDragging = true;
this._lastDragPositionX = evt.clientX;
}
return [
{
// Click-and-drag action
'mousedown .board-canvas'(evt) {
// Translating the board canvas using the click-and-drag action can
// conflict with the build-in browser mechanism to select text. We
// define a list of elements in which we disable the dragging because
// the user will legitimately expect to be able to select some text with
// his mouse.
const noDragInside = [
'a',
'input',
'textarea',
'p',
'.js-list-header',
];
if (
$(evt.target).closest(noDragInside.join(',')).length === 0 &&
this.$('.swimlane').prop('clientHeight') > evt.offsetY
) {
this._isDragging = true;
this._lastDragPositionX = evt.clientX;
}
},
mouseup() {
if (this._isDragging) {
this._isDragging = false;
}
},
mousemove(evt) {
if (this._isDragging) {
// Update the canvas position
this.listsDom.scrollLeft -= evt.clientX - this._lastDragPositionX;
this._lastDragPositionX = evt.clientX;
// Disable browser text selection while dragging
evt.stopPropagation();
evt.preventDefault();
// Don't close opened card or inlined form at the end of the
// click-and-drag.
EscapeActions.executeUpTo('popup-close');
EscapeActions.preventNextClick();
}
},
},
'mouseup'() {
if (this._isDragging) {
this._isDragging = false;
}
},
'mousemove'(evt) {
if (this._isDragging) {
// Update the canvas position
this.listsDom.scrollLeft -= evt.clientX - this._lastDragPositionX;
this._lastDragPositionX = evt.clientX;
// Disable browser text selection while dragging
evt.stopPropagation();
evt.preventDefault();
// Don't close opened card or inlined form at the end of the
// click-and-drag.
EscapeActions.executeUpTo('popup-close');
EscapeActions.preventNextClick();
}
},
}];
];
},
}).register('swimlane');
BlazeComponent.extendComponent({
onCreated() {
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
this.isListTemplatesSwimlane = this.currentBoard.isTemplatesBoard() && this.currentData().isListTemplatesSwimlane();
this.isListTemplatesSwimlane =
this.currentBoard.isTemplatesBoard() &&
this.currentData().isListTemplatesSwimlane();
this.currentSwimlane = this.currentData();
},
@@ -174,32 +205,40 @@ BlazeComponent.extendComponent({
},
events() {
return [{
submit(evt) {
evt.preventDefault();
const titleInput = this.find('.list-name-input');
const title = titleInput.value.trim();
if (title) {
Lists.insert({
title,
boardId: Session.get('currentBoard'),
sort: $('.list').length,
type: (this.isListTemplatesSwimlane)?'template-list':'list',
swimlaneId: (this.currentBoard.isTemplatesBoard())?this.currentSwimlane._id:'',
});
return [
{
submit(evt) {
evt.preventDefault();
const titleInput = this.find('.list-name-input');
const title = titleInput.value.trim();
if (title) {
Lists.insert({
title,
boardId: Session.get('currentBoard'),
sort: $('.list').length,
type: this.isListTemplatesSwimlane ? 'template-list' : 'list',
swimlaneId: this.currentBoard.isTemplatesBoard()
? this.currentSwimlane._id
: '',
});
titleInput.value = '';
titleInput.focus();
}
titleInput.value = '';
titleInput.focus();
}
},
'click .js-list-template': Popup.open('searchElement'),
},
'click .js-list-template': Popup.open('searchElement'),
}];
];
},
}).register('addListForm');
Template.swimlane.helpers({
canSeeAddList() {
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly()
);
},
});
+46 -47
View File
@@ -22,14 +22,11 @@ Template.userAvatar.helpers({
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';
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';
else return 'idle';
},
});
@@ -45,7 +42,7 @@ Template.userAvatarInitials.helpers({
viewPortWidth() {
const user = Users.findOne(this.userId);
return (user && user.getInitials().length || 1) * 12;
return ((user && user.getInitials().length) || 1) * 12;
},
});
@@ -64,7 +61,7 @@ BlazeComponent.extendComponent({
},
uploadedAvatars() {
return Avatars.find({userId: Meteor.userId()});
return Avatars.find({ userId: Meteor.userId() });
},
isSelected() {
@@ -89,46 +86,48 @@ BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-upload-avatar'() {
this.$('.js-upload-avatar-input').click();
},
'change .js-upload-avatar-input'(evt) {
let file, fileUrl;
return [
{
'click .js-upload-avatar'() {
this.$('.js-upload-avatar-input').click();
},
'change .js-upload-avatar-input'(event) {
let file, fileUrl;
FS.Utility.eachFile(evt, (f) => {
try {
file = Avatars.insert(new FS.File(f));
fileUrl = file.url(this.avatarUrlOptions());
} catch (e) {
this.setError('avatar-too-big');
FS.Utility.eachFile(event, f => {
try {
file = Avatars.insert(new FS.File(f));
fileUrl = file.url(this.avatarUrlOptions());
} catch (e) {
this.setError('avatar-too-big');
}
});
if (fileUrl) {
this.setError('');
const fetchAvatarInterval = window.setInterval(() => {
$.ajax({
url: fileUrl,
success: () => {
this.setAvatar(file.url(this.avatarUrlOptions()));
window.clearInterval(fetchAvatarInterval);
},
});
}, 100);
}
});
if (fileUrl) {
this.setError('');
const fetchAvatarInterval = window.setInterval(() => {
$.ajax({
url: fileUrl,
success: () => {
this.setAvatar(file.url(this.avatarUrlOptions()));
window.clearInterval(fetchAvatarInterval);
},
});
}, 100);
}
},
'click .js-select-avatar'() {
const avatarUrl = this.currentData().url(this.avatarUrlOptions());
this.setAvatar(avatarUrl);
},
'click .js-select-initials'() {
this.setAvatar('');
},
'click .js-delete-avatar'() {
Avatars.remove(this.currentData()._id);
},
},
'click .js-select-avatar'() {
const avatarUrl = this.currentData().url(this.avatarUrlOptions());
this.setAvatar(avatarUrl);
},
'click .js-select-initials'() {
this.setAvatar('');
},
'click .js-delete-avatar'() {
Avatars.remove(this.currentData()._id);
},
}];
];
},
}).register('changeAvatarPopup');
@@ -146,11 +145,11 @@ Template.cardMembersPopup.helpers({
});
Template.cardMembersPopup.events({
'click .js-select-member'(evt) {
'click .js-select-member'(event) {
const card = Cards.findOne(Session.get('currentCard'));
const memberId = this.userId;
card.toggleMember(memberId);
evt.preventDefault();
event.preventDefault();
},
});
+48 -36
View File
@@ -18,8 +18,8 @@ Template.memberMenuPopup.events({
'click .js-change-avatar': Popup.open('changeAvatar'),
'click .js-change-password': Popup.open('changePassword'),
'click .js-change-language': Popup.open('changeLanguage'),
'click .js-logout'(evt) {
evt.preventDefault();
'click .js-logout'(event) {
event.preventDefault();
AccountsTemplates.logout();
},
@@ -38,12 +38,12 @@ Template.editProfilePopup.helpers({
});
Template.editProfilePopup.events({
submit(evt, tpl) {
evt.preventDefault();
const fullname = tpl.find('.js-profile-fullname').value.trim();
const username = tpl.find('.js-profile-username').value.trim();
const initials = tpl.find('.js-profile-initials').value.trim();
const email = tpl.find('.js-profile-email').value.trim();
submit(event, templateInstance) {
event.preventDefault();
const fullname = templateInstance.find('.js-profile-fullname').value.trim();
const username = templateInstance.find('.js-profile-username').value.trim();
const initials = templateInstance.find('.js-profile-initials').value.trim();
const email = templateInstance.find('.js-profile-email').value.trim();
let isChangeUserName = false;
let isChangeEmail = false;
Users.update(Meteor.userId(), {
@@ -53,29 +53,36 @@ Template.editProfilePopup.events({
},
});
isChangeUserName = username !== Meteor.user().username;
isChangeEmail = email.toLowerCase() !== Meteor.user().emails[0].address.toLowerCase();
isChangeEmail =
email.toLowerCase() !== Meteor.user().emails[0].address.toLowerCase();
if (isChangeUserName && isChangeEmail) {
Meteor.call('setUsernameAndEmail', username, email.toLowerCase(), Meteor.userId(), function (error) {
const usernameMessageElement = tpl.$('.username-taken');
const emailMessageElement = tpl.$('.email-taken');
if (error) {
const errorElement = error.error;
if (errorElement === 'username-already-taken') {
usernameMessageElement.show();
emailMessageElement.hide();
} else if (errorElement === 'email-already-taken') {
Meteor.call(
'setUsernameAndEmail',
username,
email.toLowerCase(),
Meteor.userId(),
function(error) {
const usernameMessageElement = templateInstance.$('.username-taken');
const emailMessageElement = templateInstance.$('.email-taken');
if (error) {
const errorElement = error.error;
if (errorElement === 'username-already-taken') {
usernameMessageElement.show();
emailMessageElement.hide();
} else if (errorElement === 'email-already-taken') {
usernameMessageElement.hide();
emailMessageElement.show();
}
} else {
usernameMessageElement.hide();
emailMessageElement.show();
emailMessageElement.hide();
Popup.back();
}
} else {
usernameMessageElement.hide();
emailMessageElement.hide();
Popup.back();
}
});
},
);
} else if (isChangeUserName) {
Meteor.call('setUsername', username, Meteor.userId(), function (error) {
const messageElement = tpl.$('.username-taken');
Meteor.call('setUsername', username, Meteor.userId(), function(error) {
const messageElement = templateInstance.$('.username-taken');
if (error) {
messageElement.show();
} else {
@@ -84,8 +91,10 @@ Template.editProfilePopup.events({
}
});
} else if (isChangeEmail) {
Meteor.call('setEmail', email.toLowerCase(), Meteor.userId(), function (error) {
const messageElement = tpl.$('.email-taken');
Meteor.call('setEmail', email.toLowerCase(), Meteor.userId(), function(
error,
) {
const messageElement = templateInstance.$('.email-taken');
if (error) {
messageElement.show();
} else {
@@ -104,7 +113,7 @@ Template.editProfilePopup.events({
// XXX For some reason the useraccounts autofocus isnt working in this case.
// See https://github.com/meteor-useraccounts/core/issues/384
Template.changePasswordPopup.onRendered(function () {
Template.changePasswordPopup.onRendered(function() {
this.find('#at-field-current_password').focus();
});
@@ -123,7 +132,7 @@ Template.changeLanguagePopup.helpers({
name = 'Occitan';
}
return { tag, name };
}).sort(function (a, b) {
}).sort(function(a, b) {
if (a.name === b.name) {
return 0;
} else {
@@ -138,13 +147,13 @@ Template.changeLanguagePopup.helpers({
});
Template.changeLanguagePopup.events({
'click .js-set-language'(evt) {
'click .js-set-language'(event) {
Users.update(Meteor.userId(), {
$set: {
'profile.language': this.tag,
},
});
evt.preventDefault();
event.preventDefault();
},
});
@@ -161,9 +170,12 @@ Template.changeSettingsPopup.events({
'click .js-toggle-system-messages'() {
Meteor.call('toggleSystemMessages');
},
'click .js-apply-show-cards-at'(evt, tpl) {
evt.preventDefault();
const minLimit = parseInt(tpl.$('#show-cards-count-at').val(), 10);
'click .js-apply-show-cards-at'(event, templateInstance) {
event.preventDefault();
const minLimit = parseInt(
templateInstance.$('#show-cards-count-at').val(),
10,
);
if (!isNaN(minLimit)) {
Meteor.call('changeLimitToShowCardsCount', minLimit);
Popup.back();
+1 -1
View File
@@ -25,7 +25,7 @@ Blaze.registerHelper('currentList', () => {
}
});
Blaze.registerHelper('getUser', (userId) => Users.findOne(userId));
Blaze.registerHelper('getUser', userId => Users.findOne(userId));
Blaze.registerHelper('concat', (...args) => args.slice(0, -1).join(''));
+1 -4
View File
@@ -27,10 +27,7 @@ function copyTitleInAriaLabel(attributes) {
// which is a little bit hacky -- but still reasonable with our ES6 usage. If we
// end up switching to React we will probably create lower level small
// components to handle that without overwriting any build-in function.
const {
A: superA,
I: superI,
} = HTML;
const { A: superA, I: superI } = HTML;
HTML.A = (attributes, ...others) => {
return superA(copyTitleInAriaLabel(enforceHref(attributes)), ...others);
+10 -10
View File
@@ -3,11 +3,11 @@
function whichTransitionEvent() {
const el = document.createElement('fakeelement');
const transitions = {
transition:'transitionend',
OTransition:'oTransitionEnd',
MSTransition:'msTransitionEnd',
MozTransition:'transitionend',
WebkitTransition:'webkitTransitionEnd',
transition: 'transitionend',
OTransition: 'oTransitionEnd',
MSTransition: 'msTransitionEnd',
MozTransition: 'transitionend',
WebkitTransition: 'webkitTransitionEnd',
};
for (const t in transitions) {
@@ -21,11 +21,11 @@ function whichTransitionEvent() {
function whichAnimationEvent() {
const el = document.createElement('fakeelement');
const transitions = {
animation:'animationend',
OAnimation:'oAnimationEnd',
MSTransition:'msAnimationEnd',
MozAnimation:'animationend',
WebkitAnimation:'webkitAnimationEnd',
animation: 'animationend',
OAnimation: 'oAnimationEnd',
MSTransition: 'msAnimationEnd',
MozAnimation: 'animationend',
WebkitAnimation: 'webkitAnimationEnd',
};
for (const t in transitions) {
+54 -48
View File
@@ -10,15 +10,20 @@ DatePicker = BlazeComponent.extendComponent({
},
onRendered() {
const $picker = this.$('.js-datepicker').datepicker({
todayHighlight: true,
todayBtn: 'linked',
language: TAPi18n.getLanguage(),
}).on('changeDate', function(evt) {
this.find('#date').value = moment(evt.date).format('L');
this.error.set('');
this.find('#time').focus();
}.bind(this));
const $picker = this.$('.js-datepicker')
.datepicker({
todayHighlight: true,
todayBtn: 'linked',
language: TAPi18n.getLanguage(),
})
.on(
'changeDate',
function(evt) {
this.find('#date').value = moment(evt.date).format('L');
this.error.set('');
this.find('#time').focus();
}.bind(this),
);
if (this.date.get().isValid()) {
$picker.datepicker('update', this.date.get().toDate());
@@ -26,13 +31,11 @@ DatePicker = BlazeComponent.extendComponent({
},
showDate() {
if (this.date.get().isValid())
return this.date.get().format('L');
if (this.date.get().isValid()) return this.date.get().format('L');
return '';
},
showTime() {
if (this.date.get().isValid())
return this.date.get().format('LT');
if (this.date.get().isValid()) return this.date.get().format('LT');
return '';
},
dateFormat() {
@@ -43,44 +46,47 @@ DatePicker = BlazeComponent.extendComponent({
},
events() {
return [{
'keyup .js-date-field'() {
// parse for localized date format in strict mode
const dateMoment = moment(this.find('#date').value, 'L', true);
if (dateMoment.isValid()) {
this.error.set('');
this.$('.js-datepicker').datepicker('update', dateMoment.toDate());
}
},
'keyup .js-time-field'() {
// parse for localized time format in strict mode
const dateMoment = moment(this.find('#time').value, 'LT', true);
if (dateMoment.isValid()) {
this.error.set('');
}
},
'submit .edit-date'(evt) {
evt.preventDefault();
return [
{
'keyup .js-date-field'() {
// parse for localized date format in strict mode
const dateMoment = moment(this.find('#date').value, 'L', true);
if (dateMoment.isValid()) {
this.error.set('');
this.$('.js-datepicker').datepicker('update', dateMoment.toDate());
}
},
'keyup .js-time-field'() {
// parse for localized time format in strict mode
const dateMoment = moment(this.find('#time').value, 'LT', true);
if (dateMoment.isValid()) {
this.error.set('');
}
},
'submit .edit-date'(evt) {
evt.preventDefault();
// if no time was given, init with 12:00
const time = evt.target.time.value || moment(new Date().setHours(12, 0, 0)).format('LT');
// if no time was given, init with 12:00
const time =
evt.target.time.value ||
moment(new Date().setHours(12, 0, 0)).format('LT');
const dateString = `${evt.target.date.value} ${time}`;
const newDate = moment(dateString, 'L LT', true);
if (newDate.isValid()) {
this._storeDate(newDate.toDate());
const dateString = `${evt.target.date.value} ${time}`;
const newDate = moment(dateString, 'L LT', true);
if (newDate.isValid()) {
this._storeDate(newDate.toDate());
Popup.close();
} else {
this.error.set('invalid-date');
evt.target.date.focus();
}
},
'click .js-delete-date'(evt) {
evt.preventDefault();
this._deleteDate();
Popup.close();
}
else {
this.error.set('invalid-date');
evt.target.date.focus();
}
},
},
'click .js-delete-date'(evt) {
evt.preventDefault();
this._deleteDate();
Popup.close();
},
}];
];
},
});
+8 -5
View File
@@ -11,7 +11,10 @@
$.event.fix = (function(originalFix) {
return function(event) {
event = originalFix.apply(this, arguments);
if (event.type.indexOf('drag') === 0 || event.type.indexOf('drop') === 0) {
if (
event.type.indexOf('drag') === 0 ||
event.type.indexOf('drop') === 0
) {
event.dataTransfer = event.originalEvent.dataTransfer;
}
return event;
@@ -23,7 +26,7 @@
matchType: /image.*/,
};
return $.fn.dropImageReader = function(options) {
return ($.fn.dropImageReader = function(options) {
if (typeof options === 'function') {
options = {
callback: options,
@@ -40,9 +43,9 @@
return $(element).bind('drop', function(event) {
stopFn(event);
const files = event.dataTransfer.files;
for(let i=0; i<files.length; i++) {
for (let i = 0; i < files.length; i++) {
const f = files[i];
if(f.type.match(options.matchType)) {
if (f.type.match(options.matchType)) {
const reader = new FileReader();
reader.onload = function(evt) {
return options.callback.call(element, {
@@ -58,5 +61,5 @@
}
});
});
};
});
})(jQuery);
+25 -23
View File
@@ -33,13 +33,19 @@ EscapeActions = {
const noClickEscapeOn = options.noClickEscapeOn;
this._actions = _.sortBy([...this._actions, {
priority,
condition,
action,
noClickEscapeOn,
enabledOnClick,
}], (action) => action.priority);
this._actions = _.sortBy(
[
...this._actions,
{
priority,
condition,
action,
noClickEscapeOn,
enabledOnClick,
},
],
action => action.priority,
);
},
executeLowest() {
@@ -80,10 +86,8 @@ EscapeActions = {
},
_stopClick(action, clickTarget) {
if (!_.isString(action.noClickEscapeOn))
return false;
else
return $(clickTarget).closest(action.noClickEscapeOn).length > 0;
if (!_.isString(action.noClickEscapeOn)) return false;
else return $(clickTarget).closest(action.noClickEscapeOn).length > 0;
},
_execute(options) {
@@ -95,14 +99,11 @@ EscapeActions = {
let executedAtLeastOne = false;
let maxPriority;
if (!maxLabel)
maxPriority = Infinity;
else
maxPriority = this.hierarchy.indexOf(maxLabel);
if (!maxLabel) maxPriority = Infinity;
else maxPriority = this.hierarchy.indexOf(maxLabel);
for (const currentAction of this._actions) {
if (currentAction.priority > maxPriority)
return executedAtLeastOne;
if (currentAction.priority > maxPriority) return executedAtLeastOne;
if (isClick && this._stopClick(currentAction, clickTarget))
return executedAtLeastOne;
@@ -111,8 +112,7 @@ EscapeActions = {
if (isEnabled && currentAction.condition()) {
currentAction.action();
executedAtLeastOne = true;
if (!multipleActions)
return executedAtLeastOne;
if (!multipleActions) return executedAtLeastOne;
}
}
return executedAtLeastOne;
@@ -128,13 +128,15 @@ Mousetrap.bindGlobal('esc', () => {
// On a left click on the document, we try to exectute one escape action (eg,
// close the popup). We don't execute any action if the user has clicked on a
// link or a button.
$(document).on('click', (evt) => {
if (evt.button === 0 &&
$(evt.target).closest('a,button,.is-editable').length === 0) {
$(document).on('click', evt => {
if (
evt.button === 0 &&
$(evt.target).closest('a,button,.is-editable').length === 0
) {
EscapeActions.clickExecute(evt.target, 'multiselection');
}
});
$(document).on('click', 'a[href=\\#]', (evt) => {
$(document).on('click', 'a[href=\\#]', evt => {
evt.preventDefault();
});
+228 -236
View File
@@ -71,18 +71,19 @@ class SetFilter {
_getEmptySelector() {
this._dep.depend();
let includeEmpty = false;
this._selectedElements.forEach((el) => {
this._selectedElements.forEach(el => {
if (el === undefined) {
includeEmpty = true;
}
});
return includeEmpty ? {
$eq: [],
} : null;
return includeEmpty
? {
$eq: [],
}
: null;
}
}
// Advanced filter forms a MongoSelector from a users String.
// Build by: Ignatz 19.05.2018 (github feuerball11)
class AdvancedFilter {
@@ -128,7 +129,8 @@ class AdvancedFilter {
current += char;
continue;
}
if (char === '\'') {
// eslint-disable-next-line quotes
if (char === "'") {
string = !string;
if (string) wasString = true;
continue;
@@ -139,8 +141,8 @@ class AdvancedFilter {
}
if (char === ' ' && !string) {
commands.push({
'cmd': current,
'string': wasString,
cmd: current,
string: wasString,
regex,
});
wasString = false;
@@ -151,8 +153,8 @@ class AdvancedFilter {
}
if (current !== '') {
commands.push({
'cmd': current,
'string': wasString,
cmd: current,
string: wasString,
regex,
});
}
@@ -161,16 +163,19 @@ class AdvancedFilter {
_fieldNameToId(field) {
const found = CustomFields.findOne({
'name': field,
name: field,
});
return found._id;
}
_fieldValueToId(field, value) {
const found = CustomFields.findOne({
'name': field,
name: field,
});
if (found.settings.dropdownItems && found.settings.dropdownItems.length > 0) {
if (
found.settings.dropdownItems &&
found.settings.dropdownItems.length > 0
) {
for (let i = 0; i < found.settings.dropdownItems.length; i++) {
if (found.settings.dropdownItems[i].name === value) {
return found.settings.dropdownItems[i]._id;
@@ -202,37 +207,32 @@ class AdvancedFilter {
for (let i = 0; i < commands.length; i++) {
if (commands[i].cmd) {
switch (commands[i].cmd) {
case '(':
{
level++;
if (start === -1) start = i;
continue;
}
case ')':
{
level--;
commands.splice(i, 1);
i--;
continue;
}
default:
{
if (level > 0) {
subcommands.push(commands[i]);
case '(': {
level++;
if (start === -1) start = i;
continue;
}
case ')': {
level--;
commands.splice(i, 1);
i--;
continue;
}
}
default: {
if (level > 0) {
subcommands.push(commands[i]);
commands.splice(i, 1);
i--;
continue;
}
}
}
}
}
if (start !== -1) {
this._processSubCommands(subcommands);
if (subcommands.length === 1)
commands.splice(start, 0, subcommands[0]);
else
commands.splice(start, 0, subcommands);
if (subcommands.length === 1) commands.splice(start, 0, subcommands[0]);
else commands.splice(start, 0, subcommands);
}
this._processConditions(commands);
this._processLogicalOperators(commands);
@@ -242,149 +242,139 @@ class AdvancedFilter {
for (let i = 0; i < commands.length; i++) {
if (!commands[i].string && commands[i].cmd) {
switch (commands[i].cmd) {
case '=':
case '==':
case '===':
{
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
if (commands[i + 1].regex) {
const match = str.match(new RegExp('^/(.*?)/([gimy]*)$'));
let regex = null;
if (match.length > 2)
regex = new RegExp(match[1], match[2]);
else
regex = new RegExp(match[1]);
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': regex,
};
} else {
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$in: [this._fieldValueToId(field, str), parseInt(str, 10)],
},
};
}
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case '!=':
case '!==':
{
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
if (commands[i + 1].regex) {
const match = str.match(new RegExp('^/(.*?)/([gimy]*)$'));
let regex = null;
if (match.length > 2)
regex = new RegExp(match[1], match[2]);
else
regex = new RegExp(match[1]);
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$not: regex,
},
};
} else {
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$not: {
case '=':
case '==':
case '===': {
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
if (commands[i + 1].regex) {
const match = str.match(new RegExp('^/(.*?)/([gimy]*)$'));
let regex = null;
if (match.length > 2) regex = new RegExp(match[1], match[2]);
else regex = new RegExp(match[1]);
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': regex,
};
} else {
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$in: [this._fieldValueToId(field, str), parseInt(str, 10)],
},
};
}
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case '!=':
case '!==': {
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
if (commands[i + 1].regex) {
const match = str.match(new RegExp('^/(.*?)/([gimy]*)$'));
let regex = null;
if (match.length > 2) regex = new RegExp(match[1], match[2]);
else regex = new RegExp(match[1]);
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$not: regex,
},
};
} else {
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$not: {
$in: [this._fieldValueToId(field, str), parseInt(str, 10)],
},
},
};
}
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case '>':
case 'gt':
case 'Gt':
case 'GT': {
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$gt: parseInt(str, 10),
},
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case '>=':
case '>==':
case 'gte':
case 'Gte':
case 'GTE': {
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$gte: parseInt(str, 10),
},
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case '<':
case 'lt':
case 'Lt':
case 'LT': {
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$lt: parseInt(str, 10),
},
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case '<=':
case '<==':
case 'lte':
case 'Lte':
case 'LTE': {
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$lte: parseInt(str, 10),
},
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case '>':
case 'gt':
case 'Gt':
case 'GT':
{
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$gt: parseInt(str, 10),
},
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case '>=':
case '>==':
case 'gte':
case 'Gte':
case 'GTE':
{
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$gte: parseInt(str, 10),
},
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case '<':
case 'lt':
case 'Lt':
case 'LT':
{
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$lt: parseInt(str, 10),
},
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case '<=':
case '<==':
case 'lte':
case 'Lte':
case 'LTE':
{
const field = commands[i - 1].cmd;
const str = commands[i + 1].cmd;
commands[i] = {
'customFields._id': this._fieldNameToId(field),
'customFields.value': {
$lte: parseInt(str, 10),
},
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
}
}
}
@@ -394,54 +384,51 @@ class AdvancedFilter {
for (let i = 0; i < commands.length; i++) {
if (!commands[i].string && commands[i].cmd) {
switch (commands[i].cmd) {
case 'or':
case 'Or':
case 'OR':
case '|':
case '||':
{
const op1 = commands[i - 1];
const op2 = commands[i + 1];
commands[i] = {
$or: [op1, op2],
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case 'and':
case 'And':
case 'AND':
case '&':
case '&&':
{
const op1 = commands[i - 1];
const op2 = commands[i + 1];
commands[i] = {
$and: [op1, op2],
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case 'not':
case 'Not':
case 'NOT':
case '!':
{
const op1 = commands[i + 1];
commands[i] = {
$not: op1,
};
commands.splice(i + 1, 1);
//changed = true;
i--;
break;
}
case 'or':
case 'Or':
case 'OR':
case '|':
case '||': {
const op1 = commands[i - 1];
const op2 = commands[i + 1];
commands[i] = {
$or: [op1, op2],
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case 'and':
case 'And':
case 'AND':
case '&':
case '&&': {
const op1 = commands[i - 1];
const op2 = commands[i + 1];
commands[i] = {
$and: [op1, op2],
};
commands.splice(i - 1, 1);
commands.splice(i, 1);
//changed = true;
i--;
break;
}
case 'not':
case 'Not':
case 'NOT':
case '!': {
const op1 = commands[i + 1];
commands[i] = {
$not: op1,
};
commands.splice(i + 1, 1);
//changed = true;
i--;
break;
}
}
}
}
@@ -452,7 +439,6 @@ class AdvancedFilter {
const commands = this._filterToCommands();
return this._arrayToSelector(commands);
}
}
// The global Filter object.
@@ -477,23 +463,26 @@ Filter = {
_exceptionsDep: new Tracker.Dependency(),
isActive() {
return _.any(this._fields, (fieldName) => {
return this[fieldName]._isActive();
}) || this.advanced._isActive();
return (
_.any(this._fields, fieldName => {
return this[fieldName]._isActive();
}) || this.advanced._isActive()
);
},
_getMongoSelector() {
if (!this.isActive())
return {};
if (!this.isActive()) return {};
const filterSelector = {};
const emptySelector = {};
let includeEmptySelectors = false;
this._fields.forEach((fieldName) => {
this._fields.forEach(fieldName => {
const filter = this[fieldName];
if (filter._isActive()) {
if (filter.subField !== '') {
filterSelector[`${fieldName}.${filter.subField}`] = filter._getMongoSelector();
filterSelector[
`${fieldName}.${filter.subField}`
] = filter._getMongoSelector();
} else {
filterSelector[fieldName] = filter._getMongoSelector();
}
@@ -513,11 +502,15 @@ Filter = {
const selectors = [exceptionsSelector];
if (_.any(this._fields, (fieldName) => {
return this[fieldName]._isActive();
})) selectors.push(filterSelector);
if (
_.any(this._fields, fieldName => {
return this[fieldName]._isActive();
})
)
selectors.push(filterSelector);
if (includeEmptySelectors) selectors.push(emptySelector);
if (this.advanced._isActive()) selectors.push(this.advanced._getMongoSelector());
if (this.advanced._isActive())
selectors.push(this.advanced._getMongoSelector());
return {
$or: selectors,
@@ -526,8 +519,7 @@ Filter = {
mongoSelector(additionalSelector) {
const filterSelector = this._getMongoSelector();
if (_.isUndefined(additionalSelector))
return filterSelector;
if (_.isUndefined(additionalSelector)) return filterSelector;
else
return {
$and: [filterSelector, additionalSelector],
@@ -535,7 +527,7 @@ Filter = {
},
reset() {
this._fields.forEach((fieldName) => {
this._fields.forEach(fieldName => {
const filter = this[fieldName];
filter.reset();
});
+1 -1
View File
@@ -12,7 +12,7 @@ Meteor.startup(() => {
}
if (!language) {
if(navigator.languages) {
if (navigator.languages) {
language = navigator.languages[0];
} else {
language = navigator.language || navigator.userLanguage;
+37 -29
View File
@@ -48,43 +48,51 @@ InlinedForm = BlazeComponent.extendComponent({
},
events() {
return [{
'click .js-close-inlined-form': this.close,
'click .js-open-inlined-form': this.open,
return [
{
'click .js-close-inlined-form': this.close,
'click .js-open-inlined-form': this.open,
// Pressing Ctrl+Enter should submit the form
'keydown form textarea'(evt) {
if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) {
this.find('button[type=submit]').click();
}
},
// Pressing Ctrl+Enter should submit the form
'keydown form textarea'(evt) {
if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) {
this.find('button[type=submit]').click();
}
},
// Close the inlined form when after its submission
submit() {
if (this.currentData().autoclose !== false) {
Tracker.afterFlush(() => {
this.close();
});
}
// Close the inlined form when after its submission
submit() {
if (this.currentData().autoclose !== false) {
Tracker.afterFlush(() => {
this.close();
});
}
},
},
}];
];
},
}).register('inlinedForm');
// Press escape to close the currently opened inlinedForm
EscapeActions.register('inlinedForm',
() => { currentlyOpenedForm.get().close(); },
() => { return currentlyOpenedForm.get() !== null; }, {
EscapeActions.register(
'inlinedForm',
() => {
currentlyOpenedForm.get().close();
},
() => {
return currentlyOpenedForm.get() !== null;
},
{
enabledOnClick: false,
}
},
);
// submit on click outside
document.addEventListener('click', function(evt) {
const openedForm = currentlyOpenedForm.get();
const isClickOutside = $(evt.target).closest('.js-inlined-form').length === 0;
if (openedForm && isClickOutside) {
$('.js-inlined-form button[type=submit]').click();
openedForm.close();
}
}, true);
//document.addEventListener('click', function(evt) {
// const openedForm = currentlyOpenedForm.get();
// const isClickOutside = $(evt.target).closest('.js-inlined-form').length === 0;
// if (openedForm && isClickOutside) {
// $('.js-inlined-form button[type=submit]').click();
// openedForm.close();
// }
//}, true);
+39 -28
View File
@@ -40,8 +40,10 @@ Mousetrap.bind(['down', 'up'], (evt, key) => {
return;
}
const nextFunc = (key === 'down' ? 'next' : 'prev');
const nextCard = $('.js-minicard.is-selected')[nextFunc]('.js-minicard').get(0);
const nextFunc = key === 'down' ? 'next' : 'prev';
const nextCard = $('.js-minicard.is-selected')
[nextFunc]('.js-minicard')
.get(0);
if (nextCard) {
const nextCardId = Blaze.getData(nextCard)._id;
Utils.goCardId(nextCardId);
@@ -49,7 +51,7 @@ Mousetrap.bind(['down', 'up'], (evt, key) => {
});
// XXX This shortcut should also work when hovering over a card in board view
Mousetrap.bind('space', (evt) => {
Mousetrap.bind('space', evt => {
if (!Session.get('currentCard')) {
return;
}
@@ -69,29 +71,38 @@ Mousetrap.bind('space', (evt) => {
});
Template.keyboardShortcuts.helpers({
mapping: [{
keys: ['W'],
action: 'shortcut-toggle-sidebar',
}, {
keys: ['Q'],
action: 'shortcut-filter-my-cards',
}, {
keys: ['F'],
action: 'shortcut-toggle-filterbar',
}, {
keys: ['X'],
action: 'shortcut-clear-filters',
}, {
keys: ['?'],
action: 'shortcut-show-shortcuts',
}, {
keys: ['ESC'],
action: 'shortcut-close-dialog',
}, {
keys: ['@'],
action: 'shortcut-autocomplete-members',
}, {
keys: ['SPACE'],
action: 'shortcut-assign-self',
}],
mapping: [
{
keys: ['W'],
action: 'shortcut-toggle-sidebar',
},
{
keys: ['Q'],
action: 'shortcut-filter-my-cards',
},
{
keys: ['F'],
action: 'shortcut-toggle-filterbar',
},
{
keys: ['X'],
action: 'shortcut-clear-filters',
},
{
keys: ['?'],
action: 'shortcut-show-shortcuts',
},
{
keys: ['ESC'],
action: 'shortcut-close-dialog',
},
{
keys: ['@'],
action: 'shortcut-autocomplete-members',
},
{
keys: ['SPACE'],
action: 'shortcut-assign-self',
},
],
});
+8 -8
View File
@@ -1,6 +1,6 @@
const closedValue = null;
window.Modal = new class {
window.Modal = new (class {
constructor() {
this._currentModal = new ReactiveVar(closedValue);
this._onCloseGoTo = '';
@@ -21,7 +21,7 @@ window.Modal = new class {
return this.getTemplateName() !== closedValue;
}
isWide(){
isWide() {
return this._isWideModal;
}
@@ -32,23 +32,23 @@ window.Modal = new class {
}
}
openWide(modalName, { header = '', onCloseGoTo = ''} = {}) {
openWide(modalName, { header = '', onCloseGoTo = '' } = {}) {
this._currentModal.set({ header, modalName });
this._onCloseGoTo = onCloseGoTo;
this._isWideModal = true;
}
open(modalName, { header = '', onCloseGoTo = ''} = {}) {
open(modalName, { header = '', onCloseGoTo = '' } = {}) {
this._currentModal.set({ header, modalName });
this._onCloseGoTo = onCloseGoTo;
}
}();
})();
Blaze.registerHelper('Modal', Modal);
EscapeActions.register('modalWindow',
EscapeActions.register(
'modalWindow',
() => Modal.close(),
() => Modal.isOpen(),
{ noClickEscapeOn: '.modal-container' }
{ noClickEscapeOn: '.modal-container' },
);
+27 -21
View File
@@ -1,6 +1,4 @@
function getCardsBetween(idA, idB) {
function pluckId(doc) {
return doc._id;
}
@@ -15,7 +13,7 @@ function getCardsBetween(idA, idB) {
}).map(pluckId);
}
const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], (c) => {
const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], c => {
return c.sort;
});
@@ -31,17 +29,21 @@ function getCardsBetween(idA, idB) {
};
} else {
selector = {
$or: [{
listId: cards[0].listId,
sort: { $lte: cards[0].sort },
}, {
listId: {
$in: getListsStrictlyBetween(cards[0].listId, cards[1].listId),
$or: [
{
listId: cards[0].listId,
sort: { $lte: cards[0].sort },
},
}, {
listId: cards[1].listId,
sort: { $gte: cards[1].sort },
}],
{
listId: {
$in: getListsStrictlyBetween(cards[0].listId, cards[1].listId),
},
},
{
listId: cards[1].listId,
sort: { $gte: cards[1].sort },
},
],
archived: false,
};
}
@@ -133,14 +135,12 @@ MultiSelection = {
const selectedCards = this._selectedCards.get();
cardIds.forEach((cardId) => {
cardIds.forEach(cardId => {
const indexOfCard = selectedCards.indexOf(cardId);
if (options.remove && indexOfCard > -1)
selectedCards.splice(indexOfCard, 1);
else if (options.add)
selectedCards.push(cardId);
else if (options.add) selectedCards.push(cardId);
});
this._selectedCards.set(selectedCards);
@@ -153,9 +153,15 @@ MultiSelection = {
Blaze.registerHelper('MultiSelection', MultiSelection);
EscapeActions.register('multiselection',
() => { MultiSelection.disable(); },
() => { return MultiSelection.isActive(); }, {
EscapeActions.register(
'multiselection',
() => {
MultiSelection.disable();
},
() => {
return MultiSelection.isActive();
},
{
noClickEscapeOn: '.js-minicard,.js-board-sidebar-content',
}
},
);
+11 -5
View File
@@ -11,7 +11,10 @@
$.event.fix = (function(originalFix) {
return function(event) {
event = originalFix.apply(this, arguments);
if (event.type.indexOf('copy') === 0 || event.type.indexOf('paste') === 0) {
if (
event.type.indexOf('copy') === 0 ||
event.type.indexOf('paste') === 0
) {
event.clipboardData = event.originalEvent.clipboardData;
}
return event;
@@ -23,7 +26,7 @@
matchType: /image.*/,
};
return $.fn.pasteImageReader = function(options) {
return ($.fn.pasteImageReader = function(options) {
if (typeof options === 'function') {
options = {
callback: options,
@@ -35,8 +38,11 @@
return $(element).bind('paste', function(event) {
const types = event.clipboardData.types;
const items = event.clipboardData.items;
for(let i=0; i<types.length; i++) {
if(types[i].match(options.matchType) || items[i].type.match(options.matchType)) {
for (let i = 0; i < types.length; i++) {
if (
types[i].match(options.matchType) ||
items[i].type.match(options.matchType)
) {
const f = items[i].getAsFile();
const reader = new FileReader();
reader.onload = function(evt) {
@@ -53,5 +59,5 @@
}
});
});
};
});
})(jQuery);
+17 -14
View File
@@ -1,4 +1,4 @@
window.Popup = new class {
window.Popup = new (class {
constructor() {
// The template we use to render popups
this.template = Template.popup;
@@ -67,7 +67,7 @@ window.Popup = new class {
title: self._getTitle(popupName),
depth: self._stack.length,
offset: self._getOffset(openerElement),
dataContext: this.currentData && this.currentData() || this,
dataContext: (this.currentData && this.currentData()) || this,
});
// If there are no popup currently opened we use the Blaze API to render
@@ -80,11 +80,14 @@ window.Popup = new class {
// our internal dependency, and since we just changed the top element of
// our internal stack, the popup will be updated with the new data.
if (!self.isOpen()) {
self.current = Blaze.renderWithData(self.template, () => {
self._dep.depend();
return { ...self._getTopStack(), stack: self._stack };
}, document.body);
self.current = Blaze.renderWithData(
self.template,
() => {
self._dep.depend();
return { ...self._getTopStack(), stack: self._stack };
},
document.body,
);
} else {
self._dep.changed();
}
@@ -101,7 +104,7 @@ window.Popup = new class {
const self = this;
return function(evt, tpl) {
const context = this.currentData && this.currentData() || this;
const context = (this.currentData && this.currentData()) || this;
context.__afterConfirmAction = action;
self.open(name).call(context, evt, tpl);
};
@@ -136,7 +139,6 @@ window.Popup = new class {
const openerElement = this._getTopStack().openerElement;
$(openerElement).removeClass('is-active');
this._stack = [];
}
}
@@ -159,7 +161,7 @@ window.Popup = new class {
return () => {
Utils.windowResizeDep.depend();
if(Utils.isMiniScreen()) return { left:0, top:0 };
if (Utils.isMiniScreen()) return { left: 0, top: 0 };
const offset = $element.offset();
const popupWidth = 300 + 15;
@@ -188,18 +190,19 @@ window.Popup = new class {
return title !== translationKey ? title : defaultTitle;
};
}
}();
})();
// We close a potential opened popup on any left click on the document, or go
// one step back by pressing escape.
const escapeActions = ['back', 'close'];
escapeActions.forEach((actionName) => {
EscapeActions.register(`popup-${actionName}`,
escapeActions.forEach(actionName => {
EscapeActions.register(
`popup-${actionName}`,
() => Popup[actionName](),
() => Popup.isOpen(),
{
noClickEscapeOn: '.js-pop-over,.js-open-card-title-popup',
enabledOnClick: actionName === 'close',
}
},
);
});
+3 -6
View File
@@ -47,9 +47,6 @@ $.fn.escapeableTextComplete = function(strategies, options, ...otherArgs) {
});
};
EscapeActions.register('textcomplete',
() => {},
() => dropdownMenuIsOpened, {
noClickEscapeOn: '.textcomplete-dropdown',
}
);
EscapeActions.register('textcomplete', () => {}, () => dropdownMenuIsOpened, {
noClickEscapeOn: '.textcomplete-dropdown',
});
+3 -3
View File
@@ -34,13 +34,13 @@ UnsavedEdits = {
},
has({ fieldName, docId }) {
return Boolean(this.get({fieldName, docId}));
return Boolean(this.get({ fieldName, docId }));
},
set({ fieldName, docId }, value) {
const currentDoc = this._getCollectionDocument(fieldName, docId);
if (currentDoc) {
UnsavedEditCollection.update(currentDoc._id, { $set: { value }});
UnsavedEditCollection.update(currentDoc._id, { $set: { value } });
} else {
UnsavedEditCollection.insert({
fieldName,
@@ -58,7 +58,7 @@ UnsavedEdits = {
},
_getCollectionDocument(fieldName, docId) {
return UnsavedEditCollection.findOne({fieldName, docId});
return UnsavedEditCollection.findOne({ fieldName, docId });
},
};
+51 -27
View File
@@ -2,20 +2,26 @@ Utils = {
// XXX We should remove these two methods
goBoardId(_id) {
const board = Boards.findOne(_id);
return board && FlowRouter.go('board', {
id: board._id,
slug: board.slug,
});
return (
board &&
FlowRouter.go('board', {
id: board._id,
slug: board.slug,
})
);
},
goCardId(_id) {
const card = Cards.findOne(_id);
const board = Boards.findOne(card.boardId);
return board && FlowRouter.go('card', {
cardId: card._id,
boardId: board._id,
slug: board.slug,
});
return (
board &&
FlowRouter.go('card', {
cardId: card._id,
boardId: board._id,
slug: board.slug,
})
);
},
capitalize(string) {
@@ -104,13 +110,21 @@ Utils = {
return window.matchMedia(query).matches;
};
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) {
if (
'ontouchstart' in window ||
(window.DocumentTouch && document instanceof window.DocumentTouch)
) {
return true;
}
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
// https://git.io/vznFH
const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
const query = [
'(',
prefixes.join('touch-enabled),('),
'heartz',
')',
].join('');
return mq(query);
})();
Utils.isTouchDevice = () => isTouchable;
@@ -120,7 +134,7 @@ Utils = {
calculateTouchDistance(touchA, touchB) {
return Math.sqrt(
Math.pow(touchA.screenX - touchB.screenX, 2) +
Math.pow(touchA.screenY - touchB.screenY, 2)
Math.pow(touchA.screenY - touchB.screenY, 2),
);
},
@@ -136,7 +150,11 @@ Utils = {
lastTouch = touches[touches.length - 1];
});
$(document).on('touchend', selector, function(e) {
if (touchStart && lastTouch && Utils.calculateTouchDistance(touchStart, lastTouch) <= 20) {
if (
touchStart &&
lastTouch &&
Utils.calculateTouchDistance(touchStart, lastTouch) <= 20
) {
e.preventDefault();
const clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent('click', true, true);
@@ -145,30 +163,30 @@ Utils = {
});
},
manageCustomUI(){
manageCustomUI() {
Meteor.call('getCustomUI', (err, data) => {
if (err && err.error[0] === 'var-not-exist'){
if (err && err.error[0] === 'var-not-exist') {
Session.set('customUI', false); // siteId || address server not defined
}
if (!err){
if (!err) {
Utils.setCustomUI(data);
}
});
},
setCustomUI(data){
setCustomUI(data) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (currentBoard) {
DocHead.setTitle(`${currentBoard.title } - ${ data.productName}`);
DocHead.setTitle(`${currentBoard.title} - ${data.productName}`);
} else {
DocHead.setTitle(`${data.productName}`);
}
},
setMatomo(data){
setMatomo(data) {
window._paq = window._paq || [];
window._paq.push(['setDoNotTrack', data.doNotTrack]);
if (data.withUserName){
if (data.withUserName) {
window._paq.push(['setUserId', Meteor.user().username]);
}
window._paq.push(['trackPageView']);
@@ -196,12 +214,12 @@ Utils = {
manageMatomo() {
const matomo = Session.get('matomo');
if (matomo === undefined){
if (matomo === undefined) {
Meteor.call('getMatomoConf', (err, data) => {
if (err && err.error[0] === 'var-not-exist'){
if (err && err.error[0] === 'var-not-exist') {
Session.set('matomo', false); // siteId || address server not defined
}
if (!err){
if (!err) {
Utils.setMatomo(data);
}
});
@@ -220,15 +238,21 @@ Utils = {
finalString += element.text().toLowerCase();
} else if (element.hasClass('user-details')) {
let username = element.find('input').val();
if(username === undefined || username === ''){
if (username === undefined || username === '') {
username = '*';
}
finalString += `${element.find('.trigger-text').text().toLowerCase() } ${ username}`;
finalString += `${element
.find('.trigger-text')
.text()
.toLowerCase()} ${username}`;
} else if (element.find('select').length > 0) {
finalString += element.find('select option:selected').text().toLowerCase();
finalString += element
.find('select option:selected')
.text()
.toLowerCase();
} else if (element.find('input').length > 0) {
let inputvalue = element.find('input').val();
if(inputvalue === undefined || inputvalue === ''){
if (inputvalue === undefined || inputvalue === '') {
inputvalue = '*';
}
finalString += inputvalue;
+38 -22
View File
@@ -1,20 +1,25 @@
const passwordField = AccountsTemplates.removeField('password');
const emailField = AccountsTemplates.removeField('email');
AccountsTemplates.addFields([{
_id: 'username',
type: 'text',
displayName: 'username',
required: true,
minLength: 2,
}, emailField, passwordField, {
_id: 'invitationcode',
type: 'text',
displayName: 'Invitation Code',
required: false,
minLength: 6,
template: 'invitationCode',
}]);
AccountsTemplates.addFields([
{
_id: 'username',
type: 'text',
displayName: 'username',
required: true,
minLength: 2,
},
emailField,
passwordField,
{
_id: 'invitationcode',
type: 'text',
displayName: 'Invitation Code',
required: false,
minLength: 6,
template: 'invitationCode',
},
]);
AccountsTemplates.configure({
defaultLayout: 'userFormsLayout',
@@ -34,7 +39,8 @@ AccountsTemplates.configure({
});
['signIn', 'signUp', 'resetPwd', 'forgotPwd', 'enrollAccount'].forEach(
(routeName) => AccountsTemplates.configureRoute(routeName));
routeName => AccountsTemplates.configureRoute(routeName),
);
// We display the form to change the password in a popup window that already
// have a title, so we unset the title automatically displayed by useraccounts.
@@ -56,15 +62,25 @@ AccountsTemplates.configureRoute('changePwd', {
});
if (Meteor.isServer) {
['resetPassword-subject', 'resetPassword-text', 'verifyEmail-subject', 'verifyEmail-text', 'enrollAccount-subject', 'enrollAccount-text'].forEach((str) => {
[
'resetPassword-subject',
'resetPassword-text',
'verifyEmail-subject',
'verifyEmail-text',
'enrollAccount-subject',
'enrollAccount-text',
].forEach(str => {
const [templateName, field] = str.split('-');
Accounts.emailTemplates[templateName][field] = (user, url) => {
return TAPi18n.__(`email-${str}`, {
url,
user: user.getName(),
siteName: Accounts.emailTemplates.siteName,
}, user.getLanguage());
return TAPi18n.__(
`email-${str}`,
{
url,
user: user.getName(),
siteName: Accounts.emailTemplates.siteName,
},
user.getLanguage(),
);
};
});
}
+10 -6
View File
@@ -1,7 +1,9 @@
let previousPath;
FlowRouter.triggers.exit([({path}) => {
previousPath = path;
}]);
FlowRouter.triggers.exit([
({ path }) => {
previousPath = path;
},
]);
FlowRouter.route('/', {
name: 'home',
@@ -192,9 +194,11 @@ const redirections = {
_.each(redirections, (newPath, oldPath) => {
FlowRouter.route(oldPath, {
triggersEnter: [(context, redirect) => {
redirect(FlowRouter.path(newPath, context.params));
}],
triggersEnter: [
(context, redirect) => {
redirect(FlowRouter.path(newPath, context.params));
},
],
});
});
+48 -11
View File
@@ -9,6 +9,8 @@ version: '2'
# https://github.com/wekan/wekan/wiki/Forgot-Password
#---------------------------------------------------------------------------------------------------------
# ==== Upgrading Wekan to new version =====
# NOTE: MongoDB has changed from 3.x to 4.x, in that case you need backup/restore with --noIndexRestore
# see https://github.com/wekan/wekan/wiki/Backup
# 1) Stop Wekan:
# docker-compose stop
# 2) Download new version:
@@ -90,11 +92,11 @@ services:
wekandb:
#-------------------------------------------------------------------------------------
# ==== MONGODB AND METEOR VERSION ====
# a) For Wekan Meteor 1.8.x version at meteor-1.8 branch, use mongo 4.x
#image: mongo:4.0.4
# b) For Wekan Meteor 1.6.x version at master/devel/edge branches.
# a) For Wekan Meteor 1.8.x version at master branch, use mongo 4.x
image: mongo:4.0.10
# b) For Wekan Meteor 1.6.x version at devel branch.
# Only for Snap and Sandstorm while they are not upgraded yet to Meteor 1.8.x
image: mongo:3.2.21
#image: mongo:3.2.21
#-------------------------------------------------------------------------------------
container_name: wekan-db
restart: always
@@ -110,17 +112,18 @@ services:
wekan:
#-------------------------------------------------------------------------------------
# ==== MONGODB AND METEOR VERSION ====
# a) For Wekan Meteor 1.8.x version at meteor-1.8 branch,
# NOTE: Quay is currently not updated, use Docker Hub image below c)
# a) For Wekan Meteor 1.8.x version at master branch,
# using https://quay.io/wekan/wekan automatic builds
#image: quay.io/wekan/wekan:meteor-1.8
#image: quay.io/wekan/wekan:master
# b) For Wekan Meteor 1.6.x version at master/devel/edge branches.
# Only for Snap and Sandstorm while they are not upgraded yet to Meteor 1.8.x
image: quay.io/wekan/wekan:master
#image: quay.io/wekan/wekan:master
# c) Using specific Meteor 1.6.x version tag:
# image: quay.io/wekan/wekan:v1.95
# c) Using Docker Hub automatic builds https://hub.docker.com/r/wekanteam/wekan
# image: wekanteam/wekan:meteor-1.8
# image: wekanteam/wekan:v1.95
image: wekanteam/wekan
# image: wekanteam/wekan:v2.99
#-------------------------------------------------------------------------------------
container_name: wekan-app
restart: always
@@ -232,6 +235,40 @@ services:
#- ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD=60
#- ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW=15
#---------------------------------------------------------------
# ==== Allow to shrink attached/pasted image ====
# https://github.com/wekan/wekan/pull/2544
#-MAX_IMAGE_PIXEL=1024
#-IMAGE_COMPRESS_RATIO=80
#---------------------------------------------------------------
# ==== BIGEVENTS DUE ETC NOTIFICATIONS =====
# https://github.com/wekan/wekan/pull/2541
# Introduced a system env var BIGEVENTS_PATTERN default as "due",
# so any activityType matches the pattern, system will send out
# notifications to all board members no matter they are watching
# or tracking the board or not. Owner of the wekan server can
# disable the feature by setting this variable to "NONE" or
# change the pattern to any valid regex. i.e. '|' delimited
# activityType names.
# a) Default
#- BIGEVENTS_PATTERN=due
# b) All
#- BIGEVENTS_PATTERN=received|start|due|end
# c) Disabled
#- BIGEVENTS_PATTERN=NONE
#---------------------------------------------------------------
# ==== EMAIL DUE DATE NOTIFICATION =====
# https://github.com/wekan/wekan/pull/2536
# System timelines will be showing any user modification for
# dueat startat endat receivedat, also notification to
# the watchers and if any card is due, about due or past due.
#
# Notify due days, default 2 days before and after. 0 = due notifications disabled. Default: 2
#- NOTIFY_DUE_DAYS_BEFORE_AND_AFTER=2
#
# Notify due at hour of day. Default every morning at 8am. Can be 0-23.
# If env variable has parsing error, use default. Notification sent to watchers.
#- NOTIFY_DUE_AT_HOUR_OF_DAY=8
#-----------------------------------------------------------------
# ==== EMAIL NOTIFICATION TIMEOUT, ms =====
# Defaut: 30000 ms = 30s
#- EMAIL_NOTIFICATION_TIMEOUT=30000
@@ -329,9 +366,9 @@ services:
# OAuth2 Token Endpoint.
#- OAUTH2_TOKEN_ENDPOINT=/oauth/token
# OAUTH2 ID Token Whitelist Fields.
#- OAUTH2_ID_TOKEN_WHITELIST_FIELDS=[]
#- OAUTH2_ID_TOKEN_WHITELIST_FIELDS=""
# OAUTH2 Request Permissions.
#- OAUTH2_REQUEST_PERMISSIONS='openid profile email'
#- OAUTH2_REQUEST_PERMISSIONS=openid profile email
# OAuth2 ID Mapping
#- OAUTH2_ID_MAP=
# OAuth2 Username Mapping
+33 -3
View File
@@ -17,10 +17,14 @@
"act-completeChecklist": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-uncompleteChecklist": "uncompleted checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addComment": "commented on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-editComment": "edited comment on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-deleteComment": "deleted comment on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createBoard": "created board __board__",
"act-createSwimlane": "created swimlane __swimlane__ to board __board__",
"act-createCard": "created card __card__ to list __list__ at swimlane __swimlane__ at board __board__",
"act-createCustomField": "created custom field __customField__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createCustomField": "created custom field __customField__ at board __board__",
"act-deleteCustomField": "deleted custom field __customField__ at board __board__",
"act-setCustomField": "edited custom field __customField__: __customFieldValue__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createList": "added list __list__ to board __board__",
"act-addBoardMember": "added member __member__ to board __board__",
"act-archivedBoard": "Board __board__ moved to Archive",
@@ -596,7 +600,7 @@
"r-unarchived": "Restored from Archive",
"r-a-card": "a card",
"r-when-a-label-is": "When a label is",
"r-when-the-label-is": "When the label is",
"r-when-the-label": "When the label",
"r-list-name": "list name",
"r-when-a-member": "When a member is",
"r-when-the-member": "When the member",
@@ -669,6 +673,15 @@
"r-board-note": "Note: leave a field empty to match every possible value.",
"r-checklist-note": "Note: checklist's items have to be written as comma separated values.",
"r-when-a-card-is-moved": "When a card is moved to another list",
"r-set": "Set",
"r-update": "Update",
"r-datefield": "date field",
"r-df-start-at": "start",
"r-df-due-at": "due",
"r-df-end-at": "end",
"r-df-received-at": "received",
"r-to-current-datetime": "to current date/time",
"r-remove-value-from": "Remove value from",
"ldap": "LDAP",
"oauth2": "OAuth2",
"cas": "CAS",
@@ -689,5 +702,22 @@
"swimlane-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the swimlane. There is no undo.",
"restore-all": "Restore all",
"delete-all": "Delete all",
"loading": "Loading, please wait."
"loading": "Loading, please wait.",
"previous_as": "last time was",
"act-a-dueAt": "modified due time to \nWhen: __timeValue__\nWhere: __card__\n previous due was __timeOldValue__",
"act-a-endAt": "modified ending time to __timeValue__ from (__timeOldValue__)",
"act-a-startAt": "modified starting time to __timeValue__ from (__timeOldValue__)",
"act-a-receivedAt": "modified received time to __timeValue__ from (__timeOldValue__)",
"a-dueAt": "modified due time to be",
"a-endAt": "modified ending time to be",
"a-startAt": "modified starting time to be",
"a-receivedAt": "modified received time to be",
"almostdue": "current due time %s is approaching",
"pastdue": "current due time %s is past",
"duenow": "current due time %s is today",
"act-withDue": "__card__ due reminders [__board__]",
"act-almostdue": "was reminding the current due (__timeValue__) of __card__ is approaching",
"act-pastdue": "was reminding the current due (__timeValue__) of __card__ is past",
"act-duenow": "was reminding the current due (__timeValue__) of __card__ is now",
"act-atUserComment": "You were mentioned in [__board__] __card__"
}
+33 -3
View File
@@ -17,10 +17,14 @@
"act-completeChecklist": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-uncompleteChecklist": "uncompleted checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addComment": "commented on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-editComment": "edited comment on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-deleteComment": "deleted comment on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createBoard": "created board __board__",
"act-createSwimlane": "created swimlane __swimlane__ to board __board__",
"act-createCard": "created card __card__ to list __list__ at swimlane __swimlane__ at board __board__",
"act-createCustomField": "created custom field __customField__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createCustomField": "created custom field __customField__ at board __board__",
"act-deleteCustomField": "deleted custom field __customField__ at board __board__",
"act-setCustomField": "edited custom field __customField__: __customFieldValue__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createList": "added list __list__ to board __board__",
"act-addBoardMember": "added member __member__ to board __board__",
"act-archivedBoard": "Board __board__ moved to Archive",
@@ -596,7 +600,7 @@
"r-unarchived": "Възстановено от Архива",
"r-a-card": "карта",
"r-when-a-label-is": "When a label is",
"r-when-the-label-is": "When the label is",
"r-when-the-label": "When the label",
"r-list-name": "list name",
"r-when-a-member": "When a member is",
"r-when-the-member": "When the member",
@@ -669,6 +673,15 @@
"r-board-note": "Note: leave a field empty to match every possible value.",
"r-checklist-note": "Note: checklist's items have to be written as comma separated values.",
"r-when-a-card-is-moved": "When a card is moved to another list",
"r-set": "Set",
"r-update": "Update",
"r-datefield": "date field",
"r-df-start-at": "start",
"r-df-due-at": "due",
"r-df-end-at": "end",
"r-df-received-at": "received",
"r-to-current-datetime": "to current date/time",
"r-remove-value-from": "Remove value from",
"ldap": "LDAP",
"oauth2": "OAuth2",
"cas": "CAS",
@@ -689,5 +702,22 @@
"swimlane-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the swimlane. There is no undo.",
"restore-all": "Restore all",
"delete-all": "Delete all",
"loading": "Loading, please wait."
"loading": "Loading, please wait.",
"previous_as": "last time was",
"act-a-dueAt": "modified due time to \nWhen: __timeValue__\nWhere: __card__\n previous due was __timeOldValue__",
"act-a-endAt": "modified ending time to __timeValue__ from (__timeOldValue__)",
"act-a-startAt": "modified starting time to __timeValue__ from (__timeOldValue__)",
"act-a-receivedAt": "modified received time to __timeValue__ from (__timeOldValue__)",
"a-dueAt": "modified due time to be",
"a-endAt": "modified ending time to be",
"a-startAt": "modified starting time to be",
"a-receivedAt": "modified received time to be",
"almostdue": "current due time %s is approaching",
"pastdue": "current due time %s is past",
"duenow": "current due time %s is today",
"act-withDue": "__card__ due reminders [__board__]",
"act-almostdue": "was reminding the current due (__timeValue__) of __card__ is approaching",
"act-pastdue": "was reminding the current due (__timeValue__) of __card__ is past",
"act-duenow": "was reminding the current due (__timeValue__) of __card__ is now",
"act-atUserComment": "You were mentioned in [__board__] __card__"
}
+33 -3
View File
@@ -17,10 +17,14 @@
"act-completeChecklist": "completed checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-uncompleteChecklist": "uncompleted checklist __checklist__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-addComment": "commented on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-editComment": "edited comment on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-deleteComment": "deleted comment on card __card__: __comment__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createBoard": "created board __board__",
"act-createSwimlane": "created swimlane __swimlane__ to board __board__",
"act-createCard": "created card __card__ to list __list__ at swimlane __swimlane__ at board __board__",
"act-createCustomField": "created custom field __customField__ to card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createCustomField": "created custom field __customField__ at board __board__",
"act-deleteCustomField": "deleted custom field __customField__ at board __board__",
"act-setCustomField": "edited custom field __customField__: __customFieldValue__ at card __card__ at list __list__ at swimlane __swimlane__ at board __board__",
"act-createList": "added list __list__ to board __board__",
"act-addBoardMember": "added member __member__ to board __board__",
"act-archivedBoard": "Board __board__ moved to Archive",
@@ -596,7 +600,7 @@
"r-unarchived": "Restored from Archive",
"r-a-card": "a card",
"r-when-a-label-is": "When a label is",
"r-when-the-label-is": "When the label is",
"r-when-the-label": "When the label",
"r-list-name": "list name",
"r-when-a-member": "When a member is",
"r-when-the-member": "When the member",
@@ -669,6 +673,15 @@
"r-board-note": "Note: leave a field empty to match every possible value.",
"r-checklist-note": "Note: checklist's items have to be written as comma separated values.",
"r-when-a-card-is-moved": "When a card is moved to another list",
"r-set": "Set",
"r-update": "Update",
"r-datefield": "date field",
"r-df-start-at": "start",
"r-df-due-at": "due",
"r-df-end-at": "end",
"r-df-received-at": "received",
"r-to-current-datetime": "to current date/time",
"r-remove-value-from": "Remove value from",
"ldap": "LDAP",
"oauth2": "OAuth2",
"cas": "CAS",
@@ -689,5 +702,22 @@
"swimlane-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the swimlane. There is no undo.",
"restore-all": "Restore all",
"delete-all": "Delete all",
"loading": "Loading, please wait."
"loading": "Loading, please wait.",
"previous_as": "last time was",
"act-a-dueAt": "modified due time to \nWhen: __timeValue__\nWhere: __card__\n previous due was __timeOldValue__",
"act-a-endAt": "modified ending time to __timeValue__ from (__timeOldValue__)",
"act-a-startAt": "modified starting time to __timeValue__ from (__timeOldValue__)",
"act-a-receivedAt": "modified received time to __timeValue__ from (__timeOldValue__)",
"a-dueAt": "modified due time to be",
"a-endAt": "modified ending time to be",
"a-startAt": "modified starting time to be",
"a-receivedAt": "modified received time to be",
"almostdue": "current due time %s is approaching",
"pastdue": "current due time %s is past",
"duenow": "current due time %s is today",
"act-withDue": "__card__ due reminders [__board__]",
"act-almostdue": "was reminding the current due (__timeValue__) of __card__ is approaching",
"act-pastdue": "was reminding the current due (__timeValue__) of __card__ is past",
"act-duenow": "was reminding the current due (__timeValue__) of __card__ is now",
"act-atUserComment": "You were mentioned in [__board__] __card__"
}
Loaded 100 of 222 files, more files were not shown because too many files have changed in this diff. Show more