Compare commits

...
581 Commits
Author SHA1 Message Date
Lauri Ojansivu c437c2048d v5.35 2021-06-14 15:35:23 +03:00
Lauri Ojansivu f80fcfd7c0 Updated dependencies.
Thanks to developers of dependencies !
2021-06-14 15:31:06 +03:00
Lauri Ojansivu e9670aa5cb Updated ChangeLog. 2021-06-14 15:14:39 +03:00
Lauri Ojansivu 164b6e9070 Part 2: Allow board members to use more of API. Please add issue (or pull request) if this allows too much.
Thanks to JayVii and xet7 !

Fixes #3862
2021-06-14 15:13:15 +03:00
Lauri Ojansivu 5af18809a7 Updated ChangeLog. 2021-06-14 15:04:55 +03:00
Lauri Ojansivu a719e8fda1 Allow board members to use more of API. Please add issue (or pull request) if this allows too much.
Thanks to JayVii and xet7 !

Fixes #3862
2021-06-14 15:01:37 +03:00
Lauri Ojansivu 50fa8a0743 Updated translations. 2021-06-14 14:31:27 +03:00
Lauri Ojansivu 9e160d2431 Updated ChangeLog. 2021-06-14 13:04:19 +03:00
Lauri Ojansivu 77cff95c07 Merge pull request #3863 from mfilser/card_details_maximize_fixes
Card details maximize fixes
2021-06-14 13:01:41 +03:00
Martin Filser b98a46b78c forms.styl, wrong indentation 2021-06-14 11:05:37 +02:00
Martin Filser 49e31707e5 Card Details, minicard is now hidden 2021-06-14 11:05:46 +02:00
Martin Filser 92122e1fdd Card Details, maximize and minimize of card works now 2021-06-14 11:05:42 +02:00
Martin Filser 7238a65a6f Card Details, more space at maximize icon 2021-06-14 11:05:37 +02:00
Martin Filser e68ccf8532 Card Details, maximize and minimize of icon works
- Card isn't maximized yet
2021-06-14 11:05:37 +02:00
Lauri Ojansivu 362fd86dbf Updated translations. 2021-06-13 17:56:30 +03:00
Lauri Ojansivu 8aba58188d Updated ChangeLog. 2021-06-13 15:51:49 +03:00
Lauri Ojansivu 41848dd99e Merge pull request #3861 from mfilser/manual_sort_number_0_accepted
Manuel sort number 0 accepted
2021-06-13 15:49:34 +03:00
Martin Filser f2fcfd6a47 Manuel sort number 0 accepted
Fixes: #3859
2021-06-13 10:39:44 +02:00
Lauri Ojansivu 33cdb906e2 Updated translations. 2021-06-13 08:49:08 +03:00
Lauri Ojansivu 19e73009b1 Updated ChangeLog. 2021-06-13 00:17:23 +03:00
Lauri Ojansivu 401e256d84 Updated translations. 2021-06-12 23:49:49 +03:00
Lauri Ojansivu e1cd87433a Updated ChangeLog. 2021-06-12 23:37:24 +03:00
Lauri Ojansivu 23e5e1e3bd Reduced Wekan bundle size from 636 MB to 467 MB by deleting all
dependencies of lucasantoniassi:accounts-lockout and including
only required 10 files.

Thank to xet7 !
2021-06-12 23:28:57 +03:00
Lauri Ojansivu 8f19f043a1 Updated translations. 2021-06-12 15:19:20 +03:00
Lauri Ojansivu b1f07149c0 Updated ChangeLog. 2021-06-12 15:16:38 +03:00
Lauri Ojansivu 17acf18848 Export card to PDF. Part 2.
Thanks to xet7 !
2021-06-12 15:15:36 +03:00
Lauri Ojansivu f52f589f7d Updated translations. 2021-06-12 15:01:48 +03:00
Lauri Ojansivu e3e25bc233 Updated ChangeLog. 2021-06-12 14:52:43 +03:00
Lauri Ojansivu a2f2ce1135 Export Card to PDF. In Progress.
Thanks to xet7 !
2021-06-12 14:50:18 +03:00
Lauri Ojansivu 90152ab9f5 Updated ChangeLog. 2021-06-12 13:07:27 +03:00
Lauri Ojansivu 7a25f542e8 Updated translations. 2021-06-12 12:58:53 +03:00
Lauri Ojansivu 8c57250243 Maximize Card. In Progress.
Thanks to xet7 !

Related #1574
2021-06-12 12:48:12 +03:00
Lauri Ojansivu 2e1eb1e224 Add border and update label colors for better visibility.
Thanks to xet7 !
2021-06-12 12:46:30 +03:00
Lauri Ojansivu b9a15e68de Updated translations. 2021-06-12 08:53:19 +03:00
Lauri Ojansivu a9d2e03b65 Updated translations. 2021-06-11 21:01:38 +03:00
Lauri Ojansivu d84b04dc35 Updated ChangeLog. 2021-06-11 20:56:23 +03:00
Lauri Ojansivu 7f3f082557 Added more translations for Wait Spinners.
Thanks to xet7 !
2021-06-11 20:54:52 +03:00
Lauri Ojansivu c810c68923 Updated translations. 2021-06-11 20:49:55 +03:00
Lauri Ojansivu 865a585c7f Updated ChangeLog. 2021-06-11 20:38:24 +03:00
Lauri Ojansivu 8703dd4229 Wait Spinners can now be translated. Added Wait Spinners docs:
https://github.com/wekan/wekan/wiki/Wait-Spinners

Thanks to xet7 !
2021-06-11 20:35:27 +03:00
Lauri Ojansivu d0c417b17d v5.34 2021-06-11 15:35:13 +03:00
Lauri Ojansivu d09151d8f3 Updated translations. 2021-06-11 15:22:55 +03:00
Lauri Ojansivu 01a28860fe Updated ChangeLog. 2021-06-11 15:19:45 +03:00
Lauri Ojansivu 488b765f95 Added remaining WAIT_SPINNER settings.
Thanks to xet7 !

Related https://github.com/wekan/wekan/pull/3858
2021-06-11 15:17:43 +03:00
Lauri Ojansivu 8a21b69fb0 Updated translations. 2021-06-11 14:52:31 +03:00
Lauri Ojansivu eda3ed59df Updated ChangeLog. 2021-06-11 14:48:09 +03:00
Lauri Ojansivu 611ac0ab57 Merge pull request #3858 from mfilser/more_spinners_and_configureable_in_admin_panel
More spinners + configureable in admin panel
2021-06-11 14:42:38 +03:00
Martin Filser d485154a12 Spinner Double-Bounce now available
Spinner from: https://tobiasahlin.com/spinkit/
2021-06-11 13:34:33 +02:00
Martin Filser 0caff7d5d5 Spinner Cube-Grid now available
Spinner from: https://tobiasahlin.com/spinkit/
2021-06-11 13:34:33 +02:00
Martin Filser 6df7657c8e Spinner Scaleout now available
Spinner from: https://tobiasahlin.com/spinkit/
2021-06-11 13:34:33 +02:00
Martin Filser 55d0f0bacd Spinner Rotateplane now available
Spinner from: https://tobiasahlin.com/spinkit/
2021-06-11 13:34:33 +02:00
Martin Filser a74fac4cbf Spinner Dot now available
Spinner from: https://tobiasahlin.com/spinkit/
2021-06-11 13:34:33 +02:00
Martin Filser 8aa58c0b11 Spinner Cube now available
Spinner from: https://tobiasahlin.com/spinkit/
2021-06-11 13:34:33 +02:00
Martin Filser 4b9f8ab2b1 Adding DEFAULT_WAIT_SPINNER to all environments 2021-06-11 13:34:33 +02:00
Martin Filser ba41533128 Default Spinner can be configured through environment variables 2021-06-11 13:34:33 +02:00
Martin Filser 38069c6d63 Spinner description insert in translation 2021-06-11 13:34:33 +02:00
Martin Filser 1d66058240 Spinner class in own .js library file 2021-06-11 13:34:33 +02:00
Martin Filser 43ac328e8a Spinner config is now reactive
- changed at boards as soon as changed in the settings
2021-06-11 13:34:33 +02:00
Martin Filser 7519abf3fe Spinner now configureable in the Settings 2021-06-11 13:34:33 +02:00
Martin Filser 849deae11e Spinners needs  
- it's not formatted by Meteor well, \n is missing in the generated
  Javascript code, so i insert   in the template
2021-06-11 13:34:33 +02:00
Martin Filser 06a2b08780 Spinner configureable in the source code 2021-06-11 13:34:33 +02:00
Martin Filser 4f9d3d8be5 List infinite scroll now always works
- before sometimes list scrolling stopped even the spinner was visible
  and scrolling was at the end of the list
2021-06-11 13:34:33 +02:00
Lauri Ojansivu ac3d658cb1 Merge pull request #3857 from mfilser/view_and_change_card_sort_number
View and change card sort number
2021-06-11 14:33:43 +03:00
Lauri Ojansivu 8f00191617 Updated ChangeLog. 2021-06-11 14:30:19 +03:00
Lauri Ojansivu 762391965e Try to fix BUG: Database error attempting to change a account.
Thanks to bbyszio and xet7 !

Fixes #3855
2021-06-11 14:28:25 +03:00
Lauri Ojansivu 0fa3a2729d Updated ChangeLog. 2021-06-11 13:55:33 +03:00
Martin Filser 54640bb125 Minicard, show sorting number if board config is enabled 2021-06-11 12:35:57 +02:00
Martin Filser 57d35a294d CardDetails sorting, only float number input possible (only working in an extra handler)
- defining in events() doesn't handle the return value and is ignored,
  maybe a bug in Blaze / Meteor.?
2021-06-11 12:35:57 +02:00
Martin Filser 39069b322d CardDetails sorting, only float number input possible 2021-06-11 12:35:57 +02:00
Martin Filser 540ce3a6ed CardDetails sorting number is displayed at card and can be modified (if configured) 2021-06-11 12:35:57 +02:00
Lauri Ojansivu ab22fb27ce Updated ChangeLog. 2021-06-11 13:35:06 +03:00
Lauri Ojansivu 0f564365f4 Merge pull request #3856 from mfilser/custom_fields_missing_after_adding_first_card
CustomFields were not created after adding 1 card
2021-06-11 13:33:26 +03:00
Lauri Ojansivu cccb7e4a39 Updated ChangeLog. 2021-06-11 13:16:20 +03:00
Lauri Ojansivu 1e837dec11 Fix Google SSO to access Wekan has not been working
by reverting Wekan v5.31 not-working fixes to OAUTH2_LOGIN_STYLE=redirect Has No Effect.

Thanks to unpokitodxfavor and xet7 !

Fixes #3854,
opens #3845
2021-06-11 13:08:23 +03:00
Martin Filser be3325ce35 CustomFields were not created after adding 1 card 2021-06-11 12:03:29 +02:00
Lauri Ojansivu c042d54714 Updated ChangeLog. 2021-06-11 12:59:20 +03:00
Lauri Ojansivu 77e2f95c66 Merge pull request #3852 from mfilser/development_in_docker_container
Development in docker container
2021-06-11 12:57:49 +03:00
Martin Filser 403b416b2a Development volumes now in the same folder
- It's easier for the development to have the files in the same folder
  than in an extra volume
2021-06-11 11:36:55 +02:00
Martin Filser b0901ccd01 Development uses now the same Mongo Version (4.4) 2021-06-11 11:36:55 +02:00
Martin Filser 6d2f8a97af Base Image of Development and Build are now the same
- libarchive-tools contains bsdtar. bsdtar is needed for meteor
  installation, it doesn't / or didn't work with docker and overlayfs.

  see also here:

  https://github.com/jshimko/meteor-launchpad/issues/39
  https://github.com/anchore/anchore-engine/issues/106
  https://github.com/coreos/bugs/issues/1095
2021-06-11 11:36:55 +02:00
Martin Filser bbd3324b79 ignore .git directory at docker build
- COPY copies the .git directory to the image. The docker build then
  stops with this error:

=> Errors while initializing project:

While building package wekan-cfs-data-man:
error: couldn't install npm package request@https://github.com/wekan/request:
Command failed:
/home/wekan/.meteor/packages/meteor-tool/.2.2.0.1j8auib.qcbe++os.linux.x86_64+web.browser+web.browser.legacy+web.cordova/mt-os.linux.x86_64/dev_bundle/bin/npm
install https://github.com/wekan/request
npm ERR! Error while executing:
npm ERR! /usr/bin/git ls-remote -h -t https://github.com/wekan/request.git
npm ERR!
npm ERR! fatal: not a git repository: /home/wekan/app/../.git/modules/src
npm ERR!
npm ERR! exited with error code: 128

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/wekan/.npm/_logs/2021-06-10T12_54_02_777Z-debug.log
npm ERR! Error while executing:
npm ERR! /usr/bin/git ls-remote -h -t https://github.com/wekan/request.git
npm ERR!
npm ERR! fatal: not a git repository: /home/wekan/app/../.git/modules/src
npm ERR!
npm ERR! exited with error code: 128

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/wekan/.npm/_logs/2021-06-10T12_54_02_777Z-debug.log
2021-06-11 11:36:54 +02:00
Martin Filser 5697b89817 .devcontainer now ready for Wekan Development in Docker Container
Check .devcontainer/docker-compose.yml to fit your environment

Enter this commands to start Wekan Development:

$ cd .devcontainer
$ docker-compose build
$ docker-compose up -d

Visit localhost:3000 or whatever you entered in ROOT_URL

Code changes triggers a rebuild / redeploy
2021-06-11 11:36:40 +02:00
Lauri Ojansivu 6bf6bcb192 Revert upgrading Dockerfile to hirsute, because of bug:
https://github.com/wekan/wekan/pull/3852#issuecomment-859095850

Thanks to xet7 !
2021-06-11 00:43:45 +03:00
Lauri Ojansivu df74b31541 Try different gpg package for Docker and Hirsute.
Thanks to xet7 !
2021-06-11 00:34:27 +03:00
Lauri Ojansivu 0b34bcdfa8 Updated Dockerfile gpg to gpgv2, that package is in hirsute.
Thanks to xet7 !
2021-06-11 00:26:47 +03:00
Lauri Ojansivu 09a060a57b Updated ChangeLog. 2021-06-10 23:31:59 +03:00
Lauri Ojansivu 2a5147a0c1 Updated Docker Ubuntu base image to newest hirsute.
Thanks to xet7 !
2021-06-10 23:30:13 +03:00
Lauri Ojansivu 4caa0e2f2e Updated ChangeLog. 2021-06-10 23:06:49 +03:00
Lauri Ojansivu 8f5c0af88e Merge pull request #3851 from mfilser/card_description_same_color_editing
Card Description has now the same color on editing
2021-06-10 23:04:46 +03:00
Martin Filser 665d7eb831 Card Description has now the same color on editing 2021-06-10 21:57:10 +02:00
Lauri Ojansivu d08b208bc6 v5.33 2021-06-10 22:10:34 +03:00
Lauri Ojansivu c5d8117052 Updated translations. 2021-06-10 22:03:45 +03:00
Lauri Ojansivu b769d18f73 Updated ChangeLog. 2021-06-10 22:01:14 +03:00
Lauri Ojansivu b17760d228 Merge branch 'Emile840-master' 2021-06-10 21:56:33 +03:00
Lauri Ojansivu 2983c51db1 Merge branch 'master' of https://github.com/Emile840/wekan into Emile840-master 2021-06-10 21:54:41 +03:00
Lauri Ojansivu d6e11940cc Updated ChangeLog. 2021-06-10 21:52:05 +03:00
Lauri Ojansivu 17f15f546f Merge pull request #3849 from mfilser/custom-field-stringtemplate_autofocus
custom fields stringtemplate, autofocus the last input box
2021-06-10 21:49:48 +03:00
Emile NDAGIJIMANA c5df78fd8b Addressed one of the point cited in issue #802 'Assigning a user to a team or an organization' 2021-06-10 16:38:28 +02:00
Martin Filser 62bd96e06e custom fields stringtemplate, autofocus the last input box 2021-06-09 21:25:49 +02:00
Lauri Ojansivu 399fd098b8 v5.32 2021-06-09 20:30:02 +03:00
Lauri Ojansivu f9c21a9b52 Updated translations. 2021-06-09 20:23:38 +03:00
Lauri Ojansivu 41893cf06a Updated ChangeLog. 2021-06-09 20:15:46 +03:00
Lauri Ojansivu 83a8d4c14f Updated ChangeLog. 2021-06-09 20:13:19 +03:00
Lauri Ojansivu 6ce5ab40a7 Moved many button texts etc to tooltips. Added more tooltips.
Thanks to xet7 !

Fixes #3848
2021-06-09 20:08:42 +03:00
Lauri Ojansivu 328fa194a0 v5.31 2021-06-09 01:45:05 +03:00
Lauri Ojansivu 482b9c9333 Updated ChangeLog. 2021-06-09 01:40:39 +03:00
Lauri Ojansivu 122757ca9c Updated dependencies.
Thanks to developers of dependencies !
2021-06-09 01:39:16 +03:00
Lauri Ojansivu 49dd2204f4 Updated ChangeLog. 2021-06-09 01:16:38 +03:00
Lauri Ojansivu 07a3a0b388 Gantt: Retain links created between tasks. Part 1: Database changes, not active in MIT Wekan.
Thanks to benjaminhrivera !

Related https://github.com/wekan/wekan/issues/2870#issuecomment-857115753
2021-06-09 01:12:23 +03:00
Lauri Ojansivu 56efbf1de7 Updated ChangeLog. 2021-06-09 00:57:27 +03:00
Lauri Ojansivu 57f31d443f Partial Fix: Vote and Planning Poker: Setting date and time now works
for some languages that have ascii characters in date format.

Thanks to xet7 !

Related #3837
2021-06-09 00:51:52 +03:00
Lauri Ojansivu 65f308434a Updated ChangeLog. 2021-06-08 17:02:25 +03:00
Lauri Ojansivu 007e0f1c16 Try to fix: Wekan UI fails to finish import of closed Trello boards.
Thanks to berezovskyi and xet7 !

Fixes #3840
2021-06-08 17:00:53 +03:00
Lauri Ojansivu c249a2d187 Updated ChangeLog. 2021-06-08 16:53:06 +03:00
Lauri Ojansivu 78324263c1 Try to fix OAUTH2_LOGIN_STYLE=redirect Has No Effect.
Thanks to xet7 !

Fixes #3845
2021-06-08 16:50:48 +03:00
Lauri Ojansivu c20229b56a Updated translations. 2021-06-08 16:50:29 +03:00
Lauri Ojansivu 1fd10771b0 Updated ChangeLog. 2021-06-08 16:41:14 +03:00
Lauri Ojansivu 1637920170 Admin Panel Organizations/Teams: Show confirm text above delete button.
Thanks to xet7 !

Related #802
2021-06-08 16:38:21 +03:00
Lauri Ojansivu 87ba966db8 Updated translations. 2021-06-08 05:25:01 +03:00
Lauri Ojansivu 258391cd8c Updated ChangeLog. 2021-06-08 05:15:25 +03:00
Lauri Ojansivu 481404e8d7 Now new boards do not have any labels added by default.
Thanks to tedkoch and xet7 !

Related https://github.com/wekan/wekan/discussions/3835#discussioncomment-836223 Issue 7.
2021-06-08 05:07:32 +03:00
Lauri Ojansivu 48737dcd01 Updated ChangeLog. 2021-06-08 04:54:42 +03:00
Lauri Ojansivu b95585b0f6 Updated ChangeLog. 2021-06-08 04:44:59 +03:00
Lauri Ojansivu 14b2c1309f Delete Organizations and Teams.
Thanks to xet7 !

Related #802
2021-06-08 04:38:47 +03:00
Lauri Ojansivu 7e036b9df3 Merge branch 'Emile840-master' 2021-06-08 01:24:54 +03:00
Lauri Ojansivu 72fa32151d Merge branch 'master' of https://github.com/Emile840/wekan into Emile840-master 2021-06-08 01:24:25 +03:00
Emile NDAGIJIMANA f5dbe8c6f6 Addressed one of the bugs cited in issue #802 'bug when creating and modifying organization and team' 2021-06-07 11:03:49 +02:00
Lauri Ojansivu 93950a3b2e Updated translations. 2021-06-05 16:02:59 +03:00
Lauri Ojansivu eec818f9fd Updated translations. 2021-06-04 12:52:54 +03:00
Lauri Ojansivu a6f15af270 Updated ChangeLog. 2021-06-04 12:48:03 +03:00
Lauri Ojansivu 646497c3f0 Removed extra package.
Thanks to xet7 !
2021-06-04 12:46:21 +03:00
Lauri Ojansivu 2342c27ced v5.30 2021-06-03 23:29:01 +03:00
Lauri Ojansivu 80f6004404 Updated translations. 2021-06-03 23:20:51 +03:00
Lauri Ojansivu a94946c77c Updated ChangeLog. 2021-06-03 23:18:12 +03:00
Lauri Ojansivu 659a65b8b9 Moved Keyboard Shortcuts from bottom to top of sidebar.
Thanks to ClaudiaK21 and xet7 !
2021-06-03 23:15:13 +03:00
Lauri Ojansivu c4b55e862f Updated ChangeLog. 2021-06-03 22:33:04 +03:00
Lauri Ojansivu f8a75930b3 Updated ChangeLog. 2021-06-03 22:09:05 +03:00
Lauri Ojansivu 3a04b1b787 Updated ChangeLog. 2021-06-03 21:49:13 +03:00
Lauri Ojansivu ad61a15611 Updated translations. 2021-06-03 21:47:52 +03:00
Lauri Ojansivu d21bc0c277 Merge branch 'helioguardabaxo-master' 2021-06-03 21:26:55 +03:00
helioguardabaxo fa3d117372 Add Feature: Planning Poker 2021-06-03 12:01:15 -03:00
Lauri Ojansivu 26249f5928 Updated ChangeLog. 2021-06-01 18:55:25 +03:00
Lauri Ojansivu b7e6600e88 Merge pull request #3833 from Emile840/master
Fix bug #3832 'Default language is still used although this one has b…
2021-06-01 18:53:25 +03:00
Emile NDAGIJIMANA 6e46cad56c Fix bug #3832 'Default language is still used although this one has been modified previously' 2021-06-01 15:55:42 +02:00
Lauri Ojansivu e7340c5021 Reverted PR https://github.com/wekan/wekan/pull/3831
The default wekan logo appears briefly before displaying the custom logo

Thanks to xet7 !

Related #3832
2021-06-01 16:44:23 +03:00
Lauri Ojansivu 05d6c5f15a Updated translations. 2021-06-01 16:28:49 +03:00
Lauri Ojansivu 428442b310 Updated ChangeLog. 2021-06-01 16:20:52 +03:00
Lauri Ojansivu 753d247cf6 Merge pull request #3831 from Emile840/master
Fix bug #3830 '[Login page] The default wekan logo appears briefly before d…
2021-06-01 16:16:04 +03:00
Lauri Ojansivu 802f544cd5 Updated ChangeLog. 2021-06-01 12:46:35 +03:00
Lauri Ojansivu bf62a947fb Fixed Python API example: Edit card, etc.
Thanks to Lucky-Shi and xet7 !

Fixes #3767
2021-06-01 12:41:54 +03:00
Emile NDAGIJIMANA 5b08ae12a6 Fix bug '[Login page] The default wekan logo appears briefly before displaying the custom logo #3830' 2021-05-31 15:36:57 +02:00
Lauri Ojansivu 46e881bea3 v5.29 2021-05-29 01:06:44 +03:00
Lauri Ojansivu 5d1714dbd5 Updated ChangeLog. 2021-05-29 00:56:24 +03:00
Lauri Ojansivu bd1de94312 Fixed Importing JSON exports fails.
Thanks to KeptnArgo and xet7 !

Fixes #3742
2021-05-29 00:52:36 +03:00
Lauri Ojansivu 06937d0aa0 Updated translations. 2021-05-29 00:29:03 +03:00
Lauri Ojansivu 9e39731133 Updated ChangeLog. 2021-05-29 00:26:09 +03:00
Lauri Ojansivu 3908cd5413 Fix: Impersonate user can now export Excel/CSV/TSV/JSON.
Impersonate user and export Excel/CSV/TSV/JSON is now logged into
database table impersonatedUsers.

Thanks to xet7 !

Fixes #3827,
fixes #3284
2021-05-29 00:19:12 +03:00
Lauri Ojansivu 6be1a33093 Updated dependencies.
Thanks to developers of dependencies!
2021-05-29 00:15:42 +03:00
Lauri Ojansivu c656cbf6ae Updated translations. 2021-05-25 17:42:28 +03:00
Lauri Ojansivu 83045a6512 Updated ChangeLog. 2021-05-18 12:59:07 +03:00
Lauri Ojansivu 199485640f Merge pull request #3813 from spasche/typos
Fix typos
2021-05-18 12:43:18 +03:00
Sylvain Pasche 2e41ff1121 Fix typos. 2021-05-17 23:41:36 +02:00
Lauri Ojansivu 487c6fae8d Updated ChangeLog. 2021-05-16 17:10:34 +03:00
Lauri Ojansivu ea64b17b82 Reworded issue template about can not login.
Thanks to xet7 !
2021-05-16 13:34:49 +03:00
Lauri Ojansivu 6d0578fd5a Added Forgot Password page to GitHub issue template.
Thanks to xet7 !
2021-05-16 13:27:56 +03:00
Lauri Ojansivu 76a4deda78 Updated ChangeLog. 2021-05-12 19:33:05 +03:00
Lauri Ojansivu 595abd303c Merge pull request #3799 from Enishowk/feature/excel_parentNameExport
Feature/excel parent card name export
2021-05-12 19:30:43 +03:00
Lauri Ojansivu 5dd6466c0a Removed not working GitHub workflow.
Thanks to xet7 !
2021-05-10 20:26:23 +03:00
Lauri Ojansivu 38655ee478 Merge branch 'master' of github.com:wekan/wekan 2021-05-09 07:53:08 +03:00
Lauri Ojansivu 23ca25a1ca Updated translations. 2021-05-09 07:52:45 +03:00
Enishowk 120cb4820e fix: typo 2021-05-07 18:58:24 +02:00
Enishowk 3ee0add6f6 feat: add parent name column in excel export 2021-05-07 18:54:59 +02:00
Lauri Ojansivu 8911fe5c8d Try to fix Snap: Removed linting packages.
Thanks to xet7 !
2021-05-07 18:12:49 +03:00
Lauri Ojansivu 1d9346513e Update dependencies.
Thanks to developers of dependencies !
2021-05-07 17:46:22 +03:00
Lauri Ojansivu 62150ce6c4 Updated dependencies.
Thanks to developers of dependencies!
2021-05-07 17:09:31 +03:00
Lauri Ojansivu b2d4135dca v5.28 2021-05-07 16:23:55 +03:00
Lauri Ojansivu 49e3e01ece Updated translations. 2021-05-07 13:20:53 +03:00
Lauri Ojansivu 23c2ff0e29 Updated ChangeLog. 2021-05-07 12:53:18 +03:00
Lauri Ojansivu a550c255e6 Updated dependencies.
Thanks to developers of dependencies !
2021-05-07 12:51:54 +03:00
Lauri Ojansivu 6b897faaa8 Updated ChangeLog. 2021-05-07 12:34:10 +03:00
Lauri Ojansivu 48255f6f1e Updated dependencies.
Thanks to developers of dependencies !
2021-05-07 12:32:44 +03:00
Lauri Ojansivu 45bc3bd3db Updated ChangeLog. 2021-05-07 02:23:40 +03:00
Lauri Ojansivu 5ab20a9257 Added markdown-it-mermaid for some charts support in all input fields. Replaced xss with dompurify.
Thanks to xuguotong and xet7 !

Fixes #3794
2021-05-07 02:13:20 +03:00
Lauri Ojansivu 88e4918208 Updated ChangeLog. 2021-05-06 18:29:44 +03:00
Lauri Ojansivu 521ef8b6da Updated dependencies.
Thanks to developers of dependencies !
2021-05-06 18:26:32 +03:00
Lauri Ojansivu 0d86dfa571 Updated translations. 2021-05-06 18:14:05 +03:00
Lauri Ojansivu 472350e56f Merge branch 'listenerri-patch-1' 2021-05-06 18:00:06 +03:00
listenerri 68569b9640 Update cardDate.js 2021-05-06 10:08:01 +08:00
Lauri Ojansivu 823f11d5dd v5.27 2021-04-29 13:39:08 +03:00
Lauri Ojansivu ae19018831 Updated translations. 2021-04-29 13:33:13 +03:00
Lauri Ojansivu d5b09c7b3e Updated dependencies. 2021-04-29 13:32:25 +03:00
Lauri Ojansivu d3b4aa4dc7 Updated ChangeLog. 2021-04-29 13:29:06 +03:00
Lauri Ojansivu c2da477735 Fixed Non-ASCII attachment filename will crash when downloading.
Thanks to xet7 !

Fixes #2759
2021-04-29 13:26:49 +03:00
Lauri Ojansivu 843ff8eaaa v5.26 2021-04-28 12:38:15 +03:00
Lauri Ojansivu c5143e2c54 Updated translations. 2021-04-28 12:34:30 +03:00
Lauri Ojansivu 0596f5e864 Updated ChangeLog. 2021-04-28 12:28:09 +03:00
Lauri Ojansivu 8ca1b25daf Bring back Almost-Due for Start Date.
Thanks to darren-teo !

Fixes #3766
2021-04-28 12:26:31 +03:00
Lauri Ojansivu 1f76159bfe Updated ChangeLog. 2021-04-28 12:19:43 +03:00
Lauri Ojansivu 39ece35f52 Merge pull request #3765 from HappyMushroom-TechTeam/feature/miniCard_subtaskCount
Feature/mini card subtask count
2021-04-28 12:18:03 +03:00
ryanMushy 63c1bb9e17 count subtasks just like checklists 2021-04-27 18:28:23 -07:00
Lauri Ojansivu 354622c5ad v5.25 2021-04-27 23:11:23 +03:00
Lauri Ojansivu df7fd8c900 v5.25 2021-04-27 23:02:49 +03:00
Lauri Ojansivu 7957690fca Updated translations. 2021-04-27 22:57:25 +03:00
Lauri Ojansivu 63d19447a0 Updated ChangeLog. 2021-04-27 22:50:53 +03:00
Lauri Ojansivu 018a84ec59 Merge pull request #3764 from HappyMushroom-TechTeam/feature/excel_swimlanExport
cherry pick the excel export feature to add swimlanes to the output
2021-04-27 22:47:41 +03:00
ryanMushy e5c0e623a0 cherry pick the excel export feature to add swimlanes to the output 2021-04-27 12:38:38 -07:00
ryan neal 9a2d3e15e8 Merge pull request #2 from wekan/master
newest version
2021-04-27 12:36:57 -07:00
Lauri Ojansivu c07e262e68 Updated translations. 2021-04-27 20:29:01 +03:00
Lauri Ojansivu cacb2b91ee Updated ChangeLog. 2021-04-27 20:18:37 +03:00
Lauri Ojansivu 6f269d598f Merge pull request #3762 from bentiss/nested-openapi
openapi: better handle nested schemas
2021-04-27 20:16:59 +03:00
Lauri Ojansivu 57ea254bff Updated ChangeLog. 2021-04-27 19:51:09 +03:00
Lauri Ojansivu 7e183c838f Merge pull request #3761 from HappyMushroom-TechTeam/bugfix/summernoteOnPaste
Bugfix/summernote on paste
2021-04-27 19:48:46 +03:00
Lauri Ojansivu 3ffdfd9736 Updated ChangeLog. 2021-04-27 19:47:40 +03:00
Lauri Ojansivu 621c701bef Fixed language name of Deutsch (Schweiz).
Thanks to urmel1960 !

Fixes #3763
2021-04-27 19:45:18 +03:00
Lauri Ojansivu 3c24c9966c Updated ChangeLog. 2021-04-27 19:38:20 +03:00
Lauri Ojansivu 995de525d9 Added missing postgres password to ToroDB.
Thanks to xet7 !
2021-04-27 19:36:34 +03:00
Benjamin Tissoires ae30b1220a openapi: better handle nested schemas
there is a 2 levels schemas in profile.notifications.

The code previously assumed we could only have one level, and so was not
producing the correct UsersProfileNotifications.

Fix that by being more generic in the way we retrieve the nested
subschemas.
2021-04-27 10:44:27 +02:00
ryanMushy e380ad26c2 Images are uploaded twice
- make sure only pastes which contain text are processed
- remove execCommand() as it results in errors
- enable drag & drop
- fix resize buttons to be the proper summernote commands
- remove un-needed comma
2021-04-26 23:31:07 -07:00
ryan neal 9bb31d2380 Merge pull request #1 from wekan/master
newest wekan
2021-04-26 12:10:21 -07:00
Lauri Ojansivu 8ec1e4f3fa Updated ChangeLog. 2021-04-24 20:18:04 +03:00
Lauri Ojansivu 9f0f6841b0 Updated release scripts. 2021-04-24 20:16:27 +03:00
Lauri Ojansivu 5d18f98b44 v5.24 2021-04-24 19:47:12 +03:00
Lauri Ojansivu e738177e08 Updated dependencies.
Thanks to developers of dependencies !
2021-04-24 19:40:50 +03:00
Lauri Ojansivu bb201935b9 Updated translations. 2021-04-24 19:35:48 +03:00
Lauri Ojansivu bcfe6bd616 Updated translations.
Thanks to translators and xet7 !

Fixes #3756
2021-04-24 19:08:08 +03:00
Lauri Ojansivu 9c6352a7bc Updated translations. 2021-04-23 12:53:15 +03:00
Lauri Ojansivu 9110e41f20 Updated ChangeLog. 2021-04-23 00:19:39 +03:00
Lauri Ojansivu 7ae871d3a6 Merge pull request #3753 from jrsupplee/copy-swimlane
Add copy swimlane functionality
2021-04-22 22:50:27 +03:00
Lauri Ojansivu 0ddf027d43 Updated ChangeLog. 2021-04-22 16:54:37 +03:00
Lauri Ojansivu 45124a39f3 Fix Snap: Delete extra symlink that prevented building Snap.
Thanks to xet7 !
2021-04-22 16:52:51 +03:00
John R. Supplee 4940af0573 Add copy swimlane functionality 2021-04-22 14:16:35 +02:00
Lauri Ojansivu 924b5d1733 v5.23 2021-04-22 15:16:22 +03:00
Lauri Ojansivu 2119a3a51e Updated translations. 2021-04-22 14:58:24 +03:00
Lauri Ojansivu dcda99ddf3 Updated ChangeLog. 2021-04-22 14:48:39 +03:00
Lauri Ojansivu 0e35dcd5ad Merge pull request #3749 from listenerri/patch-1
Fix: The bg color of start at button is almost-due
2021-04-22 14:44:34 +03:00
listenerri 991d42ca0b Fix: The bg color of start at button is almost-due
One minute earlier than the current time is almost-due? This should be a faulty logic.
2021-04-22 18:24:18 +08:00
Lauri Ojansivu ac242c96b7 Updated translations. 2021-04-20 21:13:04 +03:00
Lauri Ojansivu 79d45c8e33 Updated ChangeLog. 2021-04-20 21:09:43 +03:00
Lauri Ojansivu 8e9f7102f9 Merge pull request #3741 from jrsupplee/master
Bug fix for Due Cards
2021-04-20 21:07:05 +03:00
John R. Supplee 1952dc309b Bug fix for Due Cards 2021-04-20 16:23:56 +02:00
Lauri Ojansivu 5e7767247f Updated ChangeLog. 2021-04-20 10:09:49 +03:00
Lauri Ojansivu 676bf686c7 Updated dependencies.
Thanks to developers of dependencies !
2021-04-20 10:08:32 +03:00
Lauri Ojansivu 5cd6985368 Updated translations. 2021-04-20 10:02:37 +03:00
Lauri Ojansivu 807e72dcce Updated ChangeLog. 2021-04-20 09:59:30 +03:00
Lauri Ojansivu 71702b5821 Merge pull request #3733 from jrsupplee/issue-1569
Fix: Trello data without labels definition
2021-04-20 09:58:18 +03:00
Lauri Ojansivu 40c56248f1 Merge branch 'mcrute-master' 2021-04-20 08:37:40 +03:00
John R. Supplee 74ac7d8d3f Fix for issue #1569 Trello data without labels definition 2021-04-19 22:37:26 +02:00
Mike Crute e7186b47b0 Support filtering by due date 2021-04-19 07:44:09 -07:00
Lauri Ojansivu 12aa7ea2cb Updated ChangeLog. 2021-04-16 22:33:34 +03:00
Lauri Ojansivu ef584e2826 v5.22 2021-04-16 21:57:36 +03:00
Lauri Ojansivu f902be10b6 Updated translations. 2021-04-16 21:54:04 +03:00
Lauri Ojansivu 29b835de59 Updated ChangeLog. 2021-04-16 21:50:25 +03:00
Lauri Ojansivu 6ff9c5b58d Added German (Switzerland) (de_CH) Part 3.
Fixed lint.

Thanks to translators and xet7 !
2021-04-16 21:47:39 +03:00
Lauri Ojansivu 1b86aeb4f5 Updated ChangeLog. 2021-04-16 21:25:40 +03:00
Lauri Ojansivu dce99c00be Updated number of translated languages.
Thanks to translators and xet7 !
2021-04-16 21:24:00 +03:00
Lauri Ojansivu e47c700c36 Updated ChangeLog. 2021-04-16 21:23:14 +03:00
Lauri Ojansivu 09506c78f3 Updated translations. Added German (Switzerland) (de_CH).
Thanks to translators !
2021-04-16 21:20:45 +03:00
Lauri Ojansivu 9ec1fc0902 Updated ChangeLog. 2021-04-16 20:58:18 +03:00
Lauri Ojansivu 0b3ec2c19e Merge pull request #3724 from jrsupplee/master
Remove allowedValues from Cards.type schema
2021-04-16 20:55:50 +03:00
John R. Supplee a94bec921c Remove allowedValues from Cards.type schema 2021-04-16 19:52:09 +02:00
Lauri Ojansivu 3884da3c06 v5.21 2021-04-16 20:28:51 +03:00
Lauri Ojansivu d3fa177c7f Updated translations. 2021-04-16 20:24:19 +03:00
Lauri Ojansivu d2176e2c08 Updated ChangeLog. 2021-04-16 20:05:20 +03:00
Lauri Ojansivu 8d9c59486d Merge branch 'master' of github.com:wekan/wekan 2021-04-16 19:59:34 +03:00
Lauri Ojansivu 0e7c2b4b94 Upgraded to Meteor 2.2.
Thanks to Meteor developers!
2021-04-16 19:58:51 +03:00
Lauri Ojansivu 5c9bc1c745 Merge pull request #3723 from mfilser/bugfix-date_format_not_changed_to_local_format
Bugfix, date format not changed to local format
2021-04-16 19:57:24 +03:00
Martin Filser 5e7efa0098 Bugfix, date format not changed to local format
- Fixes #3718
- intoduced by commit 4aee129cdc
2021-04-16 17:04:36 +02:00
Lauri Ojansivu 424862e313 Updated ChangeLog. 2021-04-15 17:50:03 +03:00
Lauri Ojansivu 9b80ad5a3c Merge branch 'HappyMushroom-TechTeam-summernoteFeatureSet' 2021-04-15 17:44:26 +03:00
ryanMushy 96c6fa0276 - Add new button to insert a URL link
- Add new popover allowing you to edit URL links
- enable spell check and grammerly extension
2021-04-14 18:31:32 -07:00
Lauri Ojansivu 69305e1833 v5.20 2021-04-14 13:14:21 +03:00
Lauri Ojansivu 8aa74ab65e Updated translations. 2021-04-14 13:10:48 +03:00
Lauri Ojansivu aee12c2494 Updated ChangeLog. 2021-04-14 12:40:07 +03:00
Lauri Ojansivu 83976b3229 Merge pull request #3715 from bentiss/fix-docs
openapi: rework the allowedValues to allow for imported variables
2021-04-14 12:37:52 +03:00
Benjamin Tissoires 39f8a138d7 openapi: rework the allowedValues to allow for imported variables
Previously I was assuming all variables were declared in the same file.
Turns out that imports exists too, and we need to recurse one more time
in those imports./

Also "clean" up a bit the function to do the parsing in 2 steps:
- first find out the actual matching node in js
- then convert it based on its type
rinse wash repeat.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
2021-04-14 11:32:03 +02:00
Lauri Ojansivu 120e4af7b2 Updated translations. 2021-04-14 12:26:58 +03:00
Lauri Ojansivu 15bddbc86a v5.19 2021-04-14 02:09:16 +03:00
Lauri Ojansivu 4e8b193801 Updated ChangeLog. 2021-04-14 02:00:15 +03:00
Lauri Ojansivu 37b65996a0 Merge branch 'master' of github.com:wekan/wekan 2021-04-14 01:55:38 +03:00
Lauri Ojansivu 9cd0d3488f Updated ChangeLog. 2021-04-14 01:55:31 +03:00
Lauri Ojansivu eaf07cef07 Merge pull request #3712 from HappyMushroom-TechTeam/bugfix/summernotePopover
popover needs to be destroyed anytime the details panel is closed.
2021-04-14 01:52:55 +03:00
Lauri Ojansivu 02a8775537 v5.18 2021-04-14 01:36:30 +03:00
ryanMushy f2d5698acb popover needs to be destroyed anytime the details panel is closed. 2021-04-13 15:34:59 -07:00
Lauri Ojansivu b0c0e456af Updated ChangeLog. 2021-04-14 01:23:40 +03:00
Lauri Ojansivu 0857a2ea91 Updated caniuse-lite etc dependencies.
Thanks to developers of dependencies !
2021-04-14 01:22:06 +03:00
Lauri Ojansivu 1f2e6d33ce Updated translations. 2021-04-14 01:12:21 +03:00
Lauri Ojansivu 250e0690d1 Updated ChangeLog. 2021-04-14 00:37:15 +03:00
Lauri Ojansivu e709094533 Merge pull request #3708 from jrsupplee/issue-3698
Bug fix for issue #3698
2021-04-14 00:35:43 +03:00
Lauri Ojansivu 4a5b16ee2e Updated ChangeLog. 2021-04-14 00:19:38 +03:00
Lauri Ojansivu 378d64f99a Merge pull request #3706 from jrsupplee/issue-3703
Bug fix: Rules for moving from list/swimlane
2021-04-14 00:18:05 +03:00
Lauri Ojansivu 4395760a40 Updated ChangeLog. 2021-04-14 00:16:12 +03:00
Lauri Ojansivu 8417fae89c Update Admin Panel Rules report icon and add missing translations.
Thanks to xet7 !
2021-04-14 00:11:05 +03:00
Lauri Ojansivu 6c8fae944c Merge branch 'jrsupplee-admin-reports' 2021-04-13 23:51:11 +03:00
Lauri Ojansivu decab9256b Merge branch 'admin-reports' of https://github.com/jrsupplee/wekan into jrsupplee-admin-reports 2021-04-13 23:50:37 +03:00
Lauri Ojansivu 183ed35ce8 Updated ChangeLog. 2021-04-13 23:33:24 +03:00
Lauri Ojansivu 2fcf85fd61 Merge branch 'tod31-customfield-stringtemplate' 2021-04-13 23:25:18 +03:00
Lauri Ojansivu 3613c1c75e Merge branch 'customfield-stringtemplate' of https://github.com/tod31/wekan into tod31-customfield-stringtemplate 2021-04-13 23:24:28 +03:00
Lauri Ojansivu e7813046f6 Updated ChangeLog. 2021-04-13 21:26:02 +03:00
Lauri Ojansivu 9871bf1963 Updated release scripts.
Thanks to xet7 !
2021-04-13 21:24:44 +03:00
Lauri Ojansivu b32e7b659b Updated ChangeLog. 2021-04-13 21:13:54 +03:00
Lauri Ojansivu 2201372744 Updated to Node.js v12.22.1. Thanks to Node.js developers. 2021-04-13 21:11:54 +03:00
Lauri Ojansivu 7431a082e2 Updated ChangeLog. 2021-04-13 21:07:45 +03:00
Lauri Ojansivu 6fe3edebb1 Added latest bundle symlink.
Thanks to xet7 !
2021-04-13 21:04:59 +03:00
Lauri Ojansivu 4b6406c264 Merge pull request #3692 from loganballard/fix-arm-dockerfile
Updating ARM Dockerfile
2021-04-13 21:03:58 +03:00
John R. Supplee 86f6bdf9af Merge branch 'master' of https://github.com/wekan/wekan into admin-reports 2021-04-13 13:02:57 +02:00
Lauri Ojansivu 1eeed6645d Updated ChangeLog. 2021-04-12 19:34:58 +03:00
Lauri Ojansivu bb8c4325c6 Updated dependencies.
Thanks to developers of dependencies !
2021-04-12 19:32:00 +03:00
John R. Supplee 07a3301414 Bug fix for issue #3698
* Rewrite routine for building the My Cards hierarchical list
* Use a separate publication for retrieving My Cards
* Fix bug with limit and skip projectsion
2021-04-12 17:34:02 +02:00
Martin Filser 1590701fc9 Custom Fields StringTemplate, Ctrl-Enter the same as the button "Save" 2021-04-12 17:23:51 +02:00
John R. Supplee 1d4a65d0b4 Add new rules report 2021-04-12 11:44:28 +02:00
tod31 c845d25ae5 add localization string 2021-04-12 11:14:25 +02:00
tod31 ceec27bf90 cleanup and cosmetics 2021-04-12 11:01:58 +02:00
tod31 4b90424773 event handling/focussing 2021-04-12 10:49:14 +02:00
tod31 31eb9b26b4 use tracker afterFlush to set focus 2021-04-11 20:07:31 +02:00
tod31 a8a3c9ad19 fix default value 2021-04-11 14:18:12 +02:00
tod31 5cfa03ec07 use string array to store items in database 2021-04-11 14:15:57 +02:00
John R. Supplee 17ab5978ad Bug fix: Rules for moving from list/swimlane
Issue: 3703
2021-04-11 00:09:32 +02:00
tod31 d4c69c3932 fix custom-field-stringtemplate-separator string 2021-04-09 12:46:12 +02:00
tod31 3778a9ebcf add configuration field for separator 2021-04-09 11:46:07 +02:00
tod31 880d94e220 use nonidentity instead of inequality 2021-04-09 11:46:03 +02:00
tod31 37607f72b2 code cosmetics 2021-04-09 11:45:56 +02:00
tod31 b1c26e6f64 remove empty lines 2021-04-09 11:45:48 +02:00
tod31 8164af281d add info text for placeholder 2021-04-09 11:45:40 +02:00
tod31 af676c8f26 fix custom field type name 2021-04-09 11:45:25 +02:00
tod31 b8dc7ff18e add custom field "stringtemplate" 2021-04-09 11:44:49 +02:00
John R. Supplee 4aee129cdc Remove redundant and unused code 2021-04-06 18:00:03 +02:00
John R. Supplee 03d29dd674 Updates to userAvatar and cardDetails template
* enable userAvatar to work with member and assignee
* remove userAvatarAssignee template
2021-04-06 17:50:03 +02:00
John R. Supplee 5a6f84ce34 * Add publications for admin reports
* remove broken cards from user menu
* Adjust report titles
2021-04-06 12:42:15 +02:00
John R. Supplee 0e593c7d81 Add admin reports to admin panel
* Broken cards
* Attachments
* Orphaned Attachments
2021-04-06 12:24:08 +02:00
John R. Supplee 4de830d663 Merge branch 'search' into admin-reports 2021-04-05 21:57:56 +02:00
Lauri Ojansivu 769bb7a55d Updated translations. 2021-04-04 22:09:23 +03:00
John R. Supplee ed6c6e5a25 Use new colors constants 2021-04-03 18:52:47 +02:00
John R. Supplee 302ba75729 * Fix bug with multiple label predicates
* Add new constants
2021-04-03 01:19:02 +02:00
John R. Supplee 69dc8f304c Only search label names in boards of type 'board' 2021-04-02 21:40:52 +02:00
John R. Supplee e43002d5ad Update Boards.userBoards() to only return type 'board' by default 2021-04-02 02:15:12 +02:00
John R. Supplee edd07befe2 Add a new search operator creator 2021-04-01 23:41:32 +02:00
John R. Supplee 5cc6a2f7d0 Add an avatar for the card creator
* Add avatar to minicard
* Add field to card details
* Add show option in Board / Card Settings
2021-04-01 23:40:07 +02:00
Lauri Ojansivu 926f39c96b Update translations. 2021-04-01 14:14:11 +03:00
Lauri Ojansivu abd38082de Updated ChangeLog. 2021-04-01 13:53:10 +03:00
Lauri Ojansivu 5ca90f4d22 Revert stable tag, because it did break Wekan version numbers.
Thanks to xet7 !
2021-04-01 13:47:57 +03:00
loganballard c9586e579a updating Dockefile 2021-03-31 21:46:52 -07:00
Lauri Ojansivu 4cadc5f4f3 v5.17 2021-04-01 01:51:20 +03:00
Lauri Ojansivu 8dfb6916c5 Added stable tag release script. 2021-04-01 01:49:41 +03:00
Lauri Ojansivu 6066be944a Updated translations. 2021-04-01 01:45:24 +03:00
Lauri Ojansivu e9f8279dbe Updated ChangeLog. 2021-04-01 01:38:05 +03:00
Lauri Ojansivu 454d3b5bbe Fix Link dialog closes card when clicking in dialog.
Thanks to ryanMushy !

Fixes #3455
2021-04-01 01:34:23 +03:00
Lauri Ojansivu fe185dd38a v5.16 2021-04-01 00:40:02 +03:00
Lauri Ojansivu 522b14d96d Updated translations. 2021-04-01 00:35:26 +03:00
Lauri Ojansivu d98b489263 Updated ChangeLog. 2021-04-01 00:33:13 +03:00
Lauri Ojansivu 47ecc654b8 Added back Summernote editor. Removed emoji picker.
Thanks to ryanMushy and xet7 !

Related https://github.com/wekan/wekan/commit/84fde1ecfc81e89ed1895cab3bcb328e4f166a87#commitcomment-48956373
2021-04-01 00:30:46 +03:00
Lauri Ojansivu b9a4ae654e Updated ChangeLog. 2021-03-31 22:00:45 +03:00
Lauri Ojansivu c40668be3f Added stable tag.
Thanks to rynr and xet7 !

Related https://github.com/wekan/wekan/discussions/3691
2021-03-31 21:58:23 +03:00
Lauri Ojansivu a9d77b975e v5.15 2021-03-31 18:20:06 +03:00
Lauri Ojansivu 085bf3b6e6 Updated ChangeLog. 2021-03-31 18:16:49 +03:00
Lauri Ojansivu 91dae9795e Updated release website scripts. Part 2.
Thanks to xet7 !
2021-03-31 18:15:21 +03:00
Lauri Ojansivu 42081db0d8 Updated translations. 2021-03-31 18:14:11 +03:00
Lauri Ojansivu 3af417209c Updated ChangeLog. 2021-03-31 18:11:13 +03:00
Lauri Ojansivu b6f60c08e5 Fixed release website script.
Thanks to xet7 !
2021-03-31 18:09:47 +03:00
Lauri Ojansivu 03d7940829 Updated ChangeLog. 2021-03-31 17:55:04 +03:00
Lauri Ojansivu 0b263cf582 - Fixed Bug: Move Swimlane to Archive does not work anymore.
- Fixed lint in router.js

Thanks to marcungeschikts and xet7 !

Fixes #3690
2021-03-31 17:52:22 +03:00
Lauri Ojansivu 8ef60a06ad Updated ChangeLog. 2021-03-31 16:18:00 +03:00
Lauri Ojansivu 91eb4b941d Merge pull request #3688 from jrsupplee/issue-1667
Fix bug in Due Cards introduced by last bug fix
2021-03-31 16:16:58 +03:00
Lauri Ojansivu 2171690d22 Updated ChangeLog. 2021-03-31 16:13:58 +03:00
Lauri Ojansivu 6819303047 Updated node update local script.
Thanks to xet7 !
2021-03-31 16:12:16 +03:00
Lauri Ojansivu 88e19bd011 Updated ChangeLog. 2021-03-31 16:08:35 +03:00
Lauri Ojansivu 09b9f690b1 Updated node-update.sh release script.
Thanks to xet7 !
2021-03-31 16:03:08 +03:00
Lauri Ojansivu 7a9c397264 Updated to Node.js v12.22.0. Thanks to Node.js developers. 2021-03-31 16:02:25 +03:00
Lauri Ojansivu c2b7525864 Updated to Node.js v12.22.0. Thanks to Node.js developers. 2021-03-31 16:01:12 +03:00
Lauri Ojansivu e2ecd490ff Updated ChangeLog. 2021-03-31 16:00:08 +03:00
Lauri Ojansivu 1d3673e9d3 Updated node update scipts. 2021-03-31 15:58:41 +03:00
Lauri Ojansivu 5bd85f975c Remove some extra text. 2021-03-31 15:44:18 +03:00
Lauri Ojansivu 89ab99b551 Updated ChangeLog. 2021-03-31 15:43:05 +03:00
Lauri Ojansivu 01de3f187c Set release script node-update.sh as executeable.
Thanks to xet7 !
2021-03-31 15:41:14 +03:00
Lauri Ojansivu dcd7925571 Updated ChangeLog. 2021-03-31 15:40:32 +03:00
Lauri Ojansivu 34b6aa0858 Updated release scripts.
Thanks to xet7 !
2021-03-31 15:39:07 +03:00
John R. Supplee 73fb62e941 Fix bug in Due Cards introduced by last bug fix 2021-03-31 13:53:35 +02:00
Lauri Ojansivu 55ced412a0 Updated ChangeLog. 2021-03-31 14:23:37 +03:00
Lauri Ojansivu 04a8d85836 Merge pull request #3687 from jrsupplee/issue-1667
Fix bug in My Cards and Global Search
2021-03-31 14:21:48 +03:00
John R. Supplee 392b701956 Fix bug in My Cards and Global Search 2021-03-31 13:05:39 +02:00
Lauri Ojansivu dee098c125 Updated translations. 2021-03-31 13:47:58 +03:00
Lauri Ojansivu 56e26a65ae Updated ChangeLog. 2021-03-31 13:15:55 +03:00
Lauri Ojansivu 69509d597f Merge pull request #3686 from ednamaeG/sort-fix
fixed sort reset
2021-03-31 13:13:44 +03:00
ednamaeG bc7b18abe7 Merge branch 'master' into sort-fix 2021-03-31 14:56:55 +08:00
mae 4a95cb42cd fixed sort reset 2021-03-31 14:51:08 +08:00
Lauri Ojansivu db311f677b Fix typo. 2021-03-29 12:05:06 +03:00
Lauri Ojansivu 685fb98e59 v5.14 2021-03-29 11:40:30 +03:00
Lauri Ojansivu 6dd98285a6 Updated translations. 2021-03-29 11:36:20 +03:00
Lauri Ojansivu e225d29d7a Updated translations. 2021-03-29 10:29:31 +03:00
Lauri Ojansivu eff7d123f2 Updated ChangeLog. 2021-03-29 10:18:22 +03:00
Lauri Ojansivu 4d62fe83f4 Merge pull request #3677 from jrsupplee/issue-3655
Require signed-in user for My Cards, Due Cards, and global search #3655
2021-03-29 10:15:31 +03:00
Lauri Ojansivu a37ca01703 Updated ChangeLog. 2021-03-29 10:13:09 +03:00
Lauri Ojansivu ba05f383ca Added environment variable RESULTS_PER_PAGE to all Wekan platforms.
Thanks to xet7 !
2021-03-29 10:11:13 +03:00
Lauri Ojansivu 4ea4913d72 Merge branch 'jrsupplee-search' 2021-03-29 09:43:21 +03:00
John R. Supplee 856f3bf864 Require signed-in user for My Cards, Due Cards, and global search 2021-03-29 02:01:12 +02:00
John R. Supplee 238b0f0725 Merge branch 'master' of https://github.com/wekan/wekan into search 2021-03-28 22:16:15 +02:00
Lauri Ojansivu a79a5c7299 Updated ChangeLog. 2021-03-28 19:31:01 +03:00
Lauri Ojansivu 59580e4b0f Updated release scripts.
Thanks to xet7 !
2021-03-28 19:28:48 +03:00
Lauri Ojansivu 7e05e02137 v5.13 2021-03-28 10:38:01 +03:00
Lauri Ojansivu d4a1611b86 Try to fix Sandstorm Wekan.
Thanks to xet7 !
2021-03-28 10:15:44 +03:00
Lauri Ojansivu 77abde7836 v5.12 2021-03-28 07:55:50 +03:00
Lauri Ojansivu 4c60916191 Fix HTTP not defined.
Thanks to xet7 !
2021-03-28 07:51:25 +03:00
Lauri Ojansivu 634eec7eb6 v5.11 2021-03-28 07:32:08 +03:00
Lauri Ojansivu 4ccbbc78cf Updated ChangeLog. 2021-03-28 07:26:05 +03:00
Lauri Ojansivu 4e1c0fdce8 Updated dependencies. Fixed lint.
Thanks to xet7 !
2021-03-28 07:24:24 +03:00
Lauri Ojansivu 9fa1d846e6 Updated translations. 2021-03-28 07:03:40 +03:00
Lauri Ojansivu 969dca292e Updated ChangeLog. 2021-03-28 07:01:28 +03:00
Lauri Ojansivu 84fde1ecfc Added emoji picker to card description edit and card comment edit.
Removed Summernote wysiwyg editor, package-lock.json etc.

Thanks to xet7 !
2021-03-28 06:56:05 +03:00
John R. Supplee db9ee59d9f Merge branch 'search' of supplee.net:wekan into search 2021-03-28 02:47:18 +02:00
John R. Supplee 20a2ea3e7a Add icon to clear the current search 2021-03-28 02:46:11 +02:00
John R. Supplee 39b4ada26d Do not include archived lists in global search help 2021-03-28 02:45:15 +02:00
Lauri Ojansivu 3ddfe7c1fd Updated dependencies. 2021-03-28 02:27:25 +02:00
Lauri Ojansivu f7955d5fd7 v5.10 2021-03-28 01:24:24 +02:00
Lauri Ojansivu f115afb64e Updated ChangeLog. 2021-03-28 01:17:10 +02:00
Lauri Ojansivu 3145ec65a3 Updated package-lock.json
Thanks to developers of dependencies!
2021-03-28 01:15:54 +02:00
Lauri Ojansivu e2f690d0db Updated ChangeLog. 2021-03-28 01:13:28 +02:00
Lauri Ojansivu e6c8c04394 Merge branch 'vagnernascimento-master' 2021-03-28 01:08:54 +02:00
Lauri Ojansivu a7741df5e4 Merge branch 'master' of https://github.com/vagnernascimento/wekan into vagnernascimento-master 2021-03-28 01:06:28 +02:00
Lauri Ojansivu 912577cab3 Updated translations. 2021-03-28 01:03:34 +02:00
Lauri Ojansivu cec43a63a7 Updated ChangeLog. 2021-03-28 00:53:19 +02:00
Lauri Ojansivu 10c9fc25a9 Merge branch 'jrsupplee-move-swimlane' 2021-03-28 00:50:10 +02:00
Lauri Ojansivu 16665bccf9 Added translatable Move Swimlane popup title.
Thanks to xet7 !
2021-03-28 00:48:55 +02:00
John R. Supplee 103cfb936d Merge branch 'master' of https://github.com/wekan/wekan into search 2021-03-27 23:10:53 +02:00
John R. Supplee 4bb8f3ab27 Merge branch 'master' of https://github.com/wekan/wekan into move-swimlane 2021-03-27 22:09:14 +02:00
John R. Supplee 36a4740429 Fix bug in call to get default swimlane 2021-03-27 19:02:07 +02:00
John R. Supplee ed54c09b48 Use a method call to move the swimlane server side 2021-03-27 18:50:05 +02:00
Vagner Nascimento 6eb90238b1 Included a new route to export (json) an attachment from a board.
GET  /api/boards/:id/attachments/:attachmentId/export
2021-03-26 22:37:42 -03:00
John R. Supplee aad300613d Add UI code and make some fixes to list move code
Still need to add new lists to all swimlanes
2021-03-27 00:56:44 +02:00
Lauri Ojansivu a2f8e54b67 v5.09 2021-03-26 23:30:40 +02:00
Lauri Ojansivu c9a10efe5c Updated translations. 2021-03-26 23:12:26 +02:00
Lauri Ojansivu 7e2f802169 Updated ChangeLog. 2021-03-26 22:56:30 +02:00
Lauri Ojansivu 9df5a0f530 Merge pull request #3672 from bentiss/fix-docs
Fix openapi docs generation
2021-03-26 22:54:08 +02:00
Lauri Ojansivu 16971ff1d8 Updated ChangeLog. 2021-03-26 22:53:07 +02:00
Lauri Ojansivu bef544ddc8 Merge branch 'sim51-patch-1' 2021-03-26 22:51:11 +02:00
Benjamin Tissoires 2c1f40357d Fix openapi docs generation
esprima-python is now safe to use
(https://github.com/Kronuz/esprima-python/pull/12)

And there was a new ArrowFunctionExpression used in db666eec65
that broke the python script
2021-03-26 18:41:34 +01:00
Benoît Simard ea544caf83 Replace edit icon by plus-square on new links 2021-03-26 16:36:26 +01:00
John Supplee be9e98b2a1 Merge branch 'master' of https://github.com/wekan/wekan into move-swimlane 2021-03-26 16:52:02 +02:00
John Supplee 59a3ac1f37 Add move() methods to Swimlanes and Lists collections 2021-03-26 16:51:01 +02:00
Lauri Ojansivu be22ca332b Updated translations. 2021-03-26 13:09:13 +02:00
Lauri Ojansivu 983e34ef80 Updated package-lock.json 2021-03-26 13:06:34 +02:00
Lauri Ojansivu c9830bc262 v5.08 2021-03-26 10:43:23 +02:00
Lauri Ojansivu fc21c6d1d6 Updated translations. 2021-03-26 10:38:15 +02:00
Lauri Ojansivu 960f332dce Updated ChangeLog. 2021-03-26 10:20:25 +02:00
Lauri Ojansivu d532a3591f Added package-lock.json and updated .gitignore
Thanks to xet7 !
2021-03-26 10:19:03 +02:00
Lauri Ojansivu 03a9f4766a Updated translations. 2021-03-26 10:17:27 +02:00
Lauri Ojansivu 96f3e3a958 Updated ChangeLog. 2021-03-26 10:09:51 +02:00
Lauri Ojansivu a249ffc805 Admin Panel/Settings/Accounts: Hide system messages of all users.
Thanks to bbyszio, r4nc0r and xet7 !

Related #3345
2021-03-26 10:05:28 +02:00
Lauri Ojansivu 5f53f8cc01 Updated translations. 2021-03-26 08:31:22 +02:00
Lauri Ojansivu ca3f621572 Updated ChangeLog. 2021-03-25 12:26:33 +02:00
Lauri Ojansivu a0e1b6f918 Fix translations. 2021-03-25 12:24:49 +02:00
Lauri Ojansivu c76d44b5c7 Updated ChangeLog. 2021-03-25 12:20:35 +02:00
Lauri Ojansivu ccc9efb270 - Added translation: español de América Latina
- Some lint fixes

Thanks to translators!
2021-03-25 12:18:33 +02:00
Lauri Ojansivu 2ebc34e901 Updated ChangeLog. 2021-03-25 11:25:26 +02:00
Lauri Ojansivu 04566d3f40 Merge pull request #3669 from jrsupplee/trello-import-links
Add Trello attached links to the card description
2021-03-25 11:16:32 +02:00
John R. Supplee 1083a92816 Add Trello attached links to the card description 2021-03-24 16:28:52 +02:00
John Supplee bb7490a32b Merge branch 'master' of https://github.com/wekan/wekan into search 2021-03-19 21:10:16 +02:00
John Supplee 9e8399612b Add environment variable and snap configuration option for results per page 2021-03-19 21:09:39 +02:00
Lauri Ojansivu df54863e72 v5.07 2021-03-19 11:12:32 +02:00
Lauri Ojansivu 8f340326b0 Updated translations. 2021-03-19 11:08:36 +02:00
Lauri Ojansivu 42975bc8ab Updated ChangeLog. 2021-03-19 11:05:29 +02:00
Lauri Ojansivu adb5487cdc Merge pull request #3662 from ednamaeG/sort-fix
Fixed sort cards feature
2021-03-19 11:03:10 +02:00
mae 4aad9ca498 fix sort cards feature 2021-03-19 12:13:20 +08:00
Lauri Ojansivu 972d023e95 v5.06 2021-03-18 18:36:13 +02:00
Lauri Ojansivu acabef4652 Updated translations. 2021-03-18 18:15:52 +02:00
Lauri Ojansivu f77651ba05 Updated ChangeLog. 2021-03-18 17:42:17 +02:00
Lauri Ojansivu 23e349d277 Merge pull request #3661 from Majed6/copy_href
Fixed Bug: copy to clipboard uses pathname
2021-03-18 17:41:47 +02:00
Lauri Ojansivu 37d9a6659a Merge pull request #3648 from Majed6/relative-url-fixes
Fixed Bug: Calendar & parent cards URLs used absolute URLs
2021-03-18 17:37:55 +02:00
Majed6 8796c46810 Fixed Bug: copy to clipboard uses pathname 2021-03-18 16:48:53 +03:00
John Supplee 0ebb427a00 Update the server error message 2021-03-18 02:04:25 +02:00
Lauri Ojansivu 4960891bd9 Updated translations. 2021-03-16 17:33:03 +02:00
Majed6 43482d9e48 Fixed Bug: Calendar & parent cards URLs used absolute URLs 2021-03-13 15:08:28 +03:00
John R. Supplee 299410f8b4 Merge branch 'master' into search 2021-03-11 18:28:55 +02:00
John R. Supplee 07aa20a3cd Fix for Due Cards and some cleanup 2021-03-11 02:05:46 +02:00
Lauri Ojansivu ee323d97b4 v5.05 2021-03-11 00:05:25 +02:00
Lauri Ojansivu d6b447f70a Updated translations. 2021-03-10 23:59:12 +02:00
John R. Supplee 06cae36199 Merge branch 'master' of https://github.com/wekan/wekan into search 2021-03-10 12:41:14 +02:00
John R. Supplee 183404a5f8 Code cleanup and remove debugging code 2021-03-10 12:40:20 +02:00
John R. Supplee 6def7d6f70 Move query parsing to Query class 2021-03-10 12:39:39 +02:00
John R. Supplee 097cae1f8c More integration with constants and query classes 2021-03-09 19:30:04 +02:00
John Supplee ba00311dd4 Add more constants and convert params object to a class 2021-03-09 02:21:43 +02:00
Lauri Ojansivu 203fafdf7c Updated translations. 2021-03-08 22:16:18 +02:00
Lauri Ojansivu 62e90723d1 Updated ChangeLog. 2021-03-08 22:13:50 +02:00
Lauri Ojansivu 77372ccce1 Merge pull request #3641 from chrisi51/master
change url scheme recognition for allowing abasurl to link
2021-03-08 22:10:49 +02:00
John R. Supplee 849b608933 Start adding constants for search operators and predicates 2021-03-08 19:18:01 +02:00
Christian Hillebrand fdb4980b68 change url scheme recognition for allowing abasurl to link
autolinking is not working for abasurl as it contains not url conform characters so you would still have to link it manually but it is not sanitized anymore.
2021-03-08 10:48:50 +01:00
Lauri Ojansivu ff4f5e6c04 v5.04 2021-03-07 18:06:27 +02:00
Lauri Ojansivu 0bb3b67075 Fixed generating API docs and Wekan Custom Fields REST API.
Thanks to xet7 !
2021-03-07 17:57:24 +02:00
Lauri Ojansivu e16b06b44a Updated ChangeLog. 2021-03-07 16:19:17 +02:00
Lauri Ojansivu ac9b23f00f OpenPower MiniCloud emergency maintenance has finished, so can now build Wekan for ppc64le.
Thanks to OpenPower Minicloud !
2021-03-07 16:16:12 +02:00
Lauri Ojansivu f562bdd801 Updated translations. 2021-03-07 16:06:22 +02:00
Lauri Ojansivu 0c05942b45 Updated ChangeLog. 2021-03-07 16:03:29 +02:00
Lauri Ojansivu 9db3c93116 Speed improvement: Delete presences older than one week, and add index to presences serverId.
Thanks to xet7 !

Related #3345
2021-03-07 15:58:15 +02:00
Lauri Ojansivu ce1f3365bb Updated translations. 2021-03-07 12:38:04 +02:00
John R. Supplee 4ed5c3e4b8 Create array of cards from card search result card ids instead of re-running
the search on the client side.
2021-03-07 02:12:58 +02:00
John R. Supplee 9061180983 Code cleanup 2021-03-07 02:12:31 +02:00
John R. Supplee be970e4cea Merge branch 'search' of github.com:jrsupplee/wekan into search 2021-03-06 10:40:28 +02:00
John Supplee 8f978c23b4 Modify Broken Cards to use new search functions and component 2021-03-05 23:47:12 +02:00
John Supplee 5f53c71b0c Merge branch 'master' into search 2021-03-05 21:46:06 +02:00
John Supplee 58020863a8 Handle subscriptions better
* use onReady and onStop callbacks when subscribing
* show an server error message when the server returns an error
* call stop() on subscriptions
2021-03-05 21:20:55 +02:00
Lauri Ojansivu 3ce3612047 Updated ChangeLog. 2021-03-05 21:15:31 +02:00
Lauri Ojansivu 44c9eebc4c Merge branch 'flawless-execution-feat/edit-custom-field' 2021-03-05 21:13:52 +02:00
Lauri Ojansivu cf6cc0e59d Merge branch 'feat/edit-custom-field' of https://github.com/flawless-execution/wekan into flawless-execution-feat/edit-custom-field 2021-03-05 21:13:41 +02:00
Lauri Ojansivu 2b1fc8d07f Updated ChangeLog. 2021-03-05 21:13:13 +02:00
Lauri Ojansivu e7d7ddd698 Merge pull request #3635 from Majed6/originRelativeUrl
Fixed Bug: inconsistent use of relative/absolute URLs
2021-03-05 21:11:42 +02:00
Lauri Ojansivu 1d6bfc5dd6 Updated ChangeLog. 2021-03-05 20:54:40 +02:00
Lauri Ojansivu 0ccdbdcbe9 Merge pull request #3633 from chrisi51/autolink-settings
Added autolinking settings in admin backend - tbc
2021-03-05 20:52:13 +02:00
Lauri Ojansivu 463346b867 Updated ChangeLog. 2021-03-05 20:37:16 +02:00
Lauri Ojansivu f293700db3 Merge pull request #3634 from jrsupplee/issue-3587
Fix search on labels server error
2021-03-05 19:40:24 +02:00
Majed6 b4e343369a Fixed Bug: inconsistent use of relative/absolute URLs
Some pages use relative links such as boards link at the home page.
 Others use absolute url such as cards in boards' lists.
 This commits goal is to allow for consistent use of relative
  urls.

Origin relative URLs also helps decoupling Wekan from the infrastructure
 it's deployed on. i.e if it's being served, it should work.
2021-03-05 15:05:53 +03:00
John R. Supplee da1d94775c Fix search on labels crashing bug 2021-03-04 18:35:02 +02:00
Christian Hillebrand 28582b7e77 correction of a typo 2021-03-04 17:04:29 +01:00
Christian Hillebrand 0f4a97f3a6 add automatic-linked-url-schemes 2021-03-04 16:45:16 +01:00
Christian Hillebrand 0f75234ed2 add automaticLinkedUrlSchemes 2021-03-04 16:42:35 +01:00
Christian Hillebrand bc2556139a add automaticLinkedUrlSchemes 2021-03-04 16:40:03 +01:00
Christian Hillebrand c1f52a5e5a add automaticLinkedUrlSchemes 2021-03-04 16:38:47 +01:00
Christian Hillebrand ab24b3262c add automaticLinkedUrlSchemes 2021-03-04 16:36:48 +01:00
chrisi51 42994efa9d Added real autolinking and simpler adding of new url schemes
to add additional URL Schemes just put your scheme to urlschemes
2021-03-04 16:30:06 +01:00
John Supplee 28aebaa06b Make search instructions code more uniform 2021-03-04 02:13:22 +02:00
Lauri Ojansivu 44cf82caab Updated ChangeLog. 2021-03-03 18:19:32 +02:00
Lauri Ojansivu a44ca39eb8 Try to fix Snap: Removed fibers multi arch from Snap, because Snap build servers do not build corretly with it.
Thanks to xet7.
2021-03-03 18:16:29 +02:00
Lauri Ojansivu 3f70c395e1 v5.03 2021-03-03 16:56:02 +02:00
Lauri Ojansivu 04383c0302 Removed temporary file. 2021-03-03 16:52:15 +02:00
Lauri Ojansivu 55d022eefc Updated ChangeLog. 2021-03-03 16:44:13 +02:00
Lauri Ojansivu 7d3917adb7 Fixed Bug: Link at board title can not be edited.
Thanks to jonesrussell42, aiac, bbyszio and xet7 !

Fixes #3622
2021-03-03 16:39:34 +02:00
Lauri Ojansivu 7eeeab8486 Updated translations. 2021-03-03 15:34:37 +02:00
Lauri Ojansivu 88a46ef59a Updated ChangeLog. 2021-03-03 15:26:20 +02:00
Lauri Ojansivu e4a9dc25ec Revert Removed extra imports of Meteor. Hopefully fixes email notifications
and rules on old cars not working.

Thanks to xet7 !
2021-03-03 15:23:43 +02:00
Lauri Ojansivu dfb563a330 Add link to issue template about email settings. 2021-03-03 15:18:04 +02:00
John R. Supplee 329256712b Merge branch 'master' into search 2021-03-03 11:47:56 +02:00
Lauri Ojansivu 16dbb88ee3 Updated ChangeLog. 2021-03-02 18:50:18 +02:00
Lauri Ojansivu 626f435edf Hide email settings from Sandstorm Wekan Admin Panel.
Thanks to ocdtrekkie and xet7 !

Related https://github.com/wekan/wekan/commit/65b8220fe53349695a335bdb8b9692f82d4b3329
2021-03-02 18:45:02 +02:00
Lauri Ojansivu d4dd5d7a61 v5.02 2021-03-02 16:40:50 +02:00
Lauri Ojansivu de13b8b9ba Removed extra imports of Meteor.
Thanks to xet7 !
2021-03-02 16:25:27 +02:00
Lauri Ojansivu 0aabb0b364 Fix lint. 2021-03-02 16:08:29 +02:00
Lauri Ojansivu 3605072650 Updated translations. 2021-03-02 16:04:25 +02:00
Lauri Ojansivu 6272aabefb Updated ChangeLog. 2021-03-02 15:56:28 +02:00
Lauri Ojansivu bf2446614c Merge pull request #3620 from n8ores/master
Add attachmentId to the Webhook data
2021-03-02 15:50:53 +02:00
Lauri Ojansivu 65b8220fe5 Fix SMTP port lost after upgrade. STMP settings are made only with environment variables on non-Sandstorm platforms.
Note: Sending email on Sandstorm Wekan does not work yet.

Thanks to jrsupplee and xet7 !

Fixes #3529,
Fixes #3016,
Fixes #2375,
Fixes #2598,
Fixes wekan/wekan-snap#78
2021-03-02 15:33:59 +02:00
John R. Supplee e0b544fc7e Add new Blaze search component 2021-03-01 20:18:44 +02:00
n8ores d296918fcd Revert "Add startup script etc"
This reverts commit 3453690fc2.
2021-03-01 18:19:09 +13:00
n8ores c9a2d439e5 Merge remote-tracking branch 'upstream/master' 2021-03-01 18:13:41 +13:00
n8ores 73f36bcf33 Add AttachmentId to webhook data 2021-03-01 18:12:09 +13:00
John R. Supplee a1bda1169e Update Global Search, Due Cards, and My Cards to use the same
code for searching and display
2021-03-01 01:49:56 +02:00
Lauri Ojansivu 8f5089fd46 Updated translations. 2021-03-01 00:02:34 +02:00
n8ores ae8b17e0fb Merge remote-tracking branch 'upstream/master' 2021-03-01 10:57:07 +13:00
n8ores 3453690fc2 Add startup script etc 2021-03-01 10:56:51 +13:00
Lauri Ojansivu bc1f607c8e Updated ChangeLog. 2021-02-28 19:20:55 +02:00
Lauri Ojansivu e0382139b6 Merge pull request #3618 from ChrisMagnuson/master
Add sort to rest API
2021-02-28 19:13:26 +02:00
Chris Magnuson 65d280da8a Add sort to rest API 2021-02-27 16:24:12 -05:00
Lauri Ojansivu e618070068 Updated translations. 2021-02-27 18:51:34 +02:00
Lauri Ojansivu 8181074238 Merge pull request #3617 from jrsupplee/search
Global Search enhancements and fixes
2021-02-27 17:24:35 +02:00
John R. Supplee b0e4aedd3d Update search instructions 2021-02-27 17:02:42 +02:00
John R. Supplee faa101224a Add new has predicates for more fields 2021-02-27 02:26:58 +02:00
John R. Supplee eb7fc0fb26 Comment out debugging code 2021-02-27 00:56:12 +02:00
John Supplee a63a61e7fc Fix problem with dates in selector being unpickled as a String 2021-02-26 23:19:12 +02:00
John Supplee 223cc07139 Add instructions for limit operator 2021-02-26 18:51:54 +02:00
John Supplee 62b0d371ee Add new limit operator 2021-02-26 17:31:44 +02:00
Lauri Ojansivu 884b678bd0 Updated ChangeLog. 2021-02-26 15:01:18 +02:00
John Supplee 2930e9cadb Merge branch 'master' of https://github.com/wekan/wekan into search 2021-02-26 14:49:53 +02:00
Lauri Ojansivu 6103265488 v5.01 2021-02-26 14:24:19 +02:00
Lauri Ojansivu c1f5dfc02e Updated translations. 2021-02-26 14:19:20 +02:00
John Supplee 8e911a42f5 Fixes to due predicates 2021-02-26 14:11:24 +02:00
Lauri Ojansivu f41c1153d2 Updated ChangeLog. 2021-02-26 13:29:13 +02:00
Lauri Ojansivu ff03171f55 Merge pull request #3610 from n8ores/customFieldsFix
Fix syntax typo
2021-02-26 13:26:49 +02:00
John Supplee 5fe58dc9ae Add instructions for sort operator 2021-02-26 13:11:54 +02:00
John Supplee 0c1cff52b2 Update explanation of days predicate 2021-02-26 12:52:36 +02:00
n8ores 8e29a52d71 Correct typo 2021-02-26 20:44:03 +13:00
n8ores 12a0e73587 Fix syntax typo 2021-02-26 20:01:09 +13:00
John Supplee a3229ea965 Fixes for duration predicates 2021-02-26 01:13:45 +02:00
John R. Supplee 43f40c4085 Fix sort operator
* Add server publications for next and previous page
* Add ability to sort ascending or descending
2021-02-25 18:38:51 +02:00
Lauri Ojansivu 250e79f53c v5.00 2021-02-25 15:14:48 +02:00
Lauri Ojansivu c8b2c19010 Updated translations. 2021-02-25 15:12:47 +02:00
Lauri Ojansivu fe1add57f1 Updated ChangeLog. 2021-02-25 15:03:16 +02:00
Lauri Ojansivu 332f830cc2 Fixed Unable to remove old Board, reappears.
Thanks to chirrut2, uusijani, cimm, anicolaides, Philipoo0 and xet7.

Fixes #2613
2021-02-25 15:00:49 +02:00
Lauri Ojansivu ccd69dfcf7 Updated translations. 2021-02-25 12:09:31 +02:00
Louis Orleans 9cbef4ba4b 🔒 fix warning from deepcode 2021-02-20 14:11:17 -08:00
Louis Orleans 24035329b8 ✨ edit custom field dropdown item 2021-02-20 13:50:24 -08:00
Louis Orleans 457977f954 ✨ add and remove dropdown items 2021-02-20 12:46:29 -08:00
Louis Orleans 373dc5cadb ⏪ Revert "🎨 format with Prettier"
This reverts commit a35cfe660e.
2021-02-20 09:27:33 -08:00
Louis Orleans a35cfe660e 🎨 format with Prettier 2021-02-20 09:02:36 -08:00
Louis Orleans db666eec65 🐛 fix updating fields 2021-02-20 09:02:12 -08:00
Louis Orleans 586473aaa7 ✨ add custom field edit REST API 2021-02-19 11:21:13 -08:00
536 changed files with 124092 additions and 71542 deletions

No files matched your search

+65 -19
View File
@@ -1,16 +1,12 @@
FROM quay.io/wekan/ubuntu:groovy-20201125.2
FROM quay.io/wekan/ubuntu:groovy-20210115
LABEL maintainer="sgr"
# 2020-12-03:
# - Above Ubuntu base image copied from Docker Hub ubuntu:groovy-20201125.2
# to Quay to avoid Docker Hub rate limits.
ENV BUILD_DEPS="gnupg gosu bsdtar wget curl bzip2 g++ build-essential python git ca-certificates iproute2"
ENV BUILD_DEPS="gnupg gosu libarchive-tools wget curl bzip2 g++ build-essential python git ca-certificates iproute2"
ENV DEBIAN_FRONTEND=noninteractive
ENV \
DEBUG=false \
NODE_VERSION=v12.21.0 \
NODE_VERSION=v12.22.1 \
METEOR_RELEASE=1.10.2 \
USE_EDGE=false \
METEOR_EDGE=1.5-beta.17 \
@@ -19,6 +15,7 @@ ENV \
ARCHITECTURE=linux-x64 \
SRC_PATH=./ \
WITH_API=true \
RESULTS_PER_PAGE="" \
ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE=3 \
ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD=60 \
ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW=15 \
@@ -133,23 +130,24 @@ ENV \
SAML_PUBLIC_CERTFILE="" \
SAML_IDENTIFIER_FORMAT="" \
SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
SAML_ATTRIBUTES=""
SAML_ATTRIBUTES="" \
DEFAULT_WAIT_SPINNER=""
# Install OS
RUN set -o xtrace \
&& useradd --user-group -m --system --home-dir /home/wekan wekan \
&& apt-get update \
&& apt-get install --assume-yes --no-install-recommends apt-utils apt-transport-https ca-certificates 2>&1 \
&& apt-get install --assume-yes --no-install-recommends ${BUILD_DEPS}
&& apt-get install --assume-yes --no-install-recommends apt-utils apt-transport-https ca-certificates 2>&1 \
&& apt-get install --assume-yes --no-install-recommends ${BUILD_DEPS}
# Install NodeJS
RUN set -o xtrace \
&& cd /tmp \
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-$ARCHITECTURE.tar.xz" \
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& grep " node-v$NODE_VERSION-$ARCHITECTURE.tar.xz\$" SHASUMS256.txt.asc | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-$ARCHITECTURE.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
&& rm "node-v$NODE_VERSION-$ARCHITECTURE.tar.xz" SHASUMS256.txt.asc \
&& curl -fsSLO --compressed "https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-$ARCHITECTURE.tar.xz" \
&& curl -fsSLO --compressed "https://nodejs.org/dist/$NODE_VERSION/SHASUMS256.txt.asc" \
&& grep " node-$NODE_VERSION-$ARCHITECTURE.tar.xz\$" SHASUMS256.txt.asc | sha256sum -c - \
&& tar -xJf "node-$NODE_VERSION-$ARCHITECTURE.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
&& rm "node-$NODE_VERSION-$ARCHITECTURE.tar.xz" SHASUMS256.txt.asc \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs \
&& mkdir -p /usr/local/lib/node_modules/fibers/.node-gyp /root/.node-gyp/${NODE_VERSION} /home/wekan/.config \
&& npm install -g npm@${NPM_VERSION} \
@@ -171,17 +169,65 @@ RUN set -o xtrace \
ENV PATH=$PATH:/home/wekan/.meteor/
# Copy source dir
USER root
RUN echo "export PATH=$PATH" >> /etc/environment
RUN set -o xtrace \
&& mkdir /home/wekan/app
USER wekan
COPY ${SRC_PATH} /home/wekan/app/
# Copy source dir
RUN set -o xtrace \
&& mkdir -p /home/wekan/app/.meteor \
&& mkdir -p /home/wekan/app/packages
COPY \
.meteor/.finished-upgraders \
.meteor/.id \
.meteor/cordova-plugins \
.meteor/packages \
.meteor/platforms \
.meteor/release \
.meteor/versions \
/home/wekan/app/.meteor/
COPY \
package.json \
settings.json \
/home/wekan/app/
COPY \
packages \
/home/wekan/app/packages/
USER root
RUN set -o xtrace \
&& chown -R wekan:wekan /home/wekan/app /home/wekan/.meteor
USER wekan
RUN \
set -o xtrace && \
sed -i 's/api\.versionsFrom/\/\/api.versionsFrom/' /home/wekan/app/packages/meteor-useraccounts-core/package.js && \
cd /home/wekan/.meteor && \
/home/wekan/.meteor/meteor -- help;
RUN \
set -o xtrace && \
# Build app
cd /home/wekan/app && \
/home/wekan/.meteor/meteor add standard-minifier-js && \
/home/wekan/.meteor/meteor npm install && \
/home/wekan/.meteor/meteor build --directory /home/wekan/app_build
RUN \
set -o xtrace && \
cd /home/wekan/app_build/bundle/programs/server/ && \
chmod u+w package.json npm-shrinkwrap.json && \
npm install
ENV PORT=3000
EXPOSE $PORT
WORKDIR /home/wekan/app
CMD ["/home/wekan/.meteor/meteor", "run", "--verbose", "--settings", "settings.json"]
+12 -7
View File
@@ -3,17 +3,18 @@ version: '3.7'
services:
wekandb-dev:
image: mongo:4.0.12
image: mongo:4.4
container_name: wekan-dev-db
restart: unless-stopped
command: mongod --smallfiles --oplogSize 128
command: mongod --oplogSize 128
networks:
- wekan-dev-tier
expose:
- 27017
volumes:
- wekan-dev-db:/data/db
- wekan-dev-db-dump:/dump
- ./volumes/wekan-db:/data/db
- ./volumes/wekan-db-dump:/dump
- /etc/localtime:/etc/localtime:ro
wekan-dev:
container_name: wekan-dev-app
@@ -35,9 +36,13 @@ services:
depends_on:
- wekandb-dev
volumes:
- ..:/app:delegated
command:
sleep infinity
- ../client:/home/wekan/app/client
- ../models:/home/wekan/app/models
- ../config:/home/wekan/app/config
- ../i18n:/home/wekan/app/i18n
- ../server:/home/wekan/app/server
- ../public:/home/wekan/app/public
- /etc/localtime:/etc/localtime:ro
volumes:
wekan-dev-db:
+36
View File
@@ -0,0 +1,36 @@
*~
*.swp
.meteor-spk
*.sublime-workspace
tmp/
node_modules/
npm-debug.log
.gitmodules
.vscode/
.idea/
.build/*
**/parts/
**/stage
**/prime
**/*.snap
snap/.snapcraft/
.idea
.DS_Store
.DS_Store?
.build*
*.browserify.js.cached
*.browserify.js.map
.build*
versions.json
.versions
.npm
.build*
._*
.Trashes
Thumbs.db
ehthumbs.db
.eslintcache
.meteor/local
.devcontainer/docker-compose.extend.yml
.devcontainer/volumes*/
.git
+1 -1
View File
@@ -81,7 +81,7 @@ parts:
wekan:
source: .
plugin: nodejs
node-engine: 12.21.0
node-engine: 12.22.1
node-packages:
- node-gyp
- node-pre-gyp
+1 -1
View File
@@ -83,7 +83,7 @@ parts:
wekan:
source: .
plugin: nodejs
node-engine: 12.21.0
node-engine: 12.22.1
node-packages:
- node-gyp
- node-pre-gyp
+6
View File
@@ -1,5 +1,11 @@
## Issue
If you can not login for any reason:
- https://github.com/wekan/wekan/wiki/Forgot-Password
Email settings:
- https://github.com/wekan/wekan/wiki/Troubleshooting-Mail
Add these issues to elsewhere:
- SECURITY ISSUES: https://github.com/wekan/wekan/blob/master/SECURITY.md
- UCS: https://github.com/wekan/univention/issues
-12
View File
@@ -1,12 +0,0 @@
on: [push]
jobs:
zap_scan:
runs-on: ubuntu-latest
name: Scan the webapplication
steps:
- name: OWASP ZAP Scan
runs-on: ubuntu-latest
uses: zaproxy/action-baseline@v0.4.0
with:
target: 'https://boards.wekan.team/sign-in'
+1 -1
View File
@@ -31,5 +31,5 @@ Thumbs.db
ehthumbs.db
.eslintcache
.meteor/local
.meteor-1.6-snap/.meteor/local
.devcontainer/docker-compose.extend.yml
.devcontainer/volumes*/
+9 -9
View File
@@ -6,7 +6,7 @@
meteor-base@1.4.0
# Build system
ecmascript@0.15.0
ecmascript@0.15.1
standard-minifier-css@1.7.2
standard-minifier-js@2.6.0
mquandalle:jade
@@ -17,13 +17,13 @@ es5-shim@4.8.0
# Collections
aldeed:collection2
cfs:standard-packages
wekan-cfs-standard-packages
cottz:publish-relations
dburles:collection-helpers
idmontie:migrations
matb33:collection-hooks
matteodem:easy-search
mongo@1.10.1
mongo@1.11.0
mquandalle:collection-mutations
# Account system
@@ -52,6 +52,7 @@ mquandalle:autofocus
ongoworks:speakingurl
raix:handlebar-helpers
tap:i18n
http@1.4.2
# UI components
blaze
@@ -74,7 +75,7 @@ horka:swipebox
dynamic-import@0.6.0
accounts-password@1.7.0
cfs:gridfs
wekan-cfs-gridfs
rzymek:fullcalendar
momentjs:moment@2.22.2
browser-policy-framing@1.1.0
@@ -82,7 +83,6 @@ mquandalle:moment
msavin:usercache
# Keep stylus in 1.1.0, because building v2 takes extra 52 minutes.
coagmano:stylus@1.1.0!
lucasantoniassi:accounts-lockout
meteorhacks:subs-manager
meteorhacks:picker
lamhieu:unblock
@@ -90,9 +90,7 @@ meteorhacks:aggregate@1.3.0
wekan-markdown
konecty:mongo-counter
percolate:synced-cron
easylogic:summernote
cfs:filesystem
tmeasday:check-npm-versions
wekan-cfs-filesystem
steffo:meteor-accounts-saml
rajit:bootstrap3-datepicker-fi
rajit:bootstrap3-datepicker-ar
@@ -144,4 +142,6 @@ rajit:bootstrap3-datepicker-zh-cn
rajit:bootstrap3-datepicker-zh-tw
staringatlights:fast-render
spacebars
jkuester:http
easylogic:summernote
pascoual:pdfkit
wekan-accounts-lockout
+1 -1
View File
@@ -1 +1 @@
METEOR@2.1
METEOR@2.2
+52 -52
View File
@@ -1,7 +1,7 @@
3stack:presence@1.1.2
accounts-base@1.8.0
accounts-base@1.9.0
accounts-oauth@1.2.0
accounts-password@1.7.0
accounts-password@1.7.1
aldeed:collection2@2.10.0
aldeed:collection2-core@1.2.0
aldeed:schema-deny@1.1.0
@@ -11,36 +11,19 @@ allow-deny@1.1.0
arillo:flow-router-helpers@0.5.2
audit-argument-checks@1.0.7
autoupdate@1.7.0
babel-compiler@7.6.0
babel-compiler@7.6.1
babel-runtime@1.5.0
base64@1.0.12
binary-heap@1.0.11
blaze@2.3.4
blaze-tools@1.0.10
blaze@2.5.0
blaze-tools@1.1.2
boilerplate-generator@1.7.1
browser-policy-common@1.0.11
browser-policy-framing@1.1.0
caching-compiler@1.2.2
caching-html-compiler@1.1.3
caching-html-compiler@1.2.0
callback-hook@1.3.0
cfs:access-point@0.1.49
cfs:base-package@0.0.30
cfs:collection@0.5.5
cfs:collection-filters@0.2.4
cfs:data-man@0.0.6
cfs:file@0.1.17
cfs:filesystem@0.1.2
cfs:gridfs@0.0.34
cfs:http-methods@0.0.32
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.10
cfs:storage-adapter@0.2.4
cfs:tempstore@0.1.6
cfs:upload-http@0.0.20
cfs:worker@0.1.5
check@1.3.1
chuangbo:cookie@1.1.0
coagmano:stylus@1.1.0
@@ -49,18 +32,18 @@ coffeescript-compiler@2.4.1
cottz:publish-relations@2.0.8
dburles:collection-helpers@1.1.0
ddp@1.4.0
ddp-client@2.4.0
ddp-client@2.4.1
ddp-common@1.4.0
ddp-rate-limiter@1.0.9
ddp-server@2.3.2
ddp-server@2.3.3
deps@1.0.12
diff-sequence@1.1.1
dynamic-import@0.6.0
easylogic:summernote@0.8.8
ecmascript@0.15.0
ecmascript@0.15.1
ecmascript-runtime@0.7.0
ecmascript-runtime-client@0.11.0
ecmascript-runtime-server@0.10.0
ecmascript-runtime-client@0.11.1
ecmascript-runtime-server@0.10.1
ejson@1.1.1
email@2.0.0
es5-shim@4.8.0
@@ -70,13 +53,12 @@ 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.4.3
id-map@1.1.0
html-tools@1.1.2
htmljs@1.1.1
http@1.4.4
id-map@1.1.1
idmontie:migrations@1.0.3
inter-process-messaging@0.1.1
jkuester:http@2.0.1
jquery@1.11.11
kadira:blaze-layout@2.3.0
kadira:dochead@1.5.0
@@ -85,11 +67,10 @@ kenton:accounts-sandstorm@0.7.0
konecty:mongo-counter@0.0.5_3
lamhieu:meteorx@2.1.1
lamhieu:unblock@1.0.0
launch-screen@1.2.0
launch-screen@1.2.1
livedata@1.0.18
localstorage@1.2.0
logging@1.2.0
lucasantoniassi:accounts-lockout@1.0.0
matb33:collection-hooks@0.9.1
matteodem:easy-search@1.6.4
mdg:validation-error@0.5.1
@@ -101,19 +82,19 @@ meteorhacks:collection-utils@1.2.0
meteorhacks:picker@1.0.3
meteorhacks:subs-manager@1.6.4
meteorspark:util@0.2.0
minifier-css@1.5.3
minifier-css@1.5.4
minifier-js@2.6.0
minifiers@1.1.8-faster-rebuild.0
minimongo@1.6.1
minimongo@1.6.2
mobile-status-bar@1.1.0
modern-browsers@0.1.5
modules@0.16.0
modules-runtime@0.12.0
momentjs:moment@2.29.1
mongo@1.10.1
mongo@1.11.1
mongo-decimal@0.1.2
mongo-dev-server@1.1.0
mongo-id@1.0.7
mongo-id@1.0.8
mongo-livedata@1.0.12
mousetrap:mousetrap@1.4.6_1
mquandalle:autofocus@1.0.0
@@ -125,13 +106,14 @@ mquandalle:jquery-ui-drag-drop-sort@0.2.0
mquandalle:moment@1.0.1
mquandalle:mousetrap-bindglobal@0.0.1
msavin:usercache@1.8.0
npm-bcrypt@0.9.3
npm-mongo@3.8.1
npm-bcrypt@0.9.4
npm-mongo@3.9.0
oauth@1.3.2
oauth2@1.3.0
observe-sequence@1.0.16
ongoworks:speakingurl@1.1.0
ordered-dict@1.1.0
pascoual:pdfkit@1.0.7
peerlibrary:assert@0.3.0
peerlibrary:base-component@0.16.0
peerlibrary:blaze-components@0.15.1
@@ -192,7 +174,7 @@ rajit:bootstrap3-datepicker-zh-cn@1.7.1
rajit:bootstrap3-datepicker-zh-tw@1.7.1
random@1.2.0
rate-limit@1.0.9
react-fast-refresh@0.1.0
react-fast-refresh@0.1.1
reactive-dict@1.3.0
reactive-var@1.0.11
reload@1.3.1
@@ -209,10 +191,10 @@ 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.3.1
socket-stream-client@0.3.3
softwarerero:accounts-t9n@1.3.11
spacebars@1.0.15
spacebars-compiler@1.1.3
spacebars@1.2.0
spacebars-compiler@1.2.1
srp@1.1.0
standard-minifier-css@1.7.2
standard-minifier-js@2.6.0
@@ -221,24 +203,42 @@ staringatlights:inject-data@2.3.0
steffo:meteor-accounts-saml@0.0.18
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
tmeasday:check-npm-versions@0.3.2
templating@1.4.0
templating-compiler@1.4.1
templating-runtime@1.4.0
templating-tools@1.2.0
tracker@1.2.0
twbs:bootstrap@3.3.6
ui@1.0.13
underscore@1.0.10
url@1.3.1
url@1.3.2
useraccounts:core@1.14.2
useraccounts:flow-routing@1.14.2
useraccounts:unstyled@1.14.2
verron:autosize@3.0.8
webapp@1.10.0
webapp@1.10.1
webapp-hashing@1.1.0
wekan-accounts-cas@0.1.0
wekan-accounts-lockout@1.0.0
wekan-accounts-oidc@1.0.10
wekan-cfs-access-point@0.1.50
wekan-cfs-base-package@0.0.30
wekan-cfs-collection@0.5.5
wekan-cfs-collection-filters@0.2.4
wekan-cfs-data-man@0.0.6
wekan-cfs-file@0.1.17
wekan-cfs-filesystem@0.1.2
wekan-cfs-gridfs@0.0.34
wekan-cfs-http-methods@0.0.32
wekan-cfs-http-publish@0.0.13
wekan-cfs-power-queue@0.9.11
wekan-cfs-reactive-list@0.0.9
wekan-cfs-reactive-property@0.0.4
wekan-cfs-standard-packages@0.5.10
wekan-cfs-storage-adapter@0.2.4
wekan-cfs-tempstore@0.1.6
wekan-cfs-upload-http@0.0.21
wekan-cfs-worker@0.1.5
wekan-ldap@0.0.2
wekan-markdown@1.0.9
wekan-oidc@1.0.12
+1 -1
View File
@@ -3,7 +3,7 @@ sudo: required
env:
TRAVIS_DOCKER_COMPOSE_VERSION: 1.24.0
TRAVIS_NODE_VERSION: 12.21.0
TRAVIS_NODE_VERSION: 12.22.1
TRAVIS_NPM_VERSION: latest
before_install:
+1 -1
View File
@@ -39,7 +39,7 @@ host = https://www.transifex.com
# tap:i18n requires us to use `-` separator in the language identifiers whereas
# Transifex uses a `_` separator, without an option to customize it on one side
# or the other, so we need to do a Manual mapping.
lang_map = ar_EG:ar-EG, bg_BG:bg, en_GB:en-GB, es_AR:es-AR, es_CL:es-CL, es_PE:es-PE, es_MX:es-MX, es_TX:es-TX, es_PY:es-PY, el_GR:el, fa_IR:fa-IR, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, no:nb, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, sl_SI:sl, zh_CN:zh-CN, zh_TW:zh-TW, zh_HK:zh-HK
lang_map = ar_EG:ar-EG, bg_BG:bg, de_CH:de-CH, en_GB:en-GB, es_AR:es-AR, es_CL:es-CL, es_419:es-LA, es_PE:es-PE, es_MX:es-MX, es_TX:es-TX, es_PY:es-PY, el_GR:el, fa_IR:fa-IR, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, sl_SI:sl, zh_CN:zh-CN, zh_TW:zh-TW, zh_HK:zh-HK
[wekan.application]
file_filter = i18n/<lang>.i18n.json
+694
View File
@@ -1,3 +1,697 @@
[Mac ChangeLog](https://github.com/wekan/wekan/wiki/Mac)
# v5.35 2021-06-14 Wekan release
This release adds the following new features:
- Wait Spinners can now be translated
[Part 1](https://github.com/wekan/wekan/commit/8703dd42296d531450eb21a3d3adea17558a8500),
[Part 1](https://github.com/wekan/wekan/commit/7f3f0825573b1f8a7b0388e4bacbb0bd2525e886).
Added Wait Spinners docs: https://github.com/wekan/wekan/wiki/Wait-Spinners .
Thanks to xet7.
- Maximize Card.
[Part 1](https://github.com/wekan/wekan/commit/8c572502436a2eb22bd1eb1e4069c1c9145e2070),
[Part 2](https://github.com/wekan/wekan/pull/3863).
Thanks to mfilser and xet7.
- Export Card to PDF. In Progress, does not work yet.
[Part 1](https://github.com/wekan/wekan/commit/a2f2ce11354a8dbfdd6759e3b65797e4be4cc6ec),
[Part 2](https://github.com/wekan/wekan/commit/17acf1884850d8d95ae79493289adf18966df652).
Thanks to xet7.
and removes some not needed files:
- [Reduced Wekan bundle size from 636 MB to 467 MB by deleting all dependencies of lucasantoniassi:accounts-lockout and including
only required 10 files](https://github.com/wekan/wekan/commit/23e5e1e3bd081699ce39ce5887db7e612616014d).
Wekan Docker image size changed from 269.6 MB to 165.1 MB.
Thanks to xet7.
and adds the following improvements:
- [Add border and update label colors for better visibility](https://github.com/wekan/wekan/commit/2e1eb1e224c83f16a384316626d7a4183639d4cd).
Thanks to xet7.
and adds the following updates:
- [Updated dependencies](https://github.com/wekan/wekan/commit/f80fcfd7c0a83f4181c7a0b8beb52da9ba1446d3).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Manual sort number 0 accepted](https://github.com/wekan/wekan/pull/3861).
Thanks to mfilser.
- Allow board members to use more of API. Please add issue (or pull request) if this allows too much.
[Part 1](https://github.com/wekan/wekan/commit/a719e8fda1f78bcbf9af6e7b4341f8be1d141e90),
[Part 2](https://github.com/wekan/wekan/commit/164b6e9070199dca36d12fa3048d6b22bf6850b0).
Thanks to JayVii and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.34 2021-06-11 Wekan release
This release adds the following new features:
- [View and change card sort number](https://github.com/wekan/wekan/pull/3857).
Thanks to mfilser.
- [More spinners + configureable in admin panel](https://github.com/wekan/wekan/pull/3858).
Thanks to mfilser.
- [Added remaining spinner settings](https://github.com/wekan/wekan/commit/488b765f95ad67b19630cd125543836c04eaa24f).
Thanks to xet7.
and adds the following new improvements:
- [Card Description has now the same color on view and editing](https://github.com/wekan/wekan/pull/3851).
Thanks to mfilser.
- [Development in docker container](https://github.com/wekan/wekan/pull/3852).
Thanks to mfilser.
and fixes the following bugs:
- [Fix Google SSO to access Wekan has not been working by reverting Wekan v5.31 not-working fixes
to OAUTH2_LOGIN_STYLE=redirect Has No Effect](https://github.com/wekan/wekan/commit/1e837dec11dc5cb266b83efcff4f462aa02d733d).
Thanks to unpokitodxfavor and xet7.
- [CustomFields were not created after adding 1 card](https://github.com/wekan/wekan/pull/3856).
Thanks to mfilser.
- [Try to fix BUG: Database error attempting to change a account](https://github.com/wekan/wekan/commit/762391965e6ae3cd5682d5b164131500e7d92338).
Thanks to bbyszio and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.33 2021-06-10 Wekan release
This release adds the following new features:
- [Assigning a user to a team or an organization](https://github.com/wekan/wekan/pull/3850).
Thanks to Emile840.
and adds the following new improvements:
- [Custom Fields stringtemplate, autofocus the last input box](https://github.com/wekan/wekan/pull/3849).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.32 2021-06-09 Wekan release
This release adds the following new features:
- [Moved many button texts etc to tooltips. Added more tooltips](https://github.com/wekan/wekan/commit/6ce5ab40a7dc013247717b5107a306eb0402cd63).
Thanks to JFa-Orkis and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.31 2021-06-09 Wekan release
This release adds the following new features:
- [Admin Panel: Edit Organizations and Teams](https://github.com/wekan/wekan/issues/802).
Thanks to Emile840.
- [Admin Panel: Delete Organizations and Teams](https://github.com/wekan/wekan/commit/14b2c1309f0f910c1e46b5681d3612d7ff0cbf81).
Thanks to xet7.
- [Admin Panel Organizations/Teams: Show confirm text above delete button](https://github.com/wekan/wekan/commit/16379201704ea1a43ce14859633ffb1b9fae6710).
Thanks to xet7.
- [Gantt: Retain links created between tasks. Part 1: Database changes, not active in
MIT Wekan](https://github.com/wekan/wekan/commit/07a3a0b3882147effac890514b19ff84f1d76bdb).
Thanks to benjaminhrivera.
and adds the following updates:
- [Removed extra package](https://github.com/wekan/wekan/commit/646497c3f041e2f562d032fe28ef29169f671ac1).
Thanks to xet7.
- [Updated dependencies](https://github.com/wekan/wekan/commit/122757ca9c091e98b31d34c3abc25caa295dbdc0).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Now new boards do not have any labels added by default](https://github.com/wekan/wekan/commit/481404e8d7bad7799c2ad34d6a94eaf5e87602c2).
Thanks to tedkoch and xet7.
- [Try to fix OAUTH2_LOGIN_STYLE=redirect Has No Effect](https://github.com/wekan/wekan/commit/78324263c1c78e7e9e99f153e3158e39f564b67a).
Thanks to 1ubuntuuser and xet7.
- [Try to fix: Wekan UI fails to finish import of closed Trello boards](https://github.com/wekan/wekan/commit/007e0f1c16c935ce580093a6aec31305c75d1e45).
Thanks to berezovskyi and xet7.
- [Partial Fix: Vote and Planning Poker: Setting date and time now works for some languages that have
ascii characters in date format](https://github.com/wekan/wekan/commit/57f31d443faaa32d6c7b53d81af3be133af5f040).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.30 2021-06-03 Wekan release
This release adds the following new features:
- [Planning Poker / Scrum Poker](https://github.com/wekan/wekan/pull/3836),
see https://github.com/wekan/wekan/wiki/Planning-Poker .
Thanks to helioguardabaxo.
and fixes the following bugs:
- [Fixed Python API example: Edit card, etc](https://github.com/wekan/wekan/commit/bf62a947fbfa7d387074550288376e682fd6ad47).
Thanks to Lucky-Shi and xet7.
- [Default language is still used although this one has been modified previously](https://github.com/wekan/wekan/pull/3833).
Thanks to Emile840.
- [Moved Keyboard Shortcuts from bottom to top of Sidebar](https://github.com/wekan/wekan/commit/659a65b8b919a49ba0beef5cc53d8e61e0f794aa).
Thanks to ClaudiaK21 and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.29 2021-05-29 Wekan release
This release adds the following new features:
- [Excel parent card name export](https://github.com/wekan/wekan/pull/3799).
Thanks to marcungeschikts and Enishowk.
and adds the following updates:
- Updated dependencies
[Part 1](https://github.com/wekan/wekan/commit/62150ce6c406359fba068552b4526c60faf392bb),
[Part 2](https://github.com/wekan/wekan/commit/1d9346513e4f378379b9f5192e8dad5535287f8a),
[Part 3](https://github.com/wekan/wekan/commit/6be1a330936c89fcf478efe98dd15244a98d266d).
Thanks to developers of dependencies.
- Added updated `Forgot Password` page to GitHub issue template
[Part 1](https://github.com/wekan/wekan/commit/6d0578fd5ad5f13f5ff9a285577e35fd62bba95f),
[Part 2](https://github.com/wekan/wekan/commit/ea64b17b82cd52320c0495e16385f11031dfbe3a).
Thanks to xet7.
and fixes the following bugs:
- [Try to fix Snap: Removed linting packages](https://github.com/wekan/wekan/commit/8911fe5c8de941808585a7d3462305d5b3d2763d).
Thanks to xet7.
- [Removed not working GitHub workflow](https://github.com/wekan/wekan/commit/5dd6466c0aa7479015c72519f36c2485b16e3341).
Thanks to xet7.
- [Fix typos](https://github.com/wekan/wekan/pull/3813).
Thanks to spasche.
- [Fix: Impersonate user can now export Excel/CSV/TSV/JSON.
Impersonate user and export Excel/CSV/TSV/JSON is now logged into database table
impersonatedUsers](https://github.com/wekan/wekan/commit/3908cd5413b775d1ee549f0a95304cf9998d3855).
Thanks to xet7.
- [Fixed Importing JSON exports fails](https://github.com/wekan/wekan/commit/bd1de94312e428e56d6cf5f343098475573cba0b).
Thanks to KeptnArgo and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.28 2021-05-07 Wekan release
This release adds the following new features:
- [Mermaid Diagram](https://github.com/wekan/wekan/wiki/Mermaid-Diagram).
Thanks to xuguotong and xet7.
and adds the following updates:
- Updated dependencies
[Part 1](https://github.com/wekan/wekan/commit/521ef8b6dad4f00662f22702331193c16b91b482),
[Part 2](https://github.com/wekan/wekan/commit/48255f6f1e4a0caf0be006196f28295d0825eb95),
[Part 3](https://github.com/wekan/wekan/commit/a550c255e6c3bd2d609a1a45a213cdae7ab4f74d).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Fix: BG color of StartDate](https://github.com/wekan/wekan/pull/3793).
Thanks to listenerri.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.27 2021-04-29 Wekan release
This release fixes the following bugs:
- [Fixed Non-ASCII attachment filename will crash when downloading](https://github.com/wekan/wekan/commit/c2da47773552a61d45b010a095f73d2e441f687c).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.26 2021-04-28 Wekan release
This release adds the following new features:
- [Feature/mini card subtask count](https://github.com/wekan/wekan/pull/3765).
Thanks to ryanMushy.
and fixes the following bugs:
- [Bring back Almost-Due for Start Date](https://github.com/wekan/wekan/commit/8ca1b25daf3be60c2dc64f03830dea8437bbd8ad).
Thanks to darren-teo.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.25 2021-04-27 Wekan release
This release adds the following new features:
- [Swimlane in Export to Excel](https://github.com/wekan/wekan/pull/3764).
Thanks to Keelan and ryanMushy.
and adds the following updates:
- [Updated release scripts](https://github.com/wekan/wekan/commit/9f0f6841b01b88f5559724b047d5e245617a02c8).
Thanks to xet7.
and fixes the following bugs:
- [Added missing PostgreSQL password to ToroDB](https://github.com/wekan/wekan/commit/995de525d96946702536f0cdcb98ef281b9df94e).
Thanks to xet7.
- [Fixed language name of Deutsch (Schweiz)](https://github.com/wekan/wekan/commit/621c701bef1d09d4ddfc93be411cfad98869f0ae).
Thanks to urmel1960.
- [Bugfix/Summernote on paste](https://github.com/wekan/wekan/pull/3761).
Thanks to ryanMushy.
- [OpenAPI: Better handle nested schemas](https://github.com/wekan/wekan/pull/3762).
Thanks to bentiss.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.24 2021-04-24 Wekan release
This release adds the following new features:
- [Copy Swimlane](https://github.com/wekan/wekan/pull/3753).
Thanks to jrsupplee.
and adds the following updates:
- [Updated dependencies](https://github.com/wekan/wekan/commit/e738177e081e4a7e83fed3389f47847403551fc2).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Fix Snap: Delete extra symlink that prevented building Snap](https://github.com/wekan/wekan/commit/45124a39f34a918b251a4a36fb016639b558f119).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.23 2021-04-22 Wekan release
This release adds the following new features:
- [Filtering by due date](https://github.com/wekan/wekan/pull/3731).
Thanks to mcrute.
and adds the following updates:
- [Updated dependencies](https://github.com/wekan/wekan/commit/676bf686c7a121b0da744afce5911807a6be48fe).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Fix: Trello data without labels definition](https://github.com/wekan/wekan/pull/3733).
Thanks to jrsupplee.
- [Bug fix for Due Cards](https://github.com/wekan/wekan/pull/3741).
Thanks to jrsupplee.
- [Fix: The bg color of start at button is almost-due](https://github.com/wekan/wekan/pull/3749).
Thanks to listenerri.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.22 2021-04-16 Wekan release
This release adds the following new translations:
- Added German (Switzerland) (de_CH) (Schwiizerdütsch). Updated translations.
[Part 1](https://github.com/wekan/wekan/commit/09506c78f3c3439db622574eb851fa0c20d3a066),
[Part 2](https://github.com/wekan/wekan/commit/dce99c00be80cceba686fd73b4b78b6c778d78a6),
[Part 3](https://github.com/wekan/wekan/commit/6ff9c5b58d25ba52b11e5429c9cfe6ed6a97000e).
Thanks to translators.
and fixes the following bugs:
- [Remove allowedValues from Cards.type schema](https://github.com/wekan/wekan/pull/3724).
Thanks to jrsupplee.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.21 2021-04-16 Wekan release
This release adds the following new features:
- [Summernote Rich Text Editor](https://github.com/wekan/wekan/pull/3720):
1) Add new button to insert a URL link.
2) Add new popover allowing you to edit existing URL links.
3) Enable spell check.
4) Allow client side grammerly extension.
Thanks to ryanMushy.
and adds the following updates:
- [Upgraded to Meteor 2.2](https://github.com/wekan/wekan/commit/0e7c2b4b94b1c48e8839cfba635b53cdc1a797b1).
Thanks to Meteor developers.
and fixes the following bugs:
- [Bugfix, date format not changed to local format](https://github.com/wekan/wekan/pull/3723).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.20 2021-04-14 Wekan release
This release fixes the following bugs:
- [OpenAPI: rework the allowedValues to allow for imported variables](https://github.com/wekan/wekan/pull/3715).
Thanks to bentiss.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.19 2021-04-14 Wekan release
This release adds the following new features:
- [Custom Field "String Template"](https://github.com/wekan/wekan/pull/3701).
Thanks to tod31.
- [1) Admin reports. An option added to the admin panel that has reports an admin can run.
Right now it has two reports for attachments and broken cards.
2) Add the creator avatar to `cardDetails` and `minicard`. Avatar is only shown if it is selected in card settings.
3) Added a new search operator `creator`.
4) Bug fix for multiple label predicates](https://github.com/wekan/wekan/pull/3705).
Thanks to jrsupplee.
- [Update Admin Panel Rules report icon and add missing translations](https://github.com/wekan/wekan/commit/8417fae89cc89adb4559874050ff7c56cc08eb00).
Thanks to xet7.
and adds the following updates:
- [Upgraded to Meteor 2.1.1 an updated dependencies](https://github.com/wekan/wekan/commit/bb8c4325c60582cdcda5d406071586f18681e737).
Thanks to developers of dependencies.
- [Updated to Node.js v12.22.1](https://github.com/wekan/wekan/commit/2201372744639ade3ba74b6ff9115988f011b9ac).
Thanks to Node.js developers.
- [Updated release scripts](https://github.com/wekan/wekan/commit/9871bf196352edcb5475e1b0ee4983e8f312e449).
Thanks to xet7.
- [Updated caniuse-lite etc dependencies](https://github.com/wekan/wekan/commit/0857a2ea91f672201ba96f2ba635165784b30fd8).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Revert stable tag, because it did break Wekan version numbers](https://github.com/wekan/wekan/commit/5ca90f4d2245910580cb0af885fac17dcec44ef0).
Thanks to xet7.
- [Updating ARM Dockerfile](https://github.com/wekan/wekan/pull/3692).
Thanks to loganballard.
- [Added latest arm64 bundle symlink](https://github.com/wekan/wekan/commit/6fe3edebb18414ebe7e69b2de3269438662b6163).
Thanks to xet7.
- [Bug fix: Rules for moving from list/swimlane](https://github.com/wekan/wekan/pull/3706).
Thanks to jrsupplee.
- [Fixed Elements are duplicated on the view "My cards".
Rewrite routine for building the My Cards hierarchical list.
Use a separate publication for retrieving My Cards.
Fixed bug with limit and skip projection](https://github.com/wekan/wekan/pull/3708).
Thanks to jrsupplee.
- [Popover needs to be destroyed anytime the details panel is closed](https://github.com/wekan/wekan/pull/3712).
Thanks to ryanMushy.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.18 2021-04-14 Wekan release
Not released version, because some version numbers not changed in all release files.
# v5.17 2021-04-01 Wekan release
This release fixes the following bugs:
- [Fix Link dialog closes card when clicking in dialog](https://github.com/wekan/wekan/commit/454d3b5bbeed6cef8ecface7e6094cabfcc4847c).
Thanks to ryanMushy.
and adds the following updates:
- [Added stable tag release script](https://github.com/wekan/wekan/commit/8dfb6916c5180f5d074748840d51dd04f9adb2bb).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.16 2021-04-01 Wekan release
This release adds the following new features:
- [Added stable tag](https://github.com/wekan/wekan/commit/c40668be3fb9c35d44698f49ab06fec5bcabbe1b).
Thanks to rynr and xet7.
- [Added back Summernote editor. Removed emoji picker](https://github.com/wekan/wekan/commit/47ecc654b825a875074dfd4826c36e2c5c55f599).
Thanks to ryanMushy and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.15 2021-03-31 Wekan release
This release fixes the following bugs:
- [Fixed card sort reset](https://github.com/wekan/wekan/pull/3686).
Thanks to ednamaeG.
- [Fix bug in My Cards and Global Search](https://github.com/wekan/wekan/pull/3687).
Thanks to jrsupplee.
- [Fix bug in Due Cards introduced by last bug fix](https://github.com/wekan/wekan/pull/3688).
Thanks to jrsupplee.
- [Fixed Bug: Move Swimlane to Archive does not work anymore. Fixed lint in
router.js](https://github.com/wekan/wekan/commit/0b263cf582a9649ef72efbd289927105a27583af).
Thanks to marcungeschikts and xet7.
and adds the following updates:
- Updated sandstorm release script and added new node update script
[Part 1](https://github.com/wekan/wekan/commit/34b6aa0858678da937eacf9a87878bbcb476fd4b),
[Part 2](https://github.com/wekan/wekan/commit/01de3f187c90af3ac94215ba7e8c7e780c98768d),
[Part 3](https://github.com/wekan/wekan/commit/1d3673e9d320926127b46383321023f149287d6d),
[Part 4](https://github.com/wekan/wekan/commit/09b9f690b162ae2797d1996e82c96ed8b8c74221),
[Part 5](https://github.com/wekan/wekan/commit/6819303047eab17b03a0c28108fd9a2cfde23d20).
Thanks to xet7.
- Updated to Node.js v12.22.0
[Part 1](https://github.com/wekan/wekan/commit/7a9c3972642601e9d89d5e7a3816643f91448c63),
[Part 2](https://github.com/wekan/wekan/commit/c2b7525864048694c39f9cbe8f8c4cd96e36f7aa).
Thanks to Node.js developers.
- Fixed release website script
[Part 1](https://github.com/wekan/wekan/commit/b6f60c08e55c2620fe6724ae2b5da0d9dfc9ec31),
[Part 2](https://github.com/wekan/wekan/commit/91dae9795ebd1a98b8ed12c68b78ad90a6983402).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.14 2021-03-29 Wekan release
This release adds the following new features:
- [Clean-up Global Search, Due Cards, and My Cards. New environment variable `RESULTS_PER_PAGE` for search
results](https://github.com/wekan/wekan/pull/3676).
Thanks to jrsupplee.
- [Added environment variable `RESULTS_PER_PAGE` to all Wekan platforms](https://github.com/wekan/wekan/commit/ba05f383ca29211c5474e06c5ba6673e712afe7a).
Thanks to xet7.
and adds the following updates:
- [Updated release scripts](https://github.com/wekan/wekan/commit/59580e4b0f711ca55e8cb0d73803a4ff8b56352d).
Thanks to xet7.
and fixes the following bugs:
- [Require signed-in user for My Cards, Due Cards, and global search](https://github.com/wekan/wekan/pull/3677).
Thanks to jrsupplee.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.13 2021-03-28 Wekan release
This release fixes the following bugs:
- [Fixed Sandstorm Wekan attachments upload](https://github.com/wekan/wekan/commit/d4a1611b86521cd5913277cfa2c86c43958eec7b).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.12 2021-03-28 Wekan release
This release fixes the following bugs:
- [Fix HTTP not defined](https://github.com/wekan/wekan/commit/4c609161915cc46ebfccad3d9e7ffdecdef1f85c).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.11 2021-03-28 Wekan release
This release adds the following new features:
- [Added emoji picker to card description edit and card comment edit.
Removed and disabled Summernote wysiwyg editor, package-lock.json
etc](https://github.com/wekan/wekan/commit/84fde1ecfc81e89ed1895cab3bcb328e4f166a87).
Thanks to xet7.
and adds the following updates:
- [Updated dependencies. Fixed lint](https://github.com/wekan/wekan/commit/4e1c0fdce82e3b4add8c4ffd1832752181573e88).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.10 2021-03-28 Wekan release
This release adds the following new features:
- [Move swimlane from one board to another](https://github.com/wekan/wekan/pull/3674).
Thanks to jrsupplee.
- [Added translatable Move Swimlane popup title](https://github.com/wekan/wekan/commit/16665bccf912c5e907739c35f7ef5a376c81740e).
Thanks to xet7.
- [REST API: Export one attachment](https://github.com/wekan/wekan/pull/3673).
Thanks to vagnernascimento.
and adds the following updates:
- [Updated package-lock.json](https://github.com/wekan/wekan/commit/3145ec65a3defb8ac8d97aed7e43595f661f7100).
Thanks to developers of dependencies.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.09 2021-03-26 Wekan release
This release adds the following improvements:
- [Replace edit icon by plus-square on new links](https://github.com/wekan/wekan/pull/3671).
Thanks to sim51.
and fixes the following bugs:
- [Fix openapi docs generation](https://github.com/wekan/wekan/pull/3672).
Thanks to bentiss.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.08 2021-03-26 Wekan release
This release adds the following new features:
- [Admin Panel/Settings/Accounts: Hide system messages of all users](https://github.com/wekan/wekan/commit/a249ffc8054189d8e3db9b4c8f082cc7ce7dcb52).
Thanks to bbyszio, r4nc0r and xet7.
and adds the following improvements:
- [Add Trello attached links to the card description](https://github.com/wekan/wekan/pull/3669).
Thanks to jrsupplee.
- [Added package-lock.json and updated .gitignore](https://github.com/wekan/wekan/commit/d532a3591f338cec9a3839d43d9a1e9d69f59dc2).
Thanks to xet7.
and adds the following new translations:
- [Added translation: español de América Latina](https://github.com/wekan/wekan/commit/ccc9efb2703efda4e199a861920b9ec88e634b59).
Thanks to translators.
and fixes the following bugs:
- [Fix typos in translations](https://github.com/wekan/wekan/commit/a0e1b6f918dbb252a13db05d6b9e1f832c28654f).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.07 2021-03-19 Wekan release
This release fixes the following bugs:
- [Fixed sort cards feature](https://github.com/wekan/wekan/pull/3662).
Thanks to ednamaeG.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.06 2021-03-18 Wekan release
This release fixes the following bugs:
- [Fixed Bug: Calendar & parent cards URLs used absolute URLs](https://github.com/wekan/wekan/pull/3648).
Thanks to Majed6.
- [Fixed Bug: copy to clipboard uses pathname](https://github.com/wekan/wekan/pull/3661).
Thanks to Majed6.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.05 2021-03-11 Wekan release
This release fixes the following bugs:
- [Change URL scheme recognition for allowing abasurl to link](https://github.com/wekan/wekan/pull/3641).
Thanks to tod31 and chrisi51.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.04 2021-03-07 Wekan release
This release adds the following speed improvements:
- [Speed improvement: Delete presences older than one week, and add database index to presences
serverId](https://github.com/wekan/wekan/commit/9db3c931161adfbeb6fc52d3e4cf621fb9a4955f).
Thanks to xet7.
and adds the following new features:
- [Added autolinking settings in Admin Panel](https://github.com/wekan/wekan/pull/3633).
Thanks to chrisi51.
- [Add custom field editing to the REST API](https://github.com/wekan/wekan/pull/3593).
Thanks to dudeofawesome.
- [Related to custom field editing, Fixed generating API docs and Wekan Custom Fields
REST API](https://github.com/wekan/wekan/commit/0bb3b670753c6ba20b0ad63f63d273036f609ee5).
Thanks to xet7.
and adds back the following platforms:
- [OpenPower Minicloud emergency maintenance has finished, so can now build Wekan for
ppc64le](https://github.com/wekan/wekan/commit/ac9b23f00f10b0170b8693e1e997bfb54f807adc).
Thanks to OpenPower Minicloud.
and fixes the following bugs:
- [Try to fix Snap: Removed fibers multi arch from Snap, because Snap build servers do not build correctly with
it](https://github.com/wekan/wekan/commit/a44ca39eb84508441f0f8bdac852745f417f12e7).
Thanks to xet7.
- [Fix search on labels server error](https://github.com/wekan/wekan/pull/3634).
Thanks to jrsupplee.
- [Fixed Bug: inconsistent use of relative/absolute URLs](https://github.com/wekan/wekan/pull/3635).
Thanks to Majed6.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.03 2021-03-03 Wekan release
This release adds the following changes:
- [Hide email settings from Sandstorm Wekan Admin Panel](https://github.com/wekan/wekan/commit/626f435edf75fac68448ba2e14c62acb749f9c9b).
Thanks to ocdtrekkie and xet7.
and fixes the following bugs:
- [Revert Removed extra imports of Meteor. Hopefully fixes email notifications and rules
on old cars not working](https://github.com/wekan/wekan/commit/e4a9dc25ecc230829afea07dbb3915b96115f7f7).
Thanks to xet7.
- [Fixed Bug: Link at board title can not be edited](https://github.com/wekan/wekan/commit/7d3917adb79be09356d32612585029392bac1e49).
Thanks to jonesrussell42, aiac, bbyszio and xet7.
Thanks to above GitHub and Wekan vanila.io community users for their contributions and translators for their translations.
# v5.02 2021-03-02 Wekan release
This release adds the following improvements:
- [Added sort to edit card REST API](https://github.com/wekan/wekan/pull/3618).
Thanks to ChrisMagnuson.
- [Add attachmentId to the Webhook data](https://github.com/wekan/wekan/pull/3620).
Thanks to n8ores.
and fixes the following bugs:
- [Fix SMTP port lost after upgrade. STMP settings are made only with environment variables on non-Sandstorm platforms.
Note: Sending email on Sandstorm Wekan does not work yet](https://github.com/wekan/wekan/commit/65b8220fe53349695a335bdb8b9692f82d4b3329).
Thanks to jrsupplee and xet7.
- [Removed extra imports of Meteor](https://github.com/wekan/wekan/commit/de13b8b9bafbfb186a037ae20e845846b296ac69).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.01 2021-02-26 Wekan release
This release fixes the following bugs:
- [Fix typo in activities code. Fixes can not edit Custom Field](https://github.com/wekan/wekan/pull/3610).
Thanks to n8ores.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.00 2021-02-25 Wekan release
This release fixes the following bugs:
- [Fixed Unable to remove old Board, reappears](https://github.com/wekan/wekan/commit/332f830cc2e44ab66ca891690b09a425b9fd7e68).
Thanks to chirrut2, uusijani, cimm, anicolaides, Philipoo0 and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v4.99 2021-02-25 Wekan release
This release fixes the following CRITICAL SECURITY ISSUES:
+4 -2
View File
@@ -12,7 +12,7 @@ ARG DEBIAN_FRONTEND=noninteractive
ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-essential git ca-certificates python3" \
DEBUG=false \
NODE_VERSION=v12.21.0 \
NODE_VERSION=v12.22.1 \
METEOR_RELEASE=1.10.2 \
USE_EDGE=false \
METEOR_EDGE=1.5-beta.17 \
@@ -21,6 +21,7 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
ARCHITECTURE=linux-x64 \
SRC_PATH=./ \
WITH_API=true \
RESULTS_PER_PAGE="" \
ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE=3 \
ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD=60 \
ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW=15 \
@@ -136,7 +137,8 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
SAML_IDENTIFIER_FORMAT="" \
SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
SAML_ATTRIBUTES="" \
ORACLE_OIM_ENABLED=false
ORACLE_OIM_ENABLED=false \
WAIT_SPINNER=""
# Copy the app to the image
COPY ${SRC_PATH} /home/wekan/app
+9 -9
View File
@@ -4,16 +4,16 @@ FROM amd64/alpine:3.7 AS builder
ENV QEMU_VERSION=v4.2.0-6 \
QEMU_ARCHITECTURE=aarch64 \
NODE_ARCHITECTURE=linux-arm64 \
NODE_VERSION=v12.21.0 \
WEKAN_VERSION=3.96 \
NODE_VERSION=v12.22.1 \
WEKAN_VERSION=latest \
WEKAN_ARCHITECTURE=arm64
# Install dependencies
RUN apk update && apk add ca-certificates outils-sha1 && \
\
# Download qemu static for our architecture
wget https://github.com/multiarch/qemu-user-static/releases/download/${QEMU_VERSION}/qemu-${QEMU_ARCHITECTURE}-static.tar.gz -O - | tar -xz && \
\
# Install dependencies
RUN apk update && apk add ca-certificates outils-sha1 && \
\
# Download qemu static for our architecture
wget https://github.com/multiarch/qemu-user-static/releases/download/${QEMU_VERSION}/qemu-${QEMU_ARCHITECTURE}-static.tar.gz -O - | tar -xz && \
\
# Download wekan and shasum
wget https://releases.wekan.team/raspi3/wekan-${WEKAN_VERSION}-${WEKAN_ARCHITECTURE}.zip && \
wget https://releases.wekan.team/raspi3/SHA256SUMS.txt && \
@@ -40,7 +40,7 @@ LABEL maintainer="wekan"
# Set the environment variables (defaults where required)
ENV QEMU_ARCHITECTURE=aarch64 \
NODE_ARCHITECTURE=linux-arm64 \
NODE_VERSION=v12.21.0 \
NODE_VERSION=v12.22.1 \
NODE_ENV=production \
NPM_VERSION=latest \
WITH_API=true \
+4 -4
View File
@@ -1,4 +1,4 @@
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/wekan/wekan)
[![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/wekan/wekan)
# Wekan - Open Source kanban
@@ -32,7 +32,7 @@ It's better than at chat where details get lost when chat scrolls up.
## FAQ
**NOTE**:
**NOTE**:
- Please read the [FAQ](https://github.com/wekan/wekan/wiki/FAQ) first
- Please don't feed the [trolls](https://github.com/wekan/wekan/wiki/FAQ#why-am-i-called-a-troll) and [spammers](https://github.com/wekan/wekan/wiki/FAQ#why-am-i-called-a-spammer) that are mentioned in the FAQ :)
@@ -52,7 +52,7 @@ that by providing one-click installation on various platforms.
- Wekan is used in [most countries of the world](https://snapcraft.io/wekan).
- Wekan largest user has 13k users using Wekan in their company.
- Wekan has been [translated](https://transifex.com/wekan/wekan) to about 61 languages.
- Wekan has been [translated](https://transifex.com/wekan/wekan) to about 63 languages.
- [Features][features]: Wekan has real-time user interface.
- [Platforms][platforms]: Wekan supports many platforms.
Wekan is critical part of new platforms Wekan is currently being integrated to.
@@ -64,7 +64,7 @@ that by providing one-click installation on various platforms.
[More Platforms](https://github.com/wekan/wekan/wiki/Platforms), bundle for RasPi3 ARM and other CPUs where Node.js and MongoDB exists.
- 1 GB RAM minimum free for Wekan. Production server should have minimum total 4 GB RAM.
For thousands of users, for example with [Docker](https://github.com/wekan/wekan/blob/master/docker-compose.yml): 3 frontend servers,
each having 2 CPU and 2 wekan-app containers. One backend wekan-db server with many CPUs.
each having 2 CPU and 2 wekan-app containers. One backend wekan-db server with many CPUs.
- Enough disk space and alerts about low disk space. If you run out disk space, MongoDB database gets corrupted.
- SECURITY: Updating to newest Wekan version very often. Please check you do not have automatic updates of Sandstorm or Snap turned off.
Old versions have security issues because of old versions Node.js etc. Only newest Wekan is supported.
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v4.99.0"
appVersion: "v5.35.0"
files:
userUploads:
- README.md
+48 -8
View File
@@ -28,12 +28,16 @@ if arguments == 0:
print(" python3 api.py board BOARDID # Info of BOARDID")
print(" python3 api.py swimlanes BOARDID # Swimlanes of BOARDID")
print(" python3 api.py lists BOARDID # Lists of BOARDID")
print(" python3 api.py list BOARDID LISTID # Info of LISTID")
print(" python3 api.py createlist BOARDID LISTTITLE # Create list")
print(" python3 api.py addcard AUTHORID BOARDID SWIMLANEID LISTID CARDTITLE CARDDESCRIPTION")
print(" python3 api.py editcard BOARDID LISTID CARDID NEWCARDTITLE NEWCARDDESCRIPTION")
print(" python3 api.py listattachments BOARDID # List attachments")
# TODO:
# print(" python3 api.py attachmentdownload BOARDID ATTACHMENTID # One attachment as file")
# print(" python3 api.py attachmentsdownload BOARDID # All attachments as files")
# print(" python3 api.py attachmentjson BOARDID ATTACHMENTID # One attachment as JSON base64")
# print(" python3 api.py attachmentbinary BOARDID ATTACHMENTID # One attachment as binary file")
# print(" python3 api.py attachmentdownload BOARDID ATTACHMENTID # One attachment as file")
# print(" python3 api.py attachmentsdownload BOARDID # All attachments as files")
exit
# ------- SETTINGS START -------------
@@ -61,13 +65,15 @@ chmod +x api.py
=== Wekan API Python CLI: Shows IDs for addcard ===
AUTHORID is USERID that writes card.
Syntax:
python3 api.py users # All users
python3 api.py boards USERID # Boards of USERID
python3 api.py board BOARDID # Info of BOARDID
python3 api.py swimlanes BOARDID # Swimlanes of BOARDID
python3 api.py lists BOARDID # Lists of BOARDID
python3 api.py users # All users
python3 api.py boards USERID # Boards of USERID
python3 api.py board BOARDID # Info of BOARDID
python3 api.py swimlanes BOARDID # Swimlanes of BOARDID
python3 api.py lists BOARDID # Lists of BOARDID
python3 api.py list BOARDID LISTID # Info of LISTID
python3 api.py createlist BOARDID LISTTITLE # Create list
python3 api.py addcard AUTHORID BOARDID SWIMLANEID LISTID CARDTITLE CARDDESCRIPTION
python3 api.py editcard BOARDID LISTID CARDID NEWCARDTITLE NEWCARDDESCRIPTION
python3 api.py listattachments BOARDID # List attachments
python3 api.py attachmentjson BOARDID ATTACHMENTID # One attachment as JSON base64
python3 api.py attachmentbinary BOARDID ATTACHMENTID # One attachment as binary file
@@ -162,6 +168,27 @@ if arguments == 7:
print(body.text)
# ------- WRITE TO CARD END -----------
if arguments == 6:
if sys.argv[1] == 'editcard':
# ------- LIST OF BOARD START -----------
boardid = sys.argv[2]
listid = sys.argv[3]
cardid = sys.argv[4]
newcardtitle = sys.argv[5]
newcarddescription = sys.argv[6]
edcard = wekanurl + apiboards + boardid + s + l + s + listid + s + cs + s + cardid
print(edcard)
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
put_data = {'title': '{}'.format(newcardtitle), 'description': '{}'.format(newcarddescription)}
body = requests.put(edcard, data=put_data, headers=headers)
print("=== EDIT CARD ===\n")
body = requests.get(edcard, headers=headers)
data2 = body.text.replace('}',"}\n")
print(data2)
# ------- LISTS OF BOARD END -----------
if arguments == 3:
if sys.argv[1] == 'createlist':
@@ -177,6 +204,19 @@ if arguments == 3:
print(body.text)
# ------- CREATE LIST END -----------
if sys.argv[1] == 'list':
# ------- LIST OF BOARD START -----------
boardid = sys.argv[2]
listid = sys.argv[3]
listone = wekanurl + apiboards + boardid + s + l + s + listid
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
print("=== INFO OF ONE LIST ===\n")
body = requests.get(listone, headers=headers)
data2 = body.text.replace('}',"}\n")
print(data2)
# ------- LISTS OF BOARD END -----------
if arguments == 2:
# ------- BOARDS LIST START -----------
@@ -217,7 +257,7 @@ if arguments == 2:
# ------- LISTS OF BOARD START -----------
boardid = sys.argv[2]
attachments = wekanurl + apiboards + boardid
lists = wekanurl + apiboards + boardid + s + l
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
print("=== LISTS ===\n")
body = requests.get(lists, headers=headers)
+3 -3
View File
@@ -82,7 +82,7 @@ template(name="activity")
+viewer
= activity.checklist.title
else
a.activity-checklist(href="{{ activity.card.absoluteUrl }}")
a.activity-checklist(href="{{ activity.card.originRelativeUrl }}")
+viewer
= activity.checklist.title
@@ -103,7 +103,7 @@ template(name="activity")
if($eq activity.activityType 'addChecklistItem')
| {{{_ 'activity-checklist-item-added' (sanitize activity.checklist.title) cardLink}}}.
.activity-checklist(href="{{ activity.card.absoluteUrl }}")
.activity-checklist(href="{{ activity.card.originRelativeUrl }}")
+viewer
= activity.checklistItem.title
@@ -139,7 +139,7 @@ template(name="activity")
//- if we are not in card mode we only display a summary of the comment
if($eq activity.activityType 'addComment')
| {{{_ 'activity-on' cardLink}}}
a.activity-comment(href="{{ activity.card.absoluteUrl }}")
a.activity-comment(href="{{ activity.card.originRelativeUrl }}")
+viewer
= activity.comment.text
+14 -10
View File
@@ -1,4 +1,4 @@
import sanitizeXss from 'xss';
import DOMPurify from 'dompurify';
const activitiesPerPage = 500;
@@ -162,11 +162,15 @@ BlazeComponent.extendComponent({
{
href: source.url,
},
sanitizeXss(source.system),
DOMPurify.sanitize(source.system, {
ALLOW_UNKNOWN_PROTOCOLS: true,
}),
),
);
} else {
return sanitizeXss(source.system);
return DOMPurify.sanitize(source.system, {
ALLOW_UNKNOWN_PROTOCOLS: true,
});
}
}
return null;
@@ -190,10 +194,10 @@ BlazeComponent.extendComponent({
href: attachment.url({ download: true }),
target: '_blank',
},
sanitizeXss(attachment.name()),
DOMPurify.sanitize(attachment.name()),
),
)) ||
sanitizeXss(this.currentData().activity.attachmentName)
DOMPurify.sanitize(this.currentData().activity.attachmentName)
);
},
@@ -232,7 +236,7 @@ BlazeComponent.extendComponent({
Template.activity.helpers({
sanitize(value) {
return sanitizeXss(value);
return DOMPurify.sanitize(value, { ALLOW_UNKNOWN_PROTOCOLS: true });
},
});
@@ -243,10 +247,10 @@ function createCardLink(card) {
Blaze.toHTML(
HTML.A(
{
href: card.absoluteUrl(),
href: card.originRelativeUrl(),
class: 'action-card',
},
sanitizeXss(card.title),
DOMPurify.sanitize(card.title, { ALLOW_UNKNOWN_PROTOCOLS: true }),
),
)
);
@@ -260,10 +264,10 @@ function createBoardLink(board, list) {
Blaze.toHTML(
HTML.A(
{
href: board.absoluteUrl(),
href: board.originRelativeUrl(),
class: 'action-board',
},
sanitizeXss(text),
DOMPurify.sanitize(text, { ALLOW_UNKNOWN_PROTOCOLS: true }),
),
)
);
+1 -1
View File
@@ -1,7 +1,7 @@
template(name="commentForm")
.new-comment.js-new-comment(
class="{{#if commentFormIsOpen}}is-open{{/if}}")
+userAvatar(userId=currentUser._id)
+userAvatar(userId=currentUser._id noRemove=true)
form.js-new-comment-form
+editor(class="js-new-comment-input")
| {{getUnsavedValue 'cardComment' currentCard._id}}
+1
View File
@@ -3,6 +3,7 @@ const commentFormIsOpen = new ReactiveVar(false);
BlazeComponent.extendComponent({
onDestroyed() {
commentFormIsOpen.set(false);
$('.note-popover').hide();
},
commentFormIsOpen() {
+1 -1
View File
@@ -360,7 +360,7 @@ BlazeComponent.extendComponent({
end: end || card.endAt,
allDay:
Math.abs(end.getTime() - start.getTime()) / 1000 === 24 * 3600,
url: FlowRouter.url('card', {
url: FlowRouter.path('card', {
boardId: currentBoard._id,
slug: currentBoard.slug,
cardId: card._id,
+16 -6
View File
@@ -1,14 +1,17 @@
template(name="boardHeaderBar")
h1.header-board-menu
with currentBoard
a(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}")
+viewer
= title
+viewer
= title
.board-header-btns.left
unless isMiniScreen
if currentBoard
if currentUser
with currentBoard
a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title)
i.fa.fa-pencil-square-o
a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}"
title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}")
i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}")
@@ -31,9 +34,12 @@ template(name="boardHeaderBar")
if $eq watchLevel "muted"
i.fa.fa-bell-slash
span {{_ watchLevel}}
a.board-header-btn.js-sort-cards(title="{{_ 'sort-cards'}}")
a.board-header-btn(title="{{_ 'sort-cards'}}" class="{{#if isSortActive }}emphasis{{else}} js-sort-cards {{/if}}")
i.fa.fa-sort
| {{_ 'sort-cards'}} {{sortCardsBy.get}}
span {{#if isSortActive }}{{_ 'Sort is on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
if isSortActive
a.board-header-btn-close.js-sort-reset(title="Remove Sort")
i.fa.fa-times-thin
else
a.board-header-btn.js-log-in(
@@ -45,6 +51,10 @@ template(name="boardHeaderBar")
if currentBoard
if isMiniScreen
if currentUser
with currentBoard
a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title)
i.fa.fa-pencil-square-o
a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}"
title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}")
i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}")
@@ -121,7 +131,7 @@ template(name="boardHeaderBar")
i.fa.fa-times-thin
.separator
a.board-header-btn.js-toggle-sidebar
a.board-header-btn.js-toggle-sidebar(title="{{_ 'sidebar-open'}} {{_ 'or'}} {{_ 'sidebar-close'}}")
i.fa.fa-navicon
template(name="boardVisibilityList")
+6 -8
View File
@@ -129,6 +129,9 @@ BlazeComponent.extendComponent({
Sidebar.setView();
Filter.reset();
},
'click .js-sort-reset'() {
Session.set('sortBy', '');
},
'click .js-open-search-view'() {
Sidebar.setView('search');
},
@@ -162,6 +165,9 @@ Template.boardHeaderBar.helpers({
boardView() {
return Utils.boardView();
},
isSortActive() {
return Session.get('sortBy') ? true : false;
},
});
Template.boardChangeViewPopup.events({
@@ -407,14 +413,6 @@ BlazeComponent.extendComponent({
sortCardsBy.set(TAPi18n.__('date-created-oldest-first'));
Popup.close();
},
'click .js-sort-default'() {
const sortBy = {
sort: 1,
};
Session.set('sortBy', sortBy);
sortCardsBy.set(TAPi18n.__('default'));
Popup.close();
},
},
];
},
+3 -2
View File
@@ -2,7 +2,8 @@ template(name="boardList")
.wrapper
ul.board-list.clearfix.js-boards
li.js-add-board
a.board-list-item.label {{_ 'add-board'}}
a.board-list-item.label(title="{{_ 'add-board'}}")
| {{_ 'add-board'}}
each boards
li(class="{{#if isStarred}}starred{{/if}}" class=colorClass).js-board
if isInvited
@@ -18,7 +19,7 @@ template(name="boardList")
else
a.js-open-board.board-list-item(href="{{pathFor 'board' id=_id slug=slug}}")
span.details
span.board-list-item-name
span.board-list-item-name(title="{{_ 'board-drag-drop-reorder-or-click-open'}}")
+viewer
= title
i.fa.js-star-board(
+9
View File
@@ -22,6 +22,15 @@ Template.boardListHeaderBar.helpers({
BlazeComponent.extendComponent({
onCreated() {
Meteor.subscribe('setting');
let currUser = Meteor.user();
let userLanguage;
if(currUser && currUser.profile){
userLanguage = currUser.profile.language
}
if (userLanguage) {
TAPi18n.setLanguage(userLanguage);
T9n.setLanguage(userLanguage);
}
},
onRendered() {
+1 -2
View File
@@ -55,6 +55,5 @@ template(name="attachmentsGalery")
unless currentUser.isCommentOnly
unless currentUser.isWorker
//li.attachment-item.add-attachment
a.js-add-attachment
a.js-add-attachment(title="{{_ 'add-attachment' }}")
i.fa.fa-plus
| {{_ 'add-attachment' }}
@@ -119,3 +119,24 @@ template(name="cardCustomField-dropdown")
if value
+viewer
= selectedItem
template(name="cardCustomField-stringtemplate")
if canModifyCard
+inlinedForm(classNames="js-card-customfield-stringtemplate")
each item in stringtemplateItems.get
input.js-card-customfield-stringtemplate-item(type="text" value=item placeholder="")
input.js-card-customfield-stringtemplate-item.last(type="text" value="" placeholder="{{_ 'custom-field-stringtemplate-item-placeholder'}}" autofocus)
.edit-controls.clearfix
button.primary(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
else
a.js-open-inlined-form
if value
+viewer
= formattedValue
else
| {{_ 'edit'}}
else
if value
+viewer
= formattedValue
@@ -1,3 +1,6 @@
import { DatePicker } from '/client/lib/datepicker';
import Cards from '/models/cards';
Template.cardCustomFieldsPopup.helpers({
hasCustomField() {
const card = Cards.findOne(Session.get('currentCard'));
@@ -234,3 +237,90 @@ CardCustomField.register('cardCustomField');
];
}
}.register('cardCustomField-dropdown'));
// cardCustomField-stringtemplate
(class extends CardCustomField {
onCreated() {
super.onCreated();
this.stringtemplateFormat = this.data().definition.settings.stringtemplateFormat;
this.stringtemplateSeparator = this.data().definition.settings.stringtemplateSeparator;
this.stringtemplateItems = new ReactiveVar(this.data().value ?? []);
}
formattedValue() {
return (this.data().value ?? [])
.filter(value => !!value.trim())
.map(value => this.stringtemplateFormat.replace(/%\{value\}/gi, value))
.join(this.stringtemplateSeparator ?? '');
}
getItems() {
return Array.from(this.findAll('input'))
.map(input => input.value)
.filter(value => !!value.trim());
}
events() {
return [
{
'submit .js-card-customfield-stringtemplate'(event) {
event.preventDefault();
const items = this.getItems();
this.card.setCustomField(this.customFieldId, items);
},
'keydown .js-card-customfield-stringtemplate-item'(event) {
if (event.keyCode === 13) {
event.preventDefault();
if (event.metaKey || event.ctrlKey) {
this.find('button[type=submit]').click();
} else if (event.target.value.trim()) {
const inputLast = this.find('input.last');
let items = this.getItems();
if (event.target === inputLast) {
inputLast.value = '';
} else if (event.target.nextSibling === inputLast) {
inputLast.focus();
} else {
event.target.blur();
const idx = Array.from(this.findAll('input')).indexOf(
event.target,
);
items.splice(idx + 1, 0, '');
Tracker.afterFlush(() => {
const element = this.findAll('input')[idx + 1];
element.focus();
element.value = '';
});
}
this.stringtemplateItems.set(items);
}
}
},
'blur .js-card-customfield-stringtemplate-item'(event) {
if (
!event.target.value.trim() ||
event.target === this.find('input.last')
) {
const items = this.getItems();
this.stringtemplateItems.set(items);
this.find('input.last').value = '';
}
},
'click .js-close-inlined-form'(event) {
this.stringtemplateItems.set(this.data().value ?? []);
},
},
];
}
}.register('cardCustomField-stringtemplate'));
+29 -120
View File
@@ -1,122 +1,4 @@
// Helper function to replace HH with H for 24 hours format, because H allows also single-digit hours
function adjustedTimeFormat() {
return moment
.localeData()
.longDateFormat('LT')
.replace(/HH/i, 'H');
}
// Edit received, start, due & end dates
BlazeComponent.extendComponent({
template() {
return 'editCardDate';
},
onCreated() {
this.error = new ReactiveVar('');
this.card = this.data();
this.date = new ReactiveVar(moment.invalid());
},
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),
);
if (this.date.get().isValid()) {
$picker.datepicker('update', this.date.get().toDate());
}
},
showDate() {
if (this.date.get().isValid()) return this.date.get().format('L');
return '';
},
showTime() {
if (this.date.get().isValid()) return this.date.get().format('LT');
return '';
},
dateFormat() {
return moment.localeData().longDateFormat('L');
},
timeFormat() {
return moment.localeData().longDateFormat('LT');
},
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,
adjustedTimeFormat(),
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');
const newTime = moment(time, adjustedTimeFormat(), true);
const newDate = moment(evt.target.date.value, 'L', true);
const dateString = `${evt.target.date.value} ${time}`;
const newCompleteDate = moment(
dateString,
'L ' + adjustedTimeFormat(),
true,
);
if (!newTime.isValid()) {
this.error.set('invalid-time');
evt.target.time.focus();
}
if (!newDate.isValid()) {
this.error.set('invalid-date');
evt.target.date.focus();
}
if (newCompleteDate.isValid()) {
this._storeDate(newCompleteDate.toDate());
Popup.close();
} else {
if (!this.error) {
this.error.set('invalid');
}
}
},
'click .js-delete-date'(evt) {
evt.preventDefault();
this._deleteDate();
Popup.close();
},
},
];
},
});
import { DatePicker } from '/client/lib/datepicker';
Template.dateBadge.helpers({
canModifyCard() {
@@ -305,7 +187,7 @@ class CardStartDate extends CardDate {
// if dueAt or endAt exist & are > startAt, startAt doesn't need to be flagged
if ((endAt && theDate.isAfter(endAt)) || (dueAt && theDate.isAfter(dueAt)))
classes += 'long-overdue';
else if (theDate.isBefore(now, 'minute')) classes += 'almost-due';
else if (theDate.isAfter(now)) classes += '';
else classes += 'current';
return classes;
}
@@ -472,3 +354,30 @@ class VoteEndDate extends CardDate {
}
}
VoteEndDate.register('voteEndDate');
class PokerEndDate extends CardDate {
onCreated() {
super.onCreated();
const self = this;
self.autorun(() => {
self.date.set(moment(self.data().getPokerEnd()));
});
}
classes() {
const classes = 'end-date' + ' ';
return classes;
}
showDate() {
return this.date.get().format('l LT');
}
showTitle() {
return `${TAPi18n.__('card-end-on')} ${this.date.get().format('LLLL')}`;
}
events() {
return super.events().concat({
'click .js-edit-date': Popup.open('editPokerEndDate'),
});
}
}
PokerEndDate.register('pokerEndDate');
+1 -1
View File
@@ -3,5 +3,5 @@ template(name="descriptionForm")
.new-description.js-new-description(
class="{{#if descriptionFormIsOpen}}is-open{{/if}}")
form.js-new-description-form
+editor(class="js-new-description-input" data-meteor-emoji-large="true" autofocus="autofocus")
+editor(class="js-new-description-input" autofocus="autofocus")
| {{getUnsavedValue 'cardDescription' _id getDescription}}
@@ -3,6 +3,7 @@ const descriptionFormIsOpen = new ReactiveVar(false);
BlazeComponent.extendComponent({
onDestroyed() {
descriptionFormIsOpen.set(false);
$('.note-popover').hide();
},
descriptionFormIsOpen() {
@@ -23,7 +23,6 @@
background-color: #fff
border: 0
box-shadow: 0 1px 2px rgba(0, 0, 0, .23)
color: #8c8c8c
height: 36px
margin: 4px 4px 6px 0
padding: 9px 11px
+573 -318
View File
@@ -1,23 +1,26 @@
template(name="cardDetails")
section.card-details.js-card-details: .card-details-canvas
section.card-details.js-card-details(class='{{#if cardMaximized}}card-details-maximized{{/if}}'): .card-details-canvas
.card-details-header(class='{{#if colorClass}}card-details-{{colorClass}}{{/if}}')
+inlinedForm(classNames="js-card-details-title")
+editCardTitleForm
else
unless isMiniScreen
a.fa.fa-times-thin.close-card-details.js-close-card-details
a.fa.fa-times-thin.close-card-details.js-close-card-details(title="{{_ 'close-card'}}")
unless cardMaximized
a.fa.fa-window-maximize.maximize-card-details.js-maximize-card-details(title="{{_ 'maximize-card'}}")
if cardMaximized
a.fa.fa-window-minimize.minimize-card-details.js-minimize-card-details(title="{{_ 'minimize-card'}}")
if currentUser.isBoardMember
a.fa.fa-navicon.card-details-menu.js-open-card-details-menu
input.inline-input(type="text" id="cardURL_copy" value="{{ absoluteUrl }}")
a.fa.fa-navicon.card-details-menu.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
input.inline-input(type="text" id="cardURL_copy" value="{{ originRelativeUrl }}")
a.fa.fa-link.card-copy-button.js-copy-link(
class="fa-link"
title="{{_ 'copy-card-link-to-clipboard'}}"
value="{{ absoluteUrl }}"
)
if isMiniScreen
a.fa.fa-times-thin.close-card-details-mobile-web.js-close-card-details
a.fa.fa-times-thin.close-card-details-mobile-web.js-close-card-details(title="{{_ 'close-card'}}")
if currentUser.isBoardMember
a.fa.fa-navicon.card-details-menu-mobile-web.js-open-card-details-menu
a.fa.fa-navicon.card-details-menu-mobile-web.js-open-card-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
a.fa.fa-link.card-copy-mobile-button
h2.card-details-title.js-card-title(
class="{{#if canModifyCard}}js-open-inlined-form is-editable{{/if}}")
@@ -42,277 +45,501 @@ template(name="cardDetails")
else
p.warning {{_ 'card-archived'}}
.card-details-items
if currentBoard.allowsLabels
.card-details-item.card-details-item-labels
h3.card-details-item-title
i.fa.fa-tags
| {{_ 'labels'}}
a(class="{{#if canModifyCard}}js-add-labels{{else}}is-disabled{{/if}}" title="{{_ 'card-labels-title'}}")
each labels
span.card-label(class="card-label-{{color}}" title=name)
+viewer
= name
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
i.fa.fa-plus
.card-details-left
.card-details-items
if currentBoard.allowsLabels
.card-details-item.card-details-item-labels
h3.card-details-item-title
i.fa.fa-tags
| {{_ 'labels'}}
a(class="{{#if canModifyCard}}js-add-labels{{else}}is-disabled{{/if}}" title="{{_ 'card-labels-title'}}")
each labels
span.card-label(class="card-label-{{color}}" title=name)
+viewer
= name
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
i.fa.fa-plus
if currentBoard.allowsReceivedDate
hr
.card-details-item.card-details-item-received
h3.card-details-item-title
i.fa.fa-sign-out
| {{_ 'card-received'}}
if getReceived
+cardReceivedDate
else
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-received-date
i.fa.fa-plus
if currentBoard.allowsStartDate
.card-details-item.card-details-item-start
h3.card-details-item-title
i.fa.fa-hourglass-start
| {{_ 'card-start'}}
if getStart
+cardStartDate
else
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-start-date
i.fa.fa-plus
if currentBoard.allowsDueDate
.card-details-item.card-details-item-due
h3.card-details-item-title
i.fa.fa-sign-in
| {{_ 'card-due'}}
if getDue
+cardDueDate
else
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-due-date
i.fa.fa-plus
if currentBoard.allowsEndDate
.card-details-item.card-details-item-end
h3.card-details-item-title
i.fa.fa-hourglass-end
| {{_ 'card-end'}}
if getEnd
+cardEndDate
else
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-end-date
i.fa.fa-plus
if currentBoard.allowsReceivedDate
hr
.card-details-item.card-details-item-received
h3.card-details-item-title
i.fa.fa-sign-out
| {{_ 'card-received'}}
if getReceived
+cardReceivedDate
else
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-received-date
i.fa.fa-plus
if currentBoard.allowsCreator
.card-details-item.card-details-item-creator
h3.card-details-item-title
i.fa.fa-user
| {{_ 'creator'}}
if currentBoard.allowsStartDate
.card-details-item.card-details-item-start
h3.card-details-item-title
i.fa.fa-hourglass-start
| {{_ 'card-start'}}
if getStart
+cardStartDate
else
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-start-date
i.fa.fa-plus
if currentBoard.allowsDueDate
.card-details-item.card-details-item-due
h3.card-details-item-title
i.fa.fa-sign-in
| {{_ 'card-due'}}
if getDue
+cardDueDate
else
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-due-date
i.fa.fa-plus
if currentBoard.allowsEndDate
.card-details-item.card-details-item-end
h3.card-details-item-title
i.fa.fa-hourglass-end
| {{_ 'card-end'}}
if getEnd
+cardEndDate
else
if canModifyCard
unless currentUser.isWorker
a.card-label.add-label.js-end-date
i.fa.fa-plus
//.card-details-items
if currentBoard.allowsMembers
hr
.card-details-item.card-details-item-members
h3.card-details-item-title
i.fa.fa-users
| {{_ 'members'}}
each getMembers
+userAvatar(userId=this cardId=../_id)
+userAvatar(userId=userId noRemove=true)
| {{! XXX Hack to hide syntaxic coloration /// }}
if canModifyCard
unless currentUser.isWorker
a.member.add-member.card-details-item-add-button.js-add-members(title="{{_ 'card-members-title'}}")
i.fa.fa-plus
//if assigneeSelected
if currentBoard.allowsAssignee
.card-details-item.card-details-item-assignees
h3.card-details-item-title
i.fa.fa-user
| {{_ 'assignee'}}
each getAssignees
+userAvatarAssignee(userId=this cardId=../_id)
| {{! XXX Hack to hide syntaxic coloration /// }}
if canModifyCard
a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}")
i.fa.fa-plus
if currentUser.isWorker
unless assigneeSelected
//.card-details-items
if currentBoard.allowsMembers
.card-details-item.card-details-item-members
h3.card-details-item-title
i.fa.fa-users
| {{_ 'members'}}
each userId in getMembers
+userAvatar(userId=userId cardId=_id)
| {{! XXX Hack to hide syntaxic coloration /// }}
if canModifyCard
unless currentUser.isWorker
a.member.add-member.card-details-item-add-button.js-add-members(title="{{_ 'card-members-title'}}")
i.fa.fa-plus
//if assigneeSelected
if currentBoard.allowsAssignee
.card-details-item.card-details-item-assignees
h3.card-details-item-title
i.fa.fa-user
| {{_ 'assignee'}}
each userId in getAssignees
+userAvatar(userId=userId cardId=_id assignee=true)
| {{! XXX Hack to hide syntaxic coloration /// }}
if canModifyCard
a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}")
i.fa.fa-plus
if currentUser.isWorker
unless assigneeSelected
a.assignee.add-assignee.card-details-item-add-button.js-add-assignees(title="{{_ 'assignee'}}")
i.fa.fa-plus
//.card-details-items
if getSpentTime
.card-details-item.card-details-item-spent
if getIsOvertime
h3.card-details-item-title
| {{_ 'overtime-hours'}}
else
h3.card-details-item-title
| {{_ 'spent-time-hours'}}
+cardSpentTime
//.card-details-items
if getSpentTime
.card-details-item.card-details-item-spent
if getIsOvertime
h3.card-details-item-title
| {{_ 'overtime-hours'}}
else
h3.card-details-item-title
| {{_ 'spent-time-hours'}}
+cardSpentTime
//.card-details-items
if currentBoard.allowsRequestedBy
.card-details-item.card-details-item-name
h3.card-details-item-title
i.fa.fa-shopping-cart
| {{_ 'requested-by'}}
if canModifyCard
unless currentUser.isWorker
+inlinedForm(classNames="js-card-details-requester")
+editCardRequesterForm
//.card-details-items
if currentBoard.allowsRequestedBy
.card-details-item.card-details-item-name
h3.card-details-item-title
i.fa.fa-shopping-cart
| {{_ 'requested-by'}}
if canModifyCard
unless currentUser.isWorker
+inlinedForm(classNames="js-card-details-requester")
+editCardRequesterForm
else
a.js-open-inlined-form
if getRequestedBy
+viewer
= getRequestedBy
else
| {{_ 'add'}}
else if getRequestedBy
+viewer
= getRequestedBy
if currentBoard.allowsAssignedBy
.card-details-item.card-details-item-name
h3.card-details-item-title
i.fa.fa-user-plus
| {{_ 'assigned-by'}}
if canModifyCard
unless currentUser.isWorker
+inlinedForm(classNames="js-card-details-assigner")
+editCardAssignerForm
else
a.js-open-inlined-form
if getAssignedBy
+viewer
= getAssignedBy
else
| {{_ 'add'}}
else if getRequestedBy
+viewer
= getAssignedBy
if currentBoard.allowsCardSortingByNumber
.card-details-item.card-details-sort-order
h3.card-details-item-title
i.fa.fa-sort
| {{_ 'sort'}}
if canModifyCard
+inlinedForm(classNames="js-card-details-sort")
+editCardSortOrderForm
else
a.js-open-inlined-form
if getRequestedBy
+viewer
= getRequestedBy
else
| {{_ 'add'}}
else if getRequestedBy
+viewer
= getRequestedBy
+viewer
= sort
if currentBoard.allowsAssignedBy
.card-details-item.card-details-item-name
h3.card-details-item-title
i.fa.fa-user-plus
| {{_ 'assigned-by'}}
if canModifyCard
unless currentUser.isWorker
+inlinedForm(classNames="js-card-details-assigner")
+editCardAssignerForm
else
a.js-open-inlined-form
if getAssignedBy
+viewer
= getAssignedBy
else
| {{_ 'add'}}
else if getRequestedBy
+viewer
= getAssignedBy
//.card-details-items
if customFieldsWD
hr
each customFieldsWD
.card-details-item.card-details-item-customfield
h3.card-details-item-title
i.fa.fa-list-alt
= definition.name
+cardCustomField
//.card-details-items
if customFieldsWD
if getVoteQuestion
hr
each customFieldsWD
.card-details-item.card-details-item-customfield
.vote-title
div.flex
h3
i.fa.fa-thumbs-up
| {{_ 'vote-question'}}
if getVoteEnd
+voteEndDate
.vote-result
if votePublic
a.card-label.card-label-green.js-show-positive-votes {{ voteCountPositive }}
a.card-label.card-label-red.js-show-negative-votes {{ voteCountNegative }}
else
.card-label.card-label-green {{ voteCountPositive }}
.card-label.card-label-red {{ voteCountNegative }}
unless ($and currentBoard.isPublic voteAllowNonBoardMembers )
.card-label.card-label-gray {{ voteCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }}
+viewer
= getVoteQuestion
if showVotingButtons
button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}")
if voteState
i.fa.fa-thumbs-up
| {{_ 'vote-for-it'}}
button.card-details-red.js-vote.js-vote-negative(class="{{#if $eq voteState false}}voted{{/if}}")
if $eq voteState false
i.fa.fa-thumbs-down
| {{_ 'vote-against'}}
if getPokerQuestion
hr
.poker-title
div.flex
h3
i.fa.fa-thumbs-up
| {{_ 'poker-question'}}
if getPokerEnd
+pokerEndDate
div.flex
.poker-result
if expiredPoker
unless ($and currentBoard.isPublic pokerAllowNonBoardMembers )
.card-label.card-label-gray {{ pokerCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }}
if showPlanningPokerButtons
.poker-result
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-one(class="{{#if $eq pokerState 'one'}}poker-voted{{/if}}") {{_ 'poker-one'}}
if $eq pokerState "one"
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-two(class="{{#if $eq pokerState 'two'}}poker-voted{{/if}}") {{_ 'poker-two'}}
if $eq pokerState "two"
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-three(class="{{#if $eq pokerState 'three'}}poker-voted{{/if}}") {{_ 'poker-three'}}
if $eq pokerState "three"
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-five(class="{{#if $eq pokerState 'five'}}poker-voted{{/if}}") {{_ 'poker-five'}}
if $eq pokerState "five"
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-eight(class="{{#if $eq pokerState 'eight'}}poker-voted{{/if}}") {{_ 'poker-eight'}}
if $eq pokerState "eight"
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-thirteen(class="{{#if $eq pokerState 'thirteen'}}poker-voted{{/if}}") {{_ 'poker-thirteen'}}
if $eq pokerState "thirteen"
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-twenty(class="{{#if $eq pokerState 'twenty'}}poker-voted{{/if}}") {{_ 'poker-twenty'}}
if $eq pokerState "twenty"
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-forty(class="{{#if $eq pokerState 'forty'}}poker-voted{{/if}}") {{_ 'poker-forty'}}
if $eq pokerState "forty"
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-one-hundred(class="{{#if $eq pokerState 'oneHundred'}}poker-voted{{/if}}") {{_ 'poker-oneHundred'}}
if $eq pokerState "oneHundred"
i.fa.fa-check
.poker-deck
.poker-card
span.inner.js-poker.js-poker-vote-unsure(class="{{#if $eq pokerState 'unsure'}}poker-voted{{/if}}") {{_ 'poker-unsure'}}
if $eq pokerState "unsure"
i.fa.fa-check
if currentUser.isBoardAdmin
button.card-details-blue.js-poker-finish(class="{{#if $eq voteState false}}poker-voted{{/if}}") {{_ 'poker-finish'}}
if expiredPoker
.poker-table
.poker-table-side-left
.poker-table-heading-left
.poker-table-row
.poker-table-cell
.poker-table-cell
| {{_ 'poker-result-votes' }}
.poker-table-cell.poker-table-cell-who
| {{_ 'poker-result-who' }}
.poker-table-body
.poker-table-row
.poker-table-cell
button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 1}}winner{{else}}loser{{/if}}") {{_ 'poker-one'}}
.poker-table-cell {{ pokerCountOne }}
.poker-table-cell.poker-table-cell-who
.poker-result
each m in pokerMemberOne
a.name
+userAvatar(userId=m._id noRemove=true)
.poker-table-row
.poker-table-cell
button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 2}}winner{{else}}loser{{/if}}") {{_ 'poker-two'}}
.poker-table-cell {{ pokerCountTwo }}
.poker-table-cell.poker-table-cell-who
.poker-result
each m in pokerMemberTwo
a.name
+userAvatar(userId=m._id noRemove=true)
.poker-table-row
.poker-table-cell
button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 3}}winner{{else}}loser{{/if}}") {{_ 'poker-three'}}
.poker-table-cell {{ pokerCountThree }}
.poker-table-cell.poker-table-cell-who
.poker-result
each m in pokerMemberThree
a.name
+userAvatar(userId=m._id noRemove=true)
.poker-table-row
.poker-table-cell
button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 5}}winner{{else}}loser{{/if}}") {{_ 'poker-five'}}
.poker-table-cell {{ pokerCountFive }}
.poker-table-cell.poker-table-cell-who
.poker-result
each m in pokerMemberFive
a.name
+userAvatar(userId=m._id noRemove=true)
.poker-table-row
.poker-table-cell
button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 8}}winner{{else}}loser{{/if}}") {{_ 'poker-eight'}}
.poker-table-cell {{ pokerCountEight }}
.poker-table-cell.poker-table-cell-who
.poker-result
each m in pokerMemberEight
a.name
+userAvatar(userId=m._id noRemove=true)
.poker-table-side-right
.poker-table-heading-right
.poker-table-row
.poker-table-cell
.poker-table-cell
| {{_ 'poker-result-votes' }}
.poker-table-cell.poker-table-cell-who
| {{_ 'poker-result-who' }}
.poker-table-body
.poker-table-row
.poker-table-cell
button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 13}}winner{{else}}loser{{/if}}") {{_ 'poker-thirteen'}}
.poker-table-cell {{ pokerCountThirteen }}
.poker-table-cell.poker-table-cell-who
.poker-result
each m in pokerMemberThirteen
a.name
+userAvatar(userId=m._id noRemove=true)
.poker-table-row
.poker-table-cell
button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 20}}winner{{else}}loser{{/if}}") {{_ 'poker-twenty'}}
.poker-table-cell {{ pokerCountTwenty }}
.poker-table-cell.poker-table-cell-who
.poker-result
each m in pokerMemberTwenty
a.name
+userAvatar(userId=m._id noRemove=true)
.poker-table-row
.poker-table-cell
button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 40}}winner{{else}}loser{{/if}}") {{_ 'poker-forty'}}
.poker-table-cell {{ pokerCountForty }}
.poker-table-cell.poker-table-cell-who
.poker-result
each m in pokerMemberForty
a.name
+userAvatar(userId=m._id noRemove=true)
.poker-table-row
.poker-table-cell
button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 100}}winner{{else}}loser{{/if}}") {{_ 'poker-oneHundred'}}
.poker-table-cell {{ pokerCountOneHundred }}
.poker-table-cell.poker-table-cell-who
.poker-result
each m in pokerMemberOneHundred
a.name
+userAvatar(userId=m._id noRemove=true)
.poker-table-row
.poker-table-cell
button.card-details-gray.js-poker.poker-card-result(class="{{#if $eq pokerWinner 'unsure'}}winner{{else}}loser{{/if}}") {{_ 'poker-unsure'}}
.poker-table-cell {{ pokerCountUnsure }}
.poker-table-cell.poker-table-cell-who
.poker-result
each m in pokerMemberUnsure
a.name
+userAvatar(userId=m._id noRemove=true)
if currentUser.isBoardAdmin
div.estimation-add
button.card-details-red.js-poker-replay(class="{{#if $eq voteState false}}voted{{/if}}") {{_ 'poker-replay'}}
div.estimation-add
button.js-poker-estimation
i.fa.fa-plus
| {{_ 'set-estimation'}}
input(type=text,autofocus value=getPokerEstimation,id="pokerEstimation")
//- XXX We should use "editable" to avoid repetiting ourselves
if canModifyCard
unless currentUser.isWorker
if currentBoard.allowsDescriptionTitle
hr
h3.card-details-item-title
i.fa.fa-list-alt
= definition.name
+cardCustomField
if getVoteQuestion
hr
.vote-title
div.flex
h3
i.fa.fa-thumbs-up
| {{_ 'vote-question'}}
if getVoteEnd
+voteEndDate
.vote-result
if votePublic
a.card-label.card-label-green.js-show-positive-votes {{ voteCountPositive }}
a.card-label.card-label-red.js-show-negative-votes {{ voteCountNegative }}
else
.card-label.card-label-green {{ voteCountPositive }}
.card-label.card-label-red {{ voteCountNegative }}
unless ($and currentBoard.isPublic voteAllowNonBoardMembers )
.card-label.card-label-gray {{ voteCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }}
+viewer
= getVoteQuestion
if showVotingButtons
button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}")
if voteState
i.fa.fa-thumbs-up
| {{_ 'vote-for-it'}}
button.card-details-red.js-vote.js-vote-negative(class="{{#if $eq voteState false}}voted{{/if}}")
if $eq voteState false
i.fa.fa-thumbs-down
| {{_ 'vote-against'}}
//- XXX We should use "editable" to avoid repetiting ourselves
if canModifyCard
unless currentUser.isWorker
i.fa.fa-align-left
| {{_ 'description'}}
if currentBoard.allowsDescriptionText
+inlinedCardDescription(classNames="card-description js-card-description")
+descriptionForm
.edit-controls.clearfix
button.primary(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
else
if currentBoard.allowsDescriptionText
a.js-open-inlined-form
if getDescription
+viewer
= getDescription
else
| {{_ 'edit'}}
if (hasUnsavedValue 'cardDescription' _id)
p.quiet
| {{_ 'unsaved-description'}}
a.js-open-inlined-form {{_ 'view-it'}}
= ' - '
a.js-close-inlined-form {{_ 'discard'}}
else if getDescription
if currentBoard.allowsDescriptionTitle
hr
h3.card-details-item-title
i.fa.fa-align-left
| {{_ 'description'}}
h3.card-details-item-title {{_ 'description'}}
if currentBoard.allowsDescriptionText
+inlinedCardDescription(classNames="card-description js-card-description")
+descriptionForm
.edit-controls.clearfix
button.primary(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
else
if currentBoard.allowsDescriptionText
a.js-open-inlined-form
if getDescription
+viewer
= getDescription
else
| {{_ 'edit'}}
if (hasUnsavedValue 'cardDescription' _id)
p.quiet
| {{_ 'unsaved-description'}}
a.js-open-inlined-form {{_ 'view-it'}}
= ' - '
a.js-close-inlined-form {{_ 'discard'}}
else if getDescription
if currentBoard.allowsDescriptionTitle
hr
h3.card-details-item-title {{_ 'description'}}
if currentBoard.allowsDescriptionText
+viewer
= getDescription
+viewer
= getDescription
.card-checklist-attachmentGalerys
.card-checklist-attachmentGalery.card-checklists
if currentBoard.allowsChecklists
.card-checklist-attachmentGalerys
.card-checklist-attachmentGalery.card-checklists
if currentBoard.allowsChecklists
hr
+checklists(cardId = _id)
if currentBoard.allowsSubtasks
hr
+subtasks(cardId = _id)
if currentBoard.allowsAttachments
hr
+checklists(cardId = _id)
if currentBoard.allowsSubtasks
hr
+subtasks(cardId = _id)
if currentBoard.allowsAttachments
hr
h3.card-details-item-title
i.fa.fa-paperclip
| {{_ 'attachments'}}
.card-checklist-attachmentGalery.card-attachmentGalery
+attachmentsGalery
h3.card-details-item-title
i.fa.fa-paperclip
| {{_ 'attachments'}}
.card-checklist-attachmentGalery.card-attachmentGalery
+attachmentsGalery
hr
unless currentUser.isNoComments
.activity-title
h3.card-details-item-title
i.fa.fa-history
| {{ _ 'activity'}}
.card-details-right
unless currentUser.isNoComments
.activity-title
h3.card-details-item-title
i.fa.fa-history
| {{ _ 'activity'}}
if currentUser.isBoardMember
.material-toggle-switch(title="{{_ 'hide-system-messages'}}")
//span.toggle-switch-title
if hiddenSystemMessages
input.toggle-switch(type="checkbox" id="toggleButton" checked="checked")
else
input.toggle-switch(type="checkbox" id="toggleButton")
label.toggle-label(for="toggleButton")
if currentBoard.allowsComments
if currentUser.isBoardMember
.material-toggle-switch
span.toggle-switch-title {{_ 'hide-system-messages'}}
if hiddenSystemMessages
input.toggle-switch(type="checkbox" id="toggleButton" checked="checked")
else
input.toggle-switch(type="checkbox" id="toggleButton")
label.toggle-label(for="toggleButton")
if currentBoard.allowsComments
if currentUser.isBoardMember
unless currentUser.isNoComments
+commentForm
unless currentUser.isNoComments
if isLoaded.get
if isLinkedCard
+activities(card=this mode="linkedcard")
else if isLinkedBoard
+activities(card=this mode="linkedboard")
else
+activities(card=this mode="card")
unless currentUser.isNoComments
+commentForm
unless currentUser.isNoComments
if isLoaded.get
if isLinkedCard
+activities(card=this mode="linkedcard")
else if isLinkedBoard
+activities(card=this mode="linkedboard")
else
+activities(card=this mode="card")
template(name="editCardTitleForm")
textarea.js-edit-card-title(rows='1' autofocus dir="auto")
@@ -333,6 +560,12 @@ template(name="editCardAssignerForm")
button.primary.confirm.js-submit-edit-card-assigner-form(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
template(name="editCardSortOrderForm")
input.js-edit-card-sort(type='text' autofocus value=sort dir="auto")
.edit-controls.clearfix
button.primary.confirm.js-submit-edit-card-sort-form(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
template(name="cardDetailsActionsPopup")
ul.pop-over-list
li
@@ -343,9 +576,9 @@ template(name="cardDetailsActionsPopup")
else
i.fa.fa-eye-slash
| {{_ 'watch'}}
hr
if canModifyCard
unless currentUser.isWorker
hr
ul.pop-over-list
//li: a.js-members {{_ 'card-edit-members'}}
//li: a.js-labels {{_ 'card-edit-labels'}}
@@ -354,6 +587,10 @@ template(name="cardDetailsActionsPopup")
a.js-start-voting
i.fa.fa-thumbs-up
| {{_ 'card-edit-voting'}}
li
a.js-start-planning-poker
i.fa.fa-thumbs-up
| {{_ 'card-edit-planning-poker'}}
if currentUser.isBoardAdmin
li
a.js-custom-fields
@@ -371,50 +608,63 @@ template(name="cardDetailsActionsPopup")
a.js-set-card-color
i.fa.fa-paint-brush
| {{_ 'setCardColorPopup-title'}}
hr
ul.pop-over-list
hr
ul.pop-over-list
li
a.js-export-card
i.fa.fa-share-alt
| {{_ 'export-card'}}
hr
ul.pop-over-list
li
a.js-move-card-to-top
i.fa.fa-arrow-up
| {{_ 'moveCardToTop-title'}}
li
a.js-move-card-to-bottom
i.fa.fa-arrow-down
| {{_ 'moveCardToBottom-title'}}
hr
ul.pop-over-list
if currentUser.isBoardAdmin
li
a.js-move-card-to-top
i.fa.fa-arrow-up
| {{_ 'moveCardToTop-title'}}
li
a.js-move-card-to-bottom
i.fa.fa-arrow-down
| {{_ 'moveCardToBottom-title'}}
hr
ul.pop-over-list
if currentUser.isBoardAdmin
li
a.js-move-card
i.fa.fa-arrow-right
| {{_ 'moveCardPopup-title'}}
unless currentUser.isWorker
li
a.js-copy-card
i.fa.fa-copy
| {{_ 'copyCardPopup-title'}}
a.js-move-card
i.fa.fa-arrow-right
| {{_ 'moveCardPopup-title'}}
unless currentUser.isWorker
li
a.js-copy-card
i.fa.fa-copy
| {{_ 'copyCardPopup-title'}}
unless currentUser.isWorker
hr
ul.pop-over-list
li
a.js-copy-checklist-cards
i.fa.fa-list
i.fa.fa-copy
| {{_ 'copyChecklistToManyCardsPopup-title'}}
unless archived
hr
ul.pop-over-list
li
a.js-copy-checklist-cards
i.fa.fa-list
i.fa.fa-copy
| {{_ 'copyChecklistToManyCardsPopup-title'}}
unless archived
hr
ul.pop-over-list
li
a.js-archive
i.fa.fa-arrow-right
i.fa.fa-archive
| {{_ 'archive-card'}}
hr
ul.pop-over-list
li
a.js-more
i.fa.fa-link
| {{_ 'cardMorePopup-title'}}
a.js-archive
i.fa.fa-arrow-right
i.fa.fa-archive
| {{_ 'archive-card'}}
hr
ul.pop-over-list
li
a.js-more
i.fa.fa-link
| {{_ 'cardMorePopup-title'}}
template(name="exportCardPopup")
ul.pop-over-list
li
a(href="{{exportUrlCardPDF}}",, download="{{exportFilenameCardPDF}}")
i.fa.fa-share-alt
| {{_ 'export-card-pdf'}}
template(name="moveCardPopup")
+boardsAndLists
@@ -489,23 +739,6 @@ template(name="cardAssigneesPopup")
if currentUser.isCardAssignee
i.fa.fa-check
template(name="userAvatarAssignee")
a.assignee.js-assignee(title="{{userData.profile.fullname}} ({{userData.username}})")
if userData.profile.avatarUrl
img.avatar.avatar-image(src="{{userData.profile.avatarUrl}}")
else
+userAvatarAssigneeInitials(userId=userData._id)
if showStatus
span.assignee-presence-status(class=presenceStatusClassName)
span.member-type(class=memberType)
unless isSandstorm
if showEdit
if $eq currentUser._id userData._id
a.edit-avatar.js-change-avatar
i.fa.fa-pencil
template(name="cardAssigneePopup")
.board-assignee-menu
.mini-profile-info
@@ -523,17 +756,13 @@ template(name="cardAssigneePopup")
with currentUser
li: a.js-edit-profile {{_ 'edit-profile'}}
template(name="userAvatarAssigneeInitials")
svg.avatar.avatar-assignee-initials(viewBox="0 0 {{viewPortWidth}} 15")
text(x="50%" y="13" text-anchor="middle")= initials
template(name="cardMorePopup")
p.quiet
span.clearfix
span {{_ 'link-card'}}
= ' '
i.fa.colorful(class="{{#if board.isPublic}}fa-globe{{else}}fa-lock{{/if}}")
input.inline-input(type="text" id="cardURL" readonly value="{{ absoluteUrl }}" autofocus="autofocus")
input.inline-input(type="text" id="cardURL" readonly value="{{ originRelativeUrl }}" autofocus="autofocus")
button.js-copy-card-link-to-clipboard(class="btn" id="clipboard") {{_ 'copy-card-link-to-clipboard'}}
span.clearfix
br
@@ -634,3 +863,29 @@ template(name="negativeVoteMembersPopup")
span.full-name
= m.profile.fullname
| (<span class="username">{{ m.username }}</span>)
template(name="deletePokerPopup")
p {{_ "poker-delete-pop"}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
template(name="cardStartPlanningPokerPopup")
form.edit-poker-question
.fields
.check-div
a.flex(class="{{#if getPokerQuestion}}is-disabled{{else}}js-toggle-poker-allow-non-members{{/if}}")
.materialCheckBox#poker-allow-non-members(name="poker-allow-non-members" class="{{#if pokerAllowNonBoardMembers}}is-checked{{/if}}")
span {{_ 'allowNonBoardMembers'}}
.check-div.flex
i.fa.fa-hourglass-end
a.js-end-date
span
| {{_ 'card-end'}}
unless getPokerEnd
i.fa.fa-plus
if getPokerEnd
+pokerEndDate
button.primary.js-submit {{_ 'save'}}
if getPokerQuestion
if currentUser.isBoardAdmin
button.js-remove-poker.negate.wide.right {{_ 'delete'}}
+607 -154
View File
@@ -1,11 +1,18 @@
import { DatePicker } from '/client/lib/datepicker';
import Cards from '/models/cards';
import Boards from '/models/boards';
import Checklists from '/models/checklists';
import Integrations from '/models/integrations';
import Users from '/models/users';
import Lists from '/models/lists';
import CardComments from '/models/cardComments';
import { ALLOWED_COLORS } from '/config/const';
import moment from 'moment';
import { UserAvatar } from '../users/userAvatar';
const subManager = new SubsManager();
const { calculateIndexData } = Utils;
let cardColors;
Meteor.startup(() => {
cardColors = Cards.simpleSchema()._schema.color.allowedValues;
});
BlazeComponent.extendComponent({
mixins() {
return [Mixins.InfiniteScrolling];
@@ -47,6 +54,10 @@ BlazeComponent.extendComponent({
return Meteor.user().hasHiddenSystemMessages();
},
cardMaximized() {
return Meteor.user().hasCardMaximized();
},
canModifyCard() {
return (
Meteor.user() &&
@@ -114,7 +125,7 @@ BlazeComponent.extendComponent({
if (card) {
const board = Boards.findOne(card.boardId);
if (board) {
result = FlowRouter.url('card', {
result = FlowRouter.path('card', {
boardId: card.boardId,
slug: board.slug,
cardId: card._id,
@@ -133,6 +144,15 @@ BlazeComponent.extendComponent({
);
},
showPlanningPokerButtons() {
const card = this.currentData();
return (
(currentUser.isBoardMember() ||
(currentUser && card.pokerAllowNonBoardMembers())) &&
!card.expiredPoker()
);
},
onRendered() {
if (Meteor.settings.public.CARD_OPENED_WEBHOOK_ENABLED) {
// Send Webhook but not create Activities records ---
@@ -154,15 +174,13 @@ BlazeComponent.extendComponent({
}).fetch();
if (integrations.length > 0) {
integrations.forEach(integration => {
integrations.forEach((integration) => {
Meteor.call(
'outgoingWebhooks',
integration,
'CardSelected',
params,
() => {
return;
},
() => {},
);
});
}
@@ -290,7 +308,9 @@ BlazeComponent.extendComponent({
Utils.goBoardId(this.data().boardId);
},
'click .js-copy-link'() {
StringToCopyElement = document.getElementById('cardURL_copy');
const StringToCopyElement = document.getElementById('cardURL_copy');
StringToCopyElement.value =
window.location.origin + window.location.pathname;
StringToCopyElement.select();
if (document.execCommand('copy')) {
StringToCopyElement.blur();
@@ -320,9 +340,7 @@ BlazeComponent.extendComponent({
},
'submit .js-card-details-title'(event) {
event.preventDefault();
const title = this.currentComponent()
.getValue()
.trim();
const title = this.currentComponent().getValue().trim();
if (title) {
this.data().setTitle(title);
} else {
@@ -331,9 +349,7 @@ BlazeComponent.extendComponent({
},
'submit .js-card-details-assigner'(event) {
event.preventDefault();
const assigner = this.currentComponent()
.getValue()
.trim();
const assigner = this.currentComponent().getValue().trim();
if (assigner) {
this.data().setAssignedBy(assigner);
} else {
@@ -342,15 +358,23 @@ BlazeComponent.extendComponent({
},
'submit .js-card-details-requester'(event) {
event.preventDefault();
const requester = this.currentComponent()
.getValue()
.trim();
const requester = this.currentComponent().getValue().trim();
if (requester) {
this.data().setRequestedBy(requester);
} else {
this.data().setRequestedBy('');
}
},
'submit .js-card-details-sort'(event) {
event.preventDefault();
const sort = parseFloat(this.currentComponent()
.getValue()
.trim());
if (!Number.isNaN(sort)) {
let card = this.data();
card.move(card.boardId, card.swimlaneId, card.listId, sort);
}
},
'click .js-go-to-linked-card'() {
Utils.goCardId(this.data().linkedId);
},
@@ -388,6 +412,14 @@ BlazeComponent.extendComponent({
'click #toggleButton'() {
Meteor.call('toggleSystemMessages');
},
'click .js-maximize-card-details'() {
Meteor.call('toggleCardMaximized');
autosize($('.card-details'));
},
'click .js-minimize-card-details'() {
Meteor.call('toggleCardMaximized');
autosize($('.card-details'));
},
'click .js-vote'(e) {
const forIt = $(e.target).hasClass('js-vote-positive');
let newState = null;
@@ -400,125 +432,124 @@ BlazeComponent.extendComponent({
}
this.data().setVote(Meteor.userId(), newState);
},
'click .js-poker'(e) {
let newState = null;
if ($(e.target).hasClass('js-poker-vote-one')) {
newState = 'one';
this.data().setPoker(Meteor.userId(), newState);
}
if ($(e.target).hasClass('js-poker-vote-two')) {
newState = 'two';
this.data().setPoker(Meteor.userId(), newState);
}
if ($(e.target).hasClass('js-poker-vote-three')) {
newState = 'three';
this.data().setPoker(Meteor.userId(), newState);
}
if ($(e.target).hasClass('js-poker-vote-five')) {
newState = 'five';
this.data().setPoker(Meteor.userId(), newState);
}
if ($(e.target).hasClass('js-poker-vote-eight')) {
newState = 'eight';
this.data().setPoker(Meteor.userId(), newState);
}
if ($(e.target).hasClass('js-poker-vote-thirteen')) {
newState = 'thirteen';
this.data().setPoker(Meteor.userId(), newState);
}
if ($(e.target).hasClass('js-poker-vote-twenty')) {
newState = 'twenty';
this.data().setPoker(Meteor.userId(), newState);
}
if ($(e.target).hasClass('js-poker-vote-forty')) {
newState = 'forty';
this.data().setPoker(Meteor.userId(), newState);
}
if ($(e.target).hasClass('js-poker-vote-one-hundred')) {
newState = 'oneHundred';
this.data().setPoker(Meteor.userId(), newState);
}
if ($(e.target).hasClass('js-poker-vote-unsure')) {
newState = 'unsure';
this.data().setPoker(Meteor.userId(), newState);
}
},
'click .js-poker-finish'(e) {
if ($(e.target).hasClass('js-poker-finish')) {
e.preventDefault();
const now = moment().format('YYYY-MM-DD HH:mm');
this.data().setPokerEnd(now);
}
},
'click .js-poker-replay'(e) {
if ($(e.target).hasClass('js-poker-replay')) {
e.preventDefault();
this.currentCard = this.currentData();
this.currentCard.replayPoker();
this.data().unsetPokerEnd();
this.data().unsetPokerEstimation();
}
},
'click .js-poker-estimation'(event) {
event.preventDefault();
const ruleTitle = this.find('#pokerEstimation').value;
if (ruleTitle !== undefined && ruleTitle !== '') {
this.find('#pokerEstimation').value = '';
if (ruleTitle) {
this.data().setPokerEstimation(parseInt(ruleTitle, 10));
} else {
this.data().setPokerEstimation('');
}
}
},
},
];
},
}).register('cardDetails');
Template.cardDetails.helpers({
userData() {
// We need to handle a special case for the search results provided by the
// `matteodem:easy-search` package. Since these results gets published in a
// separate collection, and not in the standard Meteor.Users collection as
// expected, we use a component parameter ("property") to distinguish the
// two cases.
const userCollection = this.esSearch ? ESSearchResults : Users;
return userCollection.findOne(this.userId, {
fields: {
profile: 1,
username: 1,
},
});
BlazeComponent.extendComponent({
template() {
return 'exportCard';
},
withApi() {
return Template.instance().apiEnabled.get();
},
exportUrlCardPDF() {
const params = {
boardId: Session.get('currentBoard'),
listId: this.listId,
cardId: this.cardId,
};
const queryParams = {
authToken: Accounts._storedLoginToken(),
};
return FlowRouter.path(
'/api/boards/:boardId/lists/:listId/cards/:cardId/exportPDF',
params,
queryParams,
);
},
exportFilenameCardPDF() {
//const boardId = Session.get('currentBoard');
//return `export-card-pdf-${boardId}.xlsx`;
return `export-card.pdf`;
},
}).register('exportCardPopup');
receivedSelected() {
if (this.getReceived().length === 0) {
return false;
} else {
return true;
}
},
startSelected() {
if (this.getStart().length === 0) {
return false;
} else {
return true;
}
},
endSelected() {
if (this.getEnd().length === 0) {
return false;
} else {
return true;
}
},
dueSelected() {
if (this.getDue().length === 0) {
return false;
} else {
return true;
}
},
memberSelected() {
if (this.getMembers().length === 0) {
return false;
} else {
return true;
}
},
labelSelected() {
if (this.getLabels().length === 0) {
return false;
} else {
return true;
}
},
assigneeSelected() {
if (this.getAssignees().length === 0) {
return false;
} else {
return true;
}
},
requestBySelected() {
if (this.getRequestBy().length === 0) {
return false;
} else {
return true;
}
},
assigneeBySelected() {
if (this.getAssigneeBy().length === 0) {
return false;
} else {
return true;
}
},
memberType() {
const user = Users.findOne(this.userId);
return user && user.isBoardAdmin() ? 'admin' : 'normal';
},
presenceStatusClassName() {
const user = Users.findOne(this.userId);
const userPresence = presences.findOne({ userId: this.userId });
if (user && user.isInvitedTo(Session.get('currentBoard'))) return 'pending';
else if (!userPresence) return 'disconnected';
else if (Session.equals('currentBoard', userPresence.state.currentBoardId))
return 'active';
else return 'idle';
},
});
Template.userAvatarAssigneeInitials.helpers({
initials() {
const user = Users.findOne(this.userId);
return user && user.getInitials();
},
viewPortWidth() {
const user = Users.findOne(this.userId);
return ((user && user.getInitials().length) || 1) * 12;
},
// only allow number input
Template.editCardSortOrderForm.onRendered(function() {
this.$('input').on("keypress paste", function(event) {
let keyCode = event.keyCode;
let charCode = String.fromCharCode(keyCode);
let regex = new RegExp('[-0-9.]');
let ret = regex.test(charCode);
// only working here, defining in events() doesn't handle the return value correctly
return ret;
});
});
// We extends the normal InlinedForm component to support UnsavedEdits draft
@@ -581,11 +612,13 @@ Template.cardDetailsActionsPopup.helpers({
});
Template.cardDetailsActionsPopup.events({
'click .js-export-card': Popup.open('exportCard'),
'click .js-members': Popup.open('cardMembers'),
'click .js-assignees': Popup.open('cardAssignees'),
'click .js-labels': Popup.open('cardLabels'),
'click .js-attachments': Popup.open('cardAttachments'),
'click .js-start-voting': Popup.open('cardStartVoting'),
'click .js-start-planning-poker': Popup.open('cardStartPlanningPoker'),
'click .js-custom-fields': Popup.open('cardCustomFields'),
'click .js-received-date': Popup.open('editCardReceivedDate'),
'click .js-start-date': Popup.open('editCardStartDate'),
@@ -601,7 +634,7 @@ Template.cardDetailsActionsPopup.events({
const minOrder = _.min(
this.list()
.cards(this.swimlaneId)
.map(c => c.sort),
.map((c) => c.sort),
);
this.move(this.boardId, this.swimlaneId, this.listId, minOrder - 1);
},
@@ -610,7 +643,7 @@ Template.cardDetailsActionsPopup.events({
const maxOrder = _.max(
this.list()
.cards(this.swimlaneId)
.map(c => c.sort),
.map((c) => c.sort),
);
this.move(this.boardId, this.swimlaneId, this.listId, maxOrder + 1);
},
@@ -629,7 +662,7 @@ Template.cardDetailsActionsPopup.events({
},
});
Template.editCardTitleForm.onRendered(function() {
Template.editCardTitleForm.onRendered(function () {
autosize(this.$('.js-edit-card-title'));
});
@@ -643,7 +676,7 @@ Template.editCardTitleForm.events({
},
});
Template.editCardRequesterForm.onRendered(function() {
Template.editCardRequesterForm.onRendered(function () {
autosize(this.$('.js-edit-card-requester'));
});
@@ -656,7 +689,7 @@ Template.editCardRequesterForm.events({
},
});
Template.editCardAssignerForm.onRendered(function() {
Template.editCardAssignerForm.onRendered(function () {
autosize(this.$('.js-edit-card-assigner'));
});
@@ -695,7 +728,7 @@ BlazeComponent.extendComponent({
},
boards() {
const boards = Boards.find(
return Boards.find(
{
archived: false,
'members.userId': Meteor.userId(),
@@ -705,7 +738,6 @@ BlazeComponent.extendComponent({
sort: { sort: 1 /* boards default sorting */ },
},
);
return boards;
},
swimlanes() {
@@ -734,7 +766,7 @@ Template.copyCardPopup.events({
'click .js-done'() {
const card = Cards.findOne(Session.get('currentCard'));
const lSelect = $('.js-select-lists')[0];
listId = lSelect.options[lSelect.selectedIndex].value;
const listId = lSelect.options[lSelect.selectedIndex].value;
const slSelect = $('.js-select-swimlanes')[0];
const swimlaneId = slSelect.options[slSelect.selectedIndex].value;
const bSelect = $('.js-select-boards')[0];
@@ -742,9 +774,7 @@ 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;
@@ -775,9 +805,7 @@ 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);
@@ -794,13 +822,13 @@ 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.forEach(function() {
const cursor = Cards.find({ parentId: oldId });
cursor.forEach(function () {
'use strict';
const subtask = arguments[0];
subtask.parentId = _id;
@@ -809,7 +837,7 @@ Template.copyChecklistToManyCardsPopup.events({
});
// copy card comments
CardComments.find({ cardId: oldId }).forEach(cmt => {
CardComments.find({ cardId: oldId }).forEach((cmt) => {
cmt.copy(_id);
});
}
@@ -825,7 +853,7 @@ BlazeComponent.extendComponent({
},
colors() {
return cardColors.map(color => ({ color, name: '' }));
return ALLOWED_COLORS.map((color) => ({ color, name: '' }));
},
isSelected(color) {
@@ -869,7 +897,7 @@ BlazeComponent.extendComponent({
},
boards() {
const boards = Boards.find(
return Boards.find(
{
archived: false,
'members.userId': Meteor.userId(),
@@ -881,7 +909,6 @@ BlazeComponent.extendComponent({
sort: { sort: 1 /* boards default sorting */ },
},
);
return boards;
},
cards() {
@@ -949,7 +976,7 @@ BlazeComponent.extendComponent({
}
}
},
'click .js-delete': Popup.afterConfirm('cardDelete', function() {
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
Popup.close();
// verify that there are no linked cards
if (Cards.find({ linkedId: this._id }).count() === 0) {
@@ -1056,6 +1083,8 @@ BlazeComponent.extendComponent({
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()) {
// if active vote - store it
@@ -1066,6 +1095,159 @@ BlazeComponent.extendComponent({
this.currentData().vote = { end: newDate.toDate() }; // set vote end temp
Popup.back();
}
*/
// Try to parse different date formats of all languages.
// This code is same for vote and planning poker.
const usaDate = moment(dateString, 'L LT', true);
const euroAmDate = moment(dateString, 'DD.MM.YYYY LT', true);
const euro24hDate = moment(dateString, 'DD.MM.YYYY HH.mm', true);
const eurodotDate = moment(dateString, 'DD.MM.YYYY HH:mm', true);
const minusDate = moment(dateString, 'YYYY-MM-DD HH:mm', true);
const slashDate = moment(dateString, 'DD/MM/YYYY HH.mm', true);
const dotDate = moment(dateString, 'DD/MM/YYYY HH:mm', true);
const brezhonegDate = moment(dateString, 'DD/MM/YYYY h[e]mm A', true);
const hrvatskiDate = moment(dateString, 'DD. MM. YYYY H:mm', true);
const latviaDate = moment(dateString, 'YYYY.MM.DD. H:mm', true);
const nederlandsDate = moment(dateString, 'DD-MM-YYYY HH:mm', true);
// greekDate does not work: el Greek Ελληνικά ,
// it has date format DD/MM/YYYY h:mm MM like 20/06/2021 11:15 MM
// where MM is maybe some text like AM/PM ?
// Also some other languages that have non-ascii characters in dates
// do not work.
const greekDate = moment(dateString, 'DD/MM/YYYY h:mm A', true);
const macedonianDate = moment(dateString, 'D.MM.YYYY H:mm', true);
if (usaDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(usaDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: usaDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (euroAmDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(euroAmDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: euroAmDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (euro24hDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(euro24hDate.toDate());
this.card.setPokerEnd(euro24hDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: euro24hDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (eurodotDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(eurodotDate.toDate());
this.card.setPokerEnd(eurodotDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: eurodotDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (minusDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(minusDate.toDate());
this.card.setPokerEnd(minusDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: minusDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (slashDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(slashDate.toDate());
this.card.setPokerEnd(slashDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: slashDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (dotDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(dotDate.toDate());
this.card.setPokerEnd(dotDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: dotDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (brezhonegDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(brezhonegDate.toDate());
this.card.setPokerEnd(brezhonegDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: brezhonegDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (hrvatskiDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(hrvatskiDate.toDate());
this.card.setPokerEnd(hrvatskiDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: hrvatskiDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (latviaDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(latviaDate.toDate());
this.card.setPokerEnd(latviaDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: latviaDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (nederlandsDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(nederlandsDate.toDate());
this.card.setPokerEnd(nederlandsDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: nederlandsDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (greekDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(greekDate.toDate());
this.card.setPokerEnd(greekDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: greekDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (macedonianDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(macedonianDate.toDate());
this.card.setPokerEnd(macedonianDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: macedonianDate.toDate() }; // set poker end temp
Popup.back();
}
} else {
this.error.set('invalid-date');
evt.target.date.focus();
@@ -1087,6 +1269,277 @@ BlazeComponent.extendComponent({
}
}.register('editVoteEndDatePopup'));
BlazeComponent.extendComponent({
onCreated() {
this.currentCard = this.currentData();
this.pokerQuestion = new ReactiveVar(this.currentCard.pokerQuestion);
},
events() {
return [
{
'click .js-end-date': Popup.open('editPokerEndDate'),
'submit .edit-poker-question'(evt) {
evt.preventDefault();
const pokerQuestion = true;
const allowNonBoardMembers = $('#poker-allow-non-members').hasClass(
'is-checked',
);
const endString = this.currentCard.getPokerEnd();
this.currentCard.setPokerQuestion(
pokerQuestion,
allowNonBoardMembers,
);
if (endString) {
this.currentCard.setPokerEnd(endString);
}
Popup.close();
},
'click .js-remove-poker': Popup.afterConfirm('deletePoker', (event) => {
event.preventDefault();
this.currentCard.unsetPoker();
Popup.close();
}),
'click a.js-toggle-poker-allow-non-members'(event) {
event.preventDefault();
$('#poker-allow-non-members').toggleClass('is-checked');
},
},
];
},
}).register('cardStartPlanningPokerPopup');
// editPokerEndDatePopup
(class extends DatePicker {
onCreated() {
super.onCreated(moment().format('YYYY-MM-DD HH:mm'));
this.data().getPokerEnd() &&
this.date.set(moment(this.data().getPokerEnd()));
}
/*
Tried to use dateFormat and timeFormat from client/components/lib/datepicker.js
to make detecting all date formats not necessary,
but got error "language mk does not exist".
Maybe client/components/lib/datepicker.jade could have hidden input field for
datepicker format that could be used to detect date format?
dateFormat() {
return moment.localeData().longDateFormat('L');
}
timeFormat() {
return moment.localeData().longDateFormat('LT');
}
const newDate = moment(dateString, dateformat() + ' ' + timeformat(), true);
*/
events() {
return [
{
'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');
const dateString = `${evt.target.date.value} ${time}`;
/*
Tried to use dateFormat and timeFormat from client/components/lib/datepicker.js
to make detecting all date formats not necessary,
but got error "language mk does not exist".
Maybe client/components/lib/datepicker.jade could have hidden input field for
datepicker format that could be used to detect date format?
const newDate = moment(dateString, dateformat() + ' ' + timeformat(), true);
if (newDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(newDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: newDate.toDate() }; // set poker end temp
Popup.back();
}
*/
// Try to parse different date formats of all languages.
// This code is same for vote and planning poker.
const usaDate = moment(dateString, 'L LT', true);
const euroAmDate = moment(dateString, 'DD.MM.YYYY LT', true);
const euro24hDate = moment(dateString, 'DD.MM.YYYY HH.mm', true);
const eurodotDate = moment(dateString, 'DD.MM.YYYY HH:mm', true);
const minusDate = moment(dateString, 'YYYY-MM-DD HH:mm', true);
const slashDate = moment(dateString, 'DD/MM/YYYY HH.mm', true);
const dotDate = moment(dateString, 'DD/MM/YYYY HH:mm', true);
const brezhonegDate = moment(dateString, 'DD/MM/YYYY h[e]mm A', true);
const hrvatskiDate = moment(dateString, 'DD. MM. YYYY H:mm', true);
const latviaDate = moment(dateString, 'YYYY.MM.DD. H:mm', true);
const nederlandsDate = moment(dateString, 'DD-MM-YYYY HH:mm', true);
// greekDate does not work: el Greek Ελληνικά ,
// it has date format DD/MM/YYYY h:mm MM like 20/06/2021 11:15 MM
// where MM is maybe some text like AM/PM ?
// Also some other languages that have non-ascii characters in dates
// do not work.
const greekDate = moment(dateString, 'DD/MM/YYYY h:mm A', true);
const macedonianDate = moment(dateString, 'D.MM.YYYY H:mm', true);
if (usaDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(usaDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: usaDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (euroAmDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(euroAmDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: euroAmDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (euro24hDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(euro24hDate.toDate());
this.card.setPokerEnd(euro24hDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: euro24hDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (eurodotDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(eurodotDate.toDate());
this.card.setPokerEnd(eurodotDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: eurodotDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (minusDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(minusDate.toDate());
this.card.setPokerEnd(minusDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: minusDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (slashDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(slashDate.toDate());
this.card.setPokerEnd(slashDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: slashDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (dotDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(dotDate.toDate());
this.card.setPokerEnd(dotDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: dotDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (brezhonegDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(brezhonegDate.toDate());
this.card.setPokerEnd(brezhonegDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: brezhonegDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (hrvatskiDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(hrvatskiDate.toDate());
this.card.setPokerEnd(hrvatskiDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: hrvatskiDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (latviaDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(latviaDate.toDate());
this.card.setPokerEnd(latviaDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: latviaDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (nederlandsDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(nederlandsDate.toDate());
this.card.setPokerEnd(nederlandsDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: nederlandsDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (greekDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(greekDate.toDate());
this.card.setPokerEnd(greekDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: greekDate.toDate() }; // set poker end temp
Popup.back();
}
} else if (macedonianDate.isValid()) {
// if active poker - store it
if (this.currentData().getPokerQuestion()) {
this._storeDate(macedonianDate.toDate());
this.card.setPokerEnd(macedonianDate.toDate());
Popup.close();
} else {
this.currentData().poker = { end: macedonianDate.toDate() }; // set poker end temp
Popup.back();
}
} else {
// this.error.set('invalid-date);
this.error.set('invalid-date' + ' ' + dateString);
evt.target.date.focus();
}
},
'click .js-delete-date'(evt) {
evt.preventDefault();
this._deleteDate();
Popup.close();
},
},
];
}
_storeDate(newDate) {
this.card.setPokerEnd(newDate);
}
_deleteDate() {
this.card.unsetPokerEnd();
}
}.register('editPokerEndDatePopup'));
// Close the card details pane by pressing escape
EscapeActions.register(
'detailsPane',
+180 -4
View File
@@ -110,11 +110,13 @@ avatar-radius = 50%
.card-details-header
margin: 0 -20px 5px
padding 7px 20px
padding: 7px 20px
background: darken(white, 7%)
border-bottom: 1px solid darken(white, 14%)
.close-card-details,
.maximize-card-details,
.minimize-card-details,
.card-details-menu,
.card-copy-button,
.card-copy-mobile-button,
@@ -122,9 +124,11 @@ avatar-radius = 50%
.card-details-menu-mobile-web
float: right
.close-card-details
.close-card-details,
.maximize-card-details,
.minimize-card-details
font-size: 24px
padding: 5px
padding: 5px 10px 5px 10px
margin-right: -8px
.close-card-details-mobile-web
@@ -211,6 +215,7 @@ avatar-radius = 50%
word-wrap: break-word
max-width: 36%
flex-grow: 1
&.card-details-item-creator,
&.card-details-item-received,
&.card-details-item-start,
&.card-details-item-due,
@@ -232,6 +237,43 @@ avatar-radius = 50%
.activities
padding-top: 10px
.card-details-maximized
padding: 0
flex-shrink: 0
flex-basis: calc(100% - 20px)
will-change: flex-basis
overflow-y: scroll
overflow-x: scroll
background: darken(white, 3%)
border-radius: bottom 3px
z-index: 1000 !important
animation: flexGrowIn 0.1s
box-shadow: 0 0 7px 0 darken(white, 30%)
transition: flex-basis 0.1s
box-sizing: border-box
position: absolute
top: 0
left: 0
height: calc(100% - 20px)
width: calc(100% - 20px)
float: left
.card-details-left
position: absolute
float: left
top: 60px
left: 20px
width: 47%
.card-details-right
position: absolute
float: right
top: 20px
left: 50%
.card-details-header
width: 47%
input[type="text"].attachment-add-link-input
float: left
margin: 0 0 8px
@@ -259,7 +301,13 @@ input[type="submit"].attachment-add-link-submit
margin-right: 0px
.card-details-menu
margin-right: 10px
margin-right: 40px
.maximize-card-details
margin-right: 40px
.minimize-card-details
margin-right: 40px
card-details-color(background, color...)
background: background !important
@@ -356,3 +404,131 @@ card-details-color(background, color...)
display: flex
.js-show-positive-votes
cursor: pointer
.poker-voted
opacity: .7
.poker-title
display: flex
justify-content: space-between
.js-edit-date
align-self: baseline
margin-left: 5px
.poker-result
display: flex
flex-flow: row wrap
.js-show-positive-poker-votes
cursor: pointer
.poker-deck
display: grid
flex-direction: column
text-align: center
.poker-card-result
width: 32px
font-size: 1em
font-weight: bold
padding: 4px 2px 4px 2px
cursor: default
.winner
font-weight: bold
outline: #2d2d2d solid 2px
.loser
opacity: .5
.responsive-table
overflow-x: auto
.poker-table
display: table
width: 100%
padding-top: 10px
.poker-table-row
display: table-row
.poker-table-heading
background-color: #EEE
display: table-header-group
.poker-table-cell
display: table-cell
padding: 0 0 5px 2px
border-bottom: 1px solid #d2d0d0
text-align: center
min-width: 45px
.poker-table-cell-who
width: 150px
vertical-align: middle
.poker-table-heading-left,
.poker-table-heading-right
display: table-header-group
font-weight: bold
border-top: 1px solid #808080
@media (max-width: 400px)
.poker-table-heading-right
display: none
.poker-table-body
display: table-row-group
.poker-table-side-left,
.poker-table-side-right
display: inline-block
.poker-table-side-right
padding-left: 10px
@media (max-width: 400px)
.poker-table-side-right
padding-left: 0px
.estimation-add
display: block
overflow: auto
margin-top: 15px
margin-bottom: 5px
input
display: inline-block
float: right
margin: auto
margin-right: 10px
width: 100px
button
display: inline-block
float: right
margin: auto
.poker-card
width:48px
height:72px
float:left
background:#fff
border-radius:5px
display:table
box-sizing:border-box
padding:5px
margin:3px
font-size:20px
font-weight: bold
text-shadow: #2d2d2d 1px 1px 0
box-shadow:0 0 5px #aaaaaa
text-align:center
position:relative
cursor: pointer
.inner
display:table-cell
vertical-align:middle
border-radius:5px
overflow:hidden
background-color: #cecece
+4 -6
View File
@@ -4,8 +4,8 @@ template(name="checklists")
i.fa.fa-check
| {{_ 'checklists'}}
if currentUser.isBoardMember
.material-toggle-switch
span.toggle-switch-title {{_ 'hide-checked-items'}}
.material-toggle-switch(title="{{_ 'hide-checked-items'}}")
//span.toggle-switch-title
if hideCheckedItems
input.toggle-switch(type="checkbox" id="toggleHideCheckedItemsButton" checked="checked")
else
@@ -25,9 +25,8 @@ template(name="checklists")
+inlinedForm(autoclose=false classNames="js-add-checklist" cardId = cardId)
+addChecklistItemForm
else
a.js-open-inlined-form
a.js-open-inlined-form(title="{{_ 'add-checklist'}}")
i.fa.fa-plus
| {{_ 'add-checklist'}}...
template(name="checklistDetail")
.js-checklist.checklist
@@ -93,9 +92,8 @@ template(name="checklistItems")
+inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist)
+addChecklistItemForm
else
a.add-checklist-item.js-open-inlined-form
a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}")
i.fa.fa-plus
| {{_ 'add-checklist-item'}}...
template(name='checklistItemDetail')
.js-checklist-item.checklist-item(class="{{#if item.isFinished }}is-checked{{#if hideCheckedItems}} invisible{{/if}}{{/if}}")
+11
View File
@@ -44,9 +44,20 @@
align-items: center
justify-content: center
.card-label-white
background-color: #ffffff
color: #000000 //Black text for better visibility
border: 1px solid #c0c0c0
.card-label-white:hover
color: #aaaaaa //grey text for better visibility
.card-label-green
background-color: #3cb500
.card-label-green:hover
color: #000000 //Black hover text for better visibility
.card-label-yellow
background-color: #fad900
color: #000000 //Black text for better visibility
+21
View File
@@ -82,6 +82,9 @@ template(name="minicard")
+minicardCustomFieldDate
else if $eq definition.type "checkbox"
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
else if $eq definition.type "stringtemplate"
+viewer
= formattedStringtemplateCustomFieldValue(definition)
else
+viewer
= trueValue
@@ -96,6 +99,10 @@ template(name="minicard")
each getMembers
+userAvatar(userId=this)
if showCreator
.minicard-creator
+userAvatar(userId=this.userId noRemove=true)
.badges
unless currentUser.isNoComments
if comments.count
@@ -114,6 +121,11 @@ template(name="minicard")
span.badge-text {{ voteCountPositive }}
span.badge-icon.fa.fa-thumbs-down(class="{{#if $eq voteState false}}text-red{{/if}}")
span.badge-text {{ voteCountNegative }}
if getPokerQuestion
.badge.badge-state-image-only(title=getPokerQuestion)
span.badge-icon.fa.fa-check(class="{{#if pokerState}}text-green{{/if}}")
if expiredPoker
span.badge-text {{ getPokerEstimation }}
if attachments.count
.badge
span.badge-icon.fa.fa-paperclip
@@ -122,3 +134,12 @@ template(name="minicard")
.badge(class="{{#if checklistFinished}}is-finished{{/if}}")
span.badge-icon.fa.fa-check-square-o
span.badge-text.check-list-text {{checklistFinishedCount}}/{{checklistItemCount}}
if allSubtasks.count
.badge
span.badge-icon.fa.fa-sitemap
span.badge-text.check-list-text {{subtasksFinishedCount}}/{{allSubtasksCount}}
//{{subtasksFinishedCount}}/{{subtasksCount}} does not work because when a subtaks is archived, the count goes down
if currentBoard.allowsCardSortingByNumber
.badge
span.badge-icon.fa.fa-sort
span.badge-text {{ sort }}
+28
View File
@@ -21,6 +21,34 @@ BlazeComponent.extendComponent({
}).format(customFieldTrueValue);
},
formattedStringtemplateCustomFieldValue(definition) {
const customField = this.data()
.customFieldsWD()
.find(f => f._id === definition._id);
const customFieldTrueValue =
customField && customField.trueValue ? customField.trueValue : [];
return customFieldTrueValue
.filter(value => !!value.trim())
.map(value =>
definition.settings.stringtemplateFormat.replace(/%\{value\}/gi, value),
)
.join(definition.settings.stringtemplateSeparator ?? '');
},
showCreator() {
if (this.data().board()) {
return (
this.data().board.allowsCreator === null ||
this.data().board().allowsCreator === undefined ||
this.data().board().allowsCreator
);
// return this.data().board().allowsCreator;
}
return false;
},
events() {
return [
{
+6 -2
View File
@@ -89,7 +89,7 @@
border-radius: 2px
margin-right: 3px
margin-bottom: 3px
.minicard-custom-fields
display:block;
.minicard-custom-field
@@ -163,7 +163,8 @@
line-height: 12px
.minicard-members,
.minicard-assignees
.minicard-assignees,
.minicard-creator
float: right
margin-left: 5px
margin-bottom: 4px
@@ -187,6 +188,9 @@
.minicard-assignees
border-bottom: 1px solid red
.minicard-creator
border-bottom: 1px solid green
.minicard-members:empty,
.minicard-assignees:empty
display: none
+19 -7
View File
@@ -1,13 +1,17 @@
template(name="resultCard")
.result-card-wrapper
a.minicard-wrapper.card-title(href=absoluteUrl)
a.minicard-wrapper.card-title(href=originRelativeUrl)
+minicard(this)
//= card.title
ul.result-card-context-list
li.result-card-context(title="{{_ 'board'}}")
.result-card-block-wrapper
+viewer
= getBoard.title
if boardId
+viewer
= getBoard.title
else
.broken-cards-null
| NULL
if getBoard.archived
i.fa.fa-archive
li.result-card-context.result-card-context-separator
@@ -16,8 +20,12 @@ template(name="resultCard")
= ' '
li.result-card-context(title="{{_ 'swimlane'}}")
.result-card-block-wrapper
+viewer
= getSwimlane.title
if swimlaneId
+viewer
= getSwimlane.title
else
.broken-cards-null
| NULL
if getSwimlane.archived
i.fa.fa-archive
li.result-card-context.result-card-context-separator
@@ -26,7 +34,11 @@ template(name="resultCard")
= ' '
li.result-card-context(title="{{_ 'list'}}")
.result-card-block-wrapper
+viewer
= getList.title
if listId
+viewer
= getList.title
else
.broken-cards-null
| NULL
if getList.archived
i.fa.fa-archive
+1 -2
View File
@@ -15,9 +15,8 @@ template(name="subtasks")
+inlinedForm(autoclose=false classNames="js-add-subtask" cardId = cardId)
+addSubtaskItemForm
else
a.js-open-inlined-form
a.js-open-inlined-form(title="{{_ 'add-subtask'}}")
i.fa.fa-plus
| {{_ 'add-subtask'}}...
template(name="subtaskDetail")
.js-subtasks.subtask
+1 -1
View File
@@ -86,7 +86,7 @@ select
margin-bottom: 8px
&.inline
width: 100%
width: 100%
option[disabled]
color: #8c8c8c
+5 -10
View File
@@ -5,7 +5,7 @@ template(name="listBody")
+inlinedForm(autoclose=false position="top")
+addCardForm(listId=_id position="top")
each (cardsWithLimit (idOrNull ../../_id))
a.minicard-wrapper.js-minicard(href=absoluteUrl
a.minicard-wrapper.js-minicard(href=originRelativeUrl
class="{{#if cardIsSelected}}is-selected{{/if}}"
class="{{#if MultiSelection.isSelected _id}}is-checked{{/if}}")
if MultiSelection.isActive
@@ -19,19 +19,14 @@ template(name="listBody")
+inlinedForm(autoclose=false position="bottom")
+addCardForm(listId=_id position="bottom")
else
a.open-minicard-composer.js-card-composer.js-open-inlined-form
a.open-minicard-composer.js-card-composer.js-open-inlined-form(title="{{_ 'add-card-to-bottom-of-list'}}")
i.fa.fa-plus
| {{_ 'add-card'}}
template(name="spinnerList")
.sk-spinner.sk-spinner-wave.sk-spinner-list(
class=currentBoard.colorClass
.sk-spinner.sk-spinner-list(
class="{{currentBoard.colorClass}} {{getSkSpinnerName}}"
id="showMoreResults")
.sk-rect1
.sk-rect2
.sk-rect3
.sk-rect4
.sk-rect5
+spinnerRaw
template(name="addCardForm")
.minicard.minicard-composer.js-composer
+40 -29
View File
@@ -1,3 +1,5 @@
import { Spinner } from '/client/lib/spinner';
const subManager = new SubsManager();
const InfiniteScrollIter = 10;
@@ -116,8 +118,6 @@ BlazeComponent.extendComponent({
if (position === 'bottom') {
this.scrollToBottom();
}
formComponent.reset();
}
},
@@ -698,7 +698,7 @@ BlazeComponent.extendComponent({
},
}).register('searchElementPopup');
BlazeComponent.extendComponent({
(class extends Spinner {
onCreated() {
this.cardlimit = this.parentComponent().cardlimit;
@@ -726,7 +726,7 @@ BlazeComponent.extendComponent({
.parentComponent()
.data()._id;
}
},
}
onRendered() {
this.spinner = this.find('.sk-spinner-list');
@@ -741,47 +741,58 @@ BlazeComponent.extendComponent({
);
this.updateList();
},
}
onDestroyed() {
$(this.container).off(`scroll.spinner_${this.swimlaneId}_${this.listId}`);
$(window).off(`resize.spinner_${this.swimlaneId}_${this.listId}`);
},
}
checkIdleTime() {
return window.requestIdleCallback ||
function(handler) {
const startTime = Date.now();
return setTimeout(function() {
handler({
didTimeout: false,
timeRemaining() {
return Math.max(0, 50.0 - (Date.now() - startTime));
},
});
}, 1);
};
}
updateList() {
// Use fallback when requestIdleCallback is not available on iOS and Safari
// https://www.afasterweb.com/2017/11/20/utilizing-idle-moments/
checkIdleTime =
window.requestIdleCallback ||
function(handler) {
const startTime = Date.now();
return setTimeout(function() {
handler({
didTimeout: false,
timeRemaining() {
return Math.max(0, 50.0 - (Date.now() - startTime));
},
});
}, 1);
};
if (this.spinnerInView()) {
this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter);
checkIdleTime(() => this.updateList());
this.checkIdleTime(() => this.updateList());
}
},
}
spinnerInView() {
const parentViewHeight = this.container.clientHeight;
const bottomViewPosition = this.container.scrollTop + parentViewHeight;
const threshold = this.spinner.offsetTop;
// spinner deleted
if (!this.spinner.offsetTop) {
return false;
}
return bottomViewPosition > threshold;
},
}).register('spinnerList');
const parentViewHeight = this.container.clientHeight;
const bottomViewPosition = this.container.scrollTop + parentViewHeight;
let spinnerOffsetTop = this.spinner.offsetTop;
const addCard = $(this.container).find("a.open-minicard-composer").first()[0];
if (addCard !== undefined) {
spinnerOffsetTop -= addCard.clientHeight;
}
return bottomViewPosition > spinnerOffsetTop;
}
getSkSpinnerName() {
return "sk-spinner-" + super.getSpinnerName().toLowerCase();
}
}.register('spinnerList'));
+4 -4
View File
@@ -28,8 +28,8 @@ template(name="listHeader")
div.list-header-menu
unless currentUser.isCommentOnly
if canSeeAddCard
a.js-add-card.fa.fa-plus.list-header-plus-icon
a.fa.fa-navicon.js-open-list-menu
a.js-add-card.fa.fa-plus.list-header-plus-icon(title="{{_ 'add-card-to-top-of-list'}}")
a.fa.fa-navicon.js-open-list-menu(title="{{_ 'listActionPopup-title'}}")
else
a.list-header-menu-icon.fa.fa-angle-right.js-select-list
a.list-header-handle.handle.fa.fa-arrows.js-list-handle
@@ -41,8 +41,8 @@ template(name="listHeader")
//if isBoardAdmin
// a.fa.js-list-star.list-header-plus-icon(class="fa-star{{#unless starred}}-o{{/unless}}")
if canSeeAddCard
a.js-add-card.fa.fa-plus.list-header-plus-icon
a.fa.fa-navicon.js-open-list-menu
a.js-add-card.fa.fa-plus.list-header-plus-icon(title="{{_ 'add-card-to-top-of-list'}}")
a.fa.fa-navicon.js-open-list-menu(title="{{_ 'listActionPopup-title'}}")
if currentUser.isBoardAdmin
if showDesktopDragHandles
a.list-header-handle.handle.fa.fa-arrows.js-list-handle
+12 -36
View File
@@ -3,39 +3,15 @@ template(name="brokenCardsHeaderBar")
| {{_ 'broken-cards'}}
template(name="brokenCards")
.wrapper
.broken-cards-wrapper
each card in brokenCardsList
.broken-cards-card-wrapper
.broken-cards-card-title
= card.title
ul.broken-cards-context-list
li.broken-cards-context(title="{{_ 'board'}}")
if card.boardId
+viewer
= card.getBoard.title
else
.broken-cards-null
| NULL
li.broken-cards-context.broken-cards-context-separator
= ' '
| {{_ 'context-separator'}}
= ' '
li.broken-cards-context(title="{{_ 'swimlane'}}")
if card.swimlaneId
+viewer
= card.getSwimlane.title
else
.broken-cards-null
| NULL
li.broken-cards-context
= ' '
| {{_ 'context-separator'}}
= ' '
li.broken-cards-context(title="{{_ 'list'}}")
if card.listId
+viewer
= card.getList.title
else
.broken-cards-null
| NULL
if currentUser
if searching.get
+spinner
else if hasResults.get
.global-search-results-list-wrapper
if hasQueryErrors.get
div
each msg in errorMessages
span.global-search-error-messages
= msg
else
+resultsPaged(this)
+8 -18
View File
@@ -1,3 +1,5 @@
import { CardSearchPagedComponent } from '../../lib/cardSearch';
BlazeComponent.extendComponent({}).register('brokenCardsHeaderBar');
Template.brokenCards.helpers({
@@ -6,23 +8,11 @@ Template.brokenCards.helpers({
},
});
BlazeComponent.extendComponent({
class BrokenCardsComponent extends CardSearchPagedComponent {
onCreated() {
Meteor.subscribe('setting');
Meteor.subscribe('brokenCards');
},
super.onCreated();
brokenCardsList() {
const selector = {
$or: [
{ boardId: { $in: [null, ''] } },
{ swimlaneId: { $in: [null, ''] } },
{ listId: { $in: [null, ''] } },
{ permission: 'public' },
{ members: { $elemMatch: { userId: user._id, isActive: true } } },
],
};
return Cards.find(selector);
},
}).register('brokenCards');
Meteor.subscribe('brokenCards', this.sessionId);
}
}
BrokenCardsComponent.register('brokenCards');
+10 -6
View File
@@ -22,13 +22,17 @@ template(name="dueCardsModalTitle")
template(name="dueCards")
if currentUser
if isPageReady.get
.wrapper
.due-cards-dueat-list-wrapper
each card in dueCardsList
+resultCard(card)
else
if searching.get
+spinner
else if hasResults.get
.global-search-results-list-wrapper
if hasQueryErrors.get
div
each msg in errorMessages
span.global-search-error-messages
= msg
else
+resultsPaged(this)
template(name="dueCardsViewChangePopup")
if currentUser
+45 -88
View File
@@ -1,4 +1,14 @@
const subManager = new SubsManager();
import { CardSearchPagedComponent } from '../../lib/cardSearch';
import {
OPERATOR_HAS,
OPERATOR_SORT,
OPERATOR_USER,
ORDER_ASCENDING,
PREDICATE_DUE_AT,
} from '../../../config/search-const';
import { QueryParams } from '../../../config/query-classes';
// const subManager = new SubsManager();
BlazeComponent.extendComponent({
dueCardsView() {
@@ -40,106 +50,51 @@ BlazeComponent.extendComponent({
},
}).register('dueCardsViewChangePopup');
BlazeComponent.extendComponent({
class DueCardsComponent extends CardSearchPagedComponent {
onCreated() {
this.isPageReady = new ReactiveVar(false);
super.onCreated();
this.autorun(() => {
const handle = subManager.subscribe(
'dueCards',
Utils.dueCardsView() === 'all',
);
Tracker.nonreactive(() => {
Tracker.autorun(() => {
this.isPageReady.set(handle.ready());
});
});
const queryParams = new QueryParams();
queryParams.addPredicate(OPERATOR_HAS, {
field: PREDICATE_DUE_AT,
exists: true,
});
Meteor.subscribe('setting');
},
// queryParams[OPERATOR_LIMIT] = 5;
queryParams.addPredicate(OPERATOR_SORT, {
name: PREDICATE_DUE_AT,
order: ORDER_ASCENDING,
});
if (Utils.dueCardsView() !== 'all') {
queryParams.addPredicate(OPERATOR_USER, Meteor.user().username);
}
this.runGlobalSearch(queryParams);
}
dueCardsView() {
// eslint-disable-next-line no-console
//console.log('sort:', Utils.dueCardsView());
return Utils.dueCardsView();
},
}
sortByBoard() {
return this.dueCardsView() === 'board';
},
}
dueCardsList() {
const allUsers = Utils.dueCardsView() === 'all';
const user = Meteor.user();
const archivedBoards = [];
Boards.find({ archived: true }).forEach(board => {
archivedBoards.push(board._id);
});
const permiitedBoards = [];
let selector = {
archived: false,
};
// for every user including admin allow her to see cards only from public boards
// or those where she is a member
//if (!user.isAdmin) {
selector.$or = [
{ permission: 'public' },
{ members: { $elemMatch: { userId: user._id, isActive: true } } },
];
//}
Boards.find(selector).forEach(board => {
permiitedBoards.push(board._id);
});
const archivedSwimlanes = [];
Swimlanes.find({ archived: true }).forEach(swimlane => {
archivedSwimlanes.push(swimlane._id);
});
const archivedLists = [];
Lists.find({ archived: true }).forEach(list => {
archivedLists.push(list._id);
});
selector = {
archived: false,
boardId: {
$nin: archivedBoards,
$in: permiitedBoards,
},
swimlaneId: { $nin: archivedSwimlanes },
listId: { $nin: archivedLists },
dueAt: { $ne: null },
endAt: null,
};
if (!allUsers) {
selector.$or = [{ members: user._id }, { assignees: user._id }];
const results = this.getResults();
console.log('results:', results);
const cards = [];
if (results) {
results.forEach(card => {
cards.push(card);
});
}
const cards = [];
// eslint-disable-next-line no-console
// console.log('cards selector:', selector);
Cards.find(selector).forEach(card => {
cards.push(card);
// eslint-disable-next-line no-console
// console.log(
// 'board:',
// card.board(),
// 'swimlane:',
// card.swimlane(),
// 'list:',
// card.list(),
// );
});
cards.sort((a, b) => {
const x = a.dueAt === null ? Date('2100-12-31') : a.dueAt;
const y = b.dueAt === null ? Date('2100-12-31') : b.dueAt;
const x = a.dueAt === null ? new Date('2100-12-31') : a.dueAt;
const y = b.dueAt === null ? new Date('2100-12-31') : b.dueAt;
if (x > y) return 1;
else if (x < y) return -1;
@@ -148,7 +103,9 @@ BlazeComponent.extendComponent({
});
// eslint-disable-next-line no-console
// console.log('cards:', cards);
console.log('cards:', cards);
return cards;
},
}).register('dueCards');
}
}
DueCardsComponent.register('dueCards');
+28 -11
View File
@@ -49,7 +49,7 @@ Template.editor.onRendered(() => {
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
//['insert', ['link', 'picture', 'video']], // iframe tag will be sanitized TODO if iframe[class=note-video-clip] can be added into safe list, insert video can be enabled
//['insert', ['link', 'picture']], // modal popup has issue somehow :(
['insert', ['link']], //, 'picture']], // modal popup has issue somehow :(
['view', ['fullscreen', 'help']],
];
const cleanPastedHTML = function(input) {
@@ -145,6 +145,7 @@ Template.editor.onRendered(() => {
const MAX_IMAGE_PIXEL = Utils.MAX_IMAGE_PIXEL;
const COMPRESS_RATIO = Utils.IMAGE_COMPRESS_RATIO;
const insertImage = src => {
// process all image upload types to the description/comment window
const img = document.createElement('img');
img.src = src;
img.setAttribute('width', '100%');
@@ -210,7 +211,16 @@ Template.editor.onRendered(() => {
}
}
},
onPaste() {
onPaste(e) {
var clipboardData = e.clipboardData;
var pastedData = clipboardData.getData('Text');
//if pasted data is an image, exit
if (!pastedData.length) {
e.preventDefault();
return;
}
// clear up unwanted tag info when user pasted in text
const thisNote = this;
const updatePastedText = function(object) {
@@ -219,7 +229,7 @@ Template.editor.onRendered(() => {
// (and multiplies by pasting more) by changing paste "p" to "br".
// Fixes https://github.com/wekan/wekan/2890 .
// == Fix Start ==
someNote.execCommand('defaultParagraphSeparator', false, 'br');
//someNote.execCommand('defaultParagraphSeparator', false, 'br');
// == Fix End ==
const original = someNote.summernote('code');
const cleaned = cleanPastedHTML(original); //this is where to call whatever clean function you want. I have mine in a different file, called CleanPastedHTML.
@@ -234,17 +244,17 @@ Template.editor.onRendered(() => {
},
},
dialogsInBody: true,
disableDragAndDrop: true,
spellCheck: true,
disableGrammar: false,
disableDragAndDrop: false,
toolbar,
popover: {
image: [
[
'image',
['resizeFull', 'resizeHalf', 'resizeQuarter', 'resizeNone'],
],
['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
['float', ['floatLeft', 'floatRight', 'floatNone']],
['remove', ['removeMedia']],
],
link: [['link', ['linkDialogShow', 'unlink']]],
table: [
['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
['delete', ['deleteRow', 'deleteCol', 'deleteTable']],
@@ -263,10 +273,12 @@ Template.editor.onRendered(() => {
}
});
import sanitizeXss from 'xss';
import DOMPurify from 'dompurify';
// Additional safeAttrValue function to allow for other specific protocols
// See https://github.com/leizongmin/js-xss/issues/52#issuecomment-241354114
/*
function mySafeAttrValue(tag, name, value, cssFilter) {
// only when the tag is 'a' and attribute is 'href'
// then use your custom function
@@ -292,6 +304,7 @@ function mySafeAttrValue(tag, name, value, cssFilter) {
return sanitizeXss.safeAttrValue(tag, name, value, cssFilter);
}
}
*/
// XXX I believe we should compute a HTML rendered field on the server that
// would handle markdown and user mentions. We can simply have two
@@ -307,7 +320,9 @@ Blaze.Template.registerHelper(
let content = Blaze.toHTML(view.templateContentBlock);
const currentBoard = Boards.findOne(Session.get('currentBoard'));
if (!currentBoard)
return HTML.Raw(sanitizeXss(content, { safeAttrValue: mySafeAttrValue }));
return HTML.Raw(
DOMPurify.sanitize(content, { ALLOW_UNKNOWN_PROTOCOLS: true }),
);
const knowedUsers = currentBoard.members.map(member => {
const u = Users.findOne(member.userId);
if (u) {
@@ -351,7 +366,9 @@ Blaze.Template.registerHelper(
content = content.replace(fullMention, Blaze.toHTML(link));
}
return HTML.Raw(sanitizeXss(content, { safeAttrValue: mySafeAttrValue }));
return HTML.Raw(
DOMPurify.sanitize(content, { ALLOW_UNKNOWN_PROTOCOLS: true }),
);
}),
);
+54 -62
View File
@@ -10,11 +10,30 @@ template(name="globalSearchModalTitle")
i.fa.fa-keyboard-o
| {{_ 'globalSearch-title'}}
template(name="resultsPaged")
if resultsHeading.get
h1
= resultsHeading.get
a.fa.fa-link(title="{{_ 'link-to-search' }}" href="{{ getSearchHref }}")
each card in results.get
+resultCard(card)
table.global-search-footer
tr
td.global-search-previous-page
if hasPreviousPage.get
button.js-previous-page
| {{_ 'previous-page' }}
td.global-search-next-page(align="right")
if hasNextPage.get
button.js-next-page
| {{_ 'next-page' }}
template(name="globalSearch")
if currentUser
.wrapper
form.global-search-instructions.js-search-query-form
form.global-search-page.js-search-query-form
input.global-search-query-input(
style="{# if hasResults.get #}display: inline-block;{#/if#}"
id="global-search-input"
type="text"
name="searchQuery"
@@ -22,73 +41,46 @@ template(name="globalSearch")
value="{{ query.get }}"
autofocus dir="auto"
)
a.js-new-search.fa.fa-eraser
if searching.get
+spinner
else if hasResults.get
.global-search-results-list-wrapper
if hasQueryErrors.get
div
ul
each msg in errorMessages
span.global-search-error-messages
li.global-search-error-messages
= msg
else
h1
= resultsHeading.get
a.fa.fa-link(title="{{_ 'link-to-search' }}" href="{{ getSearchHref }}")
each card in results.get
+resultCard(card)
table.global-search-footer
tr
td.global-search-previous-page
if hasPreviousPage.get
button.js-previous-page
| {{_ 'previous-page' }}
td.global-search-next-page(align="right")
if hasNextPage.get
button.js-next-page
| {{_ 'next-page' }}
+resultsPaged(this)
else if serverError.get
.global-search-page
.global-search-help
h1 {{_ 'server-error' }}
+viewer
| {{_ 'server-error-troubleshooting' }}
else
.global-search-instructions
h2 {{_ 'boards' }}
.lists-wrapper
each title in myBoardNames.get
span.card-label.list-title.js-board-title
= title
h2 {{_ 'lists' }}
.lists-wrapper
each title in myLists.get
span.card-label.list-title.js-list-title
= title
h2 {{_ 'label-colors' }}
.palette-colors: each label in labelColors
span.card-label.palette-color.js-label-color(class="card-label-{{label.color}}")
= label.name
if myLabelNames.get.length
h2 {{_ 'label-names' }}
.global-search-page
.global-search-help
h2 {{_ 'boards' }}
.lists-wrapper
each name in myLabelNames.get
span.card-label.list-title.js-label-name
= name
+viewer
= searchInstructions
template(name="globalSearchViewChangePopup")
if currentUser
ul.pop-over-list
li
with "globalSearchViewChange-choice-me"
a.js-global-search-view-me
i.fa.fa-user.colorful
| {{_ 'globalSearchViewChange-choice-me'}}
if $eq Utils.globalSearchView "me"
i.fa.fa-check
li
with "globalSearchViewChange-choice-all"
a.js-global-search-view-all
i.fa.fa-users.colorful
| {{_ 'globalSearchViewChange-choice-all'}}
span.sub-name
+viewer
| {{_ 'globalSearchViewChange-choice-all-description' }}
if $eq Utils.globalSearchView "all"
i.fa.fa-check
each title in myBoardNames.get
span.card-label.list-title.js-board-title
= title
h2 {{_ 'lists' }}
.lists-wrapper
each title in myLists.get
span.card-label.list-title.js-list-title
= title
h2 {{_ 'label-colors' }}
.palette-colors: each label in labelColors
span.card-label.palette-color.js-label-color(class="card-label-{{label.color}}")
= label.name
if myLabelNames.get.length
h2 {{_ 'label-names' }}
.lists-wrapper
each name in myLabelNames.get
span.card-label.list-title.js-label-name
= name
.global-search-instructions
+viewer
= searchInstructions
+95 -522
View File
@@ -1,4 +1,8 @@
const subManager = new SubsManager();
import { CardSearchPagedComponent } from '../../lib/cardSearch';
import Boards from '../../../models/boards';
import { Query, QueryErrors } from '../../../config/query-classes';
// const subManager = new SubsManager();
BlazeComponent.extendComponent({
events() {
@@ -16,45 +20,14 @@ Template.globalSearch.helpers({
},
});
BlazeComponent.extendComponent({
events() {
return [
{
'click .js-due-cards-view-me'() {
Utils.setDueCardsView('me');
Popup.close();
},
'click .js-due-cards-view-all'() {
Utils.setDueCardsView('all');
Popup.close();
},
},
];
},
}).register('globalSearchViewChangePopup');
BlazeComponent.extendComponent({
class GlobalSearchComponent extends CardSearchPagedComponent {
onCreated() {
this.searching = new ReactiveVar(false);
this.hasResults = new ReactiveVar(false);
this.hasQueryErrors = new ReactiveVar(false);
this.query = new ReactiveVar('');
this.resultsHeading = new ReactiveVar('');
this.searchLink = new ReactiveVar(null);
super.onCreated();
this.myLists = new ReactiveVar([]);
this.myLabelNames = new ReactiveVar([]);
this.myBoardNames = new ReactiveVar([]);
this.results = new ReactiveVar([]);
this.hasNextPage = new ReactiveVar(false);
this.hasPreviousPage = new ReactiveVar(false);
this.parsingErrors = new QueryErrors();
this.queryParams = null;
this.parsingErrors = [];
this.resultsCount = 0;
this.totalHits = 0;
this.queryErrors = null;
this.colorMap = null;
this.resultsPerPage = 25;
Meteor.call('myLists', (err, data) => {
if (!err) {
@@ -73,447 +46,71 @@ BlazeComponent.extendComponent({
this.myBoardNames.set(data);
}
});
},
}
onRendered() {
Meteor.subscribe('setting');
// eslint-disable-next-line no-console
//console.log('lang:', TAPi18n.getLanguage());
this.colorMap = Boards.colorMap();
// eslint-disable-next-line no-console
// console.log('colorMap:', this.colorMap);
if (Session.get('globalQuery')) {
this.searchAllBoards(Session.get('globalQuery'));
}
},
}
resetSearch() {
this.searching.set(false);
this.results.set([]);
this.hasResults.set(false);
this.hasQueryErrors.set(false);
this.resultsHeading.set('');
this.parsingErrors = [];
this.resultsCount = 0;
this.totalHits = 0;
this.queryErrors = null;
},
getSessionData() {
return SessionData.findOne({
userId: Meteor.userId(),
sessionId: SessionData.getSessionId(),
});
},
getResults() {
// eslint-disable-next-line no-console
// console.log('getting results');
if (this.queryParams) {
const sessionData = this.getSessionData();
// eslint-disable-next-line no-console
// console.log('selector:', sessionData.getSelector());
// console.log('session data:', sessionData);
const cards = Cards.find({ _id: { $in: sessionData.cards } });
this.queryErrors = sessionData.errors;
if (this.queryErrors.length) {
this.hasQueryErrors.set(true);
return null;
}
if (cards) {
this.totalHits = sessionData.totalHits;
this.resultsCount = cards.count();
this.resultsStart = sessionData.lastHit - this.resultsCount + 1;
this.resultsEnd = sessionData.lastHit;
this.resultsHeading.set(this.getResultsHeading());
this.results.set(cards);
this.hasNextPage.set(sessionData.lastHit < sessionData.totalHits);
this.hasPreviousPage.set(
sessionData.lastHit - sessionData.resultsCount > 0,
);
}
}
this.resultsCount = 0;
return null;
},
super.resetSearch();
this.parsingErrors = new QueryErrors();
}
errorMessages() {
if (this.parsingErrors.length) {
return this.parsingErrorMessages();
if (this.parsingErrors.hasErrors()) {
return this.parsingErrors.errorMessages();
}
return this.queryErrorMessages();
},
}
parsingErrorMessages() {
const messages = [];
this.parsingErrors.errorMessages();
}
if (this.parsingErrors.length) {
this.parsingErrors.forEach(err => {
messages.push(TAPi18n.__(err.tag, err.value));
});
}
return messages;
},
queryErrorMessages() {
messages = [];
this.queryErrors.forEach(err => {
let value = err.color ? TAPi18n.__(`color-${err.value}`) : err.value;
if (!value) {
value = err.value;
}
messages.push(TAPi18n.__(err.tag, value));
});
return messages;
},
searchAllBoards(query) {
query = query.trim();
searchAllBoards(queryText) {
queryText = queryText.trim();
// eslint-disable-next-line no-console
//console.log('query:', query);
//console.log('queryText:', queryText);
this.query.set(query);
this.query.set(queryText);
this.resetSearch();
if (!query) {
if (!queryText) {
return;
}
this.searching.set(true);
const reOperator1 = new RegExp(
'^((?<operator>[\\p{Letter}\\p{Mark}]+):|(?<abbrev>[#@]))(?<value>[\\p{Letter}\\p{Mark}]+)(\\s+|$)',
'iu',
);
const reOperator2 = new RegExp(
'^((?<operator>[\\p{Letter}\\p{Mark}]+):|(?<abbrev>[#@]))(?<quote>["\']*)(?<value>.*?)\\k<quote>(\\s+|$)',
'iu',
);
const reText = new RegExp('^(?<text>\\S+)(\\s+|$)', 'u');
const reQuotedText = new RegExp(
'^(?<quote>["\'])(?<text>.*?)\\k<quote>(\\s+|$)',
'u',
);
const operators = {
'operator-board': 'boards',
'operator-board-abbrev': 'boards',
'operator-swimlane': 'swimlanes',
'operator-swimlane-abbrev': 'swimlanes',
'operator-list': 'lists',
'operator-list-abbrev': 'lists',
'operator-label': 'labels',
'operator-label-abbrev': 'labels',
'operator-user': 'users',
'operator-user-abbrev': 'users',
'operator-member': 'members',
'operator-member-abbrev': 'members',
'operator-assignee': 'assignees',
'operator-assignee-abbrev': 'assignees',
'operator-status': 'status',
'operator-due': 'dueAt',
'operator-created': 'createdAt',
'operator-modified': 'modifiedAt',
'operator-comment': 'comments',
'operator-has': 'has',
};
const predicates = {
due: {
'predicate-overdue': 'overdue',
},
durations: {
'predicate-week': 'week',
'predicate-month': 'month',
'predicate-quarter': 'quarter',
'predicate-year': 'year',
},
status: {
'predicate-archived': 'archived',
'predicate-all': 'all',
'predicate-ended': 'ended',
'predicate-public': 'public',
'predicate-private': 'private',
},
sorts: {
'predicate-due': 'dueAt',
'predicate-created': 'createdAt',
'predicate-modified': 'modifiedAt',
},
has: {
'predicate-description': 'description',
'predicate-checklist': 'checklist',
'predicate-attachment': 'attachment',
},
};
const predicateTranslations = {};
Object.entries(predicates).forEach(([category, catPreds]) => {
predicateTranslations[category] = {};
Object.entries(catPreds).forEach(([tag, value]) => {
predicateTranslations[category][TAPi18n.__(tag)] = value;
});
});
// eslint-disable-next-line no-console
// console.log('predicateTranslations:', predicateTranslations);
const operatorMap = {};
Object.entries(operators).forEach(([key, value]) => {
operatorMap[TAPi18n.__(key).toLowerCase()] = value;
});
// eslint-disable-next-line no-console
// console.log('operatorMap:', operatorMap);
const params = {
limit: this.resultsPerPage,
boards: [],
swimlanes: [],
lists: [],
users: [],
members: [],
assignees: [],
labels: [],
status: [],
dueAt: null,
createdAt: null,
modifiedAt: null,
comments: [],
has: [],
};
let text = '';
while (query) {
m = query.match(reOperator1);
if (!m) {
m = query.match(reOperator2);
if (m) {
query = query.replace(reOperator2, '');
}
} else {
query = query.replace(reOperator1, '');
}
if (m) {
let op;
if (m.groups.operator) {
op = m.groups.operator.toLowerCase();
} else {
op = m.groups.abbrev.toLowerCase();
}
// eslint-disable-next-line no-prototype-builtins
if (operatorMap.hasOwnProperty(op)) {
let value = m.groups.value;
if (operatorMap[op] === 'labels') {
if (value in this.colorMap) {
value = this.colorMap[value];
// console.log('found color:', value);
}
} else if (
['dueAt', 'createdAt', 'modifiedAt'].includes(operatorMap[op])
) {
let days = parseInt(value, 10);
let duration = null;
if (isNaN(days)) {
if (predicateTranslations.durations[value]) {
duration = predicateTranslations.durations[value];
value = moment();
} else if (predicateTranslations.due[value] === 'overdue') {
value = moment();
duration = 'days';
days = 0;
} else {
this.parsingErrors.push({
tag: 'operator-number-expected',
value: { operator: op, value },
});
value = null;
}
} else {
value = moment();
}
if (value) {
if (operatorMap[op] === 'dueAt') {
value = value.add(days, duration ? duration : 'days').format();
} else {
value = value
.subtract(days, duration ? duration : 'days')
.format();
}
}
} else if (operatorMap[op] === 'sort') {
if (!predicateTranslations.sorts[value]) {
this.parsingErrors.push({
tag: 'operator-sort-invalid',
value,
});
} else {
value = predicateTranslations.sorts[value];
}
} else if (operatorMap[op] === 'status') {
if (!predicateTranslations.status[value]) {
this.parsingErrors.push({
tag: 'operator-status-invalid',
value,
});
} else {
value = predicateTranslations.status[value];
}
} else if (operatorMap[op] === 'has') {
if (!predicateTranslations.has[value]) {
this.parsingErrors.push({
tag: 'operator-has-invalid',
value,
});
} else {
value = predicateTranslations.has[value];
}
}
if (Array.isArray(params[operatorMap[op]])) {
params[operatorMap[op]].push(value);
} else {
params[operatorMap[op]] = value;
}
} else {
this.parsingErrors.push({
tag: 'operator-unknown-error',
value: op,
});
}
continue;
}
m = query.match(reQuotedText);
if (!m) {
m = query.match(reText);
if (m) {
query = query.replace(reText, '');
}
} else {
query = query.replace(reQuotedText, '');
}
if (m) {
text += (text ? ' ' : '') + m.groups.text;
}
}
const query = new Query();
query.buildParams(queryText);
// eslint-disable-next-line no-console
// console.log('text:', text);
params.text = text;
// console.log('params:', query.getParams());
// eslint-disable-next-line no-console
console.log('params:', params);
this.queryParams = query.getQueryParams().getParams();
this.queryParams = params;
if (this.parsingErrors.length) {
if (query.hasErrors()) {
this.searching.set(false);
this.queryErrors = this.parsingErrorMessages();
this.queryErrors = query.errors();
this.hasResults.set(true);
this.hasQueryErrors.set(true);
return;
}
this.autorun(() => {
const handle = Meteor.subscribe(
'globalSearch',
SessionData.getSessionId(),
params,
);
Tracker.nonreactive(() => {
Tracker.autorun(() => {
if (handle.ready()) {
this.getResults();
this.searching.set(false);
this.hasResults.set(true);
}
});
});
});
},
nextPage() {
sessionData = this.getSessionData();
const params = {
limit: this.resultsPerPage,
selector: sessionData.getSelector(),
skip: sessionData.lastHit,
};
this.autorun(() => {
const handle = Meteor.subscribe(
'globalSearch',
SessionData.getSessionId(),
params,
);
Tracker.nonreactive(() => {
Tracker.autorun(() => {
if (handle.ready()) {
this.getResults();
this.searching.set(false);
this.hasResults.set(true);
}
});
});
});
},
previousPage() {
sessionData = this.getSessionData();
const params = {
limit: this.resultsPerPage,
selector: sessionData.getSelector(),
skip:
sessionData.lastHit - sessionData.resultsCount - this.resultsPerPage,
};
this.autorun(() => {
const handle = Meteor.subscribe(
'globalSearch',
SessionData.getSessionId(),
params,
);
Tracker.nonreactive(() => {
Tracker.autorun(() => {
if (handle.ready()) {
this.getResults();
this.searching.set(false);
this.hasResults.set(true);
}
});
});
});
},
getResultsHeading() {
if (this.resultsCount === 0) {
return TAPi18n.__('no-cards-found');
} else if (this.resultsCount === 1) {
return TAPi18n.__('one-card-found');
} else if (this.resultsCount === this.totalHits) {
return TAPi18n.__('n-cards-found', this.resultsCount);
}
return TAPi18n.__('n-n-of-n-cards-found', {
start: this.resultsStart,
end: this.resultsEnd,
total: this.totalHits,
});
},
getSearchHref() {
const baseUrl = window.location.href.replace(/([?#].*$|\s*$)/, '');
return `${baseUrl}?q=${encodeURIComponent(this.query.get())}`;
},
this.runGlobalSearch(query.getQueryParams());
}
searchInstructions() {
tags = {
const tags = {
operator_board: TAPi18n.__('operator-board'),
operator_list: TAPi18n.__('operator-list'),
operator_swimlane: TAPi18n.__('operator-swimlane'),
@@ -526,11 +123,14 @@ BlazeComponent.extendComponent({
operator_member_abbrev: TAPi18n.__('operator-member-abbrev'),
operator_assignee: TAPi18n.__('operator-assignee'),
operator_assignee_abbrev: TAPi18n.__('operator-assignee-abbrev'),
operator_creator: TAPi18n.__('operator-creator'),
operator_due: TAPi18n.__('operator-due'),
operator_created: TAPi18n.__('operator-created'),
operator_modified: TAPi18n.__('operator-modified'),
operator_status: TAPi18n.__('operator-status'),
operator_has: TAPi18n.__('operator-has'),
operator_sort: TAPi18n.__('operator-sort'),
operator_limit: TAPi18n.__('operator-limit'),
predicate_overdue: TAPi18n.__('predicate-overdue'),
predicate_archived: TAPi18n.__('predicate-archived'),
predicate_all: TAPi18n.__('predicate-all'),
@@ -544,84 +144,56 @@ BlazeComponent.extendComponent({
predicate_checklist: TAPi18n.__('predicate-checklist'),
predicate_public: TAPi18n.__('predicate-public'),
predicate_private: TAPi18n.__('predicate-private'),
predicate_due: TAPi18n.__('predicate-due'),
predicate_created: TAPi18n.__('predicate-created'),
predicate_modified: TAPi18n.__('predicate-modified'),
predicate_start: TAPi18n.__('predicate-start'),
predicate_end: TAPi18n.__('predicate-end'),
predicate_assignee: TAPi18n.__('predicate-assignee'),
predicate_member: TAPi18n.__('predicate-member'),
};
text = `# ${TAPi18n.__('globalSearch-instructions-heading')}`;
text += `\n${TAPi18n.__('globalSearch-instructions-description', tags)}`;
text += `\n${TAPi18n.__('globalSearch-instructions-operators', tags)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-board',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-list',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-swimlane',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-comment',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-label',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-hash',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-user',
tags,
)}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-operator-at', tags)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-member',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-assignee',
tags,
)}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-operator-due', tags)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-created',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-operator-modified',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-status-archived',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-status-public',
tags,
)}`;
text += `\n* ${TAPi18n.__(
'globalSearch-instructions-status-private',
tags,
)}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-status-all', tags)}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-status-ended', tags)}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-operator-has', tags)}`;
text += `\n## ${TAPi18n.__('heading-notes')}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-1', tags)}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-2', tags)}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-3', tags)}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-3-2', tags)}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-4', tags)}`;
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-5', tags)}`;
let text = '';
[
['# ', 'globalSearch-instructions-heading'],
['\n', 'globalSearch-instructions-description'],
['\n\n', 'globalSearch-instructions-operators'],
['\n* ', 'globalSearch-instructions-operator-board'],
['\n* ', 'globalSearch-instructions-operator-list'],
['\n* ', 'globalSearch-instructions-operator-swimlane'],
['\n* ', 'globalSearch-instructions-operator-comment'],
['\n* ', 'globalSearch-instructions-operator-label'],
['\n* ', 'globalSearch-instructions-operator-hash'],
['\n* ', 'globalSearch-instructions-operator-user'],
['\n* ', 'globalSearch-instructions-operator-at'],
['\n* ', 'globalSearch-instructions-operator-member'],
['\n* ', 'globalSearch-instructions-operator-assignee'],
['\n* ', 'globalSearch-instructions-operator-creator'],
['\n* ', 'globalSearch-instructions-operator-due'],
['\n* ', 'globalSearch-instructions-operator-created'],
['\n* ', 'globalSearch-instructions-operator-modified'],
['\n* ', 'globalSearch-instructions-operator-status'],
['\n * ', 'globalSearch-instructions-status-archived'],
['\n * ', 'globalSearch-instructions-status-public'],
['\n * ', 'globalSearch-instructions-status-private'],
['\n * ', 'globalSearch-instructions-status-all'],
['\n * ', 'globalSearch-instructions-status-ended'],
['\n* ', 'globalSearch-instructions-operator-has'],
['\n* ', 'globalSearch-instructions-operator-sort'],
['\n* ', 'globalSearch-instructions-operator-limit'],
['\n## ', 'heading-notes'],
['\n* ', 'globalSearch-instructions-notes-1'],
['\n* ', 'globalSearch-instructions-notes-2'],
['\n* ', 'globalSearch-instructions-notes-3'],
['\n* ', 'globalSearch-instructions-notes-3-2'],
['\n* ', 'globalSearch-instructions-notes-4'],
['\n* ', 'globalSearch-instructions-notes-5'],
].forEach(([prefix, instruction]) => {
text += `${prefix}${TAPi18n.__(instruction, tags)}`;
});
return text;
},
}
labelColors() {
return Boards.simpleSchema()._schema['labels.$.color'].allowedValues.map(
@@ -629,23 +201,15 @@ BlazeComponent.extendComponent({
return { color, name: TAPi18n.__(`color-${color}`) };
},
);
},
}
events() {
return [
return super.events().concat([
{
'submit .js-search-query-form'(evt) {
evt.preventDefault();
this.searchAllBoards(evt.target.searchQuery.value);
},
'click .js-next-page'(evt) {
evt.preventDefault();
this.nextPage();
},
'click .js-previous-page'(evt) {
evt.preventDefault();
this.previousPage();
},
'click .js-label-color'(evt) {
evt.preventDefault();
const input = document.getElementById('global-search-input');
@@ -686,7 +250,16 @@ BlazeComponent.extendComponent({
);
document.getElementById('global-search-input').focus();
},
'click .js-new-search'(evt) {
evt.preventDefault();
const input = document.getElementById('global-search-input');
input.value = '';
this.query.set('');
this.hasResults.set(false);
},
},
];
},
}).register('globalSearch');
]);
}
}
GlobalSearchComponent.register('globalSearch');
+7 -4
View File
@@ -71,17 +71,17 @@
.global-search-error-messages
color: darkred
.global-search-instructions
.global-search-page
width: 40%
min-width: 400px
margin-right: auto
margin-left: auto
line-height: 150%
.global-search-instructions h1
.global-search-page h1
margin-top: 2rem;
.global-search-instructions h2
.global-search-page h2
margin-top: 1rem;
.global-search-query-input
@@ -100,7 +100,7 @@ code
color: black
background-color: lightgrey
padding: 0.1rem !important
font-size: 0.7rem !important
font-size: 0.8rem !important
.list-title
background-color: darkgray
@@ -116,3 +116,6 @@ code
.global-search-previous-page
border: none
text-align: left;
.global-search-instructions li
margin-bottom: 0.3rem
+3 -3
View File
@@ -31,12 +31,12 @@ template(name="header")
unless currentSetting.hideLogo
if currentSetting.customTopLeftCornerLogoImageUrl
if currentSetting.customTopLeftCornerLogoLinkUrl
a(href="{{currentSetting.customTopLeftCornerLogoLinkUrl}}")
a(href="{{currentSetting.customTopLeftCornerLogoLinkUrl}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}")
img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0")
unless currentSetting.customTopLeftCornerLogoLinkUrl
img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0")
img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}")
unless currentSetting.customTopLeftCornerLogoImageUrl
img(src="{{pathFor '/logo-header.png'}}" alt="")
img(src="{{pathFor '/logo-header.png'}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}")
span.allBoards
a(href="{{pathFor 'home'}}")
span.fa.fa-home
+12 -2
View File
@@ -77,8 +77,8 @@ Template.userFormsLayout.helpers({
} else if (lang.name === 'ar-EG') {
// ar-EG = Arabic (Egypt), simply Masri (مَصرى, [ˈmɑsˤɾi], Egyptian, Masr refers to Cairo)
name = 'مَصرى';
} else if (lang.name === 'es-PY') {
name = 'Español de Paraguayo';
} else if (lang.name === 'de-CH') {
name = 'Deutsch (Schweiz)';
} else if (lang.name === 'fa-IR') {
// fa-IR = Persian (Iran)
name = 'فارسی/پارسی (ایران‎)';
@@ -94,6 +94,14 @@ Template.userFormsLayout.helpers({
name = 'Latviešu';
} else if (lang.name === 'Español') {
name = 'español';
} else if (lang.name === 'es_419') {
name = 'español de América Latina';
} else if (lang.name === 'es-419') {
name = 'español de América Latina';
} else if (lang.name === 'Español de América Latina') {
name = 'español de América Latina';
} else if (lang.name === 'es-LA') {
name = 'español de América Latina';
} else if (lang.name === 'Español de Argentina') {
name = 'español de Argentina';
} else if (lang.name === 'Español de Chile') {
@@ -104,6 +112,8 @@ Template.userFormsLayout.helpers({
name = 'español de México';
} else if (lang.name === 'es-PY') {
name = 'español de Paraguayo';
} else if (lang.name === 'Español de Paraguayo') {
name = 'español de Paraguayo';
} else if (lang.name === 'Español de Perú') {
name = 'español de Perú';
} else if (lang.name === 'Español de Puerto Rico') {
+22 -56
View File
@@ -6,16 +6,6 @@ template(name="myCardsHeaderBar")
i.fa.fa-list
| {{_ 'my-cards'}}
.board-header-btns.left
a.board-header-btn.js-toggle-my-cards-choose-sort(title="{{_ 'myCardsSortChange-title'}}")
i.fa.fa-caret-down
if $eq myCardsSort 'board'
i.fa.fa-th-large
| {{_ 'myCardsSortChange-choice-board'}}
if $eq myCardsSort 'dueAt'
i.fa.fa-calendar
| {{_ 'myCardsSortChange-choice-dueat'}}
template(name="myCardsModalTitle")
if currentUser
h2
@@ -24,50 +14,26 @@ template(name="myCardsModalTitle")
template(name="myCards")
if currentUser
if isPageReady.get
.wrapper
if $eq myCardsSort 'board'
each board in myCardsList
.my-cards-board-wrapper
.my-cards-board-title(class=board.colorClass, id="header")
a(href=board.absoluteUrl)
+viewer
= board.title
each swimlane in board.mySwimlanes
.my-cards-swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}")
+viewer
= swimlane.title
each list in swimlane.myLists
.my-cards-list-wrapper
.my-cards-list-title(class=list.colorClass)
+viewer
= list.title
each card in list.myCards
.my-cards-card-wrapper
a.minicard-wrapper(href=card.absoluteUrl)
+minicard(card)
else
.my-cards-dueat-list-wrapper
each card in myDueCardsList
+resultCard(card)
else
if searching.get
+spinner
template(name="myCardsSortChangePopup")
if currentUser
ul.pop-over-list
li
with "my-cards-sort-board"
a.js-my-cards-sort-board
i.fa.fa-th-large.colorful
| {{_ 'myCardsSortChange-choice-board'}}
if $eq Utils.myCardsSort "board"
i.fa.fa-check
hr
li
with "my-cards-sort-dueat"
a.js-my-cards-sort-dueat
i.fa.fa-calendar.colorful
| {{_ 'myCardsSortChange-choice-dueat'}}
if $eq Utils.myCardsSort "dueAt"
i.fa.fa-check
else
.wrapper
each board in myCardsList
.my-cards-board-wrapper
.my-cards-board-title(class=board.colorClass, id="header")
a(href=board.originRelativeUrl)
+viewer
= board.title
each swimlane in board.mySwimlanes
.my-cards-swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}")
+viewer
= swimlane.title
each list in swimlane.myLists
.my-cards-list-wrapper
.my-cards-list-title(class=list.colorClass)
+viewer
= list.title
each card in list.myCards
.my-cards-card-wrapper
a.minicard-wrapper(href=card.originRelativeUrl)
+minicard(card)
+86 -198
View File
@@ -1,4 +1,4 @@
const subManager = new SubsManager();
import { CardSearchPagedComponent } from '../../lib/cardSearch';
BlazeComponent.extendComponent({
myCardsSort() {
@@ -24,227 +24,115 @@ Template.myCards.helpers({
},
});
BlazeComponent.extendComponent({
events() {
return [
{
'click .js-my-cards-sort-board'() {
Utils.setMyCardsSort('board');
Popup.close();
},
'click .js-my-cards-sort-dueat'() {
Utils.setMyCardsSort('dueAt');
Popup.close();
},
},
];
},
}).register('myCardsSortChangePopup');
BlazeComponent.extendComponent({
class MyCardsComponent extends CardSearchPagedComponent {
onCreated() {
this.isPageReady = new ReactiveVar(false);
super.onCreated();
this.autorun(() => {
const handle = subManager.subscribe('myCards');
Tracker.nonreactive(() => {
Tracker.autorun(() => {
this.isPageReady.set(handle.ready());
});
});
});
this.runGlobalSearch(null);
Meteor.subscribe('setting');
},
}
myCardsSort() {
// eslint-disable-next-line no-console
//console.log('sort:', Utils.myCardsSort());
return Utils.myCardsSort();
},
sortByBoard() {
return this.myCardsSort() === 'board';
},
// eslint-disable-next-line no-unused-vars
getSubscription(queryParams) {
return Meteor.subscribe(
'myCards',
this.sessionId,
this.subscriptionCallbacks,
);
}
myCardsList() {
const userId = Meteor.userId();
const boards = [];
let board = null;
let swimlane = null;
let list = null;
const cursor = Cards.find(
{
$or: [{ members: userId }, { assignees: userId }],
archived: false,
},
{
sort: {
boardId: 1,
swimlaneId: 1,
listId: 1,
sort: 1,
},
},
);
const cursor = this.getResults();
let newBoard = false;
let newSwimlane = false;
let newList = false;
cursor.forEach(card => {
// eslint-disable-next-line no-console
// console.log('card:', card.title);
if (list === null || card.listId !== list._id) {
if (cursor) {
cursor.forEach(card => {
// eslint-disable-next-line no-console
// console.log('new list');
list = card.getList();
if (list.archived) {
list = null;
return;
}
list.myCards = [card];
newList = true;
}
if (swimlane === null || card.swimlaneId !== swimlane._id) {
// eslint-disable-next-line no-console
// console.log('new swimlane');
swimlane = card.getSwimlane();
if (swimlane.archived) {
// console.log('card:', card.title);
if (board === null || card.boardId !== board._id) {
// eslint-disable-next-line no-console
// console.log('new board');
board = card.getBoard();
if (board.archived) {
board = null;
return;
}
// eslint-disable-next-line no-console
// console.log('board:', b, b._id, b.title);
boards.push(board);
board.mySwimlanes = [];
swimlane = null;
return;
list = null;
}
if (swimlane === null || card.swimlaneId !== swimlane._id) {
// eslint-disable-next-line no-console
// console.log('new swimlane');
swimlane = card.getSwimlane();
if (swimlane.archived) {
swimlane = null;
return;
}
board.mySwimlanes.push(swimlane);
swimlane.myLists = [];
list = null;
}
if (list === null || card.listId !== list._id) {
// eslint-disable-next-line no-console
// console.log('new list');
list = card.getList();
if (list.archived) {
list = null;
return;
}
swimlane.myLists.push(list);
list.myCards = [];
}
swimlane.myLists = [list];
newSwimlane = true;
}
if (board === null || card.boardId !== board._id) {
// eslint-disable-next-line no-console
// console.log('new board');
board = card.getBoard();
if (board.archived) {
board = null;
return;
}
// eslint-disable-next-line no-console
// console.log('board:', b, b._id, b.title);
board.mySwimlanes = [swimlane];
newBoard = true;
}
if (newBoard) {
boards.push(board);
} else if (newSwimlane) {
board.mySwimlanes.push(swimlane);
} else if (newList) {
swimlane.myLists.push(list);
} else {
list.myCards.push(card);
}
});
newBoard = false;
newSwimlane = false;
newList = false;
});
// sort the data structure
boards.forEach(board => {
board.mySwimlanes.forEach(swimlane => {
swimlane.myLists.forEach(list => {
list.myCards.sort((a, b) => {
// sort the data structure
boards.forEach(board => {
board.mySwimlanes.forEach(swimlane => {
swimlane.myLists.forEach(list => {
list.myCards.sort((a, b) => {
return a.sort - b.sort;
});
});
swimlane.myLists.sort((a, b) => {
return a.sort - b.sort;
});
});
swimlane.myLists.sort((a, b) => {
board.mySwimlanes.sort((a, b) => {
return a.sort - b.sort;
});
});
board.mySwimlanes.sort((a, b) => {
return a.sort - b.sort;
boards.sort((a, b) => {
let x = a.sort;
let y = b.sort;
// show the template board last
if (a.type === 'template-container') {
x = 99999999;
} else if (b.type === 'template-container') {
y = 99999999;
}
return x - y;
});
});
boards.sort((a, b) => {
let x = a.sort;
let y = b.sort;
// eslint-disable-next-line no-console
// console.log('boards:', boards);
return boards;
}
// show the template board last
if (a.type === 'template-container') {
x = 99999999;
} else if (b.type === 'template-container') {
y = 99999999;
}
return x - y;
});
// eslint-disable-next-line no-console
// console.log('boards:', boards);
return boards;
},
myDueCardsList() {
const userId = Meteor.userId();
const cursor = Cards.find(
{
$or: [{ members: userId }, { assignees: userId }],
archived: false,
},
{
sort: {
dueAt: -1,
boardId: 1,
swimlaneId: 1,
listId: 1,
sort: 1,
},
},
);
// eslint-disable-next-line no-console
// console.log('cursor:', cursor);
const cards = [];
cursor.forEach(card => {
if (
!card.getBoard().archived &&
!card.getSwimlane().archived &&
!card.getList().archived
) {
cards.push(card);
}
});
cards.sort((a, b) => {
const x = a.dueAt === null ? Date('2100-12-31') : a.dueAt;
const y = b.dueAt === null ? Date('2100-12-31') : b.dueAt;
if (x > y) return 1;
else if (x < y) return -1;
return 0;
});
// eslint-disable-next-line no-console
// console.log('cursor:', cards);
return cards;
},
events() {
return [
{
// 'click .js-my-card'(evt) {
// const card = this.currentData().card;
// // eslint-disable-next-line no-console
// console.log('currentData():', this.currentData());
// // eslint-disable-next-line no-console
// console.log('card:', card);
// if (card) {
// Utils.goCardId(card._id);
// }
// evt.preventDefault();
// },
},
];
},
}).register('myCards');
return [];
}
}
MyCardsComponent.register('myCards');
+5
View File
@@ -0,0 +1,5 @@
template(name="spinner")
+Template.dynamic(template=getSpinnerTemplate)
template(name="spinnerRaw")
+Template.dynamic(template=getSpinnerTemplateRaw)
+11
View File
@@ -0,0 +1,11 @@
import { Spinner } from '/client/lib/spinner';
(class extends Spinner {
}.register('spinner'));
(class extends Spinner {
getSpinnerTemplateRaw() {
let ret = super.getSpinnerTemplate() + 'Raw';
return ret;
}
}.register('spinnerRaw'));
-6
View File
@@ -1,6 +0,0 @@
.sk-spinner.sk-spinner-wave(class=currentBoard.colorClass)
.sk-rect1
.sk-rect2
.sk-rect3
.sk-rect4
.sk-rect5
@@ -0,0 +1,11 @@
template(name="spinnerBounce")
.sk-spinner.sk-spinner-bounce(class=currentBoard.colorClass)
+spinnerBounceRaw
template(name="spinnerBounceRaw")
.sk-bounce1
| &nbsp;
.sk-bounce2
| &nbsp;
.sk-bounce3
| &nbsp;
@@ -0,0 +1,44 @@
@import 'nib'
// From https://github.com/tobiasahlin/SpinKit
.sk-spinner-bounce {
margin: 100px auto 0;
width: 70px;
text-align: center;
div {
width: 18px;
height: 18px;
background-color: #333;
border-radius: 100%;
display: inline-block;
-webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both;
animation: sk-bouncedelay 1.4s infinite ease-in-out both;
}
.sk-bounce1 {
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
.sk-bounce2 {
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
}
@-webkit-keyframes sk-bouncedelay {
0%, 80%, 100% { -webkit-transform: scale(0) }
40% { -webkit-transform: scale(1.0) }
}
@keyframes sk-bouncedelay {
0%, 80%, 100% {
-webkit-transform: scale(0);
transform: scale(0);
} 40% {
-webkit-transform: scale(1.0);
transform: scale(1.0);
}
}
+8
View File
@@ -0,0 +1,8 @@
template(name="spinnerCube")
.sk-spinner.sk-spinner-cube(class=currentBoard.colorClass)
+spinnerCubeRaw
template(name="spinnerCubeRaw")
.sk-cube1
.sk-cube2
.sk-cube3
+52
View File
@@ -0,0 +1,52 @@
@import 'nib'
// From https://github.com/tobiasahlin/SpinKit
.sk-spinner-cube {
margin: 100px auto;
width: 40px;
height: 40px;
position: relative;
}
.sk-cube1, .sk-cube2 {
background-color: #333;
width: 15px;
height: 15px;
position: absolute;
top: 0;
left: 0;
-webkit-animation: sk-cubemove 1.8s infinite ease-in-out;
animation: sk-cubemove 1.8s infinite ease-in-out;
}
.sk-cube2 {
-webkit-animation-delay: -0.9s;
animation-delay: -0.9s;
}
@-webkit-keyframes sk-cubemove {
25% { -webkit-transform: translateX(35px) rotate(-90deg) scale(0.5) }
50% { -webkit-transform: translateX(35px) translateY(35px) rotate(-180deg) }
75% { -webkit-transform: translateX(0px) translateY(35px) rotate(-270deg) scale(0.5) }
100% { -webkit-transform: rotate(-360deg) }
}
@keyframes sk-cubemove {
25% {
transform: translateX(35px) rotate(-90deg) scale(0.5);
-webkit-transform: translateX(35px) rotate(-90deg) scale(0.5);
} 50% {
transform: translateX(35px) translateY(35px) rotate(-179deg);
-webkit-transform: translateX(35px) translateY(35px) rotate(-179deg);
} 50.1% {
transform: translateX(35px) translateY(35px) rotate(-180deg);
-webkit-transform: translateX(35px) translateY(35px) rotate(-180deg);
} 75% {
transform: translateX(0px) translateY(35px) rotate(-270deg) scale(0.5);
-webkit-transform: translateX(0px) translateY(35px) rotate(-270deg) scale(0.5);
} 100% {
transform: rotate(-360deg);
-webkit-transform: rotate(-360deg);
}
}
@@ -0,0 +1,14 @@
template(name="spinnerCubeGrid")
.sk-spinner.sk-spinner-cube-grid(class=currentBoard.colorClass)
+spinnerCubeGridRaw
template(name="spinnerCubeGridRaw")
.sk-cube-grid.sk-cube-grid1
.sk-cube-grid.sk-cube-grid2
.sk-cube-grid.sk-cube-grid3
.sk-cube-grid.sk-cube-grid4
.sk-cube-grid.sk-cube-grid5
.sk-cube-grid.sk-cube-grid6
.sk-cube-grid.sk-cube-grid7
.sk-cube-grid.sk-cube-grid8
.sk-cube-grid.sk-cube-grid9
@@ -0,0 +1,64 @@
@import 'nib'
// From https://github.com/tobiasahlin/SpinKit
.sk-spinner-cube-grid {
width: 40px;
height: 40px;
margin: 100px auto;
}
.sk-spinner-cube-grid .sk-cube-grid {
width: 33%;
height: 33%;
background-color: #333;
float: left;
-webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
}
.sk-spinner-cube-grid .sk-cube-grid1 {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s; }
.sk-spinner-cube-grid .sk-cube-grid2 {
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s; }
.sk-spinner-cube-grid .sk-cube-grid3 {
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s; }
.sk-spinner-cube-grid .sk-cube-grid4 {
-webkit-animation-delay: 0.1s;
animation-delay: 0.1s; }
.sk-spinner-cube-grid .sk-cube-grid5 {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s; }
.sk-spinner-cube-grid .sk-cube-grid6 {
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s; }
.sk-spinner-cube-grid .sk-cube-grid7 {
-webkit-animation-delay: 0s;
animation-delay: 0s; }
.sk-spinner-cube-grid .sk-cube-grid8 {
-webkit-animation-delay: 0.1s;
animation-delay: 0.1s; }
.sk-spinner-cube-grid .sk-cube-grid9 {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s; }
@-webkit-keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1);
} 35% {
-webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1);
}
}
@keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1);
} 35% {
-webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1);
}
}
+7
View File
@@ -0,0 +1,7 @@
template(name="spinnerDot")
.sk-spinner.sk-spinner-dot(class=currentBoard.colorClass)
+spinnerDotRaw
template(name="spinnerDotRaw")
.sk-dot1
.sk-dot2
+51
View File
@@ -0,0 +1,51 @@
@import 'nib'
// From https://github.com/tobiasahlin/SpinKit
.sk-spinner-dot {
margin: 100px auto;
width: 40px;
height: 40px;
position: relative;
text-align: center;
-webkit-animation: sk-rotate 2.0s infinite linear;
animation: sk-rotate 2.0s infinite linear;
}
.sk-dot1, .sk-dot2 {
width: 40%;
height: 40%;
display: inline-block;
position: absolute;
top: 0;
background-color: #333;
border-radius: 100%;
-webkit-animation: sk-bounce 2.0s infinite ease-in-out;
animation: sk-bounce 2.0s infinite ease-in-out;
}
.sk-dot2 {
top: auto;
bottom: 0;
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
@-webkit-keyframes sk-rotate { 100% { -webkit-transform: rotate(360deg) }}
@keyframes sk-rotate { 100% { transform: rotate(360deg); -webkit-transform: rotate(360deg) }}
@-webkit-keyframes sk-bounce {
0%, 100% { -webkit-transform: scale(0.0) }
50% { -webkit-transform: scale(1.0) }
}
@keyframes sk-bounce {
0%, 100% {
transform: scale(0.0);
-webkit-transform: scale(0.0);
} 50% {
transform: scale(1.0);
-webkit-transform: scale(1.0);
}
}
@@ -0,0 +1,7 @@
template(name="spinnerDoubleBounce")
.sk-spinner.sk-spinner-double-bounce(class=currentBoard.colorClass)
+spinnerDoubleBounceRaw
template(name="spinnerDoubleBounceRaw")
.sk-double-bounce1
.sk-double-bounce2
@@ -0,0 +1,44 @@
@import 'nib'
// From https://github.com/tobiasahlin/SpinKit
.sk-spinner-double-bounce {
width: 40px;
height: 40px;
position: relative;
margin: 100px auto;
}
.sk-double-bounce1, .sk-double-bounce2 {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #333;
opacity: 0.6;
position: absolute;
top: 0;
left: 0;
-webkit-animation: sk-bounce 2.0s infinite ease-in-out;
animation: sk-bounce 2.0s infinite ease-in-out;
}
.sk-double-bounce2 {
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
@-webkit-keyframes sk-bounce {
0%, 100% { -webkit-transform: scale(0.0) }
50% { -webkit-transform: scale(1.0) }
}
@keyframes sk-bounce {
0%, 100% {
transform: scale(0.0);
-webkit-transform: scale(0.0);
} 50% {
transform: scale(1.0);
-webkit-transform: scale(1.0);
}
}
@@ -0,0 +1,6 @@
template(name="spinnerRotateplane")
.sk-spinner.sk-spinner-rotateplane(class=currentBoard.colorClass)
+spinnerRotateplaneRaw
template(name="spinnerRotateplaneRaw")
.sk-rotateplane1
@@ -0,0 +1,38 @@
@import 'nib'
// From https://github.com/tobiasahlin/SpinKit
.sk-spinner-rotateplane {
width: 40px;
height: 40px;
text-align: center;
margin: 100px auto;
-webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
animation: sk-rotateplane 1.2s infinite ease-in-out;
div {
background-color: #333;
height: 100%;
width: 100%;
display: inline-block;
}
}
@-webkit-keyframes sk-rotateplane {
0% { -webkit-transform: perspective(120px) }
50% { -webkit-transform: perspective(120px) rotateY(180deg) }
100% { -webkit-transform: perspective(120px) rotateY(180deg) rotateX(180deg) }
}
@keyframes sk-rotateplane {
0% {
transform: perspective(120px) rotateX(0deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg)
} 50% {
transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
-webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg)
} 100% {
transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
-webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
}
}
@@ -0,0 +1,6 @@
template(name="spinnerScaleout")
.sk-spinner.sk-spinner-scaleout(class=currentBoard.colorClass)
+spinnerScaleoutRaw
template(name="spinnerScaleoutRaw")
.sk-scaleout1
@@ -0,0 +1,40 @@
@import 'nib'
// From https://github.com/tobiasahlin/SpinKit
.sk-spinner-scaleout {
width: 40px;
height: 40px;
text-align: center;
margin: 100px auto;
border-radius: 100%;
-webkit-animation: sk-scaleout 1.0s infinite ease-in-out;
animation: sk-scaleout 1.0s infinite ease-in-out;
div {
background-color: #333;
height: 100%;
width: 100%;
display: inline-block;
}
}
@-webkit-keyframes sk-scaleout {
0% { -webkit-transform: scale(0) }
100% {
-webkit-transform: scale(1.0);
opacity: 0;
}
}
@keyframes sk-scaleout {
0% {
-webkit-transform: scale(0);
transform: scale(0);
} 100% {
-webkit-transform: scale(1.0);
transform: scale(1.0);
opacity: 0;
}
}
+15
View File
@@ -0,0 +1,15 @@
template(name="spinnerWave")
.sk-spinner.sk-spinner-wave(class=currentBoard.colorClass)
+spinnerWaveRaw
template(name="spinnerWaveRaw")
.sk-rect1
| &nbsp;
.sk-rect2
| &nbsp;
.sk-rect3
| &nbsp;
.sk-rect4
| &nbsp;
.sk-rect5
| &nbsp;
@@ -1,21 +1,7 @@
@import 'nib'
/*
* From https://github.com/tobiasahlin/SpinKit
*
* Usage:
*
* <div class="sk-spinner sk-spinner-wave">
* <div class="sk-rect1"></div>
* <div class="sk-rect2"></div>
* <div class="sk-rect3"></div>
* <div class="sk-rect4"></div>
* <div class="sk-rect5"></div>
* </div>
*
*/
.sk-spinner {
// From https://github.com/tobiasahlin/SpinKit
.sk-spinner-wave {
width: 50px;
height: 50px;
margin: auto;
@@ -1,5 +1,5 @@
template(name='notifications')
#notifications.board-header-btns.right
a.notifications-drawer-toggle.fa.fa-bell(class="{{#if $gt unreadNotifications 0}}alert{{/if}}")
a.notifications-drawer-toggle.fa.fa-bell(class="{{#if $gt unreadNotifications 0}}alert{{/if}}" title="{{_ 'notifications'}}")
if $.Session.get 'showNotificationsDrawer'
+notificationsDrawer(unreadNotifications=unreadNotifications)
Binary file not shown.
@@ -0,0 +1,111 @@
template(name="adminReports")
.setting-content
unless currentUser.isAdmin
| {{_ 'error-notAuthorized'}}
else
.content-body
.side-menu
ul
li
a.js-report-broken(data-id="report-broken")
i.fa.fa-chain-broken
| {{_ 'broken-cards'}}
li
a.js-report-files(data-id="report-orphaned-files")
i.fa.fa-paperclip
| {{_ 'orphanedFilesReportTitle'}}
li
a.js-report-files(data-id="report-files")
i.fa.fa-paperclip
| {{_ 'filesReportTitle'}}
li
a.js-report-rules(data-id="report-rules")
i.fa.fa-magic
| {{_ 'rulesReportTitle'}}
.main-body
if loading.get
+spinner
else if showBrokenCardsReport.get
+brokenCardsReport
else if showFilesReport.get
+filesReport
else if showOrphanedFilesReport.get
+orphanedFilesReport
else if showRulesReport.get
+rulesReport
template(name="brokenCardsReport")
.global-search-results-list-wrapper
h1 {{_ 'broken-cards'}}
if resultsCount
+resultsPaged(this)
else
div {{_ 'no-results' }}
template(name="rulesReport")
h1 {{_ 'rulesReportTitle'}}
if resultsCount
table.table
tr
th Rule Title
th Board Title
th actionType
th activityType
each rule in rows
tr
td {{ rule.title }}
td {{ rule.boardTitle }}
td {{ rule.action.actionType }}
td {{ rule.trigger.activityType }}
else
div {{_ 'no-results' }}
template(name="filesReport")
h1 {{_ 'filesReportTitle'}}
if resultsCount
table.table
tr
th Filename
th.right Size (kB)
th MIME Type
th.center Usage
th MD5 Sum
th ID
each att in attachmentFiles
tr
td {{ att.filename }}
td.right {{fileSize att.length }}
td {{ att.contentType }}
td.center {{usageCount att._id.toHexString }}
td {{ att.md5 }}
td {{ att._id.toHexString }}
else
div {{_ 'no-results' }}
template(name="orphanedFilesReport")
h1 {{_ 'orphanedFilesReportTitle'}}
if resultsCount
table.table
tr
th Filename
th.right Size (kB)
th MIME Type
th MD5 Sum
th ID
each att in attachmentFiles
tr
td {{ att.filename }}
td.right {{fileSize att.length }}
td {{ att.contentType }}
td {{ att.md5 }}
td {{ att._id.toHexString }}
else
div {{_ 'no-results' }}
+156
View File
@@ -0,0 +1,156 @@
import { AttachmentStorage } from '/models/attachments';
import { CardSearchPagedComponent } from '/client/lib/cardSearch';
import SessionData from '/models/usersessiondata';
BlazeComponent.extendComponent({
subscription: null,
showFilesReport: new ReactiveVar(false),
showBrokenCardsReport: new ReactiveVar(false),
showOrphanedFilesReport: new ReactiveVar(false),
showRulesReport: new ReactiveVar(false),
onCreated() {
this.error = new ReactiveVar('');
this.loading = new ReactiveVar(false);
},
events() {
return [
{
'click a.js-report-broken': this.switchMenu,
'click a.js-report-files': this.switchMenu,
'click a.js-report-orphaned-files': this.switchMenu,
'click a.js-report-rules': this.switchMenu,
},
];
},
switchMenu(event) {
const target = $(event.target);
if (!target.hasClass('active')) {
this.loading.set(true);
this.showFilesReport.set(false);
this.showBrokenCardsReport.set(false);
this.showOrphanedFilesReport.set(false);
if (this.subscription) {
this.subscription.stop();
}
$('.side-menu li.active').removeClass('active');
target.parent().addClass('active');
const targetID = target.data('id');
if ('report-broken' === targetID) {
this.showBrokenCardsReport.set(true);
this.subscription = Meteor.subscribe(
'brokenCards',
SessionData.getSessionId(),
() => {
this.loading.set(false);
},
);
} else if ('report-files' === targetID) {
this.showFilesReport.set(true);
this.subscription = Meteor.subscribe('attachmentsList', () => {
this.loading.set(false);
});
} else if ('report-orphaned-files' === targetID) {
this.showOrphanedFilesReport.set(true);
this.subscription = Meteor.subscribe('orphanedAttachments', () => {
this.loading.set(false);
});
} else if ('report-rules' === targetID) {
this.subscription = Meteor.subscribe('rulesReport', () => {
this.showRulesReport.set(true);
this.loading.set(false);
});
}
}
},
}).register('adminReports');
Template.filesReport.helpers({
attachmentFiles() {
// eslint-disable-next-line no-console
// console.log('attachments:', AttachmentStorage.find());
// console.log('attachments.count:', AttachmentStorage.find().count());
return AttachmentStorage.find();
},
rulesReport() {
const rules = [];
Rules.find().forEach(rule => {
rules.push({
_id: rule._id,
title: rule.title,
boardId: rule.boardId,
boardTitle: rule.board().title,
action: rule.action().fetch(),
trigger: rule.trigger().fetch(),
});
});
return rules;
},
resultsCount() {
return AttachmentStorage.find().count();
},
fileSize(size) {
return Math.round(size / 1024);
},
usageCount(key) {
return Attachments.find({ 'copies.attachments.key': key }).count();
},
});
Template.orphanedFilesReport.helpers({
attachmentFiles() {
// eslint-disable-next-line no-console
// console.log('attachments:', AttachmentStorage.find());
// console.log('attachments.count:', AttachmentStorage.find().count());
return AttachmentStorage.find();
},
resultsCount() {
return AttachmentStorage.find().count();
},
fileSize(size) {
return Math.round(size / 1024);
},
});
Template.rulesReport.helpers({
rows() {
const rules = [];
Rules.find().forEach(rule => {
rules.push({
_id: rule._id,
title: rule.title,
boardId: rule.boardId,
boardTitle: rule.board().title,
action: rule.action(),
trigger: rule.trigger(),
});
});
console.log('rows:', rules);
return rules;
},
resultsCount() {
return Rules.find().count();
},
});
class BrokenCardsComponent extends CardSearchPagedComponent {
onCreated() {
super.onCreated();
}
}
BrokenCardsComponent.register('brokenCardsReport');
+110 -54
View File
@@ -110,6 +110,8 @@ template(name="peopleGeneral")
th {{_ 'active'}}
th {{_ 'authentication-method'}}
th {{_ 'import-usernames'}}
th {{_ 'organizations'}}
th {{_ 'teams'}}
th
+newUserRow
each user in peopleList
@@ -117,43 +119,43 @@ template(name="peopleGeneral")
template(name="newOrgRow")
a.new-org
i.fa.fa-edit
i.fa.fa-plus-square
| {{_ 'new'}}
template(name="newTeamRow")
a.new-team
i.fa.fa-edit
i.fa.fa-plus-square
| {{_ 'new'}}
template(name="newUserRow")
a.new-user
i.fa.fa-edit
i.fa.fa-plus-square
| {{_ 'new'}}
template(name="orgRow")
tr
if orgData.loginDisabled
if orgData.orgIsActive
td <s>{{ orgData.orgDisplayName }}</s>
else
td {{ orgData.orgDisplayName }}
if orgData.loginDisabled
if orgData.orgIsActive
td <s>{{ orgData.orgDesc }}</s>
else
td {{ orgData.orgDesc }}
if orgData.loginDisabled
td <s>{{ orgData.orgName }}</s>
if orgData.orgIsActive
td <s>{{ orgData.orgShortName }}</s>
else
td {{ orgData.orgName }}
if orgData.loginDisabled
td {{ orgData.orgShortName }}
if orgData.orgIsActive
td <s>{{ orgData.orgWebsite }}</s>
else
td {{ orgData.orgWebsite }}
if orgData.loginDisabled
if orgData.orgIsActive
td <s>{{ moment orgData.createdAt 'LLL' }}</s>
else
td {{ moment orgData.createdAt 'LLL' }}
td
if orgData.loginDisabled
if orgData.orgIsActive
| {{_ 'no'}}
else
| {{_ 'yes'}}
@@ -166,28 +168,28 @@ template(name="orgRow")
template(name="teamRow")
tr
if teamData.loginDisabled
if teamData.teamIsActive
td <s>{{ teamData.teamDisplayName }}</s>
else
td {{ teamData.teamDisplayName }}
if teamData.loginDisabled
if teamData.teamIsActive
td <s>{{ teamData.teamDesc }}</s>
else
td {{ teamData.teamDesc }}
if teamData.loginDisabled
td <s>{{ teamData.teamName }}</s>
if teamData.teamIsActive
td <s>{{ teamData.teamShortName }}</s>
else
td {{ teamData.teamName }}
if teamData.loginDisabled
td {{ teamData.teamShortName }}
if teamData.teamIsActive
td <s>{{ teamData.teamWebsite }}</s>
else
td {{ teamData.teamWebsite }}
if orgData.loginDisabled
if teamData.teamIsActive
td <s>{{ moment teamData.createdAt 'LLL' }}</s>
else
td {{ moment teamData.createdAt 'LLL' }}
td
if teamData.loginDisabled
if teamData.teamIsActive
| {{_ 'no'}}
else
| {{_ 'yes'}}
@@ -257,6 +259,14 @@ template(name="peopleRow")
td <s>{{ userData.importUsernamesString }}</s>
else
td {{ userData.importUsernamesString }}
if userData.loginDisabled
td <s>{{ userData.orgsUserBelongs }}</s>
else
td {{ userData.orgsUserBelongs }}
if userData.loginDisabled
td <s>{{ userData.teamsUserBelongs }}</s>
else
td {{ userData.teamsUserBelongs }}
td
a.edit-user
i.fa.fa-edit
@@ -269,7 +279,7 @@ template(name="editOrgPopup")
label.hide.orgId(type="text" value=org._id)
label
| {{_ 'displayName'}}
input.js-orgDisplayName(type="text" value=org.displayName required)
input.js-orgDisplayName(type="text" value=org.orgDisplayName required)
span.error.hide.orgname-taken
| {{_ 'error-orgname-taken'}}
label
@@ -285,7 +295,7 @@ template(name="editOrgPopup")
| {{_ 'active'}}
select.select-active.js-org-isactive
option(value="false") {{_ 'yes'}}
option(value="true" selected="{{org.loginDisabled}}") {{_ 'no'}}
option(value="true" selected="{{org.orgIsActive}}") {{_ 'no'}}
hr
div.buttonsContainer
input.primary.wide(type="submit" value="{{_ 'save'}}")
@@ -311,7 +321,7 @@ template(name="editTeamPopup")
| {{_ 'active'}}
select.select-active.js-team-isactive
option(value="false") {{_ 'yes'}}
option(value="true" selected="{{team.loginDisabled}}") {{_ 'no'}}
option(value="true" selected="{{team.teamIsActive}}") {{_ 'no'}}
hr
div.buttonsContainer
input.primary.wide(type="submit" value="{{_ 'save'}}")
@@ -367,6 +377,27 @@ template(name="editUserPopup")
option(value="{{value}}" selected) {{_ value}}
else
option(value="{{value}}") {{_ value}}
label
| {{_ 'organizations'}}
i.fa.fa-plus-square#addUserOrg
i.fa.fa-minus-square#removeUserOrg
select.js-orgs#jsOrgs
option(value="-1") {{_ 'organizations'}} :
each value in orgsDatas
option(value="{{value._id}}") {{_ value.orgDisplayName}}
input#jsUserOrgsInPut.js-userOrgs(type="text" value=user.orgsUserBelongs, disabled)
input#jsUserOrgIdsInPut.js-userOrgIds.hide(type="text" value=user.orgIdsUserBelongs)
label
| {{_ 'teams'}}
i.fa.fa-plus-square#addUserTeam
i.fa.fa-minus-square#removeUserTeam
select.js-teams#jsTeams
option(value="-1") {{_ 'teams'}} :
each value in teamsDatas
option(value="{{value._id}}") {{_ value.teamDisplayName}}
input#jsUserTeamsInPut.js-userteams(type="text" value=user.teamsUserBelongs, disabled)
input#jsUserTeamIdsInPut.js-userteamIds.hide(type="text" value=user.teamIdsUserBelongs)
hr
label
| {{_ 'password'}}
@@ -385,7 +416,7 @@ template(name="newOrgPopup")
input.js-orgDesc(type="text" value="" required)
label
| {{_ 'shortName'}}
input.js-orgName(type="text" value="" required)
input.js-orgShortName(type="text" value="" required)
label
| {{_ 'website'}}
input.js-orgWebsite(type="text" value="" required)
@@ -409,7 +440,7 @@ template(name="newTeamPopup")
input.js-teamDesc(type="text" value="" required)
label
| {{_ 'shortName'}}
input.js-teamName(type="text" value="" required)
input.js-teamShortName(type="text" value="" required)
label
| {{_ 'website'}}
input.js-teamWebsite(type="text" value="" required)
@@ -468,6 +499,27 @@ template(name="newUserPopup")
option(value="{{value}}" selected) {{_ value}}
else
option(value="{{value}}") {{_ value}}
label
| {{_ 'organizations'}}
i.fa.fa-plus-square#addUserOrgNewUser
i.fa.fa-minus-square#removeUserOrgNewUser
select.js-orgsNewUser#jsOrgsNewUser
option(value="-1") {{_ 'organizations'}} :
each value in orgsDatas
option(value="{{value._id}}") {{_ value.orgDisplayName}}
input#jsUserOrgsInPutNewUser.js-userOrgsNewUser(type="text" value=user.orgsUserBelongs, disabled)
input#jsUserOrgIdsInPutNewUser.js-userOrgIdsNewUser.hide(type="text" value=user.orgIdsUserBelongs)
label
| {{_ 'teams'}}
i.fa.fa-plus-square#addUserTeamNewUser
i.fa.fa-minus-square#removeUserTeamNewUser
select.js-teamsNewUser#jsTeamsNewUser
option(value="-1") {{_ 'teams'}} :
each value in teamsDatas
option(value="{{value._id}}") {{_ value.teamDisplayName}}
input#jsUserTeamsInPutNewUser.js-userteamsNewUser(type="text" value=user.teamsUserBelongs, disabled)
input#jsUserTeamIdsInPutNewUser.js-userteamIdsNewUser.hide(type="text" value=user.teamIdsUserBelongs)
hr
label
| {{_ 'password'}}
@@ -478,27 +530,34 @@ template(name="newUserPopup")
template(name="settingsOrgPopup")
ul.pop-over-list
li
a.impersonate-org
i.fa.fa-user
| {{_ 'impersonate-org'}}
// Delete is not enabled yet, because it does leave empty user avatars
// to boards: boards members, card members and assignees have
// empty users. See:
// - wekan/client/components/settings/peopleBody.jade deleteButton
// - wekan/client/components/settings/peopleBody.js deleteButton
// - wekan/client/components/sidebar/sidebar.js Popup.afterConfirm('removeMember'
// that does now remove member from board, card members and assignees correctly,
// but that should be used to remove user from all boards similarly
// - wekan/models/users.js Delete is not enabled
//li
// br
// br
// hr
//li
// form
// label.hide.userId(type="text" value=user._id)
// div.buttonsContainer
// input#deleteButton.card-details-red.right.wide(type="button" value="{{_ 'delete'}}")
form
label
| {{_ 'delete-org-confirm-popup'}}
br
label.hide.orgId(type="text" value=org._id)
labeldelete-org-confirm-popup
div.buttonsContainer
input#deleteButton.card-details-red.right.wide(type="button" value="{{_ 'delete'}}")
// It's not yet possible to impersonate organization. Only impersonate user,
// because that changes current user ID. What would it mean in practice
// to impersonate organization?
// li
// a.impersonate-org
// i.fa.fa-user
// | {{_ 'impersonate-org'}}
//
//
template(name="settingsTeamPopup")
ul.pop-over-list
li
form
label
| {{_ 'delete-team-confirm-popup'}}
br
label.hide.teamId(type="text" value=team._id)
div.buttonsContainer
input#deleteButton.card-details-red.right.wide(type="button" value="{{_ 'delete'}}")
template(name="settingsUserPopup")
ul.pop-over-list
@@ -506,6 +565,12 @@ template(name="settingsUserPopup")
a.impersonate-user
i.fa.fa-user
| {{_ 'impersonate-user'}}
//hr
//li
// form
// label.hide.userId(type="text" value=user._id)
// div.buttonsContainer
// input#deleteButton.card-details-red.right.wide(type="button" value="{{_ 'delete'}}")
// Delete is not enabled yet, because it does leave empty user avatars
// to boards: boards members, card members and assignees have
// empty users. See:
@@ -515,12 +580,3 @@ template(name="settingsUserPopup")
// that does now remove member from board, card members and assignees correctly,
// but that should be used to remove user from all boards similarly
// - wekan/models/users.js Delete is not enabled
//li
// br
// br
// hr
//li
// form
// label.hide.userId(type="text" value=user._id)
// div.buttonsContainer
// input#deleteButton.card-details-red.right.wide(type="button" value="{{_ 'delete'}}")
+317 -92
View File
@@ -1,6 +1,7 @@
const orgsPerPage = 25;
const teamsPerPage = 25;
const usersPerPage = 25;
let userOrgsTeamsAction = ""; //poosible actions 'addOrg', 'addTeam', 'removeOrg' or 'removeTeam' when adding or modifying a user
BlazeComponent.extendComponent({
mixins() {
@@ -101,9 +102,7 @@ BlazeComponent.extendComponent({
];
},
filterPeople() {
const value = $('#searchInput')
.first()
.val();
const value = $('#searchInput').first().val();
if (value === '') {
this.findUsersOptions.set({});
} else {
@@ -150,7 +149,7 @@ BlazeComponent.extendComponent({
const teams = Team.find(this.findTeamsOptions.get(), {
fields: { _id: true },
});
this.numberTeams.set(team.count(false));
this.numberTeams.set(teams.count(false));
return teams;
},
peopleList() {
@@ -203,7 +202,7 @@ Template.peopleRow.helpers({
},
});
Template.editUserPopup.onCreated(function() {
Template.editUserPopup.onCreated(function () {
this.authenticationMethods = new ReactiveVar([]);
this.errorMessage = new ReactiveVar('');
@@ -215,8 +214,8 @@ Template.editUserPopup.onCreated(function() {
{ value: 'password' },
// Gets only the authentication methods availables
...Object.entries(result)
.filter(e => e[1])
.map(e => ({ value: e[0] })),
.filter((e) => e[1])
.map((e) => ({ value: e[0] })),
]);
}
});
@@ -247,6 +246,12 @@ Template.editUserPopup.helpers({
authentications() {
return Template.instance().authenticationMethods.get();
},
orgsDatas() {
return Org.find({}, {sort: { createdAt: -1 }});
},
teamsDatas() {
return Team.find({}, {sort: { createdAt: -1 }});
},
isSelected(match) {
const userId = Template.instance().data.userId;
const selected = Users.findOne(userId).authenticationMethod;
@@ -262,15 +267,15 @@ Template.editUserPopup.helpers({
},
});
Template.newOrgPopup.onCreated(function() {
Template.newOrgPopup.onCreated(function () {
this.errorMessage = new ReactiveVar('');
});
Template.newTeamPopup.onCreated(function() {
Template.newTeamPopup.onCreated(function () {
this.errorMessage = new ReactiveVar('');
});
Template.newUserPopup.onCreated(function() {
Template.newUserPopup.onCreated(function () {
this.authenticationMethods = new ReactiveVar([]);
this.errorMessage = new ReactiveVar('');
@@ -282,8 +287,8 @@ Template.newUserPopup.onCreated(function() {
{ value: 'password' },
// Gets only the authentication methods availables
...Object.entries(result)
.filter(e => e[1])
.map(e => ({ value: e[0] })),
.filter((e) => e[1])
.map((e) => ({ value: e[0] })),
]);
}
});
@@ -314,10 +319,21 @@ Template.newUserPopup.helpers({
authentications() {
return Template.instance().authenticationMethods.get();
},
orgsDatas() {
return Org.find({}, {sort: { createdAt: -1 }});
},
teamsDatas() {
return Team.find({}, {sort: { createdAt: -1 }});
},
isSelected(match) {
const userId = Template.instance().data.userId;
const selected = Users.findOne(userId).authenticationMethod;
return selected === match;
if(userId){
const selected = Users.findOne(userId).authenticationMethod;
return selected === match;
}
else{
false;
}
},
isLdap() {
const userId = Template.instance().data.userId;
@@ -407,7 +423,7 @@ BlazeComponent.extendComponent({
Template.editOrgPopup.events({
submit(event, templateInstance) {
event.preventDefault();
const org = Orgs.findOne(this.orgId);
const org = Org.findOne(this.orgId);
const orgDisplayName = templateInstance
.find('.js-orgDisplayName')
@@ -415,7 +431,8 @@ Template.editOrgPopup.events({
const orgDesc = templateInstance.find('.js-orgDesc').value.trim();
const orgShortName = templateInstance.find('.js-orgShortName').value.trim();
const orgWebsite = templateInstance.find('.js-orgWebsite').value.trim();
const orgIsActive = templateInstance.find('.js-org-isactive').value.trim();
const orgIsActive =
templateInstance.find('.js-org-isactive').value.trim() == 'true';
const isChangeOrgDisplayName = orgDisplayName !== org.orgDisplayName;
const isChangeOrgDesc = orgDesc !== org.orgDesc;
@@ -423,20 +440,22 @@ Template.editOrgPopup.events({
const isChangeOrgWebsite = orgWebsite !== org.orgWebsite;
const isChangeOrgIsActive = orgIsActive !== org.orgIsActive;
if (isChangeOrgDisplayName) {
Meteor.call('setOrgDisplayName', org, orgDisplayName);
}
if (isChangeOrgDesc) {
Meteor.call('setOrgDesc', org, orgDesc);
}
if (isChangeOrgShortName) {
Meteor.call('setOrgShortName', org, orgShortName);
}
if (isChangeOrgIsActive) {
Meteor.call('setOrgIsActive', org, orgIsActive);
if (
isChangeOrgDisplayName ||
isChangeOrgDesc ||
isChangeOrgShortName ||
isChangeOrgWebsite ||
isChangeOrgIsActive
) {
Meteor.call(
'setOrgAllFields',
org,
orgDisplayName,
orgDesc,
orgShortName,
orgWebsite,
orgIsActive,
);
}
Popup.close();
@@ -446,7 +465,7 @@ Template.editOrgPopup.events({
Template.editTeamPopup.events({
submit(event, templateInstance) {
event.preventDefault();
const team = Teams.findOne(this.teamId);
const team = Team.findOne(this.teamId);
const teamDisplayName = templateInstance
.find('.js-teamDisplayName')
@@ -456,9 +475,8 @@ Template.editTeamPopup.events({
.find('.js-teamShortName')
.value.trim();
const teamWebsite = templateInstance.find('.js-teamWebsite').value.trim();
const teamIsActive = templateInstance
.find('.js-team-isactive')
.value.trim();
const teamIsActive =
templateInstance.find('.js-team-isactive').value.trim() == 'true';
const isChangeTeamDisplayName = teamDisplayName !== team.teamDisplayName;
const isChangeTeamDesc = teamDesc !== team.teamDesc;
@@ -466,20 +484,22 @@ Template.editTeamPopup.events({
const isChangeTeamWebsite = teamWebsite !== team.teamWebsite;
const isChangeTeamIsActive = teamIsActive !== team.teamIsActive;
if (isChangeTeamDisplayName) {
Meteor.call('setTeamDisplayName', team, teamDisplayName);
}
if (isChangeTeamDesc) {
Meteor.call('setTeamDesc', team, teamDesc);
}
if (isChangeTeamShortName) {
Meteor.call('setTeamShortName', team, teamShortName);
}
if (isChangeTeamIsActive) {
Meteor.call('setTeamIsActive', team, teamIsActive);
if (
isChangeTeamDisplayName ||
isChangeTeamDesc ||
isChangeTeamShortName ||
isChangeTeamWebsite ||
isChangeTeamIsActive
) {
Meteor.call(
'setTeamAllFields',
team,
teamDisplayName,
teamDesc,
teamShortName,
teamWebsite,
teamIsActive,
);
}
Popup.close();
@@ -497,15 +517,13 @@ Template.editUserPopup.events({
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 verified = templateInstance
.find('.js-profile-email-verified')
.value.trim();
const authentication = templateInstance
.find('.js-authenticationMethod')
.value.trim();
const importUsernames = templateInstance
.find('.js-import-usernames')
.value.trim();
const verified = templateInstance.find('.js-profile-email-verified').value.trim();
const authentication = templateInstance.find('.js-authenticationMethod').value.trim();
const importUsernames = templateInstance.find('.js-import-usernames').value.trim();
const userOrgs = templateInstance.find('.js-userOrgs').value.trim();
const userOrgsIds = templateInstance.find('.js-userOrgIds').value.trim();
const userTeams = templateInstance.find('.js-userteams').value.trim();
const userTeamsIds = templateInstance.find('.js-userteamIds').value.trim();
const isChangePassword = password.length > 0;
const isChangeUserName = username !== user.username;
@@ -530,6 +548,36 @@ Template.editUserPopup.events({
},
});
let userTeamsList = userTeams.split(",");
let userTeamsIdsList = userTeamsIds.split(",");
let userTms = [];
for(let i = 0; i < userTeamsList.length; i++){
userTms.push({
"teamId": userTeamsIdsList[i],
"teamDisplayName": userTeamsList[i],
})
}
Users.update(this.userId, {
$set:{
teams: userTms
}
});
let userOrgsList = userOrgs.split(",");
let userOrgsIdsList = userOrgsIds.split(",");
let userOrganizations = [];
for(let i = 0; i < userOrgsList.length; i++){
userOrganizations.push({
"orgId": userOrgsIdsList[i],
"orgDisplayName": userOrgsList[i],
})
}
Users.update(this.userId, {
$set:{
orgs: userOrganizations
}
});
if (isChangePassword) {
Meteor.call('setPassword', password, this.userId);
}
@@ -548,7 +596,7 @@ Template.editUserPopup.events({
username,
email.toLowerCase(),
this.userId,
function(error) {
function (error) {
const usernameMessageElement = templateInstance.$('.username-taken');
const emailMessageElement = templateInstance.$('.email-taken');
if (error) {
@@ -568,7 +616,7 @@ Template.editUserPopup.events({
},
);
} else if (isChangeUserName) {
Meteor.call('setUsername', username, this.userId, function(error) {
Meteor.call('setUsername', username, this.userId, function (error) {
const usernameMessageElement = templateInstance.$('.username-taken');
if (error) {
const errorElement = error.error;
@@ -581,24 +629,138 @@ Template.editUserPopup.events({
}
});
} else if (isChangeEmail) {
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') {
emailMessageElement.show();
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') {
emailMessageElement.show();
}
} else {
emailMessageElement.hide();
Popup.close();
}
} else {
emailMessageElement.hide();
Popup.close();
}
});
},
);
} else Popup.close();
},
'click #addUserOrg'(event) {
event.preventDefault();
userOrgsTeamsAction = "addOrg";
document.getElementById("jsOrgs").style.display = 'block';
document.getElementById("jsTeams").style.display = 'none';
},
'click #removeUserOrg'(event) {
event.preventDefault();
userOrgsTeamsAction = "removeOrg";
document.getElementById("jsOrgs").style.display = 'block';
document.getElementById("jsTeams").style.display = 'none';
},
'click #addUserTeam'(event) {
event.preventDefault();
userOrgsTeamsAction = "addTeam";
document.getElementById("jsTeams").style.display = 'block';
document.getElementById("jsOrgs").style.display = 'none';
},
'click #removeUserTeam'(event) {
event.preventDefault();
userOrgsTeamsAction = "removeTeam";
document.getElementById("jsTeams").style.display = 'block';
document.getElementById("jsOrgs").style.display = 'none';
},
'change #jsOrgs'(event) {
event.preventDefault();
UpdateUserOrgsOrTeamsElement();
},
'change #jsTeams'(event) {
event.preventDefault();
UpdateUserOrgsOrTeamsElement();
},
});
UpdateUserOrgsOrTeamsElement = function(isNewUser = false){
let selectedElt;
let selectedEltValue;
let selectedEltValueId;
let inputElt;
let inputEltId;
let lstInputValues = [];
let lstInputValuesIds = [];
let index;
let indexId;
switch(userOrgsTeamsAction)
{
case "addOrg":
case "removeOrg":
inputElt = !isNewUser ? document.getElementById("jsUserOrgsInPut") : document.getElementById("jsUserOrgsInPutNewUser");
inputEltId = !isNewUser ? document.getElementById("jsUserOrgIdsInPut") : document.getElementById("jsUserOrgIdsInPutNewUser");
selectedElt = !isNewUser ? document.getElementById("jsOrgs") : document.getElementById("jsOrgsNewUser");
break;
case "addTeam":
case "removeTeam":
inputElt = !isNewUser ? document.getElementById("jsUserTeamsInPut") : document.getElementById("jsUserTeamsInPutNewUser");
inputEltId = !isNewUser ? document.getElementById("jsUserTeamIdsInPut") : document.getElementById("jsUserTeamIdsInPutNewUser");
selectedElt = !isNewUser ? document.getElementById("jsTeams") : document.getElementById("jsTeamsNewUser");
break;
default:
break;
}
selectedEltValue = selectedElt.options[selectedElt.selectedIndex].text;
selectedEltValueId = selectedElt.options[selectedElt.selectedIndex].value;
lstInputValues = inputElt.value.trim().split(",");
if(lstInputValues.length == 1 && lstInputValues[0] == ''){
lstInputValues = [];
}
lstInputValuesIds = inputEltId.value.trim().split(",");
if(lstInputValuesIds.length == 1 && lstInputValuesIds[0] == ''){
lstInputValuesIds = [];
}
index = lstInputValues.indexOf(selectedEltValue);
indexId = lstInputValuesIds.indexOf(selectedEltValue);
if(userOrgsTeamsAction == "addOrg" || userOrgsTeamsAction == "addTeam"){
if(index <= -1 && selectedEltValueId != "-1"){
lstInputValues.push(selectedEltValue);
}
if(indexId <= -1 && selectedEltValueId != "-1"){
lstInputValuesIds.push(selectedEltValueId);
}
}
else{
if(index > -1 && selectedEltValueId != "-1"){
lstInputValues.splice(index, 1);
}
if(indexId > -1 && selectedEltValueId != "-1"){
lstInputValuesIds.splice(indexId, 1);
}
}
if(lstInputValues.length > 0){
inputElt.value = lstInputValues.join(",");
}
else{
inputElt.value = "";
}
if(lstInputValuesIds.length > 0){
inputEltId.value = lstInputValuesIds.join(",");
}
else{
inputEltId.value = "";
}
selectedElt.value = "-1";
selectedElt.style.display = "none";
}
Template.newOrgPopup.events({
submit(event, templateInstance) {
event.preventDefault();
@@ -608,7 +770,8 @@ Template.newOrgPopup.events({
const orgDesc = templateInstance.find('.js-orgDesc').value.trim();
const orgShortName = templateInstance.find('.js-orgShortName').value.trim();
const orgWebsite = templateInstance.find('.js-orgWebsite').value.trim();
const orgIsActive = templateInstance.find('.js-org-isactive').value.trim();
const orgIsActive =
templateInstance.find('.js-org-isactive').value.trim() == 'true';
Meteor.call(
'setCreateOrg',
@@ -633,9 +796,8 @@ Template.newTeamPopup.events({
.find('.js-teamShortName')
.value.trim();
const teamWebsite = templateInstance.find('.js-teamWebsite').value.trim();
const teamIsActive = templateInstance
.find('.js-team-isactive')
.value.trim();
const teamIsActive =
templateInstance.find('.js-team-isactive').value.trim() == 'true';
Meteor.call(
'setCreateTeam',
@@ -662,6 +824,30 @@ Template.newUserPopup.events({
const importUsernames = Users.parseImportUsernames(
templateInstance.find('.js-import-usernames').value,
);
const userOrgs = templateInstance.find('.js-userOrgsNewUser').value.trim();
const userOrgsIds = templateInstance.find('.js-userOrgIdsNewUser').value.trim();
const userTeams = templateInstance.find('.js-userteamsNewUser').value.trim();
const userTeamsIds = templateInstance.find('.js-userteamIdsNewUser').value.trim();
let userTeamsList = userTeams.split(",");
let userTeamsIdsList = userTeamsIds.split(",");
let userTms = [];
for(let i = 0; i < userTeamsList.length; i++){
userTms.push({
"teamId": userTeamsIdsList[i],
"teamDisplayName": userTeamsList[i],
})
}
let userOrgsList = userOrgs.split(",");
let userOrgsIdsList = userOrgsIds.split(",");
let userOrganizations = [];
for(let i = 0; i < userOrgsList.length; i++){
userOrganizations.push({
"orgId": userOrgsIdsList[i],
"orgDisplayName": userOrgsList[i],
})
}
Meteor.call(
'setCreateUser',
@@ -673,6 +859,8 @@ Template.newUserPopup.events({
isActive,
email.toLowerCase(),
importUsernames,
userOrganizations,
userTms,
function(error) {
const usernameMessageElement = templateInstance.$('.username-taken');
const emailMessageElement = templateInstance.$('.email-taken');
@@ -694,13 +882,65 @@ Template.newUserPopup.events({
);
Popup.close();
},
'click #addUserOrgNewUser'(event) {
event.preventDefault();
userOrgsTeamsAction = "addOrg";
document.getElementById("jsOrgsNewUser").style.display = 'block';
document.getElementById("jsTeamsNewUser").style.display = 'none';
},
'click #removeUserOrgNewUser'(event) {
event.preventDefault();
userOrgsTeamsAction = "removeOrg";
document.getElementById("jsOrgsNewUser").style.display = 'block';
document.getElementById("jsTeamsNewUser").style.display = 'none';
},
'click #addUserTeamNewUser'(event) {
event.preventDefault();
userOrgsTeamsAction = "addTeam";
document.getElementById("jsTeamsNewUser").style.display = 'block';
document.getElementById("jsOrgsNewUser").style.display = 'none';
},
'click #removeUserTeamNewUser'(event) {
event.preventDefault();
userOrgsTeamsAction = "removeTeam";
document.getElementById("jsTeamsNewUser").style.display = 'block';
document.getElementById("jsOrgsNewUser").style.display = 'none';
},
'change #jsOrgsNewUser'(event) {
event.preventDefault();
UpdateUserOrgsOrTeamsElement(true);
},
'change #jsTeamsNewUser'(event) {
event.preventDefault();
UpdateUserOrgsOrTeamsElement(true);
},
});
Template.settingsOrgPopup.events({
'click #deleteButton'(event) {
event.preventDefault();
Org.remove(this.orgId);
Popup.close();
}
});
Template.settingsTeamPopup.events({
'click #deleteButton'(event) {
event.preventDefault();
Team.remove(this.teamId);
Popup.close();
}
});
Template.settingsUserPopup.events({
'click .impersonate-user'(event) {
event.preventDefault();
Meteor.call('impersonate', this.userId, err => {
Meteor.call('impersonate', this.userId, (err) => {
if (!err) {
FlowRouter.go('/');
Meteor.connection.setUserId(this.userId);
@@ -720,21 +960,6 @@ Template.settingsUserPopup.events({
// but that should be used to remove user from all boards similarly
// - wekan/models/users.js Delete is not enabled
//
//console.log('user id: ' + this.userId);
//Popup.afterConfirm('userDelete', function(event) {
//Boards.find({ members: this.userId }).forEach(board => {
// console.log('board id: ' + board._id);
//Cards.find({ boardId: board._id, members: this.userId }).forEach(card => {
// card.unassignMember(this.userId);
//});
//Cards.find({ boardId: board._id, members: this.userId }).forEach(card => {
// card.unassignMember(this.userId);
//});
//Cards.find({ boardId: board._id, assignees: this.userId }).forEach(card => {
// card.unassignAssignee(this.userId);
//});
//Boards.findOne({ boardId: board._id }).removeMember(this.userId);
//});
//Users.remove(this.userId);
*/
Popup.close();
@@ -49,3 +49,9 @@ table
.more-settings-user,.more-settings-team,.more-settings-org
margin-left: 10px;
.js-orgs,.js-orgsNewUser
display: none;
.js-teams,.js-teamsNewUser
display: none;
+58 -43
View File
@@ -13,10 +13,11 @@ template(name="setting")
a.js-setting-menu(data-id="registration-setting")
i.fa.fa-sign-in
| {{_ 'registration'}}
li
a.js-setting-menu(data-id="email-setting")
i.fa.fa-envelope
| {{_ 'email'}}
unless isSandstorm
li
a.js-setting-menu(data-id="email-setting")
i.fa.fa-envelope
| {{_ 'email'}}
li
a.js-setting-menu(data-id="account-setting")
i.fa.fa-users
@@ -39,7 +40,8 @@ template(name="setting")
else if generalSetting.get
+general
else if emailSetting.get
+email
unless isSandstorm
+email
else if accountSetting.get
+accountSettings
else if announcementSetting.get
@@ -80,45 +82,48 @@ template(name="general")
template(name='email')
ul#email-setting.setting-detail
li.smtp-form
.title {{_ 'smtp-host'}}
.description {{_ 'smtp-host-description'}}
.form-group
input.wekan-form-control#mail-server-host(type="text", placeholder="smtp.domain.com" value="{{currentSetting.mailServer.host}}")
li.smtp-form
.title {{_ 'smtp-port'}}
.description {{_ 'smtp-port-description'}}
.form-group
input.wekan-form-control#mail-server-port(type="text", placeholder="25" value="{{currentSetting.mailServer.port}}")
li.smtp-form
.title {{_ 'smtp-username'}}
.form-group
input.wekan-form-control#mail-server-username(type="text", placeholder="{{_ 'username'}}" value="{{currentSetting.mailServer.username}}")
li.smtp-form
.title {{_ 'smtp-password'}}
.form-group
input.wekan-form-control#mail-server-password(type="password", placeholder="{{_ 'password'}}" value="")
li.smtp-form
.title {{_ 'smtp-tls'}}
.form-group
a.flex.js-toggle-tls
.materialCheckBox#mail-server-tls(class="{{#if currentSetting.mailServer.enableTLS}}is-checked{{/if}}")
span {{_ 'smtp-tls-description'}}
li.smtp-form
.title {{_ 'send-from'}}
.form-group
input.wekan-form-control#mail-server-from(type="email", placeholder="no-reply@domain.com" value="{{currentSetting.mailServer.from}}")
li
button.js-save.primary {{_ 'save'}}
//if isSandstorm
// li.smtp-form
// .title {{_ 'smtp-host'}}
// .description {{_ 'smtp-host-description'}}
// .form-group
// input.wekan-form-control#mail-server-host(type="text", placeholder="smtp.domain.com" value="{{currentSetting.mailServer.host}}")
// li.smtp-form
// .title {{_ 'smtp-port'}}
// .description {{_ 'smtp-port-description'}}
// .form-group
// input.wekan-form-control#mail-server-port(type="text", placeholder="25" value="{{currentSetting.mailServer.port}}")
// li.smtp-form
// .title {{_ 'smtp-username'}}
// .form-group
// input.wekan-form-control#mail-server-username(type="text", placeholder="{{_ 'username'}}" value="{{currentSetting.mailServer.username}}")
// li.smtp-form
// .title {{_ 'smtp-password'}}
// .form-group
// input.wekan-form-control#mail-server-password(type="password", placeholder="{{_ 'password'}}" value="")
// li.smtp-form
// .title {{_ 'smtp-tls'}}
// .form-group
// a.flex.js-toggle-tls
// .materialCheckBox#mail-server-tls(class="{{#if currentSetting.mailServer.enableTLS}}is-checked{{/if}}")
//
// span {{_ 'smtp-tls-description'}}
//
// li.smtp-form
// .title {{_ 'send-from'}}
// .form-group
// input.wekan-form-control#mail-server-from(type="email", placeholder="no-reply@domain.com" value="{{currentSetting.mailServer.from}}")
//
// li
// button.js-save.primary {{_ 'save'}}
li
button.js-send-smtp-test-email.primary {{_ 'send-smtp-test'}}
template(name='accountSettings')
ul#account-setting.setting-detail
li
button.js-all-hide-system-messages.primary {{_ 'hide-system-messages-of-all-users'}}
li.accounts-form
.title {{_ 'accounts-allowEmailChange'}}
.form-group.flex
@@ -126,23 +131,18 @@ template(name='accountSettings')
span {{_ 'yes'}}
input.wekan-form-control#accounts-allowEmailChange(type="radio" name="allowEmailChange" value="false" checked="{{#unless allowEmailChange}}checked{{/unless}}")
span {{_ 'no'}}
li
li.accounts-form
.title {{_ 'accounts-allowUserNameChange'}}
.form-group.flex
input.wekan-form-control#accounts-allowUserNameChange(type="radio" name="allowUserNameChange" value="true" checked="{{#if allowUserNameChange}}checked{{/if}}")
span {{_ 'yes'}}
input.wekan-form-control#accounts-allowUserNameChange(type="radio" name="allowUserNameChange" value="false" checked="{{#unless allowUserNameChange}}checked{{/unless}}")
span {{_ 'no'}}
li
li.accounts-form
.title {{_ 'accounts-allowUserDelete'}}
.form-group.flex
input.wekan-form-control#accounts-allowUserDelete(type="radio" name="allowUserDelete" value="true" checked="{{#if allowUserDelete}}checked{{/if}}")
span {{_ 'yes'}}
input.wekan-form-control#accounts-allowUserDelete(type="radio" name="allowUserDelete" value="false" checked="{{#unless allowUserDelete}}checked{{/unless}}")
span {{_ 'no'}}
li
button.js-accounts-save.primary {{_ 'save'}}
template(name='announcementSettings')
@@ -173,6 +173,9 @@ template(name='layoutSettings')
li.layout-form
.title {{_ 'default-authentication-method'}}
+selectAuthenticationMethod(authenticationMethod=currentSetting.defaultAuthenticationMethod)
li.layout-form
.title {{_ 'wait-spinner'}}
+selectSpinnerName(spinnerName=currentSetting.spinnerName)
li.layout-form
.title {{_ 'custom-product-name'}}
.form-group
@@ -208,6 +211,10 @@ template(name='layoutSettings')
.title {{_ 'custom-top-left-corner-logo-height'}}
.form-group
input.wekan-form-control#custom-top-left-corner-logo-height(type="text", placeholder="" value="{{currentSetting.customTopLeftCornerLogoHeight}}")
li.layout-form
.title {{_ 'automatic-linked-url-schemes'}}
.form-group
textarea#automatic-linked-url-schemes.wekan-form-control= currentSetting.automaticLinkedUrlSchemes
li
button.js-save-layout.primary {{_ 'save'}}
@@ -218,3 +225,11 @@ template(name='selectAuthenticationMethod')
option(value="{{value}}" selected) {{_ value}}
else
option(value="{{value}}") {{_ value}}
template(name='selectSpinnerName')
select#spinnerName
each spinner in spinners
if isSelected spinner
option(value="{{spinner}}" selected) {{_ spinner}}
else
option(value="{{spinner}}") {{_ spinner}}
+37 -1
View File
@@ -1,3 +1,5 @@
import { ALLOWED_WAIT_SPINNERS } from '/config/const';
BlazeComponent.extendComponent({
onCreated() {
this.error = new ReactiveVar('');
@@ -176,6 +178,9 @@ BlazeComponent.extendComponent({
const textBelowCustomLoginLogo = $('#text-below-custom-login-logo')
.val()
.trim();
const automaticLinkedUrlSchemes = $('#automatic-linked-url-schemes')
.val()
.trim();
const customTopLeftCornerLogoImageUrl = $(
'#custom-top-left-corner-logo-image-url',
)
@@ -196,6 +201,8 @@ BlazeComponent.extendComponent({
$('input[name=displayAuthenticationMethod]:checked').val() === 'true';
const defaultAuthenticationMethod = $('#defaultAuthenticationMethod').val();
const spinnerName = $('#spinnerName').val();
try {
Settings.update(Settings.findOne()._id, {
$set: {
@@ -209,6 +216,8 @@ BlazeComponent.extendComponent({
customTopLeftCornerLogoHeight,
displayAuthenticationMethod,
defaultAuthenticationMethod,
automaticLinkedUrlSchemes,
spinnerName,
},
});
} catch (e) {
@@ -270,7 +279,6 @@ BlazeComponent.extendComponent({
$set: { booleanValue: allowUserDelete },
});
},
allowEmailChange() {
return AccountSettings.findOne('accounts-allowEmailChange').booleanValue;
},
@@ -280,12 +288,31 @@ BlazeComponent.extendComponent({
allowUserDelete() {
return AccountSettings.findOne('accounts-allowUserDelete').booleanValue;
},
allHideSystemMessages() {
Meteor.call('setAllUsersHideSystemMessages', (err, ret) => {
if (!err && ret) {
if (ret === true) {
const message = `${TAPi18n.__(
'now-system-messages-of-all-users-are-hidden',
)}`;
alert(message);
}
} else {
const reason = err.reason || '';
const message = `${TAPi18n.__(err.error)}\n${reason}`;
alert(message);
}
});
},
events() {
return [
{
'click button.js-accounts-save': this.saveAccountsChange,
},
{
'click button.js-all-hide-system-messages': this.allHideSystemMessages,
},
];
},
}).register('accountSettings');
@@ -362,3 +389,12 @@ Template.selectAuthenticationMethod.helpers({
return Template.instance().data.authenticationMethod === match;
},
});
Template.selectSpinnerName.helpers({
spinners() {
return ALLOWED_WAIT_SPINNERS;
},
isSelected(match) {
return Template.instance().data.spinnerName === match;
},
});
@@ -12,6 +12,10 @@ template(name="settingHeaderBar")
i.fa(class="fa-users")
span {{_ 'people'}}
a.setting-header-btn.informations(href="{{pathFor 'admin-reports'}}")
i.fa(class="fa-list")
span {{_ 'reports'}}
a.setting-header-btn.informations(href="{{pathFor 'information'}}")
i.fa(class="fa-info-circle")
span {{_ 'info'}}
+24 -8
View File
@@ -5,10 +5,6 @@ template(name="sidebar")
// title="{{showTongueTitle}}")
// i.fa.fa-navicon
.sidebar-shadow
.sidebar-content.sidebar-shortcuts
a.board-header-btn.js-shortcuts
i.fa.fa-keyboard-o
span {{_ 'keyboard-shortcuts' }}
.sidebar-content.js-board-sidebar-content
//a.hide-btn.js-hide-sidebar
// i.fa.fa-navicon
@@ -23,7 +19,7 @@ template(name='homeSidebar')
hr
+labelsWidget
ul#cards.label-text-hidden
a.flex.js-toggle-minicard-label-text
a.flex.js-toggle-minicard-label-text(title="{{_ 'hide-minicard-label-text'}}")
span {{_ 'hide-minicard-label-text'}}
b &nbsp;
.materialCheckBox(class="{{#if hiddenMinicardLabelText}}is-checked{{/if}}")
@@ -39,6 +35,12 @@ template(name="membersWidget")
h3
i.fa.fa-users
| {{_ 'members'}}
.sidebar-shortcuts
a.board-header-btn.js-shortcuts(title="{{_ 'keyboard-shortcuts' }}")
i.fa.fa-keyboard-o
span {{_ 'keyboard-shortcuts' }}
unless currentUser.isCommentOnly
unless currentUser.isWorker
a.board-header-btn.js-open-board-menu(title="{{_ 'boardMenuPopup-title'}}").right
@@ -49,10 +51,10 @@ template(name="membersWidget")
+userAvatar(userId=this.userId showStatus=true)
if isSandstorm
if currentUser.isBoardMember
a.member.add-member.sandstorm-powerbox-request-identity
a.member.add-member.sandstorm-powerbox-request-identity(title="{{_ 'add-members'}}")
i.fa.fa-plus
else if currentUser.isBoardAdmin
a.member.add-member.js-manage-board-members
a.member.add-member.js-manage-board-members(title="{{_ 'add-members'}}")
i.fa.fa-plus
.clearfix
if isInvited
@@ -105,6 +107,14 @@ template(name="boardCardSettingsPopup")
span
i.fa.fa-users
| {{_ 'members'}}
div.check-div
a.flex.js-field-has-creator(class="{{#if allowsCreator}}is-checked{{/if}}")
.materialCheckBox(class="{{#if allowsCreator}}is-checked{{/if}}")
span
i.fa.fa-user
| {{_ 'creator'}}
div.check-div
a.flex.js-field-has-assignee(class="{{#if allowsAssignee}}is-checked{{/if}}")
.materialCheckBox(class="{{#if allowsAssignee}}is-checked{{/if}}")
@@ -123,6 +133,12 @@ template(name="boardCardSettingsPopup")
span
i.fa.fa-user-plus
| {{_ 'requested-by'}}
div.check-div
a.flex.js-field-has-card-sorting-by-number(class="{{#if allowsCardSortingByNumber}}is-checked{{/if}}")
.materialCheckBox(class="{{#if allowsCardSortingByNumber}}is-checked{{/if}}")
span
i.fa.fa-sort
| {{_ 'card-sorting-by-number'}}
div.check-div
a.flex.js-field-has-labels(class="{{#if allowsLabels}}is-checked{{/if}}")
.materialCheckBox(class="{{#if allowsLabels}}is-checked{{/if}}")
@@ -354,7 +370,7 @@ template(name="labelsWidget")
+viewer
= name
if currentUser.isBoardAdmin
a.card-label.add-label.js-add-label
a.card-label.add-label.js-add-label(title="{{_ 'label-create'}}")
i.fa.fa-plus
template(name="memberPopup")
+41
View File
@@ -730,6 +730,14 @@ BlazeComponent.extendComponent({
return this.currentBoard.allowsSubtasks;
},
allowsCreator() {
return (
this.currentBoard.allowsCreator === null ||
this.currentBoard.allowsCreator === undefined ||
this.currentBoard.allowsCreator
);
},
allowsMembers() {
return this.currentBoard.allowsMembers;
},
@@ -746,6 +754,10 @@ BlazeComponent.extendComponent({
return this.currentBoard.allowsRequestedBy;
},
allowsCardSortingByNumber() {
return this.currentBoard.allowsCardSortingByNumber;
},
allowsLabels() {
return this.currentBoard.allowsLabels;
},
@@ -889,6 +901,19 @@ BlazeComponent.extendComponent({
this.currentBoard.allowsSubtasks,
);
},
'click .js-field-has-creator'(evt) {
evt.preventDefault();
this.currentBoard.allowsCreator = !this.currentBoard.allowsCreator;
this.currentBoard.setAllowsCreator(this.currentBoard.allowsCreator);
$(`.js-field-has-creator ${MCB}`).toggleClass(
CKCLS,
this.currentBoard.allowsCreator,
);
$('.js-field-has-creator').toggleClass(
CKCLS,
this.currentBoard.allowsCreator,
);
},
'click .js-field-has-members'(evt) {
evt.preventDefault();
this.currentBoard.allowsMembers = !this.currentBoard.allowsMembers;
@@ -947,6 +972,22 @@ BlazeComponent.extendComponent({
this.currentBoard.allowsRequestedBy,
);
},
'click .js-field-has-card-sorting-by-number'(evt) {
evt.preventDefault();
this.currentBoard.allowsCardSortingByNumber = !this.currentBoard
.allowsCardSortingByNumber;
this.currentBoard.setAllowsCardSortingByNumber(
this.currentBoard.allowsCardSortingByNumber,
);
$(`.js-field-has-card-sorting-by-number ${MCB}`).toggleClass(
CKCLS,
this.currentBoard.allowsCardSortingByNumber,
);
$('.js-field-has-card-sorting-by-number').toggleClass(
CKCLS,
this.currentBoard.allowsCardSortingByNumber,
);
},
'click .js-field-has-labels'(evt) {
evt.preventDefault();
this.currentBoard.allowsLabels = !this.currentBoard.allowsLabels;
+3 -4
View File
@@ -100,13 +100,12 @@
margin-right: 10px
.sidebar-shortcuts
margin: 0
position: absolute
margin-left: 40%
padding: 0
top: auto
text-align: center
top: 7px
font-size: 0.8em
line-height: 1.6em
vertical-align: middle
color: darken(white, 40%)
.board-sidebar
@@ -50,6 +50,15 @@ template(name="createCustomFieldPopup")
each dropdownItems.get
input.js-dropdown-item(type="text" value=name placeholder="")
input.js-dropdown-item.last(type="text" value="" placeholder="{{_ 'custom-field-dropdown-options-placeholder'}}")
div.js-field-settings.js-field-settings-stringtemplate(class="{{#if isTypeNotSelected 'stringtemplate'}}hide{{/if}}")
label
| {{_ 'custom-field-stringtemplate-format'}}
input.js-field-stringtemplate-format(type="text" value=getStringtemplateFormat)
label
| {{_ 'custom-field-stringtemplate-separator'}}
input.js-field-stringtemplate-separator(type="text" value=getStringtemplateSeparator)
a.flex.js-field-show-on-card(class="{{#if showOnCard}}is-checked{{/if}}")
.materialCheckBox(class="{{#if showOnCard}}is-checked{{/if}}")
@@ -16,7 +16,15 @@ BlazeComponent.extendComponent({
}).register('customFieldsSidebar');
const CreateCustomFieldPopup = BlazeComponent.extendComponent({
_types: ['text', 'number', 'date', 'dropdown', 'currency', 'checkbox'],
_types: [
'text',
'number',
'date',
'dropdown',
'currency',
'checkbox',
'stringtemplate',
],
_currencyList: [
{
@@ -77,6 +85,18 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
? this.data().settings.dropdownItems
: [],
);
this.stringtemplateFormat = new ReactiveVar(
this.data().settings && this.data().settings.stringtemplateFormat
? this.data().settings.stringtemplateFormat
: '',
);
this.stringtemplateSeparator = new ReactiveVar(
this.data().settings && this.data().settings.stringtemplateSeparator
? this.data().settings.stringtemplateSeparator
: '',
);
},
types() {
@@ -121,6 +141,14 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
return items;
},
getStringtemplateFormat() {
return this.stringtemplateFormat.get();
},
getStringtemplateSeparator() {
return this.stringtemplateSeparator.get();
},
getSettings() {
const settings = {};
switch (this.type.get()) {
@@ -136,6 +164,14 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
settings.dropdownItems = dropdownItems;
break;
}
case 'stringtemplate': {
const stringtemplateFormat = this.stringtemplateFormat.get();
settings.stringtemplateFormat = stringtemplateFormat;
const stringtemplateSeparator = this.stringtemplateSeparator.get();
settings.stringtemplateSeparator = stringtemplateSeparator;
break;
}
}
return settings;
},
@@ -158,6 +194,14 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
evt.target.value = '';
}
},
'input .js-field-stringtemplate-format'(evt) {
const value = evt.target.value;
this.stringtemplateFormat.set(value);
},
'input .js-field-stringtemplate-separator'(evt) {
const value = evt.target.value;
this.stringtemplateSeparator.set(value);
},
'click .js-field-show-on-card'(evt) {
let $target = $(evt.target);
if (!$target.hasClass('js-field-show-on-card')) {
@@ -72,6 +72,43 @@ template(name="filterSidebar")
| (<span class="username">{{ username }}</span>)
if Filter.assignees.isSelected _id
i.fa.fa-check
hr
h3
i.fa.fa-list-alt
| {{_ 'filter-dates-label' }}
ul.sidebar-list
li(class="{{#if Filter.dueAt.isSelected 'noDate'}}active{{/if}}")
a.name.js-toggle-no-due-date-filter
span.sidebar-list-item-description
| {{_ 'filter-no-due-date' }}
if Filter.dueAt.isSelected 'noDate'
i.fa.fa-check
li(class="{{#if Filter.dueAt.isSelected 'past'}}active{{/if}}")
a.name.js-toggle-overdue-filter
span.sidebar-list-item-description
| {{_ 'filter-overdue' }}
if Filter.dueAt.isSelected 'past'
i.fa.fa-check
li(class="{{#if Filter.dueAt.isSelected 'today'}}active{{/if}}")
a.name.js-toggle-due-today-filter
span.sidebar-list-item-description
| {{_ 'filter-due-today' }}
if Filter.dueAt.isSelected 'today'
i.fa.fa-check
li(class="{{#if Filter.dueAt.isSelected 'tomorrow'}}active{{/if}}")
a.name.js-toggle-due-tomorrow-filter
span.sidebar-list-item-description
| {{_ 'filter-due-tomorrow' }}
if Filter.dueAt.isSelected 'tomorrow'
i.fa.fa-check
li(class="{{#if Filter.dueAt.isSelected 'week'}}active{{/if}}")
a.name.js-toggle-due-this-week-filter
span.sidebar-list-item-description
| {{_ 'filter-due-this-week' }}
if Filter.dueAt.isSelected 'week'
i.fa.fa-check
hr
h3
i.fa.fa-list-alt
@@ -23,6 +23,31 @@ BlazeComponent.extendComponent({
Filter.assignees.toggle(this.currentData()._id);
Filter.resetExceptions();
},
'click .js-toggle-no-due-date-filter'(evt) {
evt.preventDefault();
Filter.dueAt.noDate();
Filter.resetExceptions();
},
'click .js-toggle-overdue-filter'(evt) {
evt.preventDefault();
Filter.dueAt.past();
Filter.resetExceptions();
},
'click .js-toggle-due-today-filter'(evt) {
evt.preventDefault();
Filter.dueAt.today();
Filter.resetExceptions();
},
'click .js-toggle-due-tomorrow-filter'(evt) {
evt.preventDefault();
Filter.dueAt.tomorrow();
Filter.resetExceptions();
},
'click .js-toggle-due-this-week-filter'(evt) {
evt.preventDefault();
Filter.dueAt.thisWeek();
Filter.resetExceptions();
},
'click .js-toggle-archive-filter'(evt) {
evt.preventDefault();
Filter.archive.toggle(this.currentData()._id);
@@ -4,9 +4,9 @@ template(name="searchSidebar")
.list-body
.minilists.clearfix.js-minilists
each (lists)
a.minilist-wrapper.js-minilist(href=absoluteUrl)
a.minilist-wrapper.js-minilist(href=originRelativeUrl)
+minilist(this)
.minicards.clearfix.js-minicards
each (results)
a.minicard-wrapper.js-minicard(href=absoluteUrl)
a.minicard-wrapper.js-minicard(href=originRelativeUrl)
+minicard(this)
@@ -1,5 +1,5 @@
template(name="swimlaneHeader")
.swimlane-header-wrap.js-swimlane-header(class=colorClass)
.swimlane-header-wrap.js-swimlane-header(class=colorClass title="{{_ 'rename'}}")
if this.isTemplateContainer
+swimlaneFixedHeader(this)
else
@@ -16,8 +16,8 @@ template(name="swimlaneFixedHeader")
.swimlane-header-menu
unless currentUser.isCommentOnly
if currentUser.isBoardAdmin
a.fa.fa-plus.js-open-add-swimlane-menu.swimlane-header-plus-icon
a.fa.fa-navicon.js-open-swimlane-menu
a.fa.fa-plus.js-open-add-swimlane-menu.swimlane-header-plus-icon(title="{{_ 'add-swimlane'}}")
a.fa.fa-navicon.js-open-swimlane-menu(title="{{_ 'swimlaneActionPopup-title'}}")
unless isMiniScreen
if showDesktopDragHandles
a.swimlane-header-handle.handle.fa.fa-arrows.js-swimlane-header-handle
@@ -39,6 +39,10 @@ template(name="swimlaneActionPopup")
hr
ul.pop-over-list
li: a.js-close-swimlane {{_ 'archive-swimlane'}}
ul.pop-over-list
li: a.js-copy-swimlane {{_ 'copy-swimlane'}}
ul.pop-over-list
li: a.js-move-swimlane {{_ 'move-swimlane'}}
template(name="swimlaneAddPopup")
unless currentUser.isCommentOnly
@@ -54,9 +54,11 @@ Template.swimlaneActionPopup.events({
this.archive();
Popup.close();
},
'click .js-move-swimlane': Popup.open('moveSwimlane'),
'click .js-copy-swimlane': Popup.open('copySwimlane'),
});
Template.swimlaneActionPopup.helpers({
Template.swimlaneActionPopup.events({
isCommentOnly() {
return Meteor.user().isCommentOnly();
},
Loaded 100 of 536 files, more files were not shown because too many files have changed in this diff. Show more