Compare commits

...
626 Commits
Author SHA1 Message Date
Lauri Ojansivu 5fc5500845 v6.13 2022-04-01 22:08:31 +03:00
Lauri Ojansivu 971391eae9 Updated dependencies.
Thanks to developers of dependencies !
2022-04-01 22:03:21 +03:00
Lauri Ojansivu a19e1b3400 Updated translations. 2022-04-01 21:24:38 +03:00
Lauri Ojansivu 9be6312ce1 Updated ChangeLog. 2022-03-30 22:41:55 +03:00
Lauri Ojansivu c397b5eda8 Merge pull request #4435 from wekan/dependabot/npm_and_yarn/minimist-1.2.6
Bump minimist from 1.2.5 to 1.2.6
2022-03-30 22:40:25 +03:00
Lauri Ojansivu 3251c8f419 Updated ChangeLog. 2022-03-30 20:04:51 +03:00
Lauri Ojansivu f2f3b76eda Updated URL to meteor-spk. 2022-03-30 20:03:48 +03:00
dependabot[bot] 402fe5528f Bump minimist from 1.2.5 to 1.2.6
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-29 13:55:44 +00:00
Lauri Ojansivu e2f8989939 Updated ChangeLog. 2022-03-29 00:14:00 +03:00
Lauri Ojansivu 1da0786211 Added WRITABLE_PATH to Windows start-wekan.bat .
Thanks to BabyFnord and xet7 !

Related https://github.com/wekan/wekan/pull/4405
2022-03-29 00:12:07 +03:00
Lauri Ojansivu 744e90d680 Updated ChangeLog. 2022-03-29 00:08:49 +03:00
Lauri Ojansivu ca15e060bb Added translations: English (Brazil) en-BR and Czech (Czech Republic) cs-CZ.
Thanks to translators !
2022-03-29 00:07:01 +03:00
Lauri Ojansivu 1431e4fd48 Updated ChangeLog. 2022-03-28 22:00:33 +03:00
Lauri Ojansivu e61e9bb508 Added some more info about building on Windows, not tested yet. 2022-03-28 21:59:29 +03:00
Lauri Ojansivu 1cb52a60c1 Updated ChangeLog. 2022-03-28 21:55:46 +03:00
Lauri Ojansivu 9099e20b80 Changed from volta to n. Added info about developing on Ubuntu 22.04. 2022-03-28 21:54:20 +03:00
Lauri Ojansivu 0b6e6491f9 Updated translations. 2022-03-25 12:39:34 +02:00
Lauri Ojansivu 0fb00bb18f Updated to Node.js v14.19.1. Thanks to Node.js developers. 2022-03-22 16:46:03 +02:00
Lauri Ojansivu aa3f133f56 Updated ChangeLog. 2022-03-22 16:07:09 +02:00
Lauri Ojansivu bf023e8218 Merge pull request #4424 from helioguardabaxo/master
Add get list and board cards count to API
2022-03-22 16:03:11 +02:00
Lauri Ojansivu 60466612b6 Updated ChangeLog. 2022-03-22 15:44:23 +02:00
Lauri Ojansivu 376bcbb373 Added Perl scripts for Asana export to WeKan ®.
Thanks to GeekRuthie !
2022-03-22 15:41:07 +02:00
helioguardabaxo 556507705a Add get list and board cards count to API 2022-03-20 19:00:03 -03:00
Lauri Ojansivu 825bc4cf25 Updated readme about largest user. 2022-03-19 00:32:19 +02:00
Lauri Ojansivu 68c958a890 Updated translations. 2022-03-19 00:31:48 +02:00
Lauri Ojansivu d2414670fa Updated ChangeLog. 2022-03-16 22:44:25 +02:00
Lauri Ojansivu 2f4e201d55 Merge pull request #4413 from Ben0it-T/fix-duplicate-board-create-board
Fix Duplicate board and create board from template doesn't open board
2022-03-16 22:42:46 +02:00
Lauri Ojansivu 278a8e49b9 Updated ChangeLog. 2022-03-16 22:41:22 +02:00
Lauri Ojansivu 5514c357ca Merge pull request #4411 from Ben0it-T/fix-import-Done-Button-do-not-redirect
fix Import Done Button do not redirect
2022-03-16 22:38:13 +02:00
Ben0it-T 8280ed2d3e Create Board from template now open board 2022-03-14 22:04:38 +01:00
Ben0it-T 9fa5b59d7c Duplicate Board now open board 2022-03-14 21:46:11 +01:00
Ben0it-T f9b6978303 fix Import Done Button do not redirect 2022-03-13 17:18:32 +01:00
Lauri Ojansivu 90be8ff936 Merge branch 'master' of github.com:wekan/wekan 2022-03-12 13:17:43 +02:00
Lauri Ojansivu 221d90f34b Updated ChangeLog. 2022-03-12 13:17:35 +02:00
Lauri Ojansivu 850aef41a4 Merge pull request #4408 from mfilser/attachment_migration_remove_cardId_on_cloudron_fix
Attachment migration, try to ignore error on Cloudron on removing old index cardId
2022-03-12 13:14:59 +02:00
Martin Filser d18da20cdf Attachment migration, try to ignore error on Cloudron on removing old index cardId
- should fix: https://github.com/wekan/wekan/issues/4407#issuecomment-1065782781
2022-03-12 09:40:35 +01:00
Lauri Ojansivu 62ea3cd4bf v6.12 2022-03-11 19:51:48 +02:00
Lauri Ojansivu 8a014dbfae Updated ChangeLog. 2022-03-11 19:44:35 +02:00
Lauri Ojansivu 01a91f3a36 Docs for Snap WRITABLE_PATH.
Thanks to xet7 !
2022-03-11 19:41:50 +02:00
Lauri Ojansivu 9f807c59d7 Added Snap WRITABLE_PATH.
Thanks to xet7 !
2022-03-11 19:36:35 +02:00
Lauri Ojansivu ab0faf9b52 Updated ChangeLog. 2022-03-11 12:16:00 +02:00
Lauri Ojansivu 272aa34083 Merge pull request #4405 from mfilser/attachments_fixes_after_migration_to_meteor_files
Attachments fixes after migration to meteor files (image preview, global search)
2022-03-11 12:14:04 +02:00
Martin Filser 1f277af722 remove old attachment storagePath log message 2022-03-10 23:17:06 +01:00
Martin Filser bfef9fc14d Attachment preview on card details again 2022-03-10 23:07:57 +01:00
Martin Filser 4603948442 Global search didn't work because of wrong Attachment search 2022-03-10 23:07:57 +01:00
Martin Filser 27ea306c1c Attachments count is now visible on minicard again 2022-03-10 23:07:57 +01:00
Martin Filser 6d5651e53f Attachments, ensure index of cardId exists 2022-03-10 23:07:57 +01:00
Lauri Ojansivu ada7b3dd2d Updated ChangeLog. 2022-03-10 19:31:01 +02:00
Lauri Ojansivu 34c2c87307 Merge pull request #4404 from Viehlieb/feature/empower_sso_oicd_data_propagation
Feature/empower sso oicd data propagation
2022-03-10 19:25:08 +02:00
viehlieb 9179e5ea71 added Readme 2022-03-10 16:02:47 +01:00
viehlieb f90875d8ef updating teams from oidc possible, fixed undefined error, no need for extra login to assign/create teams/orgs 2022-03-10 15:56:35 +01:00
Lauri Ojansivu c4bf99a9b9 Updated translations. 2022-03-10 00:59:35 +02:00
Lauri Ojansivu 87ec6a1076 Updated ChangeLog. 2022-03-10 00:57:17 +02:00
Lauri Ojansivu e450337b62 Merge pull request #4402 from Ben0it-T/fix-Boards.uniqueTitle-2
fix Boards.uniqueTitle not working as expected - part 2
2022-03-10 00:54:19 +02:00
Ben0it-T a45d1fa855 fix Boards.uniqueTitle 2022-03-08 22:25:07 +01:00
Lauri Ojansivu 0712309266 Updated ChangeLog. 2022-03-06 17:52:47 +02:00
Lauri Ojansivu f8b60de988 Merge pull request #4401 from Ben0it-T/fix-Boards.uniqueTitle
fix Boards.uniqueTitle not working as expected #4400
2022-03-06 17:51:02 +02:00
Lauri Ojansivu 3887c6f412 Updated ChangeLog. 2022-03-06 17:50:23 +02:00
Lauri Ojansivu a2beaa6e83 Merge pull request #4396 from Ben0it-T/add-linkedBoard-activities-to-sidebar
Add linkedBoard Activities to sidebar
2022-03-06 17:48:19 +02:00
Lauri Ojansivu 2d30b62b70 Updated ChangeLog. 2022-03-06 17:47:51 +02:00
Ben0it-T e1550e9172 fix Boards.uniqueTitle 2022-03-06 12:14:47 +01:00
Ben0it-T 0565f58165 adjust Activities display 2022-03-05 22:17:59 +01:00
Ben0it-T bf6bfc8ed6 add linkedBoard Activities to selector 2022-03-05 22:03:41 +01:00
Lauri Ojansivu d52e0bcb6e Merge pull request #4392 from Viehlieb/feature/empower_sso_oicd_data_propagation
Feature/empower sso oicd data propagation
2022-03-05 09:06:45 +02:00
viehlieb 263b405fc8 minor changes to README 2022-03-04 18:53:43 +01:00
viehlieb a0dbfa1f7e add README and functionality for more control through oidc - create teams/orgs if not exist and addto user - make user admin when flag is set 2022-03-04 18:29:29 +01:00
viehlieb 5b60efbe82 fix weird behavior where freshly created teams/orgs as active are crossed, recreated consistency with database 2022-03-04 18:24:11 +01:00
Lauri Ojansivu 00f2b77468 v6.11 2022-03-03 00:12:03 +02:00
Lauri Ojansivu a7e510412d Updated ChangeLog. 2022-03-03 00:05:29 +02:00
Lauri Ojansivu dc6bc9ed54 Updated In Progress future snapcraft configs.
Thanks to xet7 !
2022-03-03 00:02:22 +02:00
Lauri Ojansivu 82129139a2 Updated ChangeLog. 2022-03-02 23:56:57 +02:00
Lauri Ojansivu e5cfcc84fa Try to fix Snap.
Thanks to xet7 !
2022-03-02 23:54:14 +02:00
Lauri Ojansivu 5d5605754c v6.10 2022-03-02 21:31:42 +02:00
Lauri Ojansivu 9b4179e163 Updated dependencies. 2022-03-02 21:23:59 +02:00
Lauri Ojansivu ab33866d1a Use Node 14 at rebuild-wekan.sh
Thanks to xet7 !
2022-03-02 20:50:42 +02:00
Lauri Ojansivu 41ba67538b Updated ChangeLog. 2022-03-02 20:20:38 +02:00
Lauri Ojansivu e0d8ddf003 Added WRITABLE_PATH to be usable when developing with meteor command, and to torodb.
Thanks to xet7 !
2022-03-02 20:18:22 +02:00
Lauri Ojansivu 1a7a41698c Updated dependencies.
Thanks to developers of dependencies !
2022-03-02 20:16:30 +02:00
Lauri Ojansivu 2b999d2836 Updated ChangeLog. 2022-03-02 19:47:00 +02:00
Lauri Ojansivu dc99218e4e Enabled building Sandstorm WeKan, now that file uploading with Meteor-Files works.
Thanks to imajus, mfilser and xet7 !
2022-03-02 19:44:57 +02:00
Lauri Ojansivu bec440360a Merge branch 'feature-meteor-files' of github.com:wekan/wekan into feature-meteor-files 2022-03-02 17:34:20 +02:00
Lauri Ojansivu cc0658a225 Added Meteor-Files WRITEABLE_PATH for Sandstorm, Snap and Source.
Thanks to xet7 !

Related export WRITABLE_PATH=$SNAP_COMMON/wekan-uploads/
2022-03-02 17:33:14 +02:00
Lauri Ojansivu 00b99cda73 Added Meteor-Files WRITEABLE_PATH for Sandstorm, Snap and Source.
Thanks to xet7 !
2022-03-02 17:32:34 +02:00
Lauri Ojansivu b378bb55ac Merge remote-tracking branch 'remotes/origin/master' into feature-meteor-files 2022-03-01 21:09:55 +02:00
Lauri Ojansivu 7d5eac6876 Updated translations. 2022-03-01 20:42:59 +02:00
Lauri Ojansivu 4d539f369a Updated translations. 2022-02-28 17:02:55 +02:00
Lauri Ojansivu 5dadb4f0a1 v6.09 2022-02-28 01:46:57 +02:00
Lauri Ojansivu 1629e6aae6 Updated ChangeLog. 2022-02-28 01:40:52 +02:00
Lauri Ojansivu 0775e2a3e5 Try to fix Admin Panel / Disable Registration and Disable Forgot Password.
Thanks to urmel1960, Ben0it-T and xet7 !

Fixes #4384
2022-02-28 01:34:57 +02:00
Lauri Ojansivu 454d0b270d v6.08 2022-02-27 23:19:29 +02:00
Lauri Ojansivu 3076547cee Try to allow register and login.
Thanks to xet7 !

Related #4383
2022-02-27 23:13:20 +02:00
Lauri Ojansivu 4bcddcc98a Updated translations. 2022-02-26 19:26:51 +02:00
Lauri Ojansivu 099085b416 v6.07 2022-02-26 04:20:53 +02:00
Lauri Ojansivu 9bd6879455 Fix Forgot Password to be optional.
Thanks to xet7 !
2022-02-26 04:16:16 +02:00
Lauri Ojansivu 00efbf00d3 v6.06 2022-02-26 04:03:32 +02:00
Lauri Ojansivu 5c214c143d Updated translations. 2022-02-26 03:59:33 +02:00
Lauri Ojansivu 3418b97faa Updated translations. 2022-02-26 02:02:32 +02:00
Lauri Ojansivu a484101abf Updated ChangeLog. 2022-02-26 01:47:14 +02:00
Lauri Ojansivu 2f79432e4e Merge pull request #4379 from Viehlieb/feature/propagate_oidc_data
Feature/propagate OIDC data
2022-02-26 01:43:25 +02:00
Lauri Ojansivu f71728ae16 Merge pull request #4377 from Viehlieb/feature/shortcuts_for_label_assignment
Feature/shortcuts for label assignment
2022-02-26 01:37:09 +02:00
Lauri Ojansivu e7e4296b02 Updated ChangeLog. 2022-02-26 01:35:16 +02:00
Lauri Ojansivu b85db43c47 Fixed Disable Self-Registration. Added Disable Forgot Password to same Admin Panel page.
Thanks to xet7 !

Fixes #3971,
fixes #2839
2022-02-26 01:29:40 +02:00
viehlieb db6fc57515 fix userwas used before assignment 2022-02-24 13:08:55 +01:00
viehlieb 6b404da9f8 add functionality for oidc login to change MongoDB data for email, fullname, username, user.teams 2022-02-23 15:09:03 +01:00
viehlieb 4d31985eb9 enable add/remove labels for multiselect via shortcut 2022-02-23 14:58:13 +01:00
viehlieb 0e9aa2eeed translation files de + en for shortcut overview 2022-02-23 12:49:46 +01:00
viehlieb 7d73f2bbba bring back functionality for selectedCard which is currentCard and assigned functionality to numpad for label shortcuts 2022-02-23 12:49:08 +01:00
Lauri Ojansivu 4929979221 Updated to Node.js v14.19.0. Thanks to Node.js developers. 2022-02-23 11:51:56 +02:00
Lauri Ojansivu 90cc96302d Try to fix rebuild-wekan.sh .
Thanks to xet7 !
2022-02-23 10:30:30 +02:00
Lauri Ojansivu 4a074836fd Try to fix exception: Cannot read property title of undefined.
Thanks to xet7 !
2022-02-23 10:18:11 +02:00
Lauri Ojansivu 0e0bea0139 Merged meteor-files changes PR and removed wekan-cfs. 2022-02-23 09:38:28 +02:00
Lauri Ojansivu d00596f88a Merge branch 'feature-ostrio-files' of https://github.com/majus/wekan 2022-02-23 08:42:20 +02:00
Lauri Ojansivu 9ca8d78514 Updated translations. 2022-02-23 08:37:16 +02:00
Lauri Ojansivu 11d8096b8d Merge branch 'master' of github.com:wekan/wekan 2022-02-23 08:34:33 +02:00
Lauri Ojansivu a49a918547 Updated ChangeLog. 2022-02-23 08:34:25 +02:00
Lauri Ojansivu 4ebd113bf0 Merge pull request #4375 from pablo-ng/master
add subscription to announcements collection
2022-02-23 08:31:38 +02:00
Lauri Ojansivu 14df71de5b Updated ChangeLog. 2022-02-23 08:30:41 +02:00
Lauri Ojansivu 9f459a37b8 Merge pull request #4358 from mfilser/card_details_fix_header
Card details, fix header while scrolling
2022-02-23 08:29:03 +02:00
pablo-ng 5487c015db add subscription to announcements collection 2022-02-22 18:20:34 +01:00
Martin Filser 47ca6829eb Attachment migration, add error logs 2022-02-18 10:59:12 +03:00
Martin Filser 368fe24956 Ensure to create the upload directory 2022-02-18 10:59:12 +03:00
Martin Filser 086cb9c067 Don't add activity while the attachment migration 2022-02-18 10:59:12 +03:00
Martin Filser 25a2ad1144 Fix undefined list at activities / watchers 2022-02-18 10:59:12 +03:00
Martin Filser 926b617f33 .devcontainer, update image to ubuntu:rolling
- see also: 8446640060
2022-02-18 10:59:12 +03:00
Martin Filser f94ae76609 Adding WRITABLE_PATH to docker config 2022-02-18 10:59:12 +03:00
Lauri Ojansivu f46173077b Updated translations. 2022-02-17 20:31:12 +02:00
Martin Filser c373013134 Card Details Header always at top of all other scrollable elements 2022-02-14 23:07:30 +01:00
Martin Filser 12c5d2324d Card Details, fix card header while scrolling 2022-02-14 23:07:30 +01:00
Lauri Ojansivu e6dc20f6c7 Updated ChangeLog. 2022-02-12 20:22:50 +02:00
Lauri Ojansivu ea658842a2 Merge pull request #4352 from mfilser/card_details_popup_not_maximized
Global search: Card Details popup opens now in normal view even if maximized card is configured
2022-02-12 20:20:22 +02:00
Martin Filser 12f0c85546 Global search: Card Details popup opens now in normal view even if maximized card is configured
Fixes: #4346
2022-02-12 11:02:30 +01:00
Lauri Ojansivu 033a5d8186 Updated translations. 2022-02-10 15:01:14 +02:00
Lauri Ojansivu b769a71af3 v6.05 2022-02-07 18:56:10 +02:00
Lauri Ojansivu ad35e7b7bd Update release scripts to merge latest changes.
Thanks to xet7 !
2022-02-07 18:36:03 +02:00
Lauri Ojansivu a9e56f2b09 Updated ChangeLog. 2022-02-07 18:30:21 +02:00
Lauri Ojansivu 5f807b80fe Merge pull request #4345 from mfilser/fix_copy_move_card
Fix copy move card
2022-02-07 18:27:58 +02:00
Martin Filser 4d89eb6083 Add protection to change the list of the card 2022-02-07 16:56:35 +01:00
Martin Filser bd2739e78d Fix Copy/Move Card
Fixes: #4341, #4343
2022-02-07 16:51:55 +01:00
Martin Filser 265ee9ab83 Added back Dropdown field "List" to card details 2022-02-07 16:51:45 +01:00
Lauri Ojansivu 065485168a v6.04 2022-02-07 17:00:42 +02:00
Lauri Ojansivu 7d609ef0b1 Updated ChangeLog. 2022-02-07 16:35:04 +02:00
Lauri Ojansivu dc7b97c178 Fixed Problem with selecting action in rule window.
Thanks to Meeques and xet7 !

Fixes #4342
2022-02-07 16:31:01 +02:00
Lauri Ojansivu a5b376e6b5 Fixed Copy card to list does not work, by reverting clientside changes of PR 4333.
Thanks to Meeques, PaulITsoft and xet7 !

Fixes #4341,
fixes #4343
2022-02-07 15:15:24 +02:00
Lauri Ojansivu 993e99330f Updated translations. 2022-02-07 14:47:42 +02:00
Lauri Ojansivu e563212475 v6.03 2022-02-07 04:06:40 +02:00
Lauri Ojansivu cc54867976 Updated to Node.js v12.22.10. Thanks to Node.js developers. 2022-02-07 03:35:28 +02:00
Lauri Ojansivu 36250f83b9 v6.02 2022-02-06 16:10:25 +02:00
Lauri Ojansivu e715106d65 Updated translations. 2022-02-06 16:06:57 +02:00
Lauri Ojansivu f888b5cb23 Updated dependencies. 2022-02-06 15:58:30 +02:00
Denis Perov 59823a0661 Support WRITEABLE_PATH envrionemnt variable 2022-02-06 13:19:58 +03:00
David Arnold 6a9bc12664 Revert "use tempdirs"
This reverts commit a7d51cf21b663d87f83e2585502ed9323b3d3788.
2022-02-06 13:19:58 +03:00
David Arnold e99130d3ea use tempdirs 2022-02-06 13:19:58 +03:00
David Arnold 036fb3e794 fixup: migration 2022-02-06 13:19:58 +03:00
David Arnold a15ee068d1 hack: Nasty hack for covercard auth 2022-02-06 13:19:58 +03:00
David Arnold 1da242ae35 Revert "Adios cfs:* | Hello ostrio:file"
This reverts commit 093819e33cc513db6f06aa30d5e37e3fc758d6e8.
2022-02-06 13:19:58 +03:00
David Arnold addf669d44 migration: extract files from old storage and load into new storage 2022-02-06 13:19:58 +03:00
David Arnold 1c2dbe5149 Fix: access denied on second load 2022-02-06 13:19:58 +03:00
David Arnold 77cb5d88de fix: user avatar images & upload 2022-02-06 13:19:58 +03:00
David Arnold 1b591dcda9 Ref: pass through image size error message (correctly) 2022-02-06 13:19:58 +03:00
David Arnold 545fe96c30 Fix: image download dont open -> download 2022-02-06 13:19:58 +03:00
David Arnold d8d8a6a64d Rem: upload spinner.
attachmentGalery would need refactoring to an individual attachment
component with component state that could be set on the onUpdated event.

I'm not capable of doing this within reasonable time.
2022-02-06 13:19:58 +03:00
David Arnold 5a74d98795 Rem: unused previewAttachedImagePopup 2022-02-06 13:19:58 +03:00
David Arnold 0e8a02ee2c fix: thumbnail images now wrok 2022-02-06 13:19:58 +03:00
David Arnold 2c175f2be6 fixup! fix: cover image - works now 2022-02-06 13:19:58 +03:00
David Arnold e080aea61d fixup! Hello gridfs lib + fsHooks for mongodb bucket storage 2022-02-06 13:19:58 +03:00
David Arnold 59a936ae90 fix: activity download link 2022-02-06 13:19:58 +03:00
David Arnold c7500661b8 fix: cover image - works now 2022-02-06 13:19:58 +03:00
David Arnold 0ad7eb4753 fixup! Ref: original & and use fileObj.meta 2022-02-06 13:19:58 +03:00
David Arnold 0254282daf fixup! Ref: Attachments to use modern gridfs (rm localstore) 2022-02-06 13:19:58 +03:00
David Arnold d0a27aaec2 fixup! Ref: original & and use fileObj.meta 2022-02-06 13:19:58 +03:00
David Arnold be712541d5 Revert "Do those imports!"
This reverts commit 64dcc70bd271d827c1639f8c847543a6d2ede713.
2022-02-06 13:19:58 +03:00
David Arnold 9471eb327e fixup! Ref: Attachments to use modern gridfs (rm localstore) 2022-02-06 13:19:58 +03:00
David Arnold c41335a967 fixup! Ref: Avatars to use modern gridfs 2022-02-06 13:19:58 +03:00
David Arnold 9de430fdc1 fixup! Ref: original & and use fileObj.meta 2022-02-06 13:19:58 +03:00
David Arnold 13a6067081 fixup! Ref: Avatars to use modern gridfs 2022-02-06 13:19:58 +03:00
David Arnold e2f7b94cde fixup! Ref: original & and use fileObj.meta 2022-02-06 13:19:58 +03:00
David Arnold ac7d16c40f fixup! Ref: Attachments to use modern gridfs (rm localstore) 2022-02-06 13:19:58 +03:00
David Arnold 3da88ed858 Do those imports! 2022-02-06 13:19:58 +03:00
David Arnold c85f710e74 fixup! Ref: Attachments to use modern gridfs (rm localstore) 2022-02-06 13:19:58 +03:00
David Arnold 7b64c8b235 fixup! Ref: Avatars to use modern gridfs 2022-02-06 13:19:58 +03:00
David Arnold f244125cd3 fixup! Mig: add migration cfs:* -> ostrio:files 2022-02-06 13:19:58 +03:00
David Arnold 692d853eca fixup! Ref: Attachments to use modern gridfs (rm localstore) 2022-02-06 13:19:58 +03:00
David Arnold eb747ef8e9 fixup! Ref: Avatars to use modern gridfs 2022-02-06 13:19:58 +03:00
David Arnold 412b60f794 fixup! Ref: Attachments to use modern gridfs (rm localstore) 2022-02-06 13:19:58 +03:00
David Arnold 0f91eaa0a0 fixup! Ref: Avatars to use modern gridfs 2022-02-06 13:19:58 +03:00
David Arnold 386828fe3e fixup! rm fix-download-unicode 2022-02-06 13:19:58 +03:00
David Arnold 9b1ff4dd6d Fixup(ostrio-files): wrong export 2022-02-06 13:19:58 +03:00
David Arnold 2dc6e15024 Mig: add migration cfs:* -> ostrio:files 2022-02-06 13:19:58 +03:00
David Arnold e702f17c7b Ref: original & and use fileObj.meta
fileObj.meta is part of the ostrio:files API and be passed to the
constructor. This is less hacky than trying tu update a persistet object
after the fact.
2022-02-06 13:19:58 +03:00
David Arnold 16506e7a6a Ref: Attachment upload handlers 2022-02-06 13:19:58 +03:00
David Arnold 08cc308992 Ref: Avatar upload handler 2022-02-06 13:19:58 +03:00
David Arnold ae8d4c1bbd Ref: attachment image paste 2022-02-06 13:19:58 +03:00
David Arnold e2934b9b09 Ref: trello & wekan importers 2022-02-06 13:19:58 +03:00
David Arnold 55acce9f0c Ref: Attachment upload handlers 2022-02-06 13:19:57 +03:00
Lauri Ojansivu 627d7d9456 v6.01 2022-02-06 11:30:52 +02:00
Lauri Ojansivu b62dd5782a Updated ChangeLog. 2022-02-06 11:05:03 +02:00
Lauri Ojansivu 0460a7d9d3 Added building fibers.
Thanks to xet7 !
2022-02-06 11:03:04 +02:00
Lauri Ojansivu 45d53dede4 Updated translations. 2022-02-06 10:28:03 +02:00
Lauri Ojansivu ce3c87f767 Updated ChangeLog. 2022-02-06 10:25:54 +02:00
Lauri Ojansivu ceed865e30 Updated to Node.js v14.19.0. Thanks to Node.js developers. 2022-02-06 10:09:17 +02:00
David Arnold 9c3043d40a Ref: Avatar upload handler 2022-02-06 10:56:32 +03:00
David Arnold a38a78d9a3 rm ATTACHMENTS_STORE_PATH 2022-02-06 10:56:31 +03:00
David Arnold 966541704c Ref: Attachments to use modern gridfs (rm localstore) 2022-02-06 10:55:54 +03:00
David Arnold 52a63c5423 Ref: Avatars to use modern gridfs 2022-02-06 10:55:54 +03:00
David Arnold 18bd797ab9 Hello gridfs lib + fsHooks for mongodb bucket storage 2022-02-06 10:55:54 +03:00
David Arnold d75fd69406 rm fix-download-unicode 2022-02-06 10:55:54 +03:00
Denis Perov 337470cbd0 Adios cfs:* | Hello ostrio:file 2022-02-06 10:55:54 +03:00
Lauri Ojansivu a9bd5c7496 v6.00 2022-02-05 14:34:36 +02:00
Lauri Ojansivu e1730c9912 Updated translations. 2022-02-05 14:25:43 +02:00
Lauri Ojansivu 8f1754be50 Updated ChangeLog. 2022-02-05 14:24:11 +02:00
Lauri Ojansivu 4ace1db9b0 Merge pull request #4333 from mfilser/card_details_list_select
Adding list select at card details
2022-02-05 14:15:36 +02:00
Lauri Ojansivu eff636ddd6 Updated ChangeLog. 2022-02-05 00:43:17 +02:00
Lauri Ojansivu 9b7bf1ba28 Updated release scripts.
Thanks to xet7 !
2022-02-05 00:41:29 +02:00
Lauri Ojansivu 7190057d0c Updated translations. 2022-02-04 19:16:34 +02:00
Martin Filser bb5b723520 Migrations, set "Show Lists" on card details on every board 2022-02-04 13:46:56 +01:00
Martin Filser a2e6f01469 Changed "List Icon" 2022-02-04 13:46:56 +01:00
Martin Filser 12ee7efc5f Always add space between "card details items" 2022-02-04 13:46:56 +01:00
Martin Filser 7c7640e63e Added Dropdown field "List" to card details 2022-02-04 13:46:56 +01:00
Lauri Ojansivu e668fdc500 v5.99 2022-02-04 13:08:30 +02:00
Lauri Ojansivu f02478d57c Updated ChangeLog. 2022-02-04 12:44:44 +02:00
Lauri Ojansivu 8fc117eb53 Updated ChangeLog. 2022-02-04 12:43:38 +02:00
Lauri Ojansivu af598b13e8 Remove not working options from rebuild-wekan.sh
Thanks to xet7 !
2022-02-04 12:42:03 +02:00
Lauri Ojansivu f00f164078 Updated translations. 2022-02-04 12:35:09 +02:00
Lauri Ojansivu 70ac18a7e6 Updated ChangeLog. 2022-02-04 12:31:39 +02:00
Lauri Ojansivu e461c4a018 Merge pull request #4332 from jghaanstra/master
Revert rounded corners minicard on moderndark theme
2022-02-04 12:25:54 +02:00
Jelger Haanstra 186364f227 Revert rounded corners minicard on moderndark theme 2022-02-04 08:36:27 +01:00
Lauri Ojansivu 72f9d45bbe Updated ChangeLog. 2022-02-03 22:24:50 +02:00
Lauri Ojansivu 6392e06a36 v5.98 2022-02-03 22:02:18 +02:00
Lauri Ojansivu c879e63fc2 Updated ChangeLog. 2022-02-03 21:30:44 +02:00
Lauri Ojansivu 290a6dfb6e Updated to Node.js v12.22.10. Thanks to Node.js developers. 2022-02-03 21:28:32 +02:00
Lauri Ojansivu 94c82d121c Updated translations. 2022-02-03 21:01:43 +02:00
Lauri Ojansivu 3e92d6f6a3 Merge pull request #4331 from mfilser/copy_checklist
Copy checklist
2022-02-03 20:53:25 +02:00
Martin Filser 3a2b50720e Copy Checklist added to checklist action popup
Relates to: #4306
2022-02-03 19:37:49 +01:00
Lauri Ojansivu 8f47e65684 Updated ChangeLog. 2022-02-03 20:36:37 +02:00
Martin Filser 95ebf3bda8 Extract class of current "Move Checklist Option" Component 2022-02-03 19:34:34 +01:00
Martin Filser ea95357ae4 Move Checklist, getBoardData only resets the swimlane and list if the board id was changed 2022-02-03 19:34:34 +01:00
Martin Filser 7501e255dd Move Checklist, Swimlane, Lists and Cards are now correctly loaded of the last Board wasn't the current Board 2022-02-03 19:34:34 +01:00
Lauri Ojansivu ff13571c71 Add more stack and heap to Node.js at all WeKan platforms.
Thanks to xet7 !

Related #3585
2022-02-03 20:33:58 +02:00
Lauri Ojansivu 6501173ce4 Updated ChangeLog. 2022-02-03 18:45:35 +02:00
Lauri Ojansivu 1d13040305 Merge pull request #4330 from mfilser/list_not_moveable_when_lists_require_scrolling
Lists now moveable when swimlane requires scrolling
2022-02-03 18:44:34 +02:00
Lauri Ojansivu af1439b274 Updated ChangeLog. 2022-02-03 18:43:26 +02:00
Martin Filser 32af18b33d Lists now moveable when swimlane requires scrolling
Fixes: #4322
2022-02-03 17:29:20 +01:00
Martin Filser a48e537b2d List sorting show's now the drag/drop placeholder 2022-02-03 17:29:20 +01:00
Martin Filser 424bc0e7c5 Swimlanes scrolls right/left while sorting the list column at the screen end 2022-02-03 17:29:20 +01:00
Lauri Ojansivu e98821fafc Merge pull request #4329 from mfilser/removed_space_new_checklists
Removed unnecessary space between checklist title and first checklist item if checklist progress is 0%
2022-02-03 16:43:03 +02:00
Lauri Ojansivu 2d61fcdef4 Updated ChangeLog. 2022-02-03 12:42:16 +02:00
Lauri Ojansivu 045160c7bb Make card corners round.
Thanks to Meeques and xet7 !

Fixes #4326
2022-02-03 12:39:19 +02:00
Martin Filser f98b03bee5 Removed unnecessary space between checklist title and first checklist item if checklist progress is 0% 2022-02-01 22:49:15 +01:00
Lauri Ojansivu 703baf4ce9 Updated ChangeLog. 2022-01-30 01:56:54 +02:00
Lauri Ojansivu 1bf1ed79e8 Try to fix tests by adding correct version of puppeteer, because newest puppeteer did not work.
Thanks to xet7 !
2022-01-30 01:55:03 +02:00
Lauri Ojansivu a7888f0c66 Updated ChangeLog. 2022-01-30 01:49:13 +02:00
Lauri Ojansivu 7122f59c51 Try to fix tests by adding puppeteer back.
Thanks to xet7 !
2022-01-30 01:48:11 +02:00
Lauri Ojansivu 839266903a Updated ChangeLog. 2022-01-30 01:44:28 +02:00
Lauri Ojansivu a8e3dc06fe Part 3: Added translation: Galician (Spain).
Thanks to translators!
2022-01-30 01:43:05 +02:00
Lauri Ojansivu 7e0bc91a44 Updated ChangeLog. 2022-01-30 01:34:12 +02:00
Lauri Ojansivu 62efb67d06 Fix typo in tests. 2022-01-30 01:32:52 +02:00
Lauri Ojansivu 00fd47105d Updated translations. 2022-01-30 01:26:42 +02:00
Lauri Ojansivu 1bee24fa68 Updated ChangeLog. 2022-01-30 01:24:20 +02:00
Lauri Ojansivu 9a539fb414 Updated translations. 2022-01-30 01:21:19 +02:00
Lauri Ojansivu c0828f2d00 Added translation: Galician (Spain).
Thanks to translators!
2022-01-30 01:13:22 +02:00
Lauri Ojansivu 90c70aef96 Updated dependencies. 2022-01-23 13:21:24 +02:00
Lauri Ojansivu dfc736b064 v5.97 2022-01-23 11:39:10 +02:00
Lauri Ojansivu af53afb9f8 Updated ChangeLog. 2022-01-23 11:30:56 +02:00
Lauri Ojansivu df61e471a1 Merge pull request #4319 from Ben0it-T/fix-comments-for-cards-that-link-to-a-board-are-not-shown-2538
Fix comments for cards that link to a board are not shown
2022-01-23 11:26:56 +02:00
Ben0it-T 3e364c4f35 fix comments on cardType-linkedBoard 2022-01-23 10:21:29 +01:00
Lauri Ojansivu 3fb63b518f Updated ChangeLog. 2022-01-23 11:20:02 +02:00
Lauri Ojansivu 4bf6b457ae Fix Snap OAUTH2_REQUEST_PERMISSIONS of Google/OAuth2/OIDC login.
Thanks to xet7 !

Fixes #4316
2022-01-23 11:16:47 +02:00
Lauri Ojansivu 71c575d4b5 Updated ChangeLog. 2022-01-23 11:10:14 +02:00
Lauri Ojansivu 8b2c9cc74f Merge pull request #4318 from Ben0it-T/fix-cant-add-checklist-to-cardType-linkedBoard
fix can't add Checklist on cardType-linkedBoard
2022-01-23 10:53:32 +02:00
Ben0it-T fc7c70bdc0 add checklist to cardType-linkedBoard 2022-01-23 09:44:19 +01:00
Lauri Ojansivu dd18fd2477 v5.96 2022-01-23 00:07:30 +02:00
Lauri Ojansivu 2512ea1715 Updated ChangeLog. 2022-01-22 23:30:35 +02:00
Lauri Ojansivu d63fa4aa89 Merge pull request #4315 from Ben0it-T/fix-cardType-linkedBoard-comments-not-loading
Fix comments not loading on cardType-linkedBoard
2022-01-22 23:27:34 +02:00
Ben0it-T ec51f7cced update Cards.helpers - comments() 2022-01-22 22:20:36 +01:00
Ben0it-T 3eb834c920 add LinkedBoard card comments to cursor 2022-01-22 21:01:49 +01:00
Lauri Ojansivu ba24e4a775 Updated ChangeLog. 2022-01-21 18:42:57 +02:00
Lauri Ojansivu bec25720da Fix notification drawer always on top.
Thanks to Azorimor !

Related https://github.com/wekan/wekan/pull/4301
2022-01-21 18:40:23 +02:00
Lauri Ojansivu 0db7ba5107 Updated ChangeLog. 2022-01-21 18:21:41 +02:00
Lauri Ojansivu 5e65dfc272 Try to fix OAUTH2_REQUEST_PERMISSIONS by removing quotes.
Thanks to pcurie and xet7 !

Related https://github.com/wekan/wekan/commit/892ee605270d583d800ec5ff9e1e4844eae92b38
2022-01-21 18:19:20 +02:00
Lauri Ojansivu 9b56f149e1 Updated ChangeLog. 2022-01-21 00:45:04 +02:00
Lauri Ojansivu a15ed97ab3 Merge pull request #4308 from mfilser/fix_layout_modern_dark
Fix Layout "Modern Dark", Card Color, List Header and mouse hover
2022-01-21 00:41:34 +02:00
Martin Filser d34918b08b Fix Layout "Modern Dark", Card Color, List Header and mouse hover
Fixes: #4254
2022-01-20 23:03:01 +01:00
Lauri Ojansivu e16cc34f6d Updated translations. 2022-01-20 23:38:26 +02:00
Lauri Ojansivu 87fd4880c9 Updated ChangeLog. 2022-01-20 23:28:56 +02:00
Lauri Ojansivu f325fe8436 Merge pull request #4307 from mfilser/move_checklist_and_card_popup_restore_last_selected_board_value
Move checklist and card popup restore last selected board value
2022-01-20 23:27:13 +02:00
Martin Filser 70558d00a7 Move checklist popup restores now the last selected board value in dropdown menu 2022-01-20 22:02:23 +01:00
Martin Filser d86eb74eb0 Move card popup restores now the last selected board value in dropdown menu 2022-01-20 22:02:23 +01:00
Lauri Ojansivu 6adedfd77f Updated translations. 2022-01-19 17:32:22 +02:00
Lauri Ojansivu e1a7c8abb7 Updated translations. 2022-01-18 15:48:16 +02:00
Lauri Ojansivu 8c8fba3c6c v5.95 2022-01-18 03:05:12 +02:00
Lauri Ojansivu a176a58a72 Use different OS for WeKan releases. 2022-01-18 03:00:28 +02:00
Lauri Ojansivu 1db3d9a081 Updated translations. 2022-01-18 02:53:32 +02:00
Lauri Ojansivu 8020aa4b81 Updated ChangeLog. 2022-01-18 01:28:18 +02:00
Lauri Ojansivu bbef2aff8c Merge pull request #4300 from mfilser/custom_field_stringtemplates_fix_ctrl_enter_desktop_view
Custom Field StringTemplates didn't save the last input value on desktop view after pressing Ctrl+Enter
2022-01-18 01:26:45 +02:00
Martin Filser 7e1755c89f Custom Field StringTemplates didn't save the last input value on desktop view after pressing Ctrl+Enter 2022-01-18 00:21:57 +01:00
Lauri Ojansivu 66a4562c91 Updated translations. 2022-01-18 01:21:35 +02:00
Lauri Ojansivu 6ad4e78fa8 Updated ChangeLog. 2022-01-18 01:21:12 +02:00
Lauri Ojansivu 6a92a95414 Merge pull request #4299 from mfilser/checklist_add_progress_bar
Add progress bar to checklist
2022-01-18 01:20:00 +02:00
Martin Filser 1fcc0d2ec2 Only show progress bar percent if there is any checklist item done 2022-01-18 00:16:19 +01:00
Martin Filser e7051c8ecd Smaller progress bar 2022-01-18 00:16:19 +01:00
Martin Filser 1670ba31e8 Changed progress bar layout 2022-01-18 00:16:19 +01:00
Martin Filser ac1f540763 Added progress bar to checklist
- Relates #1847
2022-01-18 00:16:19 +01:00
Lauri Ojansivu 61dd3180a4 Updated ChangeLog. 2022-01-18 01:15:39 +02:00
Lauri Ojansivu 930333d546 Merge branch 'master' of github.com:wekan/wekan 2022-01-18 01:14:45 +02:00
Lauri Ojansivu 2967d13968 Updated translations. 2022-01-18 01:14:33 +02:00
Lauri Ojansivu 56be68fcb7 Merge pull request #4298 from mfilser/add_checklist_item-each_line_becomes_new_item
Add checklist item - each line becomes new item
2022-01-18 01:14:19 +02:00
Martin Filser dbb9ddd7d3 Show "newlineBecomesNewChecklistItem" element only at new checklist items
- before it was shown at new checklists too
2022-01-18 00:09:19 +01:00
Martin Filser 879ab282e1 Adding some space between save button and the next div element 2022-01-18 00:09:19 +01:00
Martin Filser d9a7950fa4 Center all elements of checklist-item form
- before the save button, X and slider element had a strange layout. The
  save button was at the bottom, the X and slider at the top of the flex
  layout
2022-01-18 00:09:19 +01:00
Martin Filser 18e34b7f79 Add checklist item, added newline becomes new checklist item
- Related to #1846
2022-01-18 00:09:19 +01:00
Lauri Ojansivu 4abb26f8bc Updated ChangeLog. 2022-01-18 01:03:52 +02:00
Lauri Ojansivu cd6b4529be Merge pull request #4297 from mfilser/checklist_action_menu_and_move_checklist
Added "move checklist" and created a "Checklist Action Menu"
2022-01-18 01:02:08 +02:00
Lauri Ojansivu 6234fdff18 Updated ChangeLog. 2022-01-18 01:00:40 +02:00
Lauri Ojansivu d4c3f32383 Updated WeKan s390x bundle build script.
Thanks to xet7 !
2022-01-18 00:59:12 +02:00
Martin Filser a72d51d901 Checklist Action-Menu easier clickable
- especially useful at mobile devices
2022-01-17 23:38:21 +01:00
Martin Filser a66257ec21 Added "Move Checklist" to checklist menu action 2022-01-17 23:38:21 +01:00
Martin Filser 395452b54f Added spaces to delete checklist menu action 2022-01-17 23:38:21 +01:00
Martin Filser e40e42103e Delete checklist moved to checklist menu action 2022-01-17 23:38:21 +01:00
Martin Filser 7651c00d57 Add actions menu to checklist 2022-01-17 23:38:21 +01:00
Lauri Ojansivu 764dbb71f0 Updated ChangeLog. 2022-01-18 00:35:56 +02:00
Lauri Ojansivu 83ce43ac52 Merge pull request #4296 from mfilser/move_copy_card_remembers_the_last_confirmed_field_values
Move copy card remembers the last confirmed field values
2022-01-18 00:33:33 +02:00
Martin Filser e528474fc5 Move and Copy Card Popup remembers the last confirmed field values 2022-01-17 23:20:44 +01:00
Martin Filser 73ff4c7966 Use card id from component instead of global state
- was a TODO in the comments
2022-01-17 23:20:44 +01:00
Lauri Ojansivu 01d8058a3f Updated translations. 2022-01-17 18:02:08 +02:00
Lauri Ojansivu b69f08889a Updated ChangeLog. 2022-01-17 17:54:25 +02:00
Lauri Ojansivu edf3573760 Merge pull request #4295 from xeruf/patch-1
Update ISSUE_TEMPLATE.md
2022-01-17 17:51:49 +02:00
Janek 021def818f Update ISSUE_TEMPLATE.md
Use comments and rephrase
2022-01-17 15:45:19 +01:00
Lauri Ojansivu f519d277a5 v5.94 2022-01-16 21:49:48 +02:00
Lauri Ojansivu 218ddf03bc Fix Card, List and Comment colors not visible at some themes.
Thanks to Meeques, Go-rom and xet7 !

Fixes #4254,
fixes #4293
2022-01-16 21:41:49 +02:00
Lauri Ojansivu 31c7539eb9 Updated translations. 2022-01-16 20:27:26 +02:00
Lauri Ojansivu eb8d9955d5 Updated translations. 2022-01-16 19:17:15 +02:00
Lauri Ojansivu 7bcaf71bf0 Updated translations. 2022-01-16 19:13:23 +02:00
Lauri Ojansivu 7afc4638d2 Updated ChangeLog. 2022-01-16 14:27:55 +02:00
Lauri Ojansivu c9b7542a9b Merge branch 'mfilser-card_title_copy_button' 2022-01-16 14:26:15 +02:00
Martin Filser c59c7bd63d Removed unnecessary CSS code of copied tooltip 2022-01-15 18:52:07 +01:00
Martin Filser 574116b058 Reduced height of Copied! tooltip at title copy button 2022-01-15 18:52:06 +01:00
Martin Filser dbcc919768 Added copy button to card title 2022-01-15 18:18:11 +01:00
Lauri Ojansivu bf37737f44 Updated changelog. 2022-01-14 03:56:08 +02:00
Lauri Ojansivu 187b31caa5 v5.93 2022-01-14 02:47:09 +02:00
Lauri Ojansivu f75ab964be Part 2: Try to fix Sandstorm WeKan package.
Thanks to xet7 !

Related https://github.com/wekan/wekan/issues/4280,
related https://github.com/sandstorm-io/sandstorm/issues/3600
2022-01-14 02:42:49 +02:00
Lauri Ojansivu bff43c3f92 Try to fix Sandstorm WeKan package.
Thanks to xet7 !

Related https://github.com/wekan/wekan/issues/4280,
related https://github.com/sandstorm-io/sandstorm/issues/3600
2022-01-14 02:35:39 +02:00
Lauri Ojansivu fb3099eba9 Updated ChangeLog. 2022-01-13 23:58:09 +02:00
Lauri Ojansivu 5d1d90c2ff v5.92 2022-01-13 22:47:08 +02:00
Lauri Ojansivu 4d3c0c60d0 Updated ChangeLog. 2022-01-13 21:24:03 +02:00
Lauri Ojansivu 99d6f7a765 Fixed OpenAPI docs generating has some swagger error.
Thanks to bentiss !

Fixes #4280
2022-01-13 21:22:38 +02:00
Lauri Ojansivu 418b9effa7 Updated ChangeLog. 2022-01-13 21:11:29 +02:00
Lauri Ojansivu 30131ffc20 Part 2: Added translations: Estonian (Estonia) et_EE, Russian (Ukraine) ru_UA, Ukrainian (Ukraine) uk_UA.
Thanks to translators!
2022-01-13 21:05:59 +02:00
Lauri Ojansivu ac85e00e0a Added translations: Estonian (Estonia) et_EE, Russian (Ukraine) ru_UA, Ukrainian (Ukraine) uk_UA.
Thanks to translators!
2022-01-13 14:39:40 +02:00
Lauri Ojansivu 8b2e2e9b1f Merge pull request #4286 from wekan/dependabot/npm_and_yarn/markdown-it-12.3.2
Bump markdown-it from 12.2.0 to 12.3.2
2022-01-13 11:15:55 +00:00
dependabot[bot] 724f9d43b4 Bump markdown-it from 12.2.0 to 12.3.2
Bumps [markdown-it](https://github.com/markdown-it/markdown-it) from 12.2.0 to 12.3.2.
- [Release notes](https://github.com/markdown-it/markdown-it/releases)
- [Changelog](https://github.com/markdown-it/markdown-it/blob/master/CHANGELOG.md)
- [Commits](https://github.com/markdown-it/markdown-it/compare/12.2.0...12.3.2)

---
updated-dependencies:
- dependency-name: markdown-it
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-01-12 23:15:34 +00:00
Lauri Ojansivu 2ce136ee0a v5.91 2022-01-11 03:53:27 +02:00
Lauri Ojansivu 7495c1bf59 Updated ChangeLog. 2022-01-11 03:19:25 +02:00
Lauri Ojansivu ef685703cf Use volta in local node update script.
Thanks to Volta developers!
2022-01-11 03:13:51 +02:00
Lauri Ojansivu 0218f3266b Updated to Node.js v12.22.9. Thanks to Node.js developers. 2022-01-11 03:09:48 +02:00
Lauri Ojansivu 6a97dfb4b9 Updated ChangeLog. 2022-01-10 23:27:49 +02:00
Lauri Ojansivu 75fdc53746 Updated dependencies.
Thanks to developers of dependencies!
2022-01-10 23:26:41 +02:00
Lauri Ojansivu ed3c53df35 Updated ChangeLog. 2022-01-10 22:46:41 +02:00
Lauri Ojansivu 2efa42b853 In rebuild-wekan.sh, use Volta Node and NPM install manager, made with Rust https://volta.sh . Volta uses home directory also with "npm -g install", no sudo needed.
Thanks to Volta developers!
2022-01-10 22:44:17 +02:00
Lauri Ojansivu cf151b5632 Updated translations. 2022-01-08 22:30:52 +02:00
Lauri Ojansivu 2241c35e55 Updated ChangeLog. 2022-01-08 22:17:04 +02:00
Lauri Ojansivu 6f7292db5e Updated rebuild-wekan.sh 2022-01-08 22:15:48 +02:00
Lauri Ojansivu ce587d23fa Updated ChangeLog. 2022-01-05 18:57:46 +02:00
Lauri Ojansivu 9979193df5 Updated rebuild-wekan.sh script about installing dependencies.
Thanks to xet7 !
2022-01-05 18:56:07 +02:00
Lauri Ojansivu bee9dc8b3e Updated translations. 2022-01-03 21:21:02 +02:00
Lauri Ojansivu 31bf4072d3 Updated translations. 2022-01-03 10:01:19 +02:00
Lauri Ojansivu fbbd3d5174 Updated ChangeLog. 2022-01-03 09:56:35 +02:00
Lauri Ojansivu 65b7d3d50d Merge pull request #4273 from Ben0it-T/user-mentions
Fix user mentions
2022-01-03 07:52:02 +00:00
Ben0it-T 4589c3df15 User mentions now return @username (full name) - part 2 2022-01-02 19:35:47 +01:00
Ben0it-T a160b662ef User mentions now return @username (full name) 2022-01-02 18:44:28 +01:00
Ben0it-T e176410b54 Fix auto-complete username when creating new cards (addCardForm) 2022-01-02 17:22:56 +01:00
Lauri Ojansivu 2ac5f0b2d7 Updated ChangeLog. 2021-12-27 20:42:05 +00:00
Lauri Ojansivu 33f47414bb Added release scripts for starting and stopping services.
Thanks to xet7 !
2021-12-27 20:39:17 +00:00
Lauri Ojansivu fb27ce027c Updated translations. 2021-12-27 16:33:52 +02:00
Lauri Ojansivu ae180c7b85 v5.90 2021-12-26 17:59:38 +02:00
Lauri Ojansivu 95ed3a0ab5 Fix Create Board from Template not opening.
Thanks to Ben0it-T and xet7 !

Related #4263
2021-12-26 17:43:56 +02:00
Lauri Ojansivu dbe0b4922f v5.89 2021-12-26 16:06:12 +02:00
Lauri Ojansivu e69114319f Updated ChangeLog. 2021-12-26 15:57:03 +02:00
Lauri Ojansivu 8db78f8dd4 Updated ChangeLog. 2021-12-26 15:44:35 +02:00
Lauri Ojansivu f2c31f877c Trello api.py: Added additional TODO notes.
Thanks to xet7 !

Related #4261,
related #3950
2021-12-26 15:42:05 +02:00
Lauri Ojansivu a87a591600 Updated ChangeLog. 2021-12-26 15:26:18 +02:00
Lauri Ojansivu 67687110bb Fixed Duplicate board.
Thanks to Ben0it-T and xet7 !

Fixes #4260
2021-12-26 15:24:16 +02:00
Lauri Ojansivu db180fa43e Updated ChangeLog related to Trello api.py .
Thanks to xet7 !

Related #4261,
related #3950
2021-12-26 11:20:57 +02:00
Lauri Ojansivu aff6e361f0 Added api.py for using newest Trello API, to show Trello boards/cards/actions/reactions JSON and download Trello attachments as binary files from S3.
Thanks to xet7 !

Related #4261,
related #3950
2021-12-26 11:16:06 +02:00
Lauri Ojansivu a37856c937 Updated ChangeLog. 2021-12-25 22:05:19 +02:00
Lauri Ojansivu 7f32de3bec Fixed Templates are Missing, Error: Site not Found "/templates" is missing in the URL.
Shared Templates part 5: Make visible Create template board checkbox and templates at All Boards page, In Progress.

Thanks to xet7 !

Fixes #4253,
related #3313
2021-12-25 21:59:43 +02:00
Lauri Ojansivu c46ec4a155 Updated translations. 2021-12-25 21:53:03 +02:00
Lauri Ojansivu 0c38700458 Updated ChangeLog. 2021-12-25 21:35:04 +02:00
Lauri Ojansivu 942065bb29 Merge pull request #4262 from Ben0it-T/fix-getLabels-exception-in-template-helper
Fix getLabels exception in template helper
2021-12-25 21:31:41 +02:00
Ben0it-T 8aa816149f Fix Labels search (Uncaught TypeError: t.name is undefined) 2021-12-25 18:30:41 +01:00
Ben0it-T 27ee16ea1e Fix getLabels exception 2021-12-25 13:34:10 +01:00
Lauri Ojansivu d6b0b0318d Updated translations. 2021-12-25 00:30:18 +02:00
Lauri Ojansivu faf03ae1ce Merge pull request #4259 from jrsupplee/search-debug
Search debug
2021-12-23 21:18:48 +02:00
John Supplee dd3c8394e7 Add i18n of new predicates for debug operator 2021-12-22 23:34:12 +02:00
John Supplee c10f3e97bf Add instructions for searching by team and organization 2021-12-22 23:26:41 +02:00
Lauri Ojansivu ea5b93f97c Updated translations. 2021-12-22 18:50:49 +02:00
Lauri Ojansivu bd08c1a4f1 Merge branch 'master' of github.com:wekan/wekan 2021-12-22 18:47:08 +02:00
Lauri Ojansivu ea17cc8592 Updated ChangeLog. 2021-12-22 18:47:00 +02:00
Lauri Ojansivu d535469163 Merge pull request #4257 from Ben0it-T/update-users.teams.teamDisplayName-users.orgs.orgDisplayName
Edit team/org now update users.teams.teamDisplayName / users.orgs.orgDisplayName
2021-12-22 18:45:05 +02:00
Ben0it-T 349925ad6b be sure user isAdmin 2021-12-22 13:48:37 +01:00
Ben0it-T b876098dc4 Edit team/org DisplayName now update users.teams.teamDisplayName/users.orgs.orgDisplayName 2021-12-22 11:49:50 +01:00
Lauri Ojansivu dc04beb61f Updated dependencies.
Thanks to xet7 !
2021-12-22 05:48:54 +02:00
Lauri Ojansivu 04d8aee86a v5.88 2021-12-22 05:32:20 +02:00
Lauri Ojansivu 8064d203f3 Updated ChangeLog. 2021-12-22 05:22:52 +02:00
Lauri Ojansivu 2fbf411918 Updated translations. 2021-12-22 05:13:26 +02:00
Lauri Ojansivu 1e9695a428 Updated ChangeLog. 2021-12-22 05:08:24 +02:00
Lauri Ojansivu 443b40cff3 Fixed Mermaid Diagram error: Maximum call stack size exceeded.
Thanks to xet7 !

Fixes #4251
2021-12-22 05:04:11 +02:00
Lauri Ojansivu f144f8c90a Updated ChangeLog. 2021-12-22 04:36:22 +02:00
Lauri Ojansivu 998d2f5b44 Part 2: Temporarily remove Mermaid Diagram because even after updating to newest Mermaid it still has bug https://github.com/wekan/wekan/issues/4251
Thanks to xet7 !
2021-12-22 04:34:39 +02:00
Lauri Ojansivu c15c10de97 Updated dependencies. 2021-12-22 04:30:25 +02:00
Lauri Ojansivu 142fa1c73d Updated ChangeLog. 2021-12-22 04:22:04 +02:00
Lauri Ojansivu 23a403644c Temporarily remove Mermaid Diagram because even after updating to newest Mermaid it still has bug https://github.com/wekan/wekan/issues/4251
Thanks to xet7 !
2021-12-22 04:18:52 +02:00
Lauri Ojansivu 89f4cdb7e5 Updated dependencies. 2021-12-22 04:13:33 +02:00
Lauri Ojansivu c650dd2088 Updated ChangeLog. 2021-12-22 01:25:48 +02:00
Lauri Ojansivu 85d51ec403 Updated translations. 2021-12-22 01:20:36 +02:00
Lauri Ojansivu 8804ca84ec Merge pull request #4252 from jrsupplee/search-debug
Search debug
2021-12-22 01:09:38 +02:00
John Supplee aa0dee1fba Bug fix for #3864 searching archived cards and add new operators for organizations and teams 2021-12-22 00:33:13 +02:00
Lauri Ojansivu 27d55a49fb Updated translatins. 2021-12-21 22:19:38 +02:00
John Supplee 6ef612d04e Merge branch 'master' into search-debug 2021-12-21 02:42:54 +02:00
John Supplee 42610d9642 More enhancements to Admin Reports and security fixes
* update Boards Report
* use Boards.userBoards() instead of Boards.find() to make sure user has access permission
2021-12-21 02:39:16 +02:00
John R. Supplee d9c290deda Add Boards Report to Admin Reports 2021-12-20 16:52:18 +02:00
John R. Supplee 49214747cd Add copy to clipboard for debug text and some bug fixes 2021-12-20 14:33:42 +02:00
John Supplee 84d0817894 Merge branch 'master' of https://github.com/wekan/wekan 2021-12-20 10:27:32 +02:00
John Supplee 94525a4d3d Add new debug operator to search and fix some bugs 2021-12-20 10:26:00 +02:00
Lauri Ojansivu 4ded5d2f51 Fixed arm build server paths.
Thanks to xet7 !
2021-12-19 16:12:33 +02:00
Lauri Ojansivu 7f8f3f8f16 v5.87 2021-12-19 15:58:10 +02:00
Lauri Ojansivu 45d7be19b6 Updated ChangeLog. 2021-12-19 15:53:09 +02:00
Lauri Ojansivu 8446640060 Changed Docker base image to ubuntu:rolling .
Thanks to xet7 !
2021-12-19 15:51:46 +02:00
Lauri Ojansivu 184290ce98 v5.86 2021-12-19 15:22:15 +02:00
Lauri Ojansivu 39fb0e4911 Updated ChangeLog. 2021-12-19 14:56:55 +02:00
Lauri Ojansivu 1f65add7b0 Merge pull request #4248 from Ben0it-T/fix-boardadmin-cant-edit-delete-comments
Fix: boardAdmin can't edit or delete others comments on cards #4237
2021-12-19 14:55:06 +02:00
John Supplee 241c3ed8ae Merge branch 'master' of https://github.com/wekan/wekan 2021-12-19 12:18:05 +02:00
Ben0it-T ee2fafb6bc Fix: boardAdmin can't edit or delete others comments on cards #4237 2021-12-18 13:03:37 +01:00
Lauri Ojansivu fee82f7f7a v5.85 2021-12-17 23:40:57 +02:00
Lauri Ojansivu c2340c6508 Updated ChangeLog. 2021-12-17 23:29:24 +02:00
Lauri Ojansivu 5ad9ee1de6 Updated to Node.js v12.22.8. Thanks to Node.js developers. 2021-12-17 23:27:51 +02:00
Lauri Ojansivu ea6551e567 Updated translations. 2021-12-17 23:26:37 +02:00
Lauri Ojansivu 6c9a2319ba Updated ChangeLog. 2021-12-17 23:23:27 +02:00
Lauri Ojansivu e305bf019f Merge pull request #4245 from Emile840/master
fix issue #4222
2021-12-17 23:21:33 +02:00
Emile NDAGIJIMANA 505c2da072 fix issue #4222 2021-12-17 18:56:40 +01:00
Lauri Ojansivu 9085e52446 Updated ChangeLog. 2021-12-15 13:31:26 +02:00
Lauri Ojansivu 9ac5e44a29 Merge pull request #4240 from jghaanstra/master
Fix mobile card details for Modern Dark theme
2021-12-15 13:12:34 +02:00
Jelger Haanstra 3d8e9c8b09 Fix mobile card details for Modern Dark theme 2021-12-15 11:42:49 +01:00
Lauri Ojansivu 5cf352defb v5.84 2021-12-15 00:33:28 +02:00
Lauri Ojansivu 371dd7db9f Updated translations. 2021-12-14 23:52:27 +02:00
Lauri Ojansivu 051de2ea5e Updated ChangeLog. 2021-12-14 23:45:03 +02:00
Lauri Ojansivu 73408c73af Merge pull request #4232 from Ben0it-T/sort_organizations_teams_people
Sort Organizations, Teams and People
2021-12-14 23:44:21 +02:00
Lauri Ojansivu 7079b65cc1 Updated ChangeLog. 2021-12-14 23:43:48 +02:00
Lauri Ojansivu 67676c50ad Merge pull request #4226 from Emile840/master
Add full name if exists in 'email-invite-subject' for user to invite
2021-12-14 23:40:52 +02:00
Lauri Ojansivu e46d10ea4c Updated ChangeLog. 2021-12-14 23:36:31 +02:00
Lauri Ojansivu 331a64f067 Merge pull request #4224 from varac/improve_chart_readme
Add usage docs
2021-12-14 23:35:30 +02:00
Lauri Ojansivu 7f06218877 Updated ChangeLog. 2021-12-14 23:34:51 +02:00
Lauri Ojansivu fc95698953 Merge pull request #4221 from Ben0it-T/master
Fix : Clicking to view Lists or Swimlanes Archive adds temporarily many empty Lists to board
2021-12-14 23:33:52 +02:00
Emile NDAGIJIMANA 2f69501c14 Fix bug regarding non admin users who have an email on a given domain name (field in Admin panel settings) and that can't invite new users for a registration 2021-12-13 19:14:52 +01:00
Ben0it-T 8d2c5a9bbb Board view (sidebar) - sort Organizations and Teams by Display Name (addBoardOrgPopup, addBoardTeamPopup) 2021-12-12 19:07:37 +01:00
Ben0it-T cec05dae47 All boards view (boardsList) - sort Organizations and Teams by Display Name 2021-12-12 18:55:49 +01:00
Ben0it-T 8e6bd81abe People view - sort Organizations and Teams cols 2021-12-12 18:20:59 +01:00
Ben0it-T eb9d44f5f0 People view - sort Organizations and Teams by Display Name (editUserPopup, newUserPopup, modifyTeamsUsers) 2021-12-12 18:10:50 +01:00
Ben0it-T 3a83d48bef Admin Panel - sort Organizations and Teams by Display Name, sort People by username 2021-12-12 17:55:49 +01:00
Emile NDAGIJIMANA 01cd1c0fdc Add full name if exists in 'email-invite-subject' for user to invite 2021-12-09 10:55:47 +01:00
Varac c9ddad5615 Add usage docs 2021-12-08 23:02:42 +01:00
Ben0it-T 9eb6a1d6af Fix : Clicking to view Lists or Swimlanes Archive adds temporarily many empty Lists to board 2021-12-08 06:53:22 +01:00
Lauri Ojansivu 9b22e6da7a Updated ChangeLog. 2021-12-06 18:35:57 +02:00
Lauri Ojansivu 66488b834b Merge pull request #4217 from Emile840/master
Fix legal notice traduction bug when refreshing sign in page
2021-12-06 18:34:54 +02:00
Emile NDAGIJIMANA 8752225409 Fix legal notice traduction bug (when refreshing sign in page, legal notice line was always in english even if a given language isn't english 2021-12-06 15:03:42 +01:00
Lauri Ojansivu 258b31f04a Updated translations. 2021-12-03 14:19:23 +02:00
Lauri Ojansivu 6997dbc6a8 Updated ChangeLog. 2021-12-03 12:23:39 +02:00
Lauri Ojansivu 1c3f42cec1 Update version number. 2021-12-03 12:16:32 +02:00
Lauri Ojansivu fc6c4f85f0 Merge pull request #4208 from varac/kubernetes_1.22
Kubernetes 1.22 support and basic helm test
2021-12-03 12:10:21 +02:00
Lauri Ojansivu 8ad9f2fbea Updated ChangeLog. 2021-12-02 22:17:25 +02:00
Lauri Ojansivu ee5ec45c73 Merge pull request #4203 from mfilser/fix_list_header_title_overlap
List title doesn't overlap with hamburger menu anymore
2021-12-02 22:07:57 +02:00
Varac 710c65a8ae Bump Chart version to 1.1.1 2021-12-01 09:45:42 +01:00
Varac f094dfb84f Add basic helm test
See https://github.com/wekan/charts/pull/2
and https://helm.sh/docs/topics/chart_tests/
2021-12-01 09:42:41 +01:00
Varac b84cc037c1 Support k8s >= 1.22 ingress API
See https://github.com/wekan/charts/pull/1
2021-12-01 09:42:07 +01:00
Martin Filser 7aaa853d1b Edit list title on mobile view uses whole grid layout 2021-11-30 16:26:08 +01:00
Martin Filser e32225e18f Vertical center align list hamburger menu on mobile view 2021-11-30 16:26:08 +01:00
Martin Filser d7f903f3cd Fixed inlined form (title edit) on mobile view 2021-11-30 16:26:08 +01:00
Martin Filser f0ebfb7f58 List header styling on mobile view
- nearly to the same as in desktop view
2021-11-30 16:26:08 +01:00
Martin Filser f660dcaa86 List header menu in the right of "cards count" 2021-11-30 16:26:08 +01:00
Martin Filser daa5de7011 Move list header menu to top
- fix overflow bug if list name is too long
https://github.com/wekan/wekan/pull/4195#issuecomment-981878664
2021-11-30 16:26:08 +01:00
Lauri Ojansivu 2827c0e3ed v5.83 2021-11-30 11:26:03 +02:00
Lauri Ojansivu 00cd8f140c Updated translations. 2021-11-30 11:25:38 +02:00
Lauri Ojansivu 8be1d371cd Updated translations. 2021-11-30 10:39:33 +02:00
Lauri Ojansivu 2252a855dd Updated ChangeLog. 2021-11-29 23:24:00 +02:00
Lauri Ojansivu c1eb175ab8 Merge pull request #4201 from mfilser/fix_dragging_scroll_vertically
Dragging minicards scrolls now vertically at the end of the screen
2021-11-29 23:22:48 +02:00
Martin Filser e7174107e9 Dragging minicards scrolls now vertically at the end of the screen 2021-11-29 22:19:16 +01:00
Lauri Ojansivu 63c838eee9 Updated ChangeLog. 2021-11-29 23:06:40 +02:00
Lauri Ojansivu bd336dddec Updated translations. 2021-11-29 23:06:25 +02:00
Lauri Ojansivu 673e5b1987 Update translations. 2021-11-29 22:58:55 +02:00
Lauri Ojansivu d45bbc2269 Merge pull request #4200 from mfilser/change_delete_checklist_to_popup
Changed delete checklist dialog to a popup
2021-11-29 22:56:37 +02:00
Martin Filser 8884d5b7e0 Changed delete checklist dialog to a popup
- Fixes #4196
- the old "interesting" implementation didn't always show the dialog,
  especially on long and many checklists + on mobiles too. So changing to
  a popup should solve all this issues
2021-11-29 21:19:30 +01:00
Lauri Ojansivu a3b99dd02d v5.82 2021-11-29 21:50:59 +02:00
Lauri Ojansivu e7138772f0 Updated ChangeLog. 2021-11-29 21:45:42 +02:00
Lauri Ojansivu b8a976d4ad Merge pull request #4195 from mfilser/list_header_add_card_to_bottom_of_the_list
List header contains now a button to add the card to the bottom of the list
2021-11-29 21:43:53 +02:00
Lauri Ojansivu ba0fb2d985 Updated ChangeLog. 2021-11-29 21:42:11 +02:00
Lauri Ojansivu ebc7741fcb Revert change from WeKan v5.81: At Sandstorm, every WeKan user is now WeKan Admin and has Admin Panel.
Thank to ocdtrekkie and xet7 !

Related #3423
2021-11-29 21:39:08 +02:00
Lauri Ojansivu d1f8c92a99 v5.81 2021-11-29 20:13:18 +02:00
Lauri Ojansivu 4036abe3c1 Updated ChangeLog. 2021-11-29 19:53:19 +02:00
Lauri Ojansivu 23a2e90f5f At Sandstorm, every WeKan user is now Admin and has Admin Panel. This could help export, board member permissions, etc.
Thanks to PizzaProgram and xet7 !

Fixes #3423
2021-11-29 19:49:11 +02:00
Lauri Ojansivu 5792b21ed1 Updated translations. 2021-11-29 19:41:57 +02:00
Martin Filser 4a4bfef888 Restored padding-left to 4px 2021-11-28 19:49:29 +01:00
Martin Filser a2cefc595e Move "Add card to bottom" to hamburger menu 2021-11-28 17:37:30 +01:00
Martin Filser 892828c02e Restored icon color 2021-11-27 21:52:03 +01:00
Martin Filser 9cf8af0416 Plus and arrow icon as "one icon", no space between them 2021-11-27 21:52:03 +01:00
Martin Filser 2767c444b2 Add arrow up icon in the right of the plus icon 2021-11-27 21:52:03 +01:00
Martin Filser b5ee0649db Changed plus-square icon back to plus icon 2021-11-27 21:52:03 +01:00
Martin Filser a7b7bfafb5 Add arrow down icon in the right of the plus icon
- there isn't a good plus icon which means the card is added at the
  bottom, so i try to use 2 icons for this feature
2021-11-27 11:57:24 +01:00
Lauri Ojansivu 36d8949831 v5.80 2021-11-26 02:39:27 +02:00
Lauri Ojansivu 5c5c867aca Updated translations. 2021-11-26 02:32:30 +02:00
Lauri Ojansivu 383323c4ea Updated ChangeLog. 2021-11-26 02:25:49 +02:00
Lauri Ojansivu 96465ac664 Part 2: Copy text button at most textarea fields is now translatable.
Thanks to xet7 !
2021-11-26 02:24:42 +02:00
Lauri Ojansivu 98dedc697c Updated translations. 2021-11-26 02:16:47 +02:00
Lauri Ojansivu f82fbdb8a2 Updated ChangeLog. 2021-11-26 02:11:28 +02:00
Lauri Ojansivu 5088c12253 Textareas "Copy text to clipboard" is now translatable.
Thanks to xet7 !
2021-11-26 02:07:00 +02:00
Lauri Ojansivu 611af2d523 Updated ChangeLog. 2021-11-26 01:29:23 +02:00
Lauri Ojansivu 97ef13c222 Updated ChangeLog. 2021-11-26 01:28:33 +02:00
Lauri Ojansivu d7adfc779e Merge branch 'master' of github.com:wekan/wekan 2021-11-26 01:25:57 +02:00
Lauri Ojansivu 507cfbb377 Updated ChangeLog. 2021-11-26 01:25:50 +02:00
Lauri Ojansivu 1af75aa579 Merge pull request #4194 from mfilser/fix_multi_selection_sidebar_action_keep_card_order
Sidebar multi selection actions keep now the card sorting (cards moving, cards to archive etc.)
2021-11-26 01:25:08 +02:00
Martin Filser 861b98ea37 List header contains now a button to add the card to the bottom of the list 2021-11-26 00:24:57 +01:00
Lauri Ojansivu b09be8614b Updated package-lock.json
Thanks to xet7 !
2021-11-26 01:24:20 +02:00
Lauri Ojansivu 8bc047cec3 Updated ChangeLog. 2021-11-26 01:21:49 +02:00
Martin Filser cb7ec54be2 Sidebar multi selection actions keep now the card sorting (cards moving, cards to archive etc.) 2021-11-26 00:21:37 +01:00
Lauri Ojansivu 6d3b979d67 Merge pull request #4193 from mfilser/fix_multi_selection_keep_cards_order_on_dragging_to_another_column
Moving many cards with multi selection drag/drop to another list keeps the card order
2021-11-26 01:20:52 +02:00
Lauri Ojansivu fe01d35fe6 Updated ChangeLog. 2021-11-26 01:19:12 +02:00
Martin Filser f38e3db93c Moving many cards with multi selection drag/drop to another list keeps the card order 2021-11-26 00:18:13 +01:00
Lauri Ojansivu b988ef430c Merge pull request #4192 from mfilser/move_cards_to_top_ignores_the_current_filter
Move cards to top/bottom ignores the current filter if active
2021-11-26 01:17:57 +02:00
Lauri Ojansivu 4a97e70b8d Updated ChangeLog. 2021-11-26 01:14:15 +02:00
Martin Filser f082128d99 Move cards to top/bottom ignores the current filter if active 2021-11-26 00:14:03 +01:00
Lauri Ojansivu 7577b246da Merge pull request #4191 from mfilser/attachments_show_filesize
Attachments, show file size in KB in card details
2021-11-26 01:13:06 +02:00
Lauri Ojansivu 9db14a0c3b Updated translations. 2021-11-26 01:12:42 +02:00
Martin Filser f3d5b887c8 Attachments, show file size in KB in card details 2021-11-26 00:10:09 +01:00
Lauri Ojansivu 7e21589ee1 Merge pull request #4190 from mfilser/sidebar_members_settings_popup_title
Sidebar Member Settings Popup has now a Popup title
2021-11-26 01:08:24 +02:00
Martin Filser e1e4ea1205 Sidebar Member Settings Popup has now a Popup title 2021-11-26 00:04:55 +01:00
Lauri Ojansivu 54205b7c5d Updated ChangeLog. 2021-11-26 01:04:38 +02:00
Lauri Ojansivu e0b5d1c15e Merge pull request #4189 from mfilser/custom_fields_currency_autofocus
CustomFields Currency, autofocus on edit
2021-11-26 01:03:49 +02:00
Martin Filser 79b40cd8a9 CustomFields Currency, autofocus on edit 2021-11-26 00:02:16 +01:00
Lauri Ojansivu f6830ff4f3 Updated translations. 2021-11-26 01:00:59 +02:00
Lauri Ojansivu 765ac045fe Updated ChangeLog. 2021-11-26 00:57:13 +02:00
Lauri Ojansivu b9d98f58cf Fix typo. 2021-11-26 00:56:16 +02:00
Lauri Ojansivu e0978000f8 Merge pull request #4188 from mfilser/fix_save_custom_fields_StringTemplates_on_touch_devices
Custom Field StringTemplates didn't save the last input value on touch devices
2021-11-26 00:55:27 +02:00
Lauri Ojansivu bc186958ab Updated translations. 2021-11-26 00:52:11 +02:00
Martin Filser a190600934 Custom Field StringTemplates didn't save the last input value on touch devices 2021-11-25 23:48:54 +01:00
Lauri Ojansivu 65fc2a4fdd Updated ChangeLog. 2021-11-26 00:48:52 +02:00
Lauri Ojansivu d41810aca1 Merge pull request #4187 from mfilser/fix_infinite_scrolling_on_mobile_view
Fix: On mobile infinite scrolling didn't work
2021-11-26 00:48:02 +02:00
Lauri Ojansivu b75a7a6424 Revert upgrade jquery.
Thanks to mfilser!
2021-11-26 00:45:33 +02:00
Martin Filser bfb3837ee4 Fix: On mobile infinite scrolling didn't work anymore
- listBody.js:755 doesn't trigger an event when scrolling
2021-11-25 23:42:07 +01:00
Lauri Ojansivu 72fa10761a Updated ChangeLog. 2021-11-26 00:41:13 +02:00
Lauri Ojansivu 9c1523c916 Merge pull request #4186 from mfilser/settings_add_space_between_radio_buttons
Settings, add some space between radio buttons
2021-11-26 00:40:29 +02:00
Lauri Ojansivu a786262658 Updated translations. 2021-11-26 00:40:00 +02:00
Martin Filser 6245982025 Settings, add some space between radio buttons
- Fixes: #4159
2021-11-25 23:28:30 +01:00
Lauri Ojansivu c643cdaad3 Merge pull request #4185 from mfilser/add_copy_text_button_to_most_textarea_fields
Add copy text button to most textarea fields
2021-11-26 00:26:37 +02:00
Martin Filser f0cadf858d New card comments have now the same color as card comment editing 2021-11-25 23:21:45 +01:00
Martin Filser 2566286e86 Copied tooptip did only work at mobile view, now on desktop view too 2021-11-25 23:20:35 +01:00
Martin Filser 8bf3841e6c Added copy button to edit Checklist and Checklist-Items editor 2021-11-25 23:16:09 +01:00
Martin Filser 7a959ef1a2 Added copy button to new Checklist and Checklist-Items editor 2021-11-25 23:16:09 +01:00
Martin Filser 5525247f52 Copied! Tooltip of card link showed also "Copied!" at the comments 2021-11-25 23:16:09 +01:00
Martin Filser 7444c11c82 Moved "copied!" code to Utils
- same implementation in all files, so it's better to have one function
  for it
2021-11-25 23:16:09 +01:00
Martin Filser 6d3ecdea55 Changed copy icon to a "href" link
- mouse hover changes the icon
2021-11-25 23:16:09 +01:00
Martin Filser 7db1445d09 Added copy button to all editor's 2021-11-25 23:16:09 +01:00
Martin Filser 08ee969445 Added animation to tooltip "copied!" 2021-11-25 23:16:09 +01:00
Martin Filser 4bfa727e9e Show a "copied!" tooltip after successfull URL copy 2021-11-25 23:16:09 +01:00
Lauri Ojansivu ed53065a09 Merge pull request #4184 from mfilser/fix_copy_card_url
Copy card url works now again
2021-11-26 00:16:01 +02:00
Lauri Ojansivu 49fdae6e06 Updated ChangeLog. 2021-11-26 00:15:35 +02:00
Lauri Ojansivu b78dfc7149 Updated translations. 2021-11-26 00:13:33 +02:00
Martin Filser 0227b38845 Copy card url works now again
Fixes: #4155
2021-11-25 23:13:29 +01:00
Lauri Ojansivu 7d52016d79 Updated ChangeLog. 2021-11-26 00:13:20 +02:00
Lauri Ojansivu d9bc5f80a0 Merge pull request #4183 from mfilser/list_addding_cancel_button
List adding has now a cancel button
2021-11-26 00:12:17 +02:00
Lauri Ojansivu f1a0e4754f Updated ChangeLog. 2021-11-26 00:06:46 +02:00
Lauri Ojansivu 496c791629 Updated dependencies.
Thanks to developers of dependencies!
2021-11-26 00:05:21 +02:00
Martin Filser 2b7c5cfcb1 List adding has now a cancel button 2021-11-25 23:04:33 +01:00
Lauri Ojansivu f647f4580e Updated ChangeLog. 2021-11-26 00:04:31 +02:00
Lauri Ojansivu c62c705755 Merge pull request #4181 from mfilser/drag_drop_update_and_screen_and_list_scroll
Drag drop jquery-ui update + screen and list scroll
2021-11-26 00:03:38 +02:00
Lauri Ojansivu 57129eff04 Updated translations. 2021-11-26 00:01:00 +02:00
Martin Filser 3c7ca87625 Don't scroll the screen more than the scrollbar would scroll 2021-11-25 22:42:06 +01:00
Martin Filser 126c9ab853 The Minicard dragging scrolls now the board at screen outside 2021-11-25 22:42:06 +01:00
Martin Filser c9071a74bc jquery-ui works now with touch devices
- the "old" implementation at wekan source code didn't work anymore with
  jquery-ui@1.13.0, so it's necessary to use another package to get it
  work again
2021-11-25 22:42:06 +01:00
Martin Filser 292e43466e Card drag/drop scrolls now the list at top/bottom 2021-11-25 22:42:06 +01:00
Lauri Ojansivu 75af42cd8c Merge branch 'master' of github.com:wekan/wekan 2021-11-25 23:41:26 +02:00
Lauri Ojansivu 60c831521e Updated ChangeLog. 2021-11-25 23:41:19 +02:00
Lauri Ojansivu 9e0de569dc Merge pull request #4180 from mfilser/app_reconnect_link_not_clickable
App reconnect link wasn't clickable
2021-11-25 23:40:13 +02:00
Lauri Ojansivu 6dbb8c8c68 Merge pull request #4179 from Ben0it-T/master
Show or hide members and assignee(s) on minicard
2021-11-25 23:39:35 +02:00
Lauri Ojansivu ac89276ee9 Updated ChangeLog. 2021-11-25 23:38:45 +02:00
Lauri Ojansivu 7902221a96 Updated ChangeLog. 2021-11-25 23:36:47 +02:00
Lauri Ojansivu 47540df916 Merge branch 'Emile840-master' 2021-11-25 23:34:28 +02:00
Lauri Ojansivu dbef7e7cd3 Restored ChangeLog. 2021-11-25 23:34:06 +02:00
Martin Filser 4a19790b11 App reconnect link wasn't clickable 2021-11-25 22:33:40 +01:00
Ben0it-T 533eb41249 Show or hide members and assignee(s) on minicard 2021-11-25 22:27:19 +01:00
Lauri Ojansivu f09ea42981 Updated ChangeLog. 2021-11-25 23:25:55 +02:00
Lauri Ojansivu 6290b3b697 Updated ChangeLog. 2021-11-25 23:24:43 +02:00
Lauri Ojansivu 92b6b0064a Merge pull request #4176 from mfilser/label_drag_drop_show_helper_on_sub_popup
Show helper at label drag/drop if label popup opened from card details popup
2021-11-25 23:22:51 +02:00
Emile NDAGIJIMANA 8662fd59fb possibility of adding a custom legal notice page url 2021-11-25 19:31:20 +01:00
Lauri Ojansivu 16bb65f7c7 Docker build script to be executeable.
Thanks to xet7 !
2021-11-25 19:31:20 +01:00
Lauri Ojansivu 44c3449ab2 Fix typo. 2021-11-25 19:31:20 +01:00
Lauri Ojansivu ed13a3b95f v5.79 2021-11-25 19:31:20 +01:00
Lauri Ojansivu 32646fb9be Updated ChangeLog. 2021-11-25 19:31:20 +01:00
Martin Filser 38eccdb95b Fixed label popup at desktop view (add and remove labels)
Fixes: #4156
2021-11-25 19:31:20 +01:00
Lauri Ojansivu 6944a20ba4 Updated translations. 2021-11-25 19:31:20 +01:00
Lauri Ojansivu 2e8323ca6a Updated ChangeLog. 2021-11-25 19:31:20 +01:00
Martin Filser fae4d0be08 Fix label width oversize bug
Happens at Firefox zoom level 90%, probably on Windows...

Fixes: https://github.com/wekan/wekan/pull/4073#issuecomment-971563178
2021-11-25 19:31:20 +01:00
Martin Filser b58e1c0102 Show helper at label drag/drop if label popup opened from card details popup 2021-11-25 17:11:22 +01:00
Emile NDAGIJIMANA f18658c0d2 Fix bug from issue #4173 2021-11-25 16:01:43 +01:00
Lauri Ojansivu 8054f2b002 Docker build script to be executeable.
Thanks to xet7 !
2021-11-25 16:27:07 +02:00
Lauri Ojansivu 5178aade75 Fix typo. 2021-11-25 16:00:42 +02:00
Lauri Ojansivu 6628ae8b5a v5.79 2021-11-25 15:52:24 +02:00
Lauri Ojansivu 7ca0fa626c Updated ChangeLog. 2021-11-25 15:43:56 +02:00
Lauri Ojansivu 0ceff124cc Merge pull request #4170 from mfilser/fix_label_popup_desktop_view_add_remove
Fixed label popup at desktop view (add and remove labels)
2021-11-25 15:42:51 +02:00
Martin Filser 37faa41d97 Fixed label popup at desktop view (add and remove labels)
Fixes: #4156
2021-11-25 06:59:52 +01:00
Lauri Ojansivu fc0630715c Updated translations. 2021-11-25 06:42:06 +02:00
Lauri Ojansivu 9e75a70212 Updated ChangeLog. 2021-11-25 06:37:44 +02:00
Lauri Ojansivu 3d61be028a Merge pull request #4157 from mfilser/fix_label_oversize_bug_firefox_zoom_level_90_percent
Fix label width oversize bug
2021-11-25 06:35:30 +02:00
Martin Filser f9c179e9df Fix label width oversize bug
Happens at Firefox zoom level 90%, probably on Windows...

Fixes: https://github.com/wekan/wekan/pull/4073#issuecomment-971563178
2021-11-17 16:57:23 +01:00
Lauri Ojansivu 2b77a67c03 v5.78 2021-11-17 00:50:25 +02:00
Lauri Ojansivu c6fc172055 Updated ChangeLog. 2021-11-17 00:36:56 +02:00
Lauri Ojansivu 7aafb5e26e Fix typo. 2021-11-17 00:36:42 +02:00
Lauri Ojansivu 02b6df320f Show Nodejs heap stats only at Standalone WeKan.
Not shown at Sandstorm WeKan, because there's a bunch of machine performance data
Sandstorm doesn't expose to apps to prevent side channel attacks.

Thanks to ocdtrekkie and xet7 !

Fixes #4154
2021-11-17 00:26:40 +02:00
Lauri Ojansivu 6d719b8a98 v5.77 2021-11-16 19:12:02 +02:00
Lauri Ojansivu b1b12b05b5 Updated Docker Ubuntu base image.
Thanks to Ubuntu developers!
2021-11-16 19:06:59 +02:00
John Supplee 52e45211a2 Merge branch 'master' of https://github.com/wekan/wekan 2021-08-08 10:55:20 +02:00
John Supplee cca51628ef Merge branch 'master' of https://github.com/wekan/wekan 2021-07-27 18:13:47 -04:00
John Supplee 506cb696d3 Merge branch 'master' of https://github.com/wekan/wekan 2021-07-26 11:25:27 -04:00
John Supplee a4e02bb8cd Merge branch 'master' of https://github.com/wekan/wekan 2021-07-23 11:14:53 -04:00
John Supplee 6d588130dd Merge branch 'master' of https://github.com/wekan/wekan 2021-07-20 19:25:09 -04:00
John Supplee 0ce2f9ea43 Merge branch 'master' of https://github.com/wekan/wekan 2021-07-20 19:24:40 -04:00
John Supplee 80c4908fcc Merge branch 'master' of https://github.com/wekan/wekan 2021-05-31 13:59:56 -04:00
John Supplee 30a29e23d3 Merge branch 'admin-reports' of supplee.net:wekan
# Conflicts:
#	i18n/en.i18n.json
2021-05-31 13:59:40 -04:00
John R. Supplee 661e80084c Add Cards report 2021-04-17 10:27:16 +02:00
455 changed files with 16672 additions and 27823 deletions

No files matched your search

+25 -4
View File
@@ -1,4 +1,4 @@
FROM quay.io/wekan/ubuntu:groovy-20210115
FROM ubuntu:rolling
LABEL maintainer="sgr"
ENV BUILD_DEPS="gnupg gosu libarchive-tools wget curl bzip2 g++ build-essential python git ca-certificates iproute2"
@@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive
ENV \
DEBUG=false \
NODE_VERSION=v12.22.7 \
NODE_VERSION=v14.19.1 \
METEOR_RELEASE=1.10.2 \
USE_EDGE=false \
METEOR_EDGE=1.5-beta.17 \
@@ -132,7 +132,16 @@ ENV \
SAML_IDENTIFIER_FORMAT="" \
SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
SAML_ATTRIBUTES="" \
DEFAULT_WAIT_SPINNER=""
DEFAULT_WAIT_SPINNER="" \
NODE_OPTIONS="--max_old_space_size=4096"
#---------------------------------------------------------------------
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
# Add more Node heap:
# NODE_OPTIONS="--max_old_space_size=4096"
# Add more stack:
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
#---------------------------------------------------------------------
# Install OS
RUN set -o xtrace \
@@ -229,7 +238,9 @@ RUN \
set -o xtrace && \
cd /home/wekan/app_build/bundle/programs/server/ && \
chmod u+w package.json npm-shrinkwrap.json && \
npm install
npm install && \
cd node_modules/fibers && \
node build.js
USER root
# Cleanup
@@ -248,4 +259,14 @@ ENV PORT=3000
EXPOSE $PORT
WORKDIR /home/wekan/app
#---------------------------------------------------------------------
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
# Add more Node heap:
# NODE_OPTIONS="--max_old_space_size=4096"
# Add more stack:
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
#---------------------------------------------------------------------
#TODO:
#CMD ["bash", "-c", "ulimit -s 65500; exec node --stack-size=65500 /build/main.js"]
CMD ["/home/wekan/.meteor/meteor", "run", "--verbose", "--settings", "settings.json"]
+2
View File
@@ -9,4 +9,6 @@ cp -f fix-download-unicode/cfs_access-point.txt .build/bundle/programs/server/pa
cd .build/bundle/programs/server
rm -rf node_modules
/home/wekan/.meteor/meteor npm install
cd node_modules/fibers
node build.js
cd /home/wekan/app
+2
View File
@@ -33,10 +33,12 @@ services:
- WITH_API=true
- RICHER_CARD_COMMENT_EDITOR=true
- BROWSER_POLICY_ENABLED=true
- WRITABLE_PATH=/data
depends_on:
- wekandb-dev
volumes:
- /etc/localtime:/etc/localtime:ro
- ./volumes/data:/data
- ../client:/home/wekan/app/client
- ../models:/home/wekan/app/models
- ../config:/home/wekan/app/config
+1 -1
View File
@@ -81,7 +81,7 @@ parts:
wekan:
source: .
plugin: nodejs
node-engine: 12.22.7
node-engine: 14.19.1
node-packages:
- node-gyp
- node-pre-gyp
+155
View File
@@ -0,0 +1,155 @@
name: wekan
version: git
summary: The open-source kanban
description: |
Wekan is an open-source and collaborative kanban board application.
Whether you’re maintaining a personal todo list, planning your holidays with some friends, or working in a team on your next revolutionary idea, Kanban boards are an unbeatable tool to keep your things organized. They give you a visual overview of the current state of your project, and make you productive by allowing you to focus on the few items that matter the most.
Depending on target environment, some configuration settings might need to be adjusted.
For full list of configuration options call:
$ wekan.help
confinement: strict
grade: stable
base: core18
architectures:
- amd64
plugs:
mongodb-plug:
interface: content
target: $SNAP_DATA/shared
hooks:
configure:
plugs:
- network
- network-bind
slots:
mongodb-slot:
interface: content
write:
- $SNAP_DATA/share
apps:
wekan:
command: wekan-control
daemon: simple
plugs: [network, network-bind]
mongodb:
command: mongodb-control
daemon: simple
plugs: [network, network-bind]
caddy:
command: caddy-control
daemon: simple
plugs: [network, network-bind]
help:
command: wekan-help
database-backup:
command: mongodb-backup
plugs: [network, network-bind]
database-list-backups:
command: ls -al $SNAP_COMMON/db-backups/
database-restore:
command: mongodb-restore
plugs: [network, network-bind]
parts:
mongodb:
source: https://repo.mongodb.org/apt/ubuntu/dists/xenial/mongodb-org/4.2/multiverse/binary-amd64/mongodb-org-server_4.2.2_amd64.deb
#https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.14.tgz
#https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-3.2.22.tgz
plugin: dump
stage-packages: [libssl1.0.0, libcurl3]
filesets:
mongo:
- usr
- bin
- lib
stage:
- $mongo
prime:
- $mongo
wekan:
source: .
plugin: nodejs
node-engine: 14.19.0
node-packages:
- node-gyp
- node-pre-gyp
- fibers
build-packages:
- ca-certificates
- apt-utils
- build-essential
- python
- python3
- g++
- capnproto
- curl
- libcurl3
- execstack
- nodejs
- npm
stage-packages:
- libfontconfig1
override-build: |
echo "Cleaning environment first"
rm -rf ~/.meteor ~/.npm /usr/local/lib/node_modules
rm -rf .build
echo "Installing meteor"
curl https://install.meteor.com/ -o install_meteor.sh
chmod +x install_meteor.sh
sh install_meteor.sh
rm install_meteor.sh
rm -rf .build
meteor add standard-minifier-js --allow-superuser
meteor npm install --allow-superuser
meteor npm install --allow-superuser --save babel-runtime
meteor build .build --directory --allow-superuser
cp -f fix-download-unicode/cfs_access-point.txt .build/bundle/programs/server/packages/cfs_access-point.js
cd .build/bundle/programs/server
npm install
npm install --allow-superuser --save babel-runtime
# Change back to Wekan source directory
cd ../../../..
cp -r .build/bundle/* $SNAPCRAFT_PART_INSTALL/
cp .build/bundle/.node_version.txt $SNAPCRAFT_PART_INSTALL/
rm -f $SNAPCRAFT_PART_INSTALL/lib/node_modules/wekan
rm -f $SNAPCRAFT_PART_INSTALL/programs/server/npm/node_modules/meteor/rajit_bootstrap3-datepicker/lib/bootstrap-datepicker/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs
rm -f $SNAPCRAFT_PART_INSTALL/programs/server/npm/node_modules/tar/lib/.mkdir.js.swp
rm -f $SNAPCRAFT_PART_INSTALL/lib/node_modules/node-pre-gyp/node_modules/tar/lib/.mkdir.js.swp
rm -f $SNAPCRAFT_PART_INSTALL/lib/node_modules/node-gyp/node_modules/tar/lib/.mkdir.js.swp
rm -f $SNAPCRAFT_PART_INSTALL/programs/server/node_modules/node-pre-gyp/node_modules/tar/lib/.mkdir.js.swp
organize:
README: README.wekan
prime:
- -lib/node_modules/node-pre-gyp/node_modules/tar/lib/.unpack.js.swp
helpers:
source: snap-src
plugin: dump
caddy:
plugin: dump
source: https://caddyserver.com/download/linux/amd64?license=personal&telemetry=off
source-type: tar
organize:
caddy: bin/caddy
CHANGES.txt: CADDY_CHANGES.txt
EULA.txt: CADDY_EULA.txt
LICENSES.txt: CADDY_LICENSES.txt
README.txt: CADDY_README.txt
stage:
- -init
+62 -64
View File
@@ -1,8 +1,9 @@
name: wekan
version: git
summary: The open-source kanban
version: '6.10'
base: core20
summary: Open Source kanban
description: |
Wekan is an open-source and collaborative kanban board application.
WeKan ® is an Open Source and collaborative kanban board application.
Whether you’re maintaining a personal todo list, planning your holidays with some friends, or working in a team on your next revolutionary idea, Kanban boards are an unbeatable tool to keep your things organized. They give you a visual overview of the current state of your project, and make you productive by allowing you to focus on the few items that matter the most.
Depending on target environment, some configuration settings might need to be adjusted.
@@ -11,10 +12,13 @@ description: |
confinement: strict
grade: stable
base: core18
architectures:
- amd64
- build-on: amd64
run-on: amd64
- build-on: arm64
run-on: arm64
plugs:
mongodb-plug:
@@ -37,12 +41,14 @@ apps:
wekan:
command: wekan-control
daemon: simple
plugs: [network, network-bind]
plugs: [network, network-bind, mount-observe, system-observe, bluetooth-control]
restart-condition: on-failure
mongodb:
command: mongodb-control
daemon: simple
plugs: [network, network-bind]
plugs: [network, network-bind, mount-observe, system-observe, bluetooth-control]
restart-condition: on-failure
caddy:
command: caddy-control
@@ -54,22 +60,25 @@ apps:
database-backup:
command: mongodb-backup
plugs: [network, network-bind]
plugs: [network, network-bind, mount-observe, system-observe, bluetooth-control]
database-list-backups:
command: ls -al $SNAP_COMMON/db-backups/
database-restore:
command: mongodb-restore
plugs: [network, network-bind]
plugs: [network, network-bind, mount-observe, system-observe, bluetooth-control]
parts:
mongodb:
source: https://repo.mongodb.org/apt/ubuntu/dists/xenial/mongodb-org/4.2/multiverse/binary-amd64/mongodb-org-server_4.2.2_amd64.deb
#https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.14.tgz
#https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-3.2.22.tgz
plugin: dump
stage-packages: [libssl1.0.0, libcurl3]
source:
- on amd64: https://repo.mongodb.org/apt/ubuntu/dists/focal/mongodb-org/4.4/multiverse/binary-amd64/mongodb-org-server_4.4.12_amd64.deb
- on arm64: https://repo.mongodb.org/apt/ubuntu/dists/focal/mongodb-org/4.4/multiverse/binary-arm64/mongodb-org-server_4.4.12_arm64.deb
stage-packages:
- libssl1.1
- libcurl3-dev
- libcurl4-openssl-dev
filesets:
mongo:
- usr
@@ -81,61 +90,43 @@ parts:
- $mongo
wekan:
source: .
plugin: nodejs
node-engine: 12.22.7
node-packages:
- node-gyp
- node-pre-gyp
- fibers
plugin: npm
source:
# TODO: Fix URLs to some allowed GitHub releases URL.
# Non-GitHub build server file urls are not allowed at 2022-03-02 and later.
- on amd64: https://wekan.github.io/wekan-latest-x64.zip
- on arm64: https://wekan.github.io/raspi3/wekan-latest-arm64.zip
npm-node-version: 14.19.0
# node-packages:
# - node-gyp
# - node-pre-gyp
# - fibers
build-packages:
- ca-certificates
- apt-utils
- build-essential
- python
- python3
- g++
- capnproto
- curl
- libcurl3
- execstack
- nodejs
- npm
stage-packages:
- libfontconfig1
- npm
# - build-essential
# - ca-certificates
# - apt-utils
# - python
# - python3
# - g++
# - capnproto
# - curl
# - execstack
# - nodejs
# - npm
- p7zip-full
# stage-packages:
# - libfontconfig1
override-build: |
echo "Cleaning environment first"
rm -rf ~/.meteor ~/.npm /usr/local/lib/node_modules
rm -rf .build
echo "Installing meteor"
curl https://install.meteor.com/ -o install_meteor.sh
chmod +x install_meteor.sh
sh install_meteor.sh
rm install_meteor.sh
rm -rf .build
meteor add standard-minifier-js --allow-superuser
meteor npm install --allow-superuser
meteor npm install --allow-superuser --save babel-runtime
meteor build .build --directory --allow-superuser
cp -f fix-download-unicode/cfs_access-point.txt .build/bundle/programs/server/packages/cfs_access-point.js
cd .build/bundle/programs/server
npm install
npm install --allow-superuser --save babel-runtime
# Change back to Wekan source directory
cd ../../../..
cp -r .build/bundle/* $SNAPCRAFT_PART_INSTALL/
cp .build/bundle/.node_version.txt $SNAPCRAFT_PART_INSTALL/
rm -f $SNAPCRAFT_PART_INSTALL/lib/node_modules/wekan
rm -f $SNAPCRAFT_PART_INSTALL/programs/server/npm/node_modules/meteor/rajit_bootstrap3-datepicker/lib/bootstrap-datepicker/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs
rm -f $SNAPCRAFT_PART_INSTALL/programs/server/npm/node_modules/tar/lib/.mkdir.js.swp
rm -f $SNAPCRAFT_PART_INSTALL/lib/node_modules/node-pre-gyp/node_modules/tar/lib/.mkdir.js.swp
rm -f $SNAPCRAFT_PART_INSTALL/lib/node_modules/node-gyp/node_modules/tar/lib/.mkdir.js.swp
rm -f $SNAPCRAFT_PART_INSTALL/programs/server/node_modules/node-pre-gyp/node_modules/tar/lib/.mkdir.js.swp
cp -r bundle/* $SNAPCRAFT_PART_INSTALL/
cp bundle/.node_version.txt $SNAPCRAFT_PART_INSTALL/
rm -f $SNAPCRAFT_PART_INSTALL/lib/node_modules/wekan
snapcraftctl build
organize:
README: README.wekan
prime:
- -lib/node_modules/node-pre-gyp/node_modules/tar/lib/.unpack.js.swp
- -lib/node_modules/weka*
helpers:
source: snap-src
@@ -143,8 +134,15 @@ parts:
caddy:
plugin: dump
source: https://caddyserver.com/download/linux/amd64?license=personal&telemetry=off
source-type: tar
## Caddy v1 is not developed anymore. TODO: Sometime migrate to Caddy v2.
## https://caddy.community/t/caddyfile-v1-adapter/9129
## https://github.com/caddyserver/caddy/tree/v1
#source: https://caddyserver.com/download/linux/amd64?license=personal&telemetry=off
#source-type: tar
# Using last working binary that was downloaded from above URL to Wekan Snap,
# and .txt files from https://github.com/caddyserver/caddy/tree/v1/dist
source: https://wekan.github.io/caddy-v1-linux-amd64.7z
source-type: 7z
organize:
caddy: bin/caddy
CHANGES.txt: CADDY_CHANGES.txt
+23 -25
View File
@@ -1,37 +1,35 @@
## Issue
<!--
**[PLEASE UPGRADE](https://github.com/wekan/wekan/wiki/Backup)** to the newest WeKan ® before reporting an issue.
Please search existing Open and Closed issues, most questions have already been answered.
**[PLEASE UPGRADE](https://github.com/wekan/wekan/wiki/Backup)** to newest WeKan ® before adding new issue !!
- We get too many duplicate reports of already fixed bugs. Newest WeKan ® has newest bugfixes and security fixes.
- Please search existing Open and Closed issues, most questions have already been answered many times.
If you can not login for any reason: https://github.com/wekan/wekan/wiki/Forgot-Password
Email settings, only SMTP MAIL_URL and MAIL_FROM are in use: https://github.com/wekan/wekan/wiki/Troubleshooting-Mail
If you can not login for any reason:
- https://github.com/wekan/wekan/wiki/Forgot-Password
Email settings, only SMTP MAIL_URL and MAIL_FROM are in use:
- https://github.com/wekan/wekan/wiki/Troubleshooting-Mail
Add these issues to elsewhere:
The following types of issues should be reported separately:
- SECURITY ISSUES: https://github.com/wekan/wekan/blob/master/SECURITY.md
- UCS: https://github.com/wekan/univention/issues
-->
Other Wekan issues can be added here.
**Server Setup Information**:
* Note: Please anonymize info, and do not add to this public issue any of your Wekan board URLs, passwords, API tokens etc, do you understand?:
### Server Setup Information
<!-- Please anonymize info, and do not any of your Wekan board URLs, passwords, API tokens etc to this public issue. -->
* Did you test in newest Wekan?:
* For new Wekan install, did you configure root-url correctly so Wekan cards open correctly https://github.com/wekan/wekan/wiki/Settings ?
* Did you configure root-url correctly so Wekan cards open correctly (see https://github.com/wekan/wekan/wiki/Settings)?
* Operating System:
* Deployment Method(Snap/Docker/Sandstorm/bundle/source):
* Deployment Method (Snap/Docker/Sandstorm/bundle/source):
* Http frontend if any (Caddy, Nginx, Apache, see config examples from Wekan GitHub wiki first):
* Node.js Version:
* MongoDB Version:
* Wekan works on newest desktop and mobile webbrowsers that support Javascript. What webbrowser version are you using?
* What webbrowser version are you using (Wekan should work on all modern browsers that support Javascript)?
**Problem description**:
- *REQUIRED: Add recorded animated gif about how it works currently, and screenshot mockups how it should work. Use peek to record animgif in Linux https://github.com/phw/peek*
- *Explain steps how to reproduce*
- *In webbrowser, what does show Right Click / Inspect / Console ? Chrome shows more detailed info than Firefox.*
- *If using Snap, what does show command `sudo snap logs wekan.wekan` ? Please anonymize logs.*
- *If using Docker, what does show command `sudo docker logs wekan-app` ? Please anonymize logs.*
- *If logs are very long, attach them in .zip file*
### Problem description
<!-- Add a recorded animated gif (e.g. with https://github.com/phw/peek) about how it works currently, and screenshot mockups how it should work. -->
#### Reproduction Steps
#### Logs
<!-- Check Right Click>Inspect>Console in you browser - generally Chrome shows more detailed info than Firefox. -->
<!-- Please anonymize logs.
Snap: sudo snap logs wekan.wekan
Docker: sudo docker logs wekan-app
If logs are very long, attach them in .zip file -->
+1 -1
View File
@@ -118,7 +118,7 @@ jobs:
.meteor/local/isopacks
.meteor/local/bundler-cache/scanner
key: v1-meteor_build_cache-${{ github.ref }}-${{ github.sha }}
restore-key: |
restore-keys: |
v1-meteor_build_cache-
- name: Setup meteor
+1
View File
@@ -38,3 +38,4 @@ ehthumbs.db
# Helm chart
# Chart dependencies
/helm/wekan/**/*.tgz
/helm/wekan/charts
+7 -5
View File
@@ -17,7 +17,7 @@ es5-shim@4.8.0
# Collections
aldeed:collection2
wekan-cfs-standard-packages
cfs:standard-packages
cottz:publish-relations
dburles:collection-helpers
idmontie:migrations
@@ -60,7 +60,6 @@ reactive-var@1.0.11
fortawesome:fontawesome
mousetrap:mousetrap
mquandalle:jquery-textcomplete
mquandalle:jquery-ui-drag-drop-sort
mquandalle:mousetrap-bindglobal
peerlibrary:blaze-components@=0.15.1
templates:tabs
@@ -74,8 +73,8 @@ email@2.0.0
horka:swipebox
dynamic-import@0.6.0
accounts-password@1.7.0
wekan-cfs-gridfs
accounts-password@1.6.2
cfs:gridfs
rzymek:fullcalendar
momentjs:moment@2.22.2
browser-policy-framing@1.1.0
@@ -90,7 +89,10 @@ meteorhacks:aggregate@1.3.0
wekan-markdown
konecty:mongo-counter
percolate:synced-cron
wekan-cfs-filesystem
cfs:filesystem
ostrio:cookies
ostrio:files@2.0.1
tmeasday:check-npm-versions
steffo:meteor-accounts-saml
rajit:bootstrap3-datepicker-fi
rajit:bootstrap3-datepicker-ar
+22 -20
View File
@@ -23,7 +23,24 @@ browser-policy-framing@1.1.0
caching-compiler@1.2.2
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
@@ -76,6 +93,7 @@ matb33:collection-hooks@0.9.1
matteodem:easy-search@1.6.4
mdg:validation-error@0.5.1
meteor@1.9.3
meteor-autosize@5.0.1
meteor-base@1.4.0
meteor-platform@1.2.6
meteorhacks:aggregate@1.3.0
@@ -106,7 +124,6 @@ mquandalle:collection-mutations@0.1.0
mquandalle:jade@0.4.9
mquandalle:jade-compiler@0.4.5
mquandalle:jquery-textcomplete@0.8.0_1
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
@@ -117,6 +134,8 @@ oauth2@1.3.0
observe-sequence@1.0.16
ongoworks:speakingurl@1.1.0
ordered-dict@1.1.0
ostrio:cookies@2.7.0
ostrio:files@2.0.1
pascoual:pdfkit@1.0.7
peerlibrary:assert@0.3.0
peerlibrary:base-component@0.16.0
@@ -211,38 +230,21 @@ templating@1.4.0
templating-compiler@1.4.1
templating-runtime@1.4.0
templating-tools@1.2.0
tmeasday:check-npm-versions@1.0.2
tracker@1.2.0
twbs:bootstrap@3.3.6
typescript@4.2.2
ui@1.0.13
underscore@1.0.10
url@1.3.2
useraccounts:core@1.14.2
useraccounts:flow-routing@1.14.2
useraccounts:unstyled@1.14.2
meteor-autosize@5.0.1
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.22.7
TRAVIS_NODE_VERSION: 14.19.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, de_AT:de-AT, de_CH:de-CH, en_DE:en-DE, en_IT:en-IT, 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-GR, fa_IR:fa-IR, fi_FI:fi, fr_FR:fr-FR, fr_CH:fr-CH, gu_IN:gu-IN, hi_IN:hi-IN, hu_HU:hu, id_ID:id, mn_MN:mn, ms_MY:ms-MY, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, sl_SI:sl, zh_CN:zh-CN, zh_TW:zh-TW, zh_Hans:zh-Hans, zh_HK:zh-HK
lang_map = ar_EG:ar-EG, bg_BG:bg, cs_CZ:cs-CZ, de_AT:de-AT, de_CH:de-CH, en_BR:en-BR, en_DE:en-DE, en_IT:en-IT, en_GB:en-GB, et_EE:et-EE, 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-GR, fa_IR:fa-IR, fi_FI:fi, fr_FR:fr-FR, fr_CH:fr-CH, gl_ES:gl-ES, gu_IN:gu-IN, hi_IN:hi-IN, hu_HU:hu, id_ID:id, mn_MN:mn, ms_MY:ms-MY, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, ru_UA:ru-UA, sl_SI:sl, uk_UA:uk-UA, zh_CN:zh-CN, zh_TW:zh-TW, zh_Hans:zh-Hans, zh_HK:zh-HK
[wekan.application]
file_filter = i18n/<lang>.i18n.json
+663
View File
@@ -1,5 +1,668 @@
[Mac ChangeLog](https://github.com/wekan/wekan/wiki/Mac)
# v6.13 2022-04-01 WeKan ® release
This release adds the following new features:
- [Added Perl scripts for Asana export to WeKan ®](https://github.com/wekan/wekan/commit/376bcbb373d16317060adc2b1154cc20496775cc).
Thanks to GeekRuthie.
- [Add get list and board cards count to API](https://github.com/wekan/wekan/pull/4424).
Thanks to helioguardabaxo.
- [Added translations: English (Brazil) en-BR and Czech (Czech Republic) cs-CZ](https://github.com/wekan/wekan/commit/ca15e060bb182b0ff4768a3ff9d4de5b1ee125ce).
Thanks to translators.
- [Added WRITABLE_PATH to Windows start-wekan.bat](https://github.com/wekan/wekan/commit/1da0786211556697acac45bdc71b283630348081).
Thanks to BabyFnord and xet7.
and adds the following updates:
- [Changed from volta to n. Added info about developing on Ubuntu 22.04](https://github.com/wekan/wekan/commit/9099e20b806c713cc73b86122ac4a462b12e4785).
Thanks to xet7.
- [Added some more info about building on Windows, not tested yet](https://github.com/wekan/wekan/commit/e61e9bb5081efca352dc9496f0602df2f15492fd).
Thanks to xet7.
- [Updated URL to meteor-spk](https://github.com/wekan/wekan/commit/f2f3b76eda982856f88f5289c6d574fdf95abd82).
Thanks to xet7.
- Updated dependencies.
[Part 1](https://github.com/wekan/wekan/commit/c397b5eda8e60ef41ce66bec716f859c352d4744),
[Part 2](https://github.com/wekan/wekan/commit/971391eae9e9d7df341de630a28e074408991c2c).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Attachment migration, try to ignore error on Cloudron on removing old index cardId](https://github.com/wekan/wekan/pull/4408).
Thanks to mfilser.
- [Fix Import Done Button do not redirect](https://github.com/wekan/wekan/pull/4411).
Thanks to Ben0it-T.
- [Fix Duplicate board and create board from template doesn't open board](https://github.com/wekan/wekan/pull/4413).
Thanks to Ben0it-T.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.12 2022-03-11 WeKan ® release
This release adds the following new features:
- Feature/empower sso oicd data propagation.
[Part 1](https://github.com/wekan/wekan/pull/4392),
[Part 2](https://github.com/wekan/wekan/pull/4404).
Thanks to Viehlieb.
- [Add linkedBoard Activities to sidebar](https://github.com/wekan/wekan/pull/4396).
Thanks to Ben0it-T.
- [Added Snap WRITABLE_PATH](https://github.com/wekan/wekan/commit/9f807c59d76b08476b79b0173c2c3a59248fa65b).
Thanks to xet7.
- [Docs for Snap WRITABLE_PATH](https://github.com/wekan/wekan/commit/01a91f3a36747311fb69123124254db13156e4da).
Thanks to xet7.
and fixes the following bugs:
- Fix Boards.uniqueTitle not working as expected.
[Part 1](https://github.com/wekan/wekan/pull/4401),
[Part 2](https://github.com/wekan/wekan/pull/4402).
Thanks to Ben0it-T.
- [Attachments fixes after migration to meteor files (image preview, global search)](https://github.com/wekan/wekan/pull/4405).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.11 2022-03-03 WeKan ® release
This release adds the following updates:
- [Updated In Progress future Snap configs](https://github.com/wekan/wekan/commit/dc6bc9ed54e46ad2ba55fb1dd73f41c0432a7b8f).
Thanks to xet7.
and tries to fix the following bugs:
- [Try to fix Snap](https://github.com/wekan/wekan/commit/e5cfcc84faea551ea49b588348ade44b027718ce).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.10 2022-03-02 WeKan ® release
This release adds the following new features:
- [Switch from CollectionFS to Meteor-Files](https://github.com/wekan/wekan/pull/4336).
NOTE: This does not yet have migration feature to filesystem or S3.
Thanks to imajus, mfilser and xet7.
- [Added Meteor-Files WRITEABLE_PATH for Sandstorm, Snap and Source](https://github.com/wekan/wekan/commit/cc0658a225ef35a6153feab2ad0c0eb40ad66eeb).
Thanks to xet7.
- [Added WRITABLE_PATH to be usable when developing with meteor command, and to torodb](https://github.com/wekan/wekan/commit/e0d8ddf0034a6d2a7f259a71544ec4c57d23f0c5).
Thanks to xet7.
- [Enabled building Sandstorm WeKan, now that file uploading with Meteor-Files works](https://github.com/wekan/wekan/commit/dc99218e4ecb766e7947f8a0298236dead140b9f).
Thanks to imajus, mfilser and xet7.
and adds the following updates:
- [Updated to Node.js v14.19.0](https://github.com/wekan/wekan/commit/492997922129f4076c61c1bd8822851d39ce3f11).
Thanks to Node.js developers.
- [Use Node 14 at rebuild-wekan.sh](https://github.com/wekan/wekan/commit/ab33866d1a5a9080688c0c5f857d12c4117b9311).
Thanks to xet7.
- Updated dependencies.
[Part 1](https://github.com/wekan/wekan/commit/1a7a41698c1a5180e5ffa7d6b84820e05864ac77),
[Part 2](https://github.com/wekan/wekan/commit/9b4179e163bbf6690070fe1e6a14799f2ea17df6).
Thanks to developers of dependencies.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.09 2022-02-28 WeKan ® release
This release tries to fix the following bugs:
- [Try to fix Admin Panel / Disable Registration and Disable Forgot Password](https://github.com/wekan/wekan/commit/0775e2a3e5c5d98e4d8c1954a15beb0688c73075).
Thanks to urmel1960, Ben0it-T and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.08 2022-02-27 WeKan ® release
This release tries to fix the following bugs:
- [Try to allow register and login](https://github.com/wekan/wekan/commit/3076547cee3a5fabe8df106ddbbd6ce1e6c91a8b).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.07 2022-02-26 WeKan ® release
This release fixes the following bugs:
- [Fix Forgot Password to be optional](https://github.com/wekan/wekan/commit/9bd68794555009f5eabad269ed642efa4e3010f1).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.06 2022-02-26 WeKan ® release
This release adds the following new features:
- [Feature/shortcuts for label assignment](https://github.com/wekan/wekan/pull/4377).
Thanks to Viehlieb.
- [Feature/propagate OIDC data](https://github.com/wekan/wekan/pull/4379).
Thanks to Viehlieb.
and fixes the following bugs:
- [Global search: Card Details popup opens now in normal view even if maximized card is configured](https://github.com/wekan/wekan/pull/4352).
Thanks to mfilser.
- [Card details, fix header while scrolling](https://github.com/wekan/wekan/pull/4358).
Thanks to mfilser.
- [Add subscription to announcements, so that system wide announcements are shown to all](https://github.com/wekan/wekan/pull/4375).
Thanks to pablo-ng.
- [Fixed Disable Self-Registration. Added Disable Forgot Password to same Admin Panel page](https://github.com/wekan/wekan/commit/b85db43c4755cf54e550f664311cd95097d68ae1).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.05 2022-02-07 WeKan ® release
This release adds the following updates:
- [Update release scripts to merge latest changes](https://github.com/wekan/wekan/commit/ad35e7b7bd1d6d7568b3a5d692941e03e4623c1a).
Thanks to xet7.
and fixes the following bugs:
- [Fix copy move card](https://github.com/wekan/wekan/pull/4345).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.04 2022-02-07 WeKan ® release
This release fixes the following bugs:
- [Fixed Copy card to list does not work, by reverting clientside changes of PR 4333](https://github.com/wekan/wekan/commit/a5b376e6b5f9b171c39cd9341b8c2a4346fc3f5e).
Thanks to Meeques, PaulITsoft and xet7.
- [Fixed Problem with selecting action in rule window](https://github.com/wekan/wekan/commit/dc7b97c1780849b04389696f0dac38e4477e28cf).
Thanks to Meeques and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.03 2022-02-07 WeKan ® release
This release adds the following updates:
- [Updated to Node.js v12.22.10](https://github.com/wekan/wekan/commit/cc5486797648b8098e50fa4f68cc4b588f41ab60).
Thanks to Node.js developers.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.02 2022-02-06 WeKan ® release
This release adds the following updates:
- [Updated dependencies](https://github.com/wekan/wekan/commit/f888b5cb23917c01cef7a84cf23314051ec6bfff).
Thanks to developers of dependencies.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.01 2022-02-06 WeKan ® release
This release adds the following updates:
- [Updated to Node.js v14.19.0](https://github.com/wekan/wekan/commit/ceed865e305f41ec027f1ed345b041841c9812c0).
Thanks to Node.js developers.
and fixes the following bugs:
- [Fixed WeKan on Sandstorm](https://github.com/sandstorm-io/meteor-spk/pull/41).
Thanks to xet7.
- [Fixed building fibers](https://github.com/wekan/wekan/commit/0460a7d9d3219ed7ba5aa5040349b9d56e6a45e0).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v6.00 2022-02-05 WeKan ® release
This release adds the following new features:
- [Adding list select at card details](https://github.com/wekan/wekan/pull/4333).
Thanks to mfilser.
and adds the following updates:
- [Updated release scripts](https://github.com/wekan/wekan/commit/9b7bf1ba289f0026f0bf957527c86b6f4696686e).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.99 2022-02-04 WeKan ® release
This release adds the following changes:
- [Revert rounded corners minicard on moderndark theme](https://github.com/wekan/wekan/pull/4332).
Thanks to jghaanstra.
and fixes the following bugs:
- [Remove not working options from rebuild-wekan.sh](https://github.com/wekan/wekan/commit/af598b13e8266654ab52425f71840c3628c9835a).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.98 2022-02-03 WeKan ® release
This release adds the following CRITICAL SECURITY UPDATES:
- [Updated to Node.js v12.22.10](https://github.com/wekan/wekan/commit/290a6dfb6e104b887f9ee2cc70db84b83fe3be35).
Thanks to Node.js developers.
and adds the following new features:
- [Make card corners round](https://github.com/wekan/wekan/commit/045160c7bb7c8696a181d9ed4e0b54d0c27b5f59).
Thanks to Meeques and xet7.
- [Copy checklist](https://github.com/wekan/wekan/pull/4331).
Thanks to mfilser.
and adds the following new translations:
- Added translation: Galician (Spain).
[Part 1](https://github.com/wekan/wekan/commit/c0828f2d00095c68b4533a10ff7ede0a16131093),
[Part 2](https://github.com/wekan/wekan/commit/9a539fb414c3ffeae2ea94f863d2bb3bc6e314f1),
[Part 3](https://github.com/wekan/wekan/commit/a8e3dc06fe76620d09eddbc7d118a749c85b1c7c).
Thanks to translators.
and fixes the following bugs:
- [Fix typo in tests](https://github.com/wekan/wekan/commit/62efb67d06a4aeb3299805911391b6e936901b42).
Thanks to xet7.
- Try to fix tests by adding puppeteer back.
[Part 1](https://github.com/wekan/wekan/commit/7122f59c51775f9b382cdbcf5690eba2ad907ccf),
[Part 2](https://github.com/wekan/wekan/commit/1bf1ed79e85e091d79fa70feb46d072c81e55810).
Thanks to xet7.
- [Removed unnecessary space between checklist title and first checklist item if checklist progress is 0%](https://github.com/wekan/wekan/pull/4329).
Thanks to mfilser.
- [Lists now moveable when swimlane requires scrolling](https://github.com/wekan/wekan/pull/4330).
Thanks to mfilser.
- [Add more stack and heap to Node.js at all WeKan platforms](https://github.com/wekan/wekan/commit/ff13571c719ad24e24ea6dc871ced827a7120ac8).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.97 2022-01-23 WeKan ® release
This release fixes the following bugs:
- [Fix can't add Checklist on cardType-linkedBoard](https://github.com/wekan/wekan/pull/4318).
Thanks to Ben0it-T.
- [Fix comments for cards that link to a board are not shown](https://github.com/wekan/wekan/pull/4319).
Thanks to Ben0it-T.
- [Fix Snap OAUTH2_REQUEST_PERMISSIONS of Google/OAuth2/OIDC login](https://github.com/wekan/wekan/commit/4bf6b457ae6bfb6d28127f696344019765d0467d).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.96 2022-01-23 WeKan ® release
This release adds the following new features:
- [Move checklist and card popup restore last selected board value](https://github.com/wekan/wekan/pull/4307).
Thanks to mfilser.
and fixes the following bugs:
- [Fix Layout "Modern Dark", Card Color, List Header and mouse hover](https://github.com/wekan/wekan/pull/4308).
Thanks to mfilser.
- [Try to fix OAUTH2_REQUEST_PERMISSIONS by removing quotes](https://github.com/wekan/wekan/commit/5e65dfc272925490b4ad20c49d8d3fd74597beac).
Thanks to pcurie and xet7.
- [Fix notification drawer always on top](https://github.com/wekan/wekan/commit/bec25720da947e048a63541b4e421bd9bd846c58).
Thanks to Azorimor.
- [Fix comments not loading on cardType-linkedBoard](https://github.com/wekan/wekan/pull/4315).
Thanks to Ben0it-T.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.95 2022-01-18 WeKan ® release
This release adds the following new features:
- [Move copy card remembers the last confirmed field values](https://github.com/wekan/wekan/pull/4296).
Thanks to mfilser.
- [Added "move checklist" and created a "Checklist Action Menu"](https://github.com/wekan/wekan/pull/4297).
Thanks to mfilser.
- [Add checklist item - each line becomes new item](https://github.com/wekan/wekan/pull/4298).
Thanks to mfilser.
- [Add progress bar to checklist](https://github.com/wekan/wekan/pull/4299).
Thanks to mfilser.
and adds the following updates:
- [Update ISSUE_TEMPLATE.md: Use comments and rephrase](https://github.com/wekan/wekan/pull/4295).
Thanks to xeruf.
- [Updated WeKan s390x bundle build script](https://github.com/wekan/wekan/commit/d4c3f323830e4692aac0f1d0faa413302087303b).
Thanks to xet7.
- [Use different distro for building WeKan releases](https://github.com/wekan/wekan/commit/a176a58a728ffc2bb410b3e8a0036fee25f0b0bd).
Thanks to xet7.
and fixes the following bugs:
- [Custom Field StringTemplates didn't save the last input value on desktop view after pressing Ctrl+Enter](https://github.com/wekan/wekan/pull/4300).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.94 2022-01-16 WeKan ® release
This release adds the following new features:
- [Added copy button to card title](https://github.com/wekan/wekan/pull/4291).
Thanks to mfilser.
and fixes the following bugs:
- [Fix Card, List and Comment colors not visible at some themes](https://github.com/wekan/wekan/commit/218ddf03bc109b954d1fe741d1aa533467b51a4d).
Thanks to Meeques, Go-rom and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.93 2022-01-14 WeKan ® release
This release tries to fix the following bugs:
- Try to fix Sandstorm WeKan package. This did not fix it. Do not try broken experimental Sandstorm WeKan versions yet.
[Part 1](https://github.com/wekan/wekan/commit/bff43c3f9252e3133acedb9ccf4fb4f91d1c908d),
[Part 2](https://github.com/wekan/wekan/commit/f75ab964be784bf7f6accb3ab0085f623196d811).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.92 2022-01-13 WeKan ® release
This release adds the following CRITICAL SECURITY UPDATES:
- [Upgraded markdown-it to 12.3.2](https://github.com/wekan/wekan/commit/724f9d43b47aab3198730801200c0faa53c73e5c).
Thanks to markdown-it developers.
and adds the following new translations:
- Added translations: Estonian (Estonia) et_EE, Russian (Ukraine) ru_UA, Ukrainian (Ukraine) uk_UA.
[Part 1](https://github.com/wekan/wekan/commit/ac85e00e0a99574499786ddf97823dcf2802a47f),
[Part 2](https://github.com/wekan/wekan/commit/30131ffc20173d222cb02b283f38a8c0d6a28ccc).
Thanks to translators.
and fixes the following bugs:
- [Fixed OpenAPI docs generating has some swagger error](https://github.com/wekan/wekan/commit/99d6f7a765e2945fb17411f5b8545cd7d6010c5f).
Thanks to bentiss.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.91 2022-01-11 WeKan ® release
This release adds the following CRITICAL SECURITY UPDATES:
- [Updated to Node.js v12.22.9](https://github.com/wekan/wekan/commit/0218f3266bbab2e044f83a06042ca61afab65bdf).
Thanks to Node.js developers.
and adds the following updates:
- [Added release scripts for starting and stopping services](https://github.com/wekan/wekan/commit/33f47414bbecdc3bca10e807c38562e833997db4).
Thanks to xet7.
- Updated rebuild-wekan.sh script about installing dependencies.
[Part1](https://github.com/wekan/wekan/commit/9979193df5b896efb1a8c0ac9c244972fa08aae1),
[Part2](https://github.com/wekan/wekan/commit/6f7292db5e8427fb63305e1e0e41d2337d8d9a60).
Thanks to xet7.
- In install scripts, use Volta Node and NPM install manager, made with Rust https://volta.sh .
Volta uses home directory also with "npm -g install", no sudo needed.
xet7 found info about Volta from Miniflare docs.
[Part 1](https://github.com/wekan/wekan/commit/2efa42b8537b8a404a0f82d78c5299f098130183),
[Part 2](https://github.com/wekan/wekan/commit/ef685703cf8180c3fedef381d3c10aaf405ee8b4).
Thanks to Volta developers.
- [Updated dependencies](https://github.com/wekan/wekan/commit/75fdc53746710206482b66513b02216dab5a4ad6).
Thanks to developers of dependencies.
and fixes the following bugs:
- [Fix user mentions](https://github.com/wekan/wekan/pull/4273).
Thanks to Ben0it-T.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.90 2021-12-26 WeKan ® release
This release fixes the following bugs:
- [Fix Create Board from Template not opening](https://github.com/wekan/wekan/commit/95ed3a0ab56a52a04c13856cf9d1d845659ea1b7).
Thanks to Ben0it-T and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.89 2021-12-26 WeKan ® release
This release adds the following new features:
- [Edit team/org now update users.teams.teamDisplayName / users.orgs.orgDisplayName](https://github.com/wekan/wekan/pull/4257).
Thanks to Ben0it-T.
- [Trello api.py: Added for using newest Trello API, to show Trello boards/cards/actions/reactions JSON and download Trello attachments
as binary files from S3](https://github.com/wekan/wekan/commit/aff6e361f03f1a7e269edc184884313557c94362).
Thanks to xet7.
- [Trello api.py: Added additional TODO notes](https://github.com/wekan/wekan/commit/f2c31f877c5a22af4429688fe2620919858ca69f).
Thanks to xet7.
- [Added Info about Shared Templates In Progress](https://github.com/wekan/wekan/issues/3313#issuecomment-1001187003).
Thanks to xet7.
and fixes the following bugs:
- [Fix getLabels exception in template helper](https://github.com/wekan/wekan/pull/4262).
Thanks to Ben0it-T.
- [Fixed Templates are Missing, Error: Site not Found "/templates" is missing in the URL.
Shared Templates part 5: Make visible Create template board checkbox and templates at All Boards page, In Progress](https://github.com/wekan/wekan/commit/7f32de3bec151df9e656013e8e910eb650b8ce80).
Thanks to xet7.
- [Fixed Duplicate board](https://github.com/wekan/wekan/commit/67687110bb715028dd646d5879c109a095e584d5).
Thanks to Ben0it-T and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.88 2021-12-22 WeKan ® release
This release adds to following CRITICAL SECURITY FIXES:
- [User now should only see archived cards belonging to boards to which he has permission](https://github.com/wekan/wekan/pull/4252).
Thanks to jrsupplee.
- [Fix `Boards.userBoards()` method to take into account organizations and teams of the user when determining which boards are accessible](https://github.com/wekan/wekan/pull/4252).
Thanks to jrsupplee.
and adds the following new features:
- [New `debug` search operator that should help debugging future problems with search](https://github.com/wekan/wekan/pull/4252).
Thanks to jrsupplee.
- [New `org` and `team` search operators for finding cards belonging to boards with the given organization or team](https://github.com/wekan/wekan/pull/4252).
Thanks to jrsupplee.
- [New admin report to list boards](https://github.com/wekan/wekan/pull/4252).
Thanks to jrsupplee.
and adds the following accessibility improvements:
- Made WeKan zoomable by recommendation of Axe browser extension
https://github.com/wekan/wekan/issues/459#issuecomment-999098233 by changing meta viewport settings at
https://github.com/wekan/wekan/blob/master/client/components/main/layouts.jade#L3 ,
in some commit of this WeKan v5.88.
Thanks to xet7.
and fixes the following bugs:
- Fixed Mermaid Diagram error: Maximum call stack size exceeded.
[Part 1](https://github.com/wekan/wekan/commit/23a403644c7db44392d4b0498ee0fc85c504d974),
[Part 2](https://github.com/wekan/wekan/commit/998d2f5b445b6bf2bc6cd16beac7231a0cf94fc3),
[Part 3](https://github.com/wekan/wekan/commit/443b40cff3cf507887c20639224ac1447acfaf88).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.87 2021-12-19 WeKan ® release
This release adds the following updates:
- [Changed Docker base image to ubuntu:rolling](https://github.com/wekan/wekan/commit/8446640060e6e5058d0d186d71831a32a9e606e3).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.86 2021-12-19 WeKan ® release
This release fixes the following bugs:
- [Fix: BoardAdmin can't edit or delete others comments on cards](https://github.com/wekan/wekan/pull/4248).
Thanks to Ben0it-T.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.85 2021-12-17 WeKan ® release
This release adds the following updates:
- [Updated to Node.js v12.22.8](https://github.com/wekan/wekan/commit/5ad9ee1de6446e3b2f3e4a5df207d12de76e1b95).
Thanks to Node.js developers.
and fixes the following bugs:
- [Fix mobile card details for Modern Dark theme](https://github.com/wekan/wekan/pull/4240).
Thanks to jghaanstra.
- [Fixed undefinded added member to board](https://github.com/wekan/wekan/pull/4245).
Thanks to Emile840.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.84 2021-12-15 WeKan ® release
This release adds the following new features:
- [Kubernetes 1.22 support and basic helm test](https://github.com/wekan/wekan/pull/4208).
Thanks to varac.
- [Added Helm Chart usage docs](https://github.com/wekan/wekan/pull/4224).
Thanks to varac.
- [Add full name if exists in `email-invite-subject` for user to invite](https://github.com/wekan/wekan/pull/4226).
Thanks to Emile840.
- [Sort Organizations, Teams and People](https://github.com/wekan/wekan/pull/4232).
Thanks to Emile840.
and fixes the following bugs:
- [List title doesn't overlap with hamburger menu anymore](https://github.com/wekan/wekan/pull/4203).
Thanks to mfilser.
- [Fix legal notice traduction bug when refreshing sign in page](https://github.com/wekan/wekan/pull/4217).
Thanks to Emile840.
- [Fix: Clicking to view Lists or Swimlanes Archive adds temporarily many empty Lists to board](https://github.com/wekan/wekan/pull/4221).
Thanks to Ben0it-T.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.83 2021-11-30 WeKan ® release
This release adds to following new improvements:
- [Changed delete checklist dialog to a popup](https://github.com/wekan/wekan/pull/4200).
Thanks to mfilser.
- [Dragging minicards scrolls now vertically at the end of the screen](https://github.com/wekan/wekan/pull/4201).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.82 2021-11-29 WeKan ® release
This release removes the following new features:
- [Revert change from WeKan v5.81: At Sandstorm, every WeKan user is now WeKan Admin and has Admin Panel](https://github.com/wekan/wekan/commit/ebc7741fcb9ad854234921ed0546255411adeec9).
Thanks to ocdtrekkie and xet7.
and adds the following new features:
- [List header contains now a button to add the card to the bottom of the list](https://github.com/wekan/wekan/pull/4195).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.81 2021-11-29 WeKan ® release
This release adds the following new features:
- [At Sandstorm, every WeKan user is now WeKan Admin and has WeKan Admin Panel. This could help export, board member permissions, etc](https://github.com/wekan/wekan/commit/23a2e90f5f553c2051978a0b4cd5b0d6d4ee03da).
Thanks to PizzaProgram and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.80 2021-11-26 WeKan ® release
This release adds the following new features:
- [Show helper at label drag/drop if label popup opened from card details popup](https://github.com/wekan/wekan/pull/4176).
Thanks to mfilser.
- [Show or hide members and assignee(s) on minicard](https://github.com/wekan/wekan/pull/4179).
Thanks to Ben0it-T.
- [List adding has now a cancel button](https://github.com/wekan/wekan/pull/4183).
Thanks to mfilser.
- [CustomFields Currency, autofocus on edit](https://github.com/wekan/wekan/pull/4189).
Thanks to mfilser.
- [Attachments, show file size in KB in card details](https://github.com/wekan/wekan/pull/4191).
Thanks to mfilser.
- [Sidebar Member Settings Popup has now a Popup title](https://github.com/wekan/wekan/pull/4190).
Thanks to mfilser.
- [Add copy text button to most textarea fields](https://github.com/wekan/wekan/pull/4185).
Thanks to mfilser.
- Copy text button at most textarea fields is now translatable.
[Part 1](https://github.com/wekan/wekan/commit/5088c122536e13b44cf2fdbcfabeefd00cee332e),
[Part 2](https://github.com/wekan/wekan/commit/96465ac664c526d8749dcad158704b512317e256).
Thanks to xet7.
and adds the following updates:
- [Docker build script to be executeable](https://github.com/wekan/wekan/commit/8054f2b0025c4cb3f6a3ddf71754ae7c707d6ac0).
Thanks to xet7.
- [Drag drop jquery-ui update + screen and list scroll](https://github.com/wekan/wekan/pull/4181).
Thanks to mfilser.
- [Settings, add some space between radio buttons](https://github.com/wekan/wekan/pull/4186).
Thanks to mfilser.
and fixes the following bugs:
- [Default Top Left Corner Logo Image display few seconds before a display of custom Top Left Corner Logo Image](https://github.com/wekan/wekan/issues/4173).
Thanks to Emile840.
- [App reconnect link wasn't clickable](https://github.com/wekan/wekan/pull/4180).
Thanks to mfilser.
- [Copy card URL works now again](https://github.com/wekan/wekan/pull/4184).
Thanks to mfilser.
- [Fix: On mobile infinite scrolling didn't work](https://github.com/wekan/wekan/pull/4187).
Thanks to mfilser.
- [Custom Field StringTemplates didn't save the last input value on touch devices](https://github.com/wekan/wekan/pull/4188).
Thanks to mfilser.
- [Move cards to top/bottom ignores the current filter if active](https://github.com/wekan/wekan/pull/4192).
Thanks to mfilser.
- [Moving many cards with multi selection drag/drop to another list keeps the card order](https://github.com/wekan/wekan/pull/4193).
Thanks to mfilser.
- [Sidebar multi selection actions keep now the card sorting (cards moving, cards to archive etc)](https://github.com/wekan/wekan/pull/4194).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.79 2021-11-25 WeKan ® release
This release fixes the following bugs:
- [Fix label width oversize bug](https://github.com/wekan/wekan/pull/4157).
Thanks to mfilser.
- [Fixed label popup at desktop view (add and remove labels)](https://github.com/wekan/wekan/pull/4170).
Thanks to mfilser.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.78 2021-11-17 WeKan ® release
This release fixes the following bugs:
- [Fix: Sandstorm WeKan Admin Panel version info broken](https://github.com/wekan/wekan/commit/02b6df320fc98e18e5a97105a35196bdffec98bb).
Thanks to ocdtrekkie and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.77 2021-11-16 WeKan ® release
This release adds the following updates:
- [Updated Docker Ubuntu base image](https://github.com/wekan/wekan/commit/b1b12b05b571f4eebd38e7486dea28dfd97a885d).
Thanks to Ubuntu developers.
Thanks to above GitHub users for their contributions and translators for their translations.
# v5.76 2021-11-16 WeKan ® release
This release adds the following new features:
+26 -7
View File
@@ -1,4 +1,4 @@
FROM quay.io/wekan/ubuntu:impish-20211015
FROM ubuntu:rolling
LABEL maintainer="wekan"
# 2021-09-18:
@@ -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.22.7 \
NODE_VERSION=v14.19.1 \
METEOR_RELEASE=1.10.2 \
USE_EDGE=false \
METEOR_EDGE=1.5-beta.17 \
@@ -31,7 +31,6 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS=90 \
RICHER_CARD_COMMENT_EDITOR=false \
CARD_OPENED_WEBHOOK_ENABLED=false \
ATTACHMENTS_STORE_PATH="" \
MAX_IMAGE_PIXEL="" \
IMAGE_COMPRESS_RATIO="" \
NOTIFICATION_TRAY_AFTER_READ_DAYS_BEFORE_REMOVE="" \
@@ -140,7 +139,16 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
SAML_ATTRIBUTES="" \
ORACLE_OIM_ENABLED=false \
WAIT_SPINNER=""
WAIT_SPINNER="" \
NODE_OPTIONS="--max_old_space_size=4096"
#---------------------------------------------------------------------
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
# Add more Node heap:
# NODE_OPTIONS="--max_old_space_size=4096"
# Add more stack:
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
#---------------------------------------------------------------------
# Copy the app to the image
COPY ${SRC_PATH} /home/wekan/app
@@ -281,9 +289,7 @@ RUN \
chmod u+w *.json && \
gosu wekan:wekan npm install && \
gosu wekan:wekan /home/wekan/.meteor/meteor build --directory /home/wekan/app_build && \
#cp /home/wekan/app/fix-download-unicode/cfs_access-point.txt /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
#rm /home/wekan/app_build/bundle/programs/server/npm/node_modules/meteor/rajit_bootstrap3-datepicker/lib/bootstrap-datepicker/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs && \
#chown wekan /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
#Removed binary version of bcrypt because of security vulnerability that is not fixed yet.
#https://github.com/wekan/wekan/commit/4b2010213907c61b0e0482ab55abb06f6a668eac
#https://github.com/wekan/wekan/commit/7eeabf14be3c63fae2226e561ef8a0c1390c8d3c
@@ -298,6 +304,9 @@ RUN \
cd /home/wekan/app_build/bundle/programs/server/ && \
chmod u+w *.json && \
gosu wekan:wekan npm install && \
cd node_modules/fibers && \
node build.js && \
cd ../.. && \
#gosu wekan:wekan npm install bcrypt && \
# Remove legacy webbroser bundle, so that Wekan works also at Android Firefox, iOS Safari, etc.
rm -rf /home/wekan/app_build/bundle/programs/web.browser.legacy && \
@@ -323,4 +332,14 @@ ENV PORT=8080
EXPOSE $PORT
USER wekan
CMD ["node", "/build/main.js"]
#---------------------------------------------------------------------
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
# Add more Node heap:
# NODE_OPTIONS="--max_old_space_size=4096"
# Add more stack:
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
#---------------------------------------------------------------------
#
# CMD ["node", "/build/main.js"]
CMD ["bash", "-c", "ulimit -s 65500; exec node --stack-size=65500 /build/main.js"]
+24 -4
View File
@@ -4,9 +4,18 @@ FROM amd64/alpine:3.7 AS builder
ENV QEMU_VERSION=v4.2.0-6 \
QEMU_ARCHITECTURE=aarch64 \
NODE_ARCHITECTURE=linux-arm64 \
NODE_VERSION=v12.22.7 \
NODE_VERSION=v14.19.1 \
WEKAN_VERSION=latest \
WEKAN_ARCHITECTURE=arm64
WEKAN_ARCHITECTURE=arm64 \
NODE_OPTIONS="--max_old_space_size=4096"
#---------------------------------------------------------------------
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
# Add more Node heap:
# NODE_OPTIONS="--max_old_space_size=4096"
# Add more stack:
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
#---------------------------------------------------------------------
# Install dependencies
RUN apk update && apk add ca-certificates outils-sha1 && \
@@ -40,7 +49,7 @@ LABEL maintainer="wekan"
# Set the environment variables (defaults where required)
ENV QEMU_ARCHITECTURE=aarch64 \
NODE_ARCHITECTURE=linux-arm64 \
NODE_VERSION=v12.22.7 \
NODE_VERSION=v14.19.1 \
NODE_ENV=production \
NPM_VERSION=latest \
WITH_API=true \
@@ -74,4 +83,15 @@ RUN \
EXPOSE $PORT
USER wekan
CMD ["node", "/home/wekan/bundle/main.js"]
#---------------------------------------------------------------------
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
# Add more Node heap:
# NODE_OPTIONS="--max_old_space_size=4096"
# Add more stack:
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
#---------------------------------------------------------------------
#
#CMD ["node", "/home/wekan/bundle/main.js"]
CMD ["bash", "-c", "ulimit -s 65500; exec node --stack-size=65500 /home/wekan/bundle/main.js"]
+1 -1
View File
@@ -56,7 +56,7 @@ install Wekan on your own computer or server. In fact we encourage you to do
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 largest user has 22k users using Wekan in their company.
- Wekan has been [translated](https://transifex.com/wekan/wekan) to about 70 languages.
- [Features][features]: WeKan ® has real-time user interface.
- [Platforms][platforms]: WeKan ® supports many platforms.
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v5.76.0"
appVersion: "v6.13.0"
files:
userUploads:
- README.md
+8
View File
@@ -0,0 +1,8 @@
# v1.0 2022-03-22 Perl Asana export to WeKan ® release
This release adds the following new features:
- [Added Perl scripts for Asana export to WeKan ®](https://github.com/wekan/wekan/commit/376bcbb373d16317060adc2b1154cc20496775cc).
Thanks to GeekRuthie.
Thanks to above GitHub users for their contributions and translators for their translations.
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2022 WeKan ® Team and GeekRuthie
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+178
View File
@@ -0,0 +1,178 @@
#!/usr/local/perl-cbt/bin/perl
use Modern::Perl;
use Carp;
use Data::Dumper;
use HTTP::Request;
use JSON;
use LWP::UserAgent;
use MIME::Base64 qw/encode_base64/;
my $BASE_URL = 'https://app.asana.com/api/1.0';
my $ASANA_API_KEY = 'ASANA_PERSONAL_TOKEN';
my $ua = LWP::UserAgent->new();
open my $input_wekan, '<', 'template.json';
my $wekan_json = readline($input_wekan);
close $input_wekan;
my $wekan_board = decode_json($wekan_json);
my %users;
my %users_by_gid;
# get user IDs from template board
foreach my $user ( @{ $wekan_board->{users} } ) {
$users{ $user->{profile}->{fullname} } = $user->{_id};
}
# get list IDs from template (we ended up not using these)
my %lists;
foreach my $list ( @{ $wekan_board->{lists} } ) {
$lists{ $list->{title} } = $list->{_id};
}
my @headers;
push @headers, ( 'Accept', 'application/json' );
push @headers, ( 'Authorization', "Bearer $ASANA_API_KEY" );
my $projects_req = HTTP::Request->new( "GET", "$BASE_URL/projects", \@headers, );
my $projects_res = $ua->request($projects_req);
my $projects = decode_json( $projects_res->content )->{data};
foreach my $project (@$projects) {
say "Project: ".$project->{name};
my $tasks_url =
'/tasks?project='
. $project->{gid}
. '&opt_fields=completed,name,notes,assignee,created_by,memberships.project.name, memberships.section.name,due_on,created_at,custom_fields';
my $tasks_req = HTTP::Request->new( 'GET', "$BASE_URL$tasks_url", \@headers );
my $tasks_res = $ua->request($tasks_req);
my @output_tasks;
my $tasks = decode_json( $tasks_res->content )->{data};
foreach my $task (@$tasks) {
next if $task->{completed};
say ' - '.$task->{name};
my $git_branch;
my $prio;
foreach my $custom ( @{ $task->{custom_fields} } ) {
if ( $custom->{name} eq 'git branch' ) {
$git_branch = $custom->{text_value};
next;
}
# We ended up not importing these.
if ( $custom->{name} eq 'Priority' && defined $custom->{display_value} ) {
$prio =
$custom->{display_value} eq 'High' ? 'fwccC9'
: $custom->{display_value} eq 'Med' ? 'yPnaFa'
: $custom->{display_value} eq 'Low' ? 'W4vMvm'
: 'ML5drH';
next;
}
}
if ( !defined $users_by_gid{ $task->{created_by}->{gid} } ) {
my $user_req =
HTTP::Request->new( 'GET', "$BASE_URL/users/" . $task->{created_by}->{gid},
\@headers );
my $user_res = $ua->request($user_req);
my $user = decode_json( $user_res->content )->{data};
if ( defined $users{ $user->{name} } ) {
$users_by_gid{ $task->{created_by}->{gid} } = $users{ $user->{name} };
}
}
my $creator = $users_by_gid{ $task->{created_by}->{gid} } // undef;
if ( defined $task->{assignee} && !defined $users_by_gid{ $task->{assignee}->{gid} } ) {
my $user_req =
HTTP::Request->new( 'GET', "$BASE_URL/users/" . $task->{assignee}->{gid},
\@headers );
my $user_res = $ua->request($user_req);
my $user = decode_json( $user_res->content )->{data};
if ( defined $users{ $user->{name} } ) {
$users_by_gid{ $task->{assignee}->{gid} } = $users{ $user->{name} };
}
}
my $assignee = defined $task->{assignee} ? $users_by_gid{ $task->{assignee}->{gid} } : undef;
my $list;
foreach my $membership ( @{ $task->{memberships} } ) {
next if $membership->{project}->{name} ne $project->{name};
$list = $membership->{section}->{name};
}
# I was trying to create JSON that I could use on the import screen in Wekan,
# but for bigger boards, it was just *too* hefty, so I took that JSON and used
# APIs to import.
my %output_task = (
swimlaneId => 'As4SNerx4Y4mMnJ8n', # 'Bugs'
sort => 0,
type => 'cardType-card',
archived => JSON::false,
title => $task->{name},
description => $task->{notes},
createdAt => $task->{created_at},
dueAt => defined $task->{due_on} ? $task->{due_on} . 'T22:00:00.000Z' : undef,
customFields => [
{
_id => 'rL8BpFHp5xxSFbDdr',
value => $git_branch,
},
],
labelIds => [$prio],
listId => $list,
userId => $creator,
assignees => [$assignee],
);
my @final_comments;
my $comments_req =
HTTP::Request->new( 'GET', "$BASE_URL/tasks/" . $task->{gid} . '/stories',
\@headers );
my $comments_res = $ua->request($comments_req);
my $comments = decode_json( $comments_res->content )->{data};
foreach my $comment (@$comments) {
next if $comment->{type} ne 'comment';
if ( !defined $users_by_gid{ $comment->{created_by}->{gid} } ) {
my $user_req =
HTTP::Request->new( 'GET', "$BASE_URL/users/" . $comment->{created_by}->{gid},
\@headers );
my $user_res = $ua->request($user_req);
my $user = decode_json( $user_res->content )->{data};
if ( defined $users{ $user->{name} } ) {
$users_by_gid{ $comment->{created_bye}->{gid} } = $users{ $user->{name} };
}
}
my $commentor = $users_by_gid{ $comment->{created_by}->{gid} };
my %this_comment = (
text => $comment->{text},
createdAt => $comment->{created_at},
userId => $commentor,
);
push @final_comments, \%this_comment;
}
$output_task{comments} = \@final_comments;
my @final_attachments;
my $attachments_req =
HTTP::Request->new( 'GET', "$BASE_URL/tasks/" . $task->{gid} . '/attachments',
\@headers );
my $attachments_res = $ua->request($attachments_req);
my $attachments = decode_json( $attachments_res->content )->{data};
foreach my $attachment (@$attachments) {
my $att_req =
HTTP::Request->new( 'GET', "$BASE_URL/attachments/" . $attachment->{gid},
\@headers );
my $att_res = $ua->request($att_req);
my $att = decode_json( $att_res->content )->{data};
my $file_req=HTTP::Request->new('GET',$att->{download_url});
my $file_res=$ua->request($file_req);
my $file=encode_base64($file_res->content);
my %this_attachment = (
file => $file,
name => $att->{name},
createdAt => $att->{created_at},
);
push @final_attachments, \%this_attachment;
}
$output_task{attachments} = \@final_attachments;
push @output_tasks, \%output_task;
}
my $file_name = $project->{name};
$file_name =~ s/\//_/g;
open my $output_file, '>',$file_name.'_exported.json';
print $output_file encode_json(\@output_tasks);
close $output_file;
}
+122
View File
@@ -0,0 +1,122 @@
#!/usr/local/perl-cbt/bin/perl
use Modern::Perl;
use Carp;
use Data::Dumper;
use HTTP::Request;
use JSON;
use LWP::UserAgent;
use MIME::Base64 qw/decode_base64/;
use Try::Tiny;
my $BASE_URL = 'https://taskboard.example.com/api';
my $TOKEN = 'MY_TOKEN';
my $me = 'MY_USER_ID';
my $ua = LWP::UserAgent->new();
my @headers;
push @headers, ( 'Accept', 'application/json' );
push @headers, ( 'Authorization', "Bearer $TOKEN" );
my @form_headers;
push @form_headers, ( 'Content-Type', 'application/json' );
push @form_headers, ( 'Accept', 'application/json' );
push @form_headers, ( 'Authorization', "Bearer $TOKEN" );
# Prior to running this, I built all the boards, with labels and lists and swimlanes.
# Grabbed the IDs for the boards for each project, and put them here to match up with
# filenames from the Asana export script.
my %board_to_use = (
Project_1 => 'F5ZiCXnf4d7qNBRjp',
Project_2 => 'Shw3tyfC2JWCutBLj',
);
opendir my $files_dir, '.'
or croak "Cannot open input directory: $!";
my @files = readdir $files_dir;
closedir $files_dir;
foreach my $tasks_file (@files) {
next if $tasks_file !~ /_exported.json/;
my $project = $tasks_file;
$project =~ s/_exported.json//;
say "Project - $project";
my $board;
if ( $board_to_use{$project} ) {
$board = $board_to_use{$project};
}
say ' No board!' if !$board;
next if !$board;
my $labels_req = HTTP::Request->new( 'GET', "$BASE_URL/boards/$board", \@headers );
my $labels_res = $ua->request($labels_req);
my $board_data = decode_json( $labels_res->content);
my $labels = $board_data->{labels};
my $label_to_use;
# We're merging several Asana boards onto one Wekan board, with labels per project.
foreach my $label (@$labels) {
$label_to_use = $label->{_id} if $label->{name} eq $project;
}
my $lanes_req = HTTP::Request->new( 'GET', "$BASE_URL/boards/$board/swimlanes", \@headers );
my $lanes_res = $ua->request($lanes_req);
my $lanes = decode_json( $lanes_res->content );
my $lane_to_use;
foreach my $lane (@$lanes) {
# Our Asana didn't use swimlanes; all of our Wekan boards have a "Bugs" lane, so use that.
$lane_to_use = $lane->{_id} if $lane->{title} eq 'Bugs';
}
my $lists_req = HTTP::Request->new( 'GET', "$BASE_URL/boards/$board/lists", \@headers );
my $lists_res = $ua->request($lists_req);
my $lists = decode_json( $lists_res->content );
my %list_to_use;
foreach my $list (@$lists) {
$list_to_use{ $list->{title} } = $list->{_id};
}
open my $task_export_file, '<', $tasks_file;
my $tasks_json = readline($task_export_file);
close $task_export_file;
my $tasks = decode_json($tasks_json);
foreach my $task (@$tasks) {
say ' - ' . $task->{title};
my %body_info = (
swimlaneId => $lane_to_use,
authorId => $task->{userId},
assignees => $task->{assignees},
title => $task->{title},
description => $task->{description},
);
my $body = encode_json( \%body_info );
my $list = $list_to_use{ $task->{listId} } // $list_to_use{'Backlog'};
my $task_req = HTTP::Request->new( 'POST', "$BASE_URL/boards/$board/lists/$list/cards",
\@form_headers, $body );
my $task_res = $ua->request($task_req);
my $res;
try {
$res = decode_json( $task_res->content );
} catch {
# Did these manually afterward.
say "--->UNABLE TO LOAD TASK";
next;
};
my $card = $res->{_id};
if ($label_to_use) {
my $card_edit_body = encode_json( { labelIds => [ $label_to_use ]});
my $card_edit_req = HTTP::Request->new( 'PUT', "$BASE_URL/boards/$board/lists/$list/cards/$card",
\@form_headers, $card_edit_body );
my $card_edit_res = $ua->request($card_edit_req);
}
foreach my $comment ( @{ $task->{comments} } ) {
my $comment_body =
encode_json( { authorId => $comment->{userId}, comment => $comment->{text} } );
my $comment_req =
HTTP::Request->new( 'POST', "$BASE_URL/boards/$board/cards/$card/comments",
\@form_headers, $comment_body );
my $comment_res = $ua->request($comment_req);
}
}
}
+26 -43
View File
@@ -59,18 +59,17 @@ template(name="activity")
img.attachment-image-preview(src=activity.attachment.url)
//- board activity ------------------------------------------------------
if($eq mode 'board')
if($eq activity.activityType 'createBoard')
| {{{_ 'activity-created' boardLabelLink}}}.
if($eq activity.activityType 'createBoard')
| {{{_ 'activity-created' boardLabelLink}}}.
if($eq activity.activityType 'importBoard')
| {{{_ 'activity-imported-board' boardLabelLink sourceLink}}}.
if($eq activity.activityType 'importBoard')
| {{{_ 'activity-imported-board' boardLabelLink sourceLink}}}.
if($eq activity.activityType 'addBoardMember')
| {{{_ 'activity-added' memberLink boardLabelLink}}}.
if($eq activity.activityType 'addBoardMember')
| {{{_ 'activity-added' memberLink boardLabelLink}}}.
if($eq activity.activityType 'removeBoardMember')
| {{{_ 'activity-excluded' memberLink boardLabelLink}}}.
if($eq activity.activityType 'removeBoardMember')
| {{{_ 'activity-excluded' memberLink boardLabelLink}}}.
//- card activity -------------------------------------------------------
if($eq activity.activityType 'createCard')
@@ -166,42 +165,27 @@ template(name="activity")
= activity.comment.text
//- date activity ------------------------------------------------
if($eq mode 'card')
if($eq activity.activityType 'a-receivedAt')
| {{{_ 'activity-receivedDate' (sanitize receivedDate) cardLink}}}.
if($eq activity.activityType 'a-receivedAt')
| {{{_ 'activity-receivedDate' (sanitize receivedDate) cardLink}}}.
if($eq activity.activityType 'a-startAt')
| {{{_ 'activity-startDate' (sanitize startDate) cardLink}}}.
if($eq activity.activityType 'a-startAt')
| {{{_ 'activity-startDate' (sanitize startDate) cardLink}}}.
if($eq activity.activityType 'a-dueAt')
| {{{_ 'activity-dueDate' (sanitize dueDate) cardLink}}}.
if($eq activity.activityType 'a-dueAt')
| {{{_ 'activity-dueDate' (sanitize dueDate) cardLink}}}.
if($eq activity.activityType 'a-endAt')
| {{{_ 'activity-endDate' (sanitize endDate) cardLink}}}.
if($eq mode 'board')
if($eq activity.activityType 'a-receivedAt')
| {{{_ 'activity-receivedDate' (sanitize receivedDate) cardLink}}}.
if($eq activity.activityType 'a-startAt')
| {{{_ 'activity-startDate' (sanitize startDate) cardLink}}}.
if($eq activity.activityType 'a-dueAt')
| {{{_ 'activity-dueDate' (sanitize dueDate) cardLink}}}.
if($eq activity.activityType 'a-endAt')
| {{{_ 'activity-endDate' (sanitize endDate) cardLink}}}.
if($eq activity.activityType 'a-endAt')
| {{{_ 'activity-endDate' (sanitize endDate) cardLink}}}.
//- customField activity ------------------------------------------------
if($eq mode 'board')
if($eq activity.activityType 'createCustomField')
| {{_ 'activity-customfield-created' customField}}.
if($eq activity.activityType 'createCustomField')
| {{_ 'activity-customfield-created' customField}}.
if($eq activity.activityType 'setCustomField')
| {{{_ 'activity-set-customfield' (sanitize lastCustomField) (sanitize lastCustomFieldValue) cardLink}}}.
if($eq activity.activityType 'setCustomField')
| {{{_ 'activity-set-customfield' (sanitize lastCustomField) (sanitize lastCustomFieldValue) cardLink}}}.
if($eq activity.activityType 'unsetCustomField')
| {{{_ 'activity-unset-customfield' (sanitize lastCustomField) cardLink}}}.
if($eq activity.activityType 'unsetCustomField')
| {{{_ 'activity-unset-customfield' (sanitize lastCustomField) cardLink}}}.
//- label activity ------------------------------------------------------
if($eq activity.activityType 'addedLabel')
@@ -238,12 +222,11 @@ template(name="activity")
| {{{_ 'activity-removed' memberLink cardLink}}}.
//- swimlane activity --------------------------------------------------
if($neq mode 'card')
if($eq activity.activityType 'createSwimlane')
| {{_ 'activity-added' (sanitize activity.swimlane.title) boardLabelLink}}.
if($eq activity.activityType 'createSwimlane')
| {{{_ 'activity-added' (sanitize activity.swimlane.title) boardLabelLink}}}.
if($eq activity.activityType 'archivedSwimlane')
| {{_ 'activity-archived' (sanitize activity.swimlane.title)}}.
if($eq activity.activityType 'archivedSwimlane')
| {{{_ 'activity-archived' (sanitize activity.swimlane.title)}}}.
//- I don't understand this part ----------------------------------------
+41 -10
View File
@@ -70,22 +70,51 @@ BlazeComponent.extendComponent({
boardLabelLink() {
const data = this.currentData();
const currentBoardId = Session.get('currentBoard');
if (data.mode !== 'board') {
return createBoardLink(data.activity.board(), data.activity.listName);
// data.mode: card, linkedcard, linkedboard
return createBoardLink(data.activity.board(), data.activity.listName ? data.activity.listName : null);
}
else if (currentBoardId != data.activity.boardId) {
// data.mode: board
// current activitie is linked
return createBoardLink(data.activity.board(), data.activity.listName ? data.activity.listName : null);
}
return TAPi18n.__('this-board');
},
cardLabelLink() {
const data = this.currentData();
if (data.mode !== 'card') {
return createCardLink(data.activity.card());
const currentBoardId = Session.get('currentBoard');
if (data.mode == 'card') {
// data.mode: card
return TAPi18n.__('this-card');
}
return TAPi18n.__('this-card');
else if (data.mode !== 'board') {
// data.mode: linkedcard, linkedboard
return createCardLink(data.activity.card(), null);
}
else if (currentBoardId != data.activity.boardId) {
// data.mode: board
// current activitie is linked
return createCardLink(data.activity.card(), data.activity.board().title);
}
return createCardLink(this.currentData().activity.card(), null);
},
cardLink() {
return createCardLink(this.currentData().activity.card());
const data = this.currentData();
const currentBoardId = Session.get('currentBoard');
if (data.mode !== 'board') {
// data.mode: card, linkedcard, linkedboard
return createCardLink(data.activity.card(), null);
}
else if (currentBoardId != data.activity.boardId) {
// data.mode: board
// current activitie is linked
return createCardLink(data.activity.card(), data.activity.board().title);
}
return createCardLink(this.currentData().activity.card(), null);
},
receivedDate() {
@@ -196,14 +225,14 @@ BlazeComponent.extendComponent({
// trying to display url before file is stored generates js errors
return (
(attachment &&
attachment.url({ download: true }) &&
attachment.path &&
Blaze.toHTML(
HTML.A(
{
href: attachment.url({ download: true }),
href: `${attachment.link()}?download=true`,
target: '_blank',
},
DOMPurify.sanitize(attachment.name()),
DOMPurify.sanitize(attachment.name),
),
)) ||
DOMPurify.sanitize(this.currentData().activity.attachmentName)
@@ -304,8 +333,10 @@ Template.commentReactions.helpers({
}
})
function createCardLink(card) {
function createCardLink(card, board) {
if (!card) return '';
let text = card.title;
if (board) text = `${board} > ` + text;
return (
card &&
Blaze.toHTML(
@@ -314,7 +345,7 @@ function createCardLink(card) {
href: card.originRelativeUrl(),
class: 'action-card',
},
DOMPurify.sanitize(card.title, { ALLOW_UNKNOWN_PROTOCOLS: true }),
DOMPurify.sanitize(text, { ALLOW_UNKNOWN_PROTOCOLS: true }),
),
)
);
+2
View File
@@ -26,6 +26,8 @@ BlazeComponent.extendComponent({
if (card.isLinkedCard()) {
boardId = Cards.findOne(card.linkedId).boardId;
cardId = card.linkedId;
} else if (card.isLinkedBoard()) {
boardId = card.linkedId;
}
if (text) {
CardComments.insert({
@@ -31,7 +31,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
+56 -29
View File
@@ -15,9 +15,16 @@ setBoardColor(color)
.is-selected .minicard
border-left: 3px solid color
// All minicards rounded corners:
.minicard
border-radius: 7px
padding: 10px 10px 4px 10px
box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15)
button[type=submit].primary, input[type=submit].primary,
.sidebar .sidebar-content .sidebar-btn
background-color: darken(color, 20%)
border-radius: 7px
&.pop-over .pop-over-list li a:not(.disabled):hover,
.sidebar .sidebar-content .sidebar-btn:hover,
@@ -186,9 +193,10 @@ setBoardColor(color)
.list >.list-header, .swimlane-header
color:rgba(255,255,255,.7)
/* minicards */
/* minicards
.minicard
background-color:rgba(255,255,255,.4)
*/
.minicard-wrapper.is-selected .minicard,
.minicard:hover,
@@ -196,9 +204,12 @@ setBoardColor(color)
.open-minicard-composer:hover
background-color:rgba(255,255,255,.8) !important
color:#000
border-radius: 7px
/*
.minicard, .minicard .badge
color:#fff
*/
.minicard:hover .badge, .minicard-wrapper.is-selected .badge
color:#000
@@ -214,6 +225,10 @@ setBoardColor(color)
.sidebar-content h3, .sidebar-content h2, .sidebar-content
color:rgba(255,255,255,.7) !important
.card-details .activities .activity .activity-desc .activity-comment
background-color: #cccccc
color: #222222
.board-color-relax
setBoardColor(#27AE61)
@@ -225,7 +240,7 @@ setBoardColor(color)
.list-header
background-color:#a7e366
border-bottom: 6px solid #a7e366
// border-bottom: 6px solid #a7e366
.list-body
background-color:#a7e366
@@ -450,7 +465,7 @@ setBoardClear(color1,color2)
background-color: rgba(255,255,255,0.7)
color: rgba(0,0,0,0.8)
box-shadow: 0 1px 2px rgba(0,0,0,.2)
border-radius: 7px
.quiet, .quiet a
color: rgba(0,0,0,0.4)
@@ -465,6 +480,7 @@ setBoardClear(color1,color2)
a:not(.disabled).is-active.fa, a:not(.disabled).is-active i.fa, a:not(.disabled):hover.fa, a:not(.disabled):hover i.fa
color: rgba(0,0,0,0.6)
border-radius: 7px
input[type="email"], input[type="password"], input[type="text"]
border: 0
@@ -541,8 +557,8 @@ setBoardClear(color1,color2)
background-color:#dedede
.list-header
background-color: #c9cfc3
border-bottom: 6px solid #c9cfc3
// background-color: #c9cfc3
// border-bottom: 6px solid #c9cfc3
.swimlane .swimlane-header-wrap
background-color: #c2c0ab
@@ -645,7 +661,7 @@ setBoardClear(color1,color2)
.list-header
background: none
border-bottom-width: 0px
// border-bottom-width: 0px
.list-header .list-header-name
font-family: Poppins
@@ -758,16 +774,17 @@ setBoardClear(color1,color2)
/* Forms */
button[type=submit].primary, .board-color-modern input[type=submit].primary
background-color: #819C5D
background-color: #777777
border-radius: 7px
.toggle-switch:checked~.toggle-label
background-color: #D2E9B4
background-color: #f7f7f7
.toggle-label:after, .board-color-modern .toggle-switch:checked~.toggle-label:after
background-color: #819C5D !important
background-color: #777777 !important
button, input:not([type=file]), select, textarea
border-radius: 2px
border-radius: 7px
/* Headers */
&#header
@@ -854,21 +871,22 @@ setBoardClear(color1,color2)
.swimlane .list:first-child
margin-left: 0
.swimlane .list:nth-child(even)
background: #5f5f5f
.swimlane .list:nth-child(even) .list-header,
.swimlane .list:nth-child(even) .list-body
background: #6a6a6a
.swimlane .list:nth-child(odd) .list-header
background: #3b3b3b
.swimlane .list:nth-child(odd) .list-header,
.swimlane .list:nth-child(odd) .list-body
background: #555555
.list-header
background: #333333
padding: 10px
border-bottom: 0
.list-header .viewer
padding-left: 10px
.list-header .list-header-name
.list-header .list-header-name,
.minicard
line-height: 14px
color: #eeeeee
@@ -876,7 +894,7 @@ setBoardClear(color1,color2)
padding: 10px
top: 0
.list-header .list-header-plus-icon
.list-header .list-header-plus-top
color: #a6a6a6
.list-body
@@ -906,6 +924,7 @@ setBoardClear(color1,color2)
.list-body a.open-minicard-composer:hover, .list-body a.open-minicard-composer:hover i, .list .list-composer .open-list-composer:hover i
color: #ffffff
border-radius: 7px
/* Mini Card */
.minicard-wrapper
@@ -916,12 +935,13 @@ setBoardClear(color1,color2)
color: #cccccc
border-radius: 2px
font-size: 0.95em
padding: 10px
box-shadow: 0 4px 3px -3px rgba(0,0,0,0.8)
border-bottom: 1px solid #666666
padding: 8px
.minicard:hover
background-color: #494949 !important
color: #f7f7f7
background-color: #4d4d4d !important
.minicard .minicard-labels
margin-bottom: 4px
@@ -956,17 +976,24 @@ setBoardClear(color1,color2)
/* Card Details */
.card-details
position: absolute
top: 30px
left: calc(50% - 384px)
width: 768px
max-height: calc(100% - 60px)
background-color: #454545
color: #cccccc
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)
border: 1px solid #111111
z-index: 100 !important
@media screen and (max-width: 800px)
.card-details
width: 98%
@media screen and (min-width: 801px)
.card-details
position: absolute
top: 30px
left: calc(50% - 384px)
width: 768px
max-height: calc(100% - 60px)
.card-details
scrollbar-width: thin
scrollbar-color: #343434 #999999
@@ -1018,8 +1045,8 @@ setBoardClear(color1,color2)
border-color: #ffffff
.card-details .check-box.materialCheckBox.is-checked
border-bottom: 2px solid #819C5D
border-right: 2px solid #819C5D
border-bottom: 2px solid #ffffff
border-right: 2px solid #ffffff
border-top: 0
border-left: 0
@@ -1059,5 +1086,5 @@ setBoardClear(color1,color2)
font-size: 16px
color: #cccccc
.pop-over.board-color-moderndark .pop-over-list li:hover > a
background-color: #819C5D !important
.pop-over.board-color-moderndark .pop-over-list li > a:hover
background-color: rgba(255,255,255,0.2)
+3 -3
View File
@@ -235,9 +235,9 @@ template(name="createBoard")
= " "
| {{{_ 'board-private-info'}}}
a.js-change-visibility {{_ 'change'}}.
//a.flex.js-toggle-add-template-container
// .materialCheckBox#add-template-container
// span {{_ 'add-template-container'}}
a.flex.js-toggle-add-template-container
.materialCheckBox#add-template-container
span {{_ 'add-template-container'}}
input.primary.wide(type="submit" value="{{_ 'create'}}")
span.quiet
| {{_ 'or'}}
+8
View File
@@ -14,6 +14,14 @@ template(name="boardList")
option(value="-1") {{_ 'organizations'}} :
each orgsDatas
option(value="{{orgId}}") {{_ orgDisplayName}}
//li.AllBoardTemplates
// if userHasTemplates
// select.js-AllBoardTemplates#jsAllBoardTemplates("multiple")
// option(value="-1") {{_ 'templates'}} :
// each templatesDatas
// option(value="{{templateId}}") {{_ templateDisplayName}}
li.AllBoardBtns
div.AllBoardButtonsContainer
if userHasOrgsOrTeams
+25 -12
View File
@@ -1,5 +1,4 @@
const subManager = new SubsManager();
const { calculateIndex, enableClickOnTouch } = Utils;
Template.boardListHeaderBar.events({
'click .js-open-archived-board'() {
@@ -9,7 +8,11 @@ Template.boardListHeaderBar.events({
Template.boardListHeaderBar.helpers({
title() {
//if (FlowRouter.getRouteName() === 'template-container') {
// return 'template-container';
//} else {
return FlowRouter.getRouteName() === 'home' ? 'my-boards' : 'public';
//}
},
templatesBoardId() {
return Meteor.user() && Meteor.user().getTemplatesBoardId();
@@ -56,7 +59,7 @@ BlazeComponent.extendComponent({
// of the previous and the following card -- if any.
const prevBoardDom = ui.item.prev('.js-board').get(0);
const nextBoardBom = ui.item.next('.js-board').get(0);
const sortIndex = calculateIndex(prevBoardDom, nextBoardBom, 1);
const sortIndex = Utils.calculateIndex(prevBoardDom, nextBoardBom, 1);
const boardDomElement = ui.item.get(0);
const board = Blaze.getData(boardDomElement);
@@ -73,9 +76,6 @@ BlazeComponent.extendComponent({
},
});
// ugly touch event hotfix
enableClickOnTouch(itemsSelector);
// Disable drag-dropping if the current user is not a board member or is comment only
this.autorun(() => {
if (Utils.isMiniScreenOrShowDesktopDragHandles()) {
@@ -93,7 +93,7 @@ BlazeComponent.extendComponent({
},
teamsDatas() {
if(Meteor.user().teams)
return Meteor.user().teams;
return Meteor.user().teams.sort((a, b) => a.teamDisplayName.localeCompare(b.teamDisplayName));
else
return [];
},
@@ -103,9 +103,17 @@ BlazeComponent.extendComponent({
else
return false;
},
/*
userHasTemplates(){
if(Meteor.user() != null && Meteor.user().orgs && Meteor.user().orgs.length > 0)
return true;
else
return false;
},
*/
orgsDatas() {
if(Meteor.user().orgs)
return Meteor.user().orgs;
return Meteor.user().orgs.sort((a, b) => a.orgDisplayName.localeCompare(b.orgDisplayName));
else
return [];
},
@@ -126,12 +134,11 @@ BlazeComponent.extendComponent({
},
boards() {
let query = {
//archived: false,
////type: { $in: ['board','template-container'] },
//type: 'board',
// { type: 'board' },
// { type: { $in: ['board','template-container'] } },
$and: [
{ archived: false },
{ type: 'board' },
{ type: { $in: ['board','template-container'] } },
{ $or:[] }
]
};
@@ -221,6 +228,7 @@ BlazeComponent.extendComponent({
evt.preventDefault();
},
'click .js-clone-board'(evt) {
let title = getSlug(Boards.findOne(this.currentData()._id).title) || 'cloned-board';
Meteor.call(
'copyBoard',
this.currentData()._id,
@@ -234,7 +242,12 @@ BlazeComponent.extendComponent({
this.setError(err.error);
} else {
Session.set('fromBoard', null);
Utils.goBoardId(res);
subManager.subscribe('board', res, false);
FlowRouter.go('board', {
id: res,
slug: title,
});
//Utils.goBoardId(res);
}
},
);
+9 -11
View File
@@ -11,9 +11,6 @@ template(name="previewClipboardImagePopup")
img.preview-clipboard-image()
button.primary.js-upload-pasted-image {{_ 'upload'}}
template(name="previewAttachedImagePopup")
img.preview-large-image.js-large-image-clicked(src="{{url}}")
template(name="attachmentDeletePopup")
p {{_ "attachment-delete-pop"}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
@@ -22,30 +19,31 @@ template(name="attachmentsGalery")
.attachments-galery
each attachments
.attachment-item
a.attachment-thumbnail.swipebox(href="{{url}}" title="{{name}}")
if isUploaded
a.attachment-thumbnail.swipebox(href="{{link}}" title="{{name}}")
if link
if isImage
img.attachment-thumbnail-img(src="{{url}}")
img.attachment-thumbnail-img(src="{{link}}")
else if($eq extension 'mp3')
video(width="100%" height="100%" controls="true")
source(src="{{url}}" type="audio/mpeg")
source(src="{{link}}" type="audio/mpeg")
else if($eq extension 'ogg')
video(width="100%" height="100%" controls="true")
source(src="{{url}}" type="video/ogg")
source(src="{{link}}" type="video/ogg")
else if($eq extension 'webm')
video(width="100%" height="100%" controls="true")
source(src="{{url}}" type="video/webm")
source(src="{{link}}" type="video/webm")
else if($eq extension 'mp4')
video(width="100%" height="100%" controls="true")
source(src="{{url}}" type="video/mp4")
source(src="{{link}}" type="video/mp4")
else
span.attachment-thumbnail-ext= extension
else
+spinner
p.attachment-details
= name
span.file-size ({{fileSize size}} KB)
span.attachment-details-actions
a.js-download(href="{{url download=true}}")
a.js-download(href="{{link}}?download=true", download="{{name}}")
i.fa.fa-download
| {{_ 'download'}}
if currentUser.isBoardMember
+46 -95
View File
@@ -13,35 +13,10 @@ Template.attachmentsGalery.events({
event.stopPropagation();
},
'click .js-add-cover'() {
Cards.findOne(this.cardId).setCover(this._id);
Cards.findOne(this.meta.cardId).setCover(this._id);
},
'click .js-remove-cover'() {
Cards.findOne(this.cardId).unsetCover();
},
'click .js-preview-image'(event) {
Popup.open('previewAttachedImage').call(this, event);
// when multiple thumbnails, if click one then another very fast,
// we might get a wrong width from previous img.
// when popup reused, onRendered() won't be called, so we cannot get there.
// here make sure to get correct size when this img fully loaded.
const img = $('img.preview-large-image')[0];
if (!img) return;
const rePosPopup = () => {
const w = img.width;
const h = img.height;
// if the image is too large, we resize & center the popup.
if (w > 300) {
$('div.pop-over').css({
width: w + 20,
position: 'absolute',
left: (window.innerWidth - w) / 2,
top: (window.innerHeight - h) / 2,
});
}
};
const url = $(event.currentTarget).attr('src');
if (img.src === url && img.complete) rePosPopup();
else img.onload = rePosPopup;
Cards.findOne(this.meta.cardId).unsetCover();
},
});
@@ -49,61 +24,35 @@ Template.attachmentsGalery.helpers({
isBoardAdmin() {
return Meteor.user().isBoardAdmin();
},
});
Template.previewAttachedImagePopup.events({
'click .js-large-image-clicked'() {
Popup.back();
fileSize(size) {
return Math.round(size / 1024);
},
});
Template.cardAttachmentsPopup.events({
'change .js-attach-file'(event) {
const card = this;
const processFile = f => {
Utils.processUploadedAttachment(card, f, attachment => {
if (attachment && attachment._id && attachment.isImage()) {
card.setCover(attachment._id);
if (event.currentTarget.files && event.currentTarget.files[0]) {
const uploader = Attachments.insert(
{
file: event.currentTarget.files[0],
meta: Utils.getCommonAttachmentMetaFrom(card),
chunkSize: 'dynamic',
},
false,
);
uploader.on('uploaded', (error, fileRef) => {
if (!error) {
if (fileRef.isImage) {
card.setCover(fileRef._id);
}
}
});
uploader.on('end', (error, fileRef) => {
Popup.back();
});
};
FS.Utility.eachFile(event, f => {
if (
MAX_IMAGE_PIXEL > 0 &&
typeof f.type === 'string' &&
f.type.match(/^image/)
) {
// is image
const reader = new FileReader();
reader.onload = function(e) {
const dataurl = e && e.target && e.target.result;
if (dataurl !== undefined) {
Utils.shrinkImage({
dataurl,
maxSize: MAX_IMAGE_PIXEL,
ratio: COMPRESS_RATIO,
toBlob: true,
callback(blob) {
if (blob === false) {
processFile(f);
} else {
blob.name = f.name;
processFile(blob);
}
},
});
} else {
// couldn't process it let other function handle it?
processFile(f);
}
};
reader.readAsDataURL(f);
} else {
processFile(f);
}
});
uploader.start();
}
},
'click .js-computer-upload'(event, templateInstance) {
templateInstance.find('.js-attach-file').click();
@@ -151,30 +100,32 @@ Template.previewClipboardImagePopup.onRendered(() => {
Template.previewClipboardImagePopup.events({
'click .js-upload-pasted-image'() {
const results = pastedResults;
if (results && results.file) {
const card = this;
if (pastedResults && pastedResults.file) {
const file = pastedResults.file;
window.oPasted = pastedResults;
const card = this;
const file = new FS.File(results.file);
if (!results.name) {
// if no filename, it's from clipboard. then we give it a name, with ext name from MIME type
if (typeof results.file.type === 'string') {
file.name(results.file.type.replace('image/', 'clipboard.'));
const uploader = Attachments.insert(
{
file,
meta: Utils.getCommonAttachmentMetaFrom(card),
fileName: file.name || file.type.replace('image/', 'clipboard.'),
chunkSize: 'dynamic',
},
false,
);
uploader.on('uploaded', (error, fileRef) => {
if (!error) {
if (fileRef.isImage) {
card.setCover(fileRef._id);
}
}
}
file.updatedAt(new Date());
file.boardId = card.boardId;
file.cardId = card._id;
file.userId = Meteor.userId();
const attachment = Attachments.insert(file);
if (attachment && attachment._id && attachment.isImage()) {
card.setCover(attachment._id);
}
pastedResults = null;
$(document.body).pasteImageReader(() => {});
Popup.back();
});
uploader.on('end', (error, fileRef) => {
pastedResults = null;
$(document.body).pasteImageReader(() => {});
Popup.back();
});
uploader.start();
}
},
});
-5
View File
@@ -51,11 +51,6 @@
display: block
box-shadow: 0 1px 2px rgba(0,0,0,.2)
.preview-large-image
max-width: 1000px
display: block
box-shadow: 0 1px 2px rgba(0,0,0,.2)
.preview-clipboard-image
width: 280px
max-width: 100%;
@@ -63,7 +63,7 @@ template(name="cardCustomField-checkbox")
template(name="cardCustomField-currency")
if canModifyCard
+inlinedForm(classNames="js-card-customfield-currency")
input(type="text" value=data.value)
input(type="text" value=data.value autofocus)
.edit-controls.clearfix
button.primary(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
+5 -4
View File
@@ -271,7 +271,7 @@ CardCustomField.register('cardCustomField');
{
'submit .js-card-customfield-stringtemplate'(event) {
event.preventDefault();
const items = this.getItems();
const items = this.stringtemplateItems.get();
this.card.setCustomField(this.customFieldId, items);
},
@@ -279,9 +279,7 @@ CardCustomField.register('cardCustomField');
if (event.keyCode === 13) {
event.preventDefault();
if (event.metaKey || event.ctrlKey) {
this.find('button[type=submit]').click();
} else if (event.target.value.trim()) {
if (event.target.value.trim() || event.metaKey || event.ctrlKey) {
const inputLast = this.find('input.last');
let items = this.getItems();
@@ -307,6 +305,9 @@ CardCustomField.register('cardCustomField');
this.stringtemplateItems.set(items);
}
if (event.metaKey || event.ctrlKey) {
this.find('button[type=submit]').click();
}
}
},
+17 -3
View File
@@ -22,6 +22,7 @@ template(name="cardDetails")
title="{{_ 'copy-card-link-to-clipboard'}}"
href="{{ originRelativeUrl }}"
)
span.copied-tooltip {{_ 'copied'}}
else
unless isPopup
a.fa.fa-times-thin.close-card-details.js-close-card-details(title="{{_ 'close-card'}}")
@@ -33,6 +34,7 @@ template(name="cardDetails")
title="{{_ 'copy-card-link-to-clipboard'}}"
href="{{ originRelativeUrl }}"
)
span.copied-tooltip {{_ 'copied'}}
h2.card-details-title.js-card-title(
class="{{#if canModifyCard}}js-open-inlined-form is-editable{{/if}}")
+viewer
@@ -232,6 +234,15 @@ template(name="cardDetails")
+viewer
= sort
if currentBoard.allowsShowLists
.card-details-item.card-details-show-lists
h3.card-details-item-title
i.fa.fa-list
| {{_ 'list'}}
select.js-select-card-details-lists(disabled="{{#unless canModifyCard}}disabled{{/unless}}")
each currentBoard.lists
option(value="{{_id}}" selected="{{#if isCurrentListId _id}}selected{{/if}}") {{title}}
//.card-details-items
if getSpentTime
.card-details-item.card-details-item-spent
@@ -574,6 +585,8 @@ template(name="cardDetails")
+activities(card=this mode="card")
template(name="editCardTitleForm")
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
span.copied-tooltip {{_ 'copied'}}
textarea.js-edit-card-title(rows='1' autofocus dir="auto")
= getTitle
.edit-controls.clearfix
@@ -721,17 +734,17 @@ template(name="boardsAndLists")
if $eq _id currentBoard._id
option(value="{{_id}}" selected) {{_ 'current'}}
else
option(value="{{_id}}") {{title}}
option(value="{{_id}}" selected="{{#if isMoveAndCopyDialogOptionBoardId _id}}selected{{/if}}") {{title}}
label {{_ 'swimlanes'}}:
select.js-select-swimlanes
each swimlanes
option(value="{{_id}}") {{title}}
option(value="{{_id}}" selected="{{#if isMoveAndCopyDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}}
label {{_ 'lists'}}:
select.js-select-lists
each aBoardLists
option(value="{{_id}}") {{title}}
option(value="{{_id}}" selected="{{#if isMoveAndCopyDialogOptionListId _id}}selected{{/if}}") {{title}}
.edit-controls.clearfix
button.primary.confirm.js-done {{_ 'done'}}
@@ -798,6 +811,7 @@ template(name="cardMorePopup")
i.fa.colorful(class="{{#if board.isPublic}}fa-globe{{else}}fa-lock{{/if}}")
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'}}
.copied-tooltip {{_ 'copied'}}
span.clearfix
br
h2 {{_ 'change-card-parent'}}
+128 -72
View File
@@ -70,7 +70,7 @@ BlazeComponent.extendComponent({
cardMaximized() {
return Meteor.user().hasCardMaximized();
return !Utils.getPopupCardId() && Meteor.user().hasCardMaximized();
},
canModifyCard() {
@@ -168,6 +168,15 @@ BlazeComponent.extendComponent({
);
},
/** returns if the list id is the current list id
* @param listId list id to check
* @return is the list id the current list id ?
*/
isCurrentListId(listId) {
const ret = this.data().listId == listId;
return ret;
},
onRendered() {
if (Meteor.settings.public.CARD_OPENED_WEBHOOK_ENABLED) {
// Send Webhook but not create Activities records ---
@@ -325,29 +334,10 @@ BlazeComponent.extendComponent({
},
'click .js-copy-link'(event) {
event.preventDefault();
const StringToCopyElement = document.getElementById('cardURL_copy');
StringToCopyElement.value =
window.location.origin + window.location.pathname;
StringToCopyElement.select();
if (document.execCommand('copy')) {
StringToCopyElement.blur();
} else {
document.getElementById('cardURL_copy').selectionStart = 0;
document.getElementById('cardURL_copy').selectionEnd = 999;
document.execCommand('copy');
if (window.getSelection) {
if (window.getSelection().empty) {
// Chrome
window.getSelection().empty();
} else if (window.getSelection().removeAllRanges) {
// Firefox
window.getSelection().removeAllRanges();
}
} else if (document.selection) {
// IE?
document.selection.empty();
}
}
const promise = Utils.copyTextToClipboard(event.target.href);
const $tooltip = this.$('.card-details-header .copied-tooltip');
Utils.showCopied(promise, $tooltip);
},
'click .js-open-card-details-menu': Popup.open('cardDetailsActions'),
'submit .js-card-description'(event) {
@@ -398,6 +388,12 @@ BlazeComponent.extendComponent({
card.move(card.boardId, card.swimlaneId, card.listId, sort);
}
},
'change .js-select-card-details-lists'(event) {
let card = this.data();
const listSelect = this.$('.js-select-card-details-lists')[0];
const listId = listSelect.options[listSelect.selectedIndex].value;
card.move(card.boardId, card.swimlaneId, listId, card.sort);
},
'click .js-go-to-linked-card'() {
Utils.goCardId(this.data().linkedId);
},
@@ -677,7 +673,7 @@ Template.cardDetailsActionsPopup.events({
event.preventDefault();
const minOrder = _.min(
this.list()
.cards(this.swimlaneId)
.cardsUnfiltered(this.swimlaneId)
.map((c) => c.sort),
);
this.move(this.boardId, this.swimlaneId, this.listId, minOrder - 1);
@@ -687,7 +683,7 @@ Template.cardDetailsActionsPopup.events({
event.preventDefault();
const maxOrder = _.max(
this.list()
.cards(this.swimlaneId)
.cardsUnfiltered(this.swimlaneId)
.map((c) => c.sort),
);
this.move(this.boardId, this.swimlaneId, this.listId, maxOrder + 1);
@@ -708,9 +704,31 @@ Template.cardDetailsActionsPopup.events({
},
});
Template.editCardTitleForm.onRendered(function () {
autosize(this.$('.js-edit-card-title'));
});
BlazeComponent.extendComponent({
onRendered() {
autosize(this.$('textarea.js-edit-card-title'));
},
events() {
return [
{
'click a.fa.fa-copy'(event) {
const $editor = this.$('textarea');
const promise = Utils.copyTextToClipboard($editor[0].value);
const $tooltip = this.$('.copied-tooltip');
Utils.showCopied(promise, $tooltip);
},
'keydown .js-edit-card-title'(event) {
// If enter key was pressed, submit the data
// Unless the shift key is also being pressed
if (event.keyCode === 13 && !event.shiftKey) {
$('.js-submit-edit-card-title-form').click();
}
},
}
];
}
}).register('editCardTitleForm');
Template.cardMembersPopup.onCreated(function () {
let currBoard = Boards.findOne(Session.get('currentBoard'));
@@ -770,16 +788,6 @@ const filterMembers = (filterTerm) => {
return members;
}
Template.editCardTitleForm.events({
'keydown .js-edit-card-title'(event) {
// If enter key was pressed, submit the data
// Unless the shift key is also being pressed
if (event.keyCode === 13 && !event.shiftKey) {
$('.js-submit-edit-card-title-form').click();
}
},
});
Template.editCardRequesterForm.onRendered(function () {
autosize(this.$('.js-edit-card-requester'));
});
@@ -808,15 +816,16 @@ Template.editCardAssignerForm.events({
Template.moveCardPopup.events({
'click .js-done'() {
// XXX We should *not* get the currentCard from the global state, but
// instead from a “component” state.
const card = Utils.getCurrentCard();
const card = Cards.findOne(this._id);
const bSelect = $('.js-select-boards')[0];
let boardId;
// if we are a worker, we won't have a board select so we just use the
// current boardId of the card.
if (bSelect) boardId = bSelect.options[bSelect.selectedIndex].value;
else boardId = card.boardId;
if (bSelect) {
boardId = bSelect.options[bSelect.selectedIndex].value;
} else {
boardId = card.boardId;
}
const lSelect = $('.js-select-lists')[0];
const listId = lSelect.options[lSelect.selectedIndex].value;
const slSelect = $('.js-select-swimlanes')[0];
@@ -833,8 +842,56 @@ Template.moveCardPopup.events({
});
BlazeComponent.extendComponent({
onCreated() {
subManager.subscribe('board', Session.get('currentBoard'), false);
this.selectedBoardId = new ReactiveVar(Session.get('currentBoard'));
this.currentBoardId = Utils.getCurrentBoardId();
this.selectedBoardId = new ReactiveVar(this.currentBoardId);
this.setMoveAndCopyDialogOption(this.currentBoardId);
},
/** set the last confirmed dialog field values
* @param boardId the current board id
*/
setMoveAndCopyDialogOption(boardId) {
this.moveAndCopyDialogOption = {
'boardId' : "",
'swimlaneId' : "",
'listId' : "",
}
let currentOptions = Meteor.user().getMoveAndCopyDialogOptions();
if (currentOptions && boardId && currentOptions[boardId]) {
this.moveAndCopyDialogOption = currentOptions[boardId];
if (this.moveAndCopyDialogOption.boardId) {
this.selectedBoardId.set(this.moveAndCopyDialogOption.boardId)
}
}
subManager.subscribe('board', this.selectedBoardId.get(), false);
},
/** returns if the board id was the last confirmed one
* @param boardId check this board id
* @return if the board id was the last confirmed one
*/
isMoveAndCopyDialogOptionBoardId(boardId) {
let ret = this.moveAndCopyDialogOption.boardId == boardId;
return ret;
},
/** returns if the swimlane id was the last confirmed one
* @param swimlaneId check this swimlane id
* @return if the swimlane id was the last confirmed one
*/
isMoveAndCopyDialogOptionSwimlaneId(swimlaneId) {
let ret = this.moveAndCopyDialogOption.swimlaneId == swimlaneId;
return ret;
},
/** returns if the list id was the last confirmed one
* @param listId check this list id
* @return if the list id was the last confirmed one
*/
isMoveAndCopyDialogOptionListId(listId) {
let ret = this.moveAndCopyDialogOption.listId == listId;
return ret;
},
boards() {
@@ -863,9 +920,27 @@ BlazeComponent.extendComponent({
events() {
return [
{
'click .js-done'() {
const boardSelect = this.$('.js-select-boards')[0];
const boardId = boardSelect.options[boardSelect.selectedIndex].value;
const listSelect = this.$('.js-select-lists')[0];
const listId = listSelect.options[listSelect.selectedIndex].value;
const swimlaneSelect = this.$('.js-select-swimlanes')[0];
const swimlaneId = swimlaneSelect.options[swimlaneSelect.selectedIndex].value;
const options = {
'boardId' : boardId,
'swimlaneId' : swimlaneId,
'listId' : listId,
}
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
},
'change .js-select-boards'(event) {
this.selectedBoardId.set($(event.currentTarget).val());
subManager.subscribe('board', this.selectedBoardId.get(), false);
const boardId = $(event.currentTarget).val();
this.selectedBoardId.set(boardId);
subManager.subscribe('board', boardId, false);
},
},
];
@@ -1089,30 +1164,11 @@ BlazeComponent.extendComponent({
events() {
return [
{
'click .js-copy-card-link-to-clipboard'() {
// Clipboard code from:
// https://stackoverflow.com/questions/6300213/copy-selected-text-to-the-clipboard-without-using-flash-must-be-cross-browser
const StringToCopyElement = document.getElementById('cardURL');
StringToCopyElement.select();
if (document.execCommand('copy')) {
StringToCopyElement.blur();
} else {
document.getElementById('cardURL').selectionStart = 0;
document.getElementById('cardURL').selectionEnd = 999;
document.execCommand('copy');
if (window.getSelection) {
if (window.getSelection().empty) {
// Chrome
window.getSelection().empty();
} else if (window.getSelection().removeAllRanges) {
// Firefox
window.getSelection().removeAllRanges();
}
} else if (document.selection) {
// IE?
document.selection.empty();
}
}
'click .js-copy-card-link-to-clipboard'(event) {
const promise = Utils.copyTextToClipboard(location.origin + document.getElementById('cardURL').value);
const $tooltip = this.$('.copied-tooltip');
Utils.showCopied(promise, $tooltip);
},
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
Popup.close();
+21 -6
View File
@@ -76,6 +76,12 @@ avatar-radius = 50%
box-shadow: 0 0 0 2px darken(white, 60%) inset
// Other card details
.copied-tooltip
display: none
padding: 0px 10px;
background-color: #000000df;
color: #fff;
border-radius: 5px;
.card-details
padding: 0
@@ -86,7 +92,7 @@ avatar-radius = 50%
overflow-x: hidden
background: darken(white, 3%)
border-radius: bottom 3px
z-index: 20 !important
z-index: 20
animation: flexGrowIn 0.1s
box-shadow: 0 0 7px 0 darken(white, 30%)
transition: flex-basis 0.1s
@@ -104,6 +110,9 @@ avatar-radius = 50%
padding: 7px 20px
background: darken(white, 7%)
border-bottom: 1px solid darken(white, 14%)
position: sticky
top: 0px
z-index: 500
.card-number {
color: darken(white, 30%);
@@ -118,7 +127,8 @@ avatar-radius = 50%
.card-copy-button,
.card-copy-mobile-button,
.close-card-details-mobile-web,
.card-details-menu-mobile-web
.card-details-menu-mobile-web,
.copied-tooltip
float: right
.close-card-details,
@@ -174,6 +184,9 @@ avatar-radius = 50%
margin-top: 5px
margin-bottom: 10px
.copied-tooltip
padding: 0px 10px
.card-details-list
font-size: 0.85em
margin-bottom: 3px
@@ -187,6 +200,10 @@ avatar-radius = 50%
border-radius: 3px
padding: 0px 5px
.copied-tooltip
margin-right: 10px
padding: 10px;
.card-description textarea
min-height: 100px
@@ -197,13 +214,13 @@ avatar-radius = 50%
.card-details-item
margin-right: 0.5em
flex-grow: 1
&:last-child
margin-right: 0
&.card-details-item-labels
display: block
word-wrap: break-word
max-width: 95%
flex-grow: 1
&.card-details-item-members,
&.card-details-item-assignees,
&.card-details-item-customfield,
@@ -211,7 +228,6 @@ avatar-radius = 50%
display: block
word-wrap: break-word
max-width: 36%
flex-grow: 1
&.card-details-item-creator,
&.card-details-item-received,
&.card-details-item-start,
@@ -220,7 +236,6 @@ avatar-radius = 50%
display: block
word-wrap: break-word
max-width: 28%
flex-grow: 1
&.custom-fields
padding-left: 10px
@@ -243,7 +258,7 @@ avatar-radius = 50%
overflow-x: scroll
background: darken(white, 3%)
border-radius: bottom 3px
z-index: 1000 !important
z-index: 100
animation: flexGrowIn 0.1s
box-shadow: 0 0 7px 0 darken(white, 30%)
transition: flex-basis 0.1s
+67 -19
View File
@@ -12,18 +12,13 @@ template(name="checklists")
input.toggle-switch(type="checkbox" id="toggleHideCheckedItemsButton")
label.toggle-label(for="toggleHideCheckedItemsButton")
if toggleDeleteDialog.get
.board-overlay#card-details-overlay
+checklistDeleteDialog(checklist = checklistToDelete)
.card-checklist-items
each checklist in checklists
+checklistDetail(checklist = checklist)
if canModifyCard
+inlinedForm(autoclose=false classNames="js-add-checklist" cardId = cardId)
+addChecklistItemForm
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=false)
else
a.add-checklist.js-open-inlined-form(title="{{_ 'add-checklist'}}")
i.fa.fa-plus
@@ -36,7 +31,7 @@ template(name="checklistDetail")
.checklist-title
span
if canModifyCard
a.js-delete-checklist.toggle-delete-checklist-dialog {{_ "delete"}}...
a.fa.fa-navicon.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}")
if canModifyCard
h2.title.js-open-inlined-form.is-editable
@@ -48,27 +43,33 @@ template(name="checklistDetail")
h2.title
+viewer
= checklist.title
if $gt finishedPercent 0
.checklist-progress-bar-container
.checklist-progress-text {{finishedPercent}}%
.checklist-progress-bar
.checklist-progress(style="width:{{finishedPercent}}%")
+checklistItems(checklist = checklist)
template(name="checklistDeleteDialog")
.js-confirm-checklist-delete
p
i(class="fa fa-exclamation-triangle" aria-hidden="true")
p
| {{_ 'confirm-checklist-delete-dialog'}}
span {{checklist.title}}
| ?
.js-checklist-delete-buttons
button.confirm-checklist-delete(type="button") {{_ 'delete'}}
button.toggle-delete-checklist-dialog(type="button") {{_ 'cancel'}}
template(name="checklistDeletePopup")
p {{_ 'confirm-checklist-delete-popup'}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
template(name="addChecklistItemForm")
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
span.copied-tooltip {{_ 'copied'}}
textarea.js-add-checklist-item(rows='1' autofocus)
.edit-controls.clearfix
button.primary.confirm.js-submit-add-checklist-item-form(type="submit") {{_ 'save'}}
a.fa.fa-times-thin.js-close-inlined-form
if showNewlineBecomesNewChecklistItem
.material-toggle-switch(title="{{_ 'newlineBecomesNewChecklistItem'}}")
input.toggle-switch(type="checkbox" id="toggleNewlineBecomesNewChecklistItem")
label.toggle-label(for="toggleNewlineBecomesNewChecklistItem")
template(name="editChecklistItemForm")
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
span.copied-tooltip {{_ 'copied'}}
textarea.js-edit-checklist-item(rows='1' autofocus dir="auto")
if $eq type 'item'
= item.title
@@ -93,7 +94,7 @@ template(name="checklistItems")
+checklistItemDetail(item = item checklist = checklist)
if canModifyCard
+inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist)
+addChecklistItemForm
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true)
else
a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}")
i.fa.fa-plus
@@ -142,3 +143,50 @@ template(name="boardsSwimlanesAndLists")
.edit-controls.clearfix
button.primary.confirm.js-done {{_ 'done'}}
template(name="checklistActionsPopup")
ul.pop-over-list
li
a.js-delete-checklist.delete-checklist
i.fa.fa-trash
| {{_ "delete"}} ...
a.js-move-checklist.move-checklist
i.fa.fa-arrow-right
| {{_ "moveChecklist"}} ...
a.js-copy-checklist.copy-checklist
i.fa.fa-copy
| {{_ "copyChecklist"}} ...
template(name="copyChecklistPopup")
+copyAndMoveChecklist
template(name="moveChecklistPopup")
+copyAndMoveChecklist
template(name="copyAndMoveChecklist")
unless currentUser.isWorker
label {{_ 'boards'}}:
select.js-select-boards(autofocus)
each boards
if $eq _id currentBoard._id
option(value="{{_id}}" selected) {{_ 'current'}}
else
option(value="{{_id}}" selected="{{#if isChecklistDialogOptionBoardId _id}}selected{{/if}}") {{title}}
label {{_ 'swimlanes'}}:
select.js-select-swimlanes
each swimlanes
option(value="{{_id}}" selected="{{#if isChecklistDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}}
label {{_ 'lists'}}:
select.js-select-lists
each lists
option(value="{{_id}}" selected="{{#if isChecklistDialogOptionListId _id}}selected{{/if}}") {{title}}
label {{_ 'cards'}}:
select.js-select-cards
each cards
option(value="{{_id}}" selected="{{#if isChecklistDialogOptionCardId _id}}selected{{/if}}") {{title}}
.edit-controls.clearfix
button.primary.confirm.js-done {{_ 'done'}}
+317 -56
View File
@@ -77,6 +77,12 @@ BlazeComponent.extendComponent({
!Meteor.user().isWorker()
);
},
/** returns the finished percent of the checklist */
finishedPercent() {
const ret = this.data().checklist.finishedPercent();
return ret;
},
}).register('checklistDetail');
BlazeComponent.extendComponent({
@@ -86,7 +92,8 @@ BlazeComponent.extendComponent({
const title = textarea.value.trim();
let cardId = this.currentData().cardId;
const card = Cards.findOne(cardId);
if (card.isLinked()) cardId = card.linkedId;
//if (card.isLinked()) cardId = card.linkedId;
if (card.isLinkedCard()) cardId = card.linkedId;
if (title) {
Checklists.insert({
@@ -105,16 +112,23 @@ BlazeComponent.extendComponent({
addChecklistItem(event) {
event.preventDefault();
const textarea = this.find('textarea.js-add-checklist-item');
const newlineBecomesNewChecklistItem = this.find('input#toggleNewlineBecomesNewChecklistItem');
const title = textarea.value.trim();
const checklist = this.currentData().checklist;
if (title) {
ChecklistItems.insert({
title,
checklistId: checklist._id,
cardId: checklist.cardId,
sort: Utils.calculateIndexData(checklist.lastItem()).base,
});
let checklistItems = [title];
if (newlineBecomesNewChecklistItem.checked) {
checklistItems = title.split('\n').map(_value => _value.trim());
}
for (let checklistItem of checklistItems) {
ChecklistItems.insert({
title: checklistItem,
checklistId: checklist._id,
cardId: checklist.cardId,
sort: Utils.calculateIndexData(checklist.lastItem()).base,
});
}
}
// We keep the form opened, empty it.
textarea.value = '';
@@ -130,14 +144,6 @@ BlazeComponent.extendComponent({
);
},
deleteChecklist() {
const checklist = this.currentData().checklist;
if (checklist && checklist._id) {
Checklists.remove(checklist._id);
this.toggleDeleteDialog.set(false);
}
},
deleteItem() {
const checklist = this.currentData().checklist;
const item = this.currentData().item;
@@ -163,11 +169,6 @@ BlazeComponent.extendComponent({
item.setTitle(title);
},
onCreated() {
this.toggleDeleteDialog = new ReactiveVar(false);
this.checklistToDelete = null; //Store data context to pass to checklistDeleteDialog template
},
pressKey(event) {
//If user press enter key inside a form, submit it
//Unless the user is also holding down the 'shift' key
@@ -195,12 +196,6 @@ BlazeComponent.extendComponent({
events() {
const events = {
'click .toggle-delete-checklist-dialog'(event) {
if ($(event.target).hasClass('js-delete-checklist')) {
this.checklistToDelete = this.currentData().checklist; //Store data context
}
this.toggleDeleteDialog.set(!this.toggleDeleteDialog.get());
},
'click #toggleHideCheckedItemsButton'() {
Meteor.call('toggleHideCheckedItems');
},
@@ -209,13 +204,13 @@ BlazeComponent.extendComponent({
return [
{
...events,
'click .js-open-checklist-details-menu': Popup.open('checklistActions'),
'submit .js-add-checklist': this.addChecklist,
'submit .js-edit-checklist-title': this.editChecklist,
'submit .js-add-checklist-item': this.addChecklistItem,
'submit .js-edit-checklist-item': this.editChecklistItem,
'click .js-convert-checklist-item-to-card': Popup.open('convertChecklistItemToCard'),
'click .js-delete-checklist-item': this.deleteItem,
'click .confirm-checklist-delete': this.deleteChecklist,
'focus .js-add-checklist-item': this.focusChecklistItem,
// add and delete checklist / checklist-item
'click .js-open-inlined-form': this.closeAllInlinedForms,
@@ -279,39 +274,77 @@ Template.checklists.helpers({
},
});
Template.addChecklistItemForm.onRendered(() => {
autosize($('textarea.js-add-checklist-item'));
});
BlazeComponent.extendComponent({
onRendered() {
autosize(this.$('textarea.js-add-checklist-item'));
},
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
events() {
return [
{
'click a.fa.fa-copy'(event) {
const $editor = this.$('textarea');
const promise = Utils.copyTextToClipboard($editor[0].value);
Template.editChecklistItemForm.onRendered(() => {
autosize($('textarea.js-edit-checklist-item'));
});
const $tooltip = this.$('.copied-tooltip');
Utils.showCopied(promise, $tooltip);
},
}
];
}
}).register('addChecklistItemForm');
Template.checklistDeleteDialog.onCreated(() => {
const $cardDetails = this.$('.card-details');
this.scrollState = {
position: $cardDetails.scrollTop(), //save current scroll position
top: false, //required for smooth scroll animation
};
//Callback's purpose is to only prevent scrolling after animation is complete
$cardDetails.animate({ scrollTop: 0 }, 500, () => {
this.scrollState.top = true;
});
BlazeComponent.extendComponent({
events() {
return [
{
'click .js-delete-checklist' : Popup.afterConfirm('checklistDelete', function () {
Popup.back(2);
const checklist = this.checklist;
if (checklist && checklist._id) {
Checklists.remove(checklist._id);
}
}),
'click .js-move-checklist' : Popup.open('moveChecklist'),
'click .js-copy-checklist' : Popup.open('copyChecklist'),
}
]
}
}).register('checklistActionsPopup');
//Prevent scrolling while dialog is open
$cardDetails.on('scroll', () => {
if (this.scrollState.top) {
//If it's already in position, keep it there. Otherwise let animation scroll
$cardDetails.scrollTop(0);
}
});
});
BlazeComponent.extendComponent({
onRendered() {
autosize(this.$('textarea.js-edit-checklist-item'));
},
canModifyCard() {
return (
Meteor.user() &&
Meteor.user().isBoardMember() &&
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
);
},
events() {
return [
{
'click a.fa.fa-copy'(event) {
const $editor = this.$('textarea');
const promise = Utils.copyTextToClipboard($editor[0].value);
Template.checklistDeleteDialog.onDestroyed(() => {
const $cardDetails = this.$('.card-details');
$cardDetails.off('scroll'); //Reactivate scrolling
$cardDetails.animate({ scrollTop: this.scrollState.position });
});
const $tooltip = this.$('.copied-tooltip');
Utils.showCopied(promise, $tooltip);
},
}
];
}
}).register('editChecklistItemForm');
Template.checklistItemDetail.helpers({
canModifyCard() {
@@ -345,3 +378,231 @@ BlazeComponent.extendComponent({
];
},
}).register('checklistItemDetail');
class DialogWithBoardSwimlaneListAndCard extends BlazeComponent {
/** returns the checklist dialog options
* @return Object with properties { boardId, swimlaneId, listId, cardId }
*/
getChecklistDialogOptions() {
}
/** checklist is done
* @param cardId the selected card id
* @param options the selected options (Object with properties { boardId, swimlaneId, listId, cardId })
*/
setDone(cardId, options) {
}
onCreated() {
this.currentBoardId = Utils.getCurrentBoardId();
this.selectedBoardId = new ReactiveVar(this.currentBoardId);
this.selectedSwimlaneId = new ReactiveVar('');
this.selectedListId = new ReactiveVar('');
this.setChecklistDialogOption(this.currentBoardId);
}
/** set the last confirmed dialog field values
* @param boardId the current board id
*/
setChecklistDialogOption(boardId) {
this.checklistDialogOption = {
'boardId' : "",
'swimlaneId' : "",
'listId' : "",
'cardId': "",
}
let currentOptions = this.getChecklistDialogOptions();
if (currentOptions && boardId && currentOptions[boardId]) {
this.checklistDialogOption = currentOptions[boardId];
if (this.checklistDialogOption.boardId &&
this.checklistDialogOption.swimlaneId &&
this.checklistDialogOption.listId
)
{
this.selectedBoardId.set(this.checklistDialogOption.boardId)
this.selectedSwimlaneId.set(this.checklistDialogOption.swimlaneId);
this.selectedListId.set(this.checklistDialogOption.listId);
}
}
this.getBoardData(this.selectedBoardId.get());
if (!this.selectedSwimlaneId.get() || !Swimlanes.findOne({_id: this.selectedSwimlaneId.get(), boardId: this.selectedBoardId.get()})) {
this.setFirstSwimlaneId();
}
if (!this.selectedListId.get() || !Lists.findOne({_id: this.selectedListId.get(), boardId: this.selectedBoardId.get()})) {
this.setFirstListId();
}
}
/** sets the first swimlane id */
setFirstSwimlaneId() {
try {
const board = Boards.findOne(this.selectedBoardId.get());
const swimlaneId = board.swimlanes().fetch()[0]._id;
this.selectedSwimlaneId.set(swimlaneId);
} catch (e) {}
}
/** sets the first list id */
setFirstListId() {
try {
const board = Boards.findOne(this.selectedBoardId.get());
const listId = board.lists().fetch()[0]._id;
this.selectedListId.set(listId);
} catch (e) {}
}
/** returns if the board id was the last confirmed one
* @param boardId check this board id
* @return if the board id was the last confirmed one
*/
isChecklistDialogOptionBoardId(boardId) {
let ret = this.checklistDialogOption.boardId == boardId;
return ret;
}
/** returns if the swimlane id was the last confirmed one
* @param swimlaneId check this swimlane id
* @return if the swimlane id was the last confirmed one
*/
isChecklistDialogOptionSwimlaneId(swimlaneId) {
let ret = this.checklistDialogOption.swimlaneId == swimlaneId;
return ret;
}
/** returns if the list id was the last confirmed one
* @param listId check this list id
* @return if the list id was the last confirmed one
*/
isChecklistDialogOptionListId(listId) {
let ret = this.checklistDialogOption.listId == listId;
return ret;
}
/** returns if the card id was the last confirmed one
* @param cardId check this card id
* @return if the card id was the last confirmed one
*/
isChecklistDialogOptionCardId(cardId) {
let ret = this.checklistDialogOption.cardId == cardId;
return ret;
}
/** returns all available board */
boards() {
const ret = Boards.find(
{
archived: false,
'members.userId': Meteor.userId(),
_id: { $ne: Meteor.user().getTemplatesBoardId() },
},
{
sort: { sort: 1 },
},
);
return ret;
}
/** returns all available swimlanes of the current board */
swimlanes() {
const board = Boards.findOne(this.selectedBoardId.get());
const ret = board.swimlanes();
return ret;
}
/** returns all available lists of the current board */
lists() {
const board = Boards.findOne(this.selectedBoardId.get());
const ret = board.lists();
return ret;
}
/** returns all available cards of the current list */
cards() {
const list = Lists.findOne(this.selectedListId.get());
const ret = list.cards(this.selectedSwimlaneId.get());
return ret;
}
/** get the board data from the server
* @param boardId get the board data of this board id
*/
getBoardData(boardId) {
const self = this;
Meteor.subscribe('board', boardId, false, {
onReady() {
const sameBoardId = self.selectedBoardId.get() == boardId;
self.selectedBoardId.set(boardId);
if (!sameBoardId) {
// reset swimlane id (for selection in cards())
self.setFirstSwimlaneId();
// reset list id (for selection in cards())
self.setFirstListId();
}
},
});
}
events() {
return [
{
'click .js-done'() {
const boardSelect = this.$('.js-select-boards')[0];
const boardId = boardSelect.options[boardSelect.selectedIndex].value;
const listSelect = this.$('.js-select-lists')[0];
const listId = listSelect.options[listSelect.selectedIndex].value;
const swimlaneSelect = this.$('.js-select-swimlanes')[0];
const swimlaneId = swimlaneSelect.options[swimlaneSelect.selectedIndex].value;
const cardSelect = this.$('.js-select-cards')[0];
const cardId = cardSelect.options[cardSelect.selectedIndex].value;
const options = {
'boardId' : boardId,
'swimlaneId' : swimlaneId,
'listId' : listId,
'cardId': cardId,
}
this.setDone(cardId, options);
Popup.back(2);
},
'change .js-select-boards'(event) {
const boardId = $(event.currentTarget).val();
this.getBoardData(boardId);
},
'change .js-select-swimlanes'(event) {
this.selectedSwimlaneId.set($(event.currentTarget).val());
},
'change .js-select-lists'(event) {
this.selectedListId.set($(event.currentTarget).val());
},
},
];
}
}
/** Move Checklist Dialog */
(class extends DialogWithBoardSwimlaneListAndCard {
getChecklistDialogOptions() {
const ret = Meteor.user().getMoveChecklistDialogOptions();
return ret;
}
setDone(cardId, options) {
Meteor.user().setMoveChecklistDialogOption(this.currentBoardId, options);
this.data().checklist.move(cardId);
}
}).register('moveChecklistPopup');
/** Copy Checklist Dialog */
(class extends DialogWithBoardSwimlaneListAndCard {
getChecklistDialogOptions() {
const ret = Meteor.user().getCopyChecklistDialogOptions();
return ret;
}
setDone(cardId, options) {
Meteor.user().setCopyChecklistDialogOption(this.currentBoardId, options);
this.data().checklist.copy(cardId);
}
}).register('copyChecklistPopup');
+27 -38
View File
@@ -20,6 +20,25 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
display: flex
justify-content: space-between
.checklist-progress-bar-container
display: flex
flex-direction: row
align-items: center
.checklist-progress-text
margin-right: 10px
.checklist-progress-bar
width: 80%
height: 10px
.checklist-progress
color: #fff !important
background-color: #2196F3 !important
padding: 0.01em 16px
border-radius: 16px
height: 100%
.checklist-title
.checkbox
float: left
@@ -39,49 +58,11 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
&.is-finished
color: #3cb500
.js-delete-checklist
@extends .delete-text
span.fa.checklist-handle
padding-right: 20px
padding-top: 3px
float: left
.js-confirm-checklist-delete
background-color: darken(white, 3%)
position: absolute
float: left;
width: 60%
margin-top: 0
margin-left: 13%
padding-bottom: 2%
padding-left: 3%
padding-right: 3%
z-index: 17
border-radius: 3px
p
position: relative
margin-top: 3%
width: 100%
text-align: center
span
font-weight: bold
i
font-size: 2em
.js-checklist-delete-buttons
position: relative
padding: left 2% right 2%
.confirm-checklist-delete
margin-left: 12%
float: left
.toggle-delete-checklist-dialog
margin-right: 12%
float: right
#card-details-overlay
top: 0
bottom: -600px
@@ -177,3 +158,11 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
background: #dbdbdb
color: #222
box-shadow: 0 1px 2px rgba(0,0,0,.2)
.checklist-details-menu
float: right
padding: 6px 10px 6px 10px
.edit-controls
label.toggle-label
margin-left: 2px
+12 -3
View File
@@ -48,7 +48,17 @@ BlazeComponent.extendComponent({
connectWith: '.edit-labels-pop-over',
tolerance: 'pointer',
appendTo: '.edit-labels-pop-over',
helper: 'clone',
helper(element, currentItem) {
let ret = currentItem.clone();
if (currentItem.closest('.popup-container-depth-0').size() == 0)
{ // only set css transform at every sub-popup, not at the main popup
const content = currentItem.closest('.content')[0]
const offsetLeft = content.offsetLeft;
const offsetTop = $('.pop-over > .header').height() * -1;
ret.css("transform", `translate(${offsetLeft}px, ${offsetTop}px)`);
}
return ret;
},
distance: 7,
items: itemsSelector,
placeholder: 'card-label-wrapper placeholder',
@@ -63,7 +73,6 @@ BlazeComponent.extendComponent({
card.board().setNewLabelOrder(newLabelOrderOnlyIds);
},
});
Utils.enableClickOnTouch(itemsSelector);
// Disable drag-dropping if the current user is not a board member or is comment only
this.autorun(() => {
@@ -78,7 +87,7 @@ BlazeComponent.extendComponent({
return [
{
'click .js-select-label'(event) {
const card = Utils.getCurrentCard();
const card = this.data();
const labelId = this.currentData()._id;
card.toggleLabel(labelId);
event.preventDefault();
+1
View File
@@ -146,6 +146,7 @@
height: 25px
margin: 0px 3% 7px 0px
width: 10.5%
max-width: 10.5%
cursor: pointer
.edit-labels
+13 -11
View File
@@ -7,7 +7,7 @@ template(name="minicard")
.handle
.fa.fa-arrows
if cover
.minicard-cover(style="background-image: url('{{cover.url}}');")
.minicard-cover(style="background-image: url('{{cover.link 'original' '/'}}?dummyReloadAfterSessionEstablished={{sess}}');")
if labels
.minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}")
each labels
@@ -88,15 +88,17 @@ template(name="minicard")
+viewer
= trueValue
if getAssignees
.minicard-assignees.js-minicard-assignees
each getAssignees
+userAvatar(userId=this)
if showAssignee
if getAssignees
.minicard-assignees.js-minicard-assignees
each getAssignees
+userAvatar(userId=this)
if getMembers
.minicard-members.js-minicard-members
each getMembers
+userAvatar(userId=this)
if showMembers
if getMembers
.minicard-members.js-minicard-members
each getMembers
+userAvatar(userId=this)
if showCreator
.minicard-creator
@@ -125,10 +127,10 @@ template(name="minicard")
span.badge-icon.fa.fa-check(class="{{#if pokerState}}text-green{{/if}}")
if expiredPoker
span.badge-text {{ getPokerEstimation }}
if attachments.count
if attachments.length
.badge
span.badge-icon.fa.fa-paperclip
span.badge-text= attachments.count
span.badge-text= attachments.length
if checklists.count
.badge(class="{{#if checklistFinished}}is-finished{{/if}}")
span.badge-icon.fa.fa-check-square-o
+28
View File
@@ -49,6 +49,28 @@ BlazeComponent.extendComponent({
return false;
},
showMembers() {
if (this.data().board()) {
return (
this.data().board.allowsMembers === null ||
this.data().board().allowsMembers === undefined ||
this.data().board().allowsMembers
);
}
return false;
},
showAssignee() {
if (this.data().board()) {
return (
this.data().board.allowsAssignee === null ||
this.data().board().allowsAssignee === undefined ||
this.data().board().allowsAssignee
);
}
return false;
},
/** opens the card label popup only if clicked onto a label
* <li> this is necessary to have the data context of the minicard.
* if .js-card-label is used at click event, then only the data context of the label itself is available at this.currentData()
@@ -92,6 +114,12 @@ Template.minicard.helpers({
return false;
}
},
// XXX resolve this nasty hack for https://github.com/veliovgroup/Meteor-Files/issues/763
sess() {
return Meteor.connection && Meteor.connection._lastSessionId
? Meteor.connection._lastSessionId
: null;
},
});
BlazeComponent.extendComponent({
+5 -7
View File
@@ -117,7 +117,6 @@ button
display: inline-block
font-weight: 700
line-height: 22px
margin: 8px 4px 0 0
padding: 7px 20px
text-align: center
@@ -226,20 +225,19 @@ textarea
.edit-controls,
.add-controls
display: flex
align-items: baseline
margin-top: 0
align-items: center
margin-top: 0px
margin-bottom: 12px
button[type=submit]
input[type=button]
float: left
height: 32px
margin-top: -2px
padding-top: 5px
padding-bottom: 5px
margin-bottom: 0px
.fa-times-thin
font-size: 26px
margin: 3px 4px
margin: 3px 10px
// Material Design checkboxes
[type="checkbox"]:not(:checked),
+6 -1
View File
@@ -87,8 +87,13 @@ BlazeComponent.extendComponent({
if (err) {
this.setError(err.error);
} else {
let title = getSlug(this.importedData.get().title) || 'imported-board';
Session.set('fromBoard', null);
Utils.goBoardId(res);
FlowRouter.go('board', {
id: res,
slug: title,
})
//Utils.goBoardId(res);
}
},
);
+40 -1
View File
@@ -1,3 +1,5 @@
require('/client/lib/jquery-ui.js')
const { calculateIndex } = Utils;
BlazeComponent.extendComponent({
@@ -93,7 +95,7 @@ BlazeComponent.extendComponent({
$cards.sortable('cancel');
if (MultiSelection.isActive()) {
Cards.find(MultiSelection.getMongoSelector()).forEach((card, i) => {
Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).forEach((card, i) => {
const newSwimlaneId = targetSwimlaneId
? targetSwimlaneId
: card.swimlaneId || defaultSwimlaneId;
@@ -114,6 +116,43 @@ BlazeComponent.extendComponent({
}
boardComponent.setIsDragging(false);
},
sort(event, ui) {
const $boardCanvas = $('.board-canvas');
const boardCanvas = $boardCanvas[0];
if (event.pageX < 10)
{ // scroll to the left
boardCanvas.scrollLeft -= 15;
ui.helper[0].offsetLeft -= 15;
}
if (
event.pageX > boardCanvas.offsetWidth - 10 &&
boardCanvas.scrollLeft < $boardCanvas.data('scrollLeftMax') // don't scroll more than possible
)
{ // scroll to the right
boardCanvas.scrollLeft += 15;
}
if (
event.pageY > boardCanvas.offsetHeight - 10 &&
event.pageY + boardCanvas.scrollTop < $boardCanvas.data('scrollTopMax') // don't scroll more than possible
)
{ // scroll to the bottom
boardCanvas.scrollTop += 15;
}
if (event.pageY < 10)
{ // scroll to the top
boardCanvas.scrollTop -= 15;
}
},
activate(event, ui) {
const $boardCanvas = $('.board-canvas');
const boardCanvas = $boardCanvas[0];
// scrollTopMax and scrollLeftMax only available at Firefox (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTopMax)
// https://www.it-swarm.com.de/de/javascript/so-erhalten-sie-den-maximalen-dokument-scrolltop-wert/1069126844/
$boardCanvas.data('scrollTopMax', boardCanvas.scrollHeight - boardCanvas.clientTop);
// https://stackoverflow.com/questions/5138373/how-do-i-get-the-max-value-of-scrollleft/5704386#5704386
$boardCanvas.data('scrollLeftMax', boardCanvas.scrollWidth - boardCanvas.clientWidth);
},
});
this.autorun(() => {
+32 -22
View File
@@ -4,7 +4,6 @@
box-sizing: border-box
display: flex
flex-direction: column
flex: 0 0 270px
position: relative
// Even if this background color is the same as the body we can't leave it
// transparent, because that won't work during a list drag.
@@ -12,6 +11,8 @@
border-left: 1px solid darken(white, 20%)
padding: 0
float: left
min-width: 270px
max-width: 270px
&:first-child
margin-left: 5px
@@ -85,13 +86,9 @@
color: #a6a6a6
.list-header-menu
position: absolute
padding: 27px 19px
margin-top: 1px
top: -7px
right: 3px
float: right
.list-header-plus-icon
.list-header-plus-top
color: #a6a6a6
margin-right: 15px
@@ -100,9 +97,10 @@
.cardCount
color: #8c8c8c
font-size: 0.8em
font-size: 12px
font-weight: bold
.list-header .list-header-plus-icon, .js-open-list-menu, .list-header-menu a
.list-header .list-header-plus-top, .js-open-list-menu, .list-header-menu a
color #4d4d4d
padding-left 4px
@@ -160,18 +158,6 @@
float: left
@media screen and (max-width: 800px)
.list-header-menu
position: absolute
padding: 27px 19px
margin-top: 1px
top: -7px
margin-right: 7px
right: -3px
.list-header
.list-header-name
margin-left: 1.4rem
.mini-list
flex: 0 0 60px
height: auto
@@ -180,6 +166,7 @@
border-bottom: 1px solid darken(white, 20%)
.list
display: contents
flex-basis: auto
width: 100%
border-left: 0px
@@ -214,7 +201,6 @@
display: flex
align-items: center
.list-header-left-icon
display: inline
padding: 7px
padding-right: 27px
margin-top: 1px
@@ -237,6 +223,30 @@
right: 10px
font-size: 24px
.list-header
display: grid
grid-template-columns: 30px 5fr 1fr
.list-header-left-icon
display: grid
grid-row: 1/3
grid-column: 1
.list-header-name
grid-row: 1
grid-column: 2
align-self: end
.cardCount
grid-row: 2
grid-column: 2
align-self: start
.list-header-menu
grid-row: 1/3
grid-column: 3
.inlined-form
grid-row: 1/3
grid-column: 1/4
.edit-controls
align-items: initial
.link-board-wrapper
display: flex
align-items: baseline
+20 -5
View File
@@ -277,9 +277,12 @@ BlazeComponent.extendComponent({
getLabels() {
const currentBoardId = Session.get('currentBoard');
return Boards.findOne(currentBoardId).labels.filter(label => {
return this.labels.get().indexOf(label._id) > -1;
});
if (Boards.findOne(currentBoardId).labels) {
return Boards.findOne(currentBoardId).labels.filter(label => {
return this.labels.get().indexOf(label._id) > -1;
});
}
return false;
},
pressKey(evt) {
@@ -333,7 +336,7 @@ BlazeComponent.extendComponent({
[
// User mentions
{
match: /\B@([\w.]*)$/,
match: /\B@([\w.-]*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
callback(
@@ -344,6 +347,9 @@ BlazeComponent.extendComponent({
);
},
template(user) {
if (user.profile && user.profile.fullname) {
return (user.username + " (" + user.profile.fullname + ")");
}
return user.username;
},
replace(user) {
@@ -360,6 +366,9 @@ BlazeComponent.extendComponent({
const currentBoard = Boards.findOne(Session.get('currentBoard'));
callback(
$.map(currentBoard.labels, label => {
if (label.name == undefined) {
label.name = "";
}
if (
label.name.indexOf(term) > -1 ||
label.color.indexOf(term) > -1
@@ -569,7 +578,8 @@ BlazeComponent.extendComponent({
this.isBoardTemplateSearch;
let board = {};
if (this.isTemplateSearch) {
board = Boards.findOne((Meteor.user().profile || {}).templatesBoardId);
//board = Boards.findOne((Meteor.user().profile || {}).templatesBoardId);
board._id = (Meteor.user().profile || {}).templatesBoardId;
} else {
// Prefetch first non-current board id
board = Boards.find({
@@ -708,6 +718,11 @@ BlazeComponent.extendComponent({
},
(err, data) => {
_id = data;
subManager.subscribe('board', _id, false);
FlowRouter.go('board', {
id: _id,
slug: getSlug(element.title),
});
},
);
}
+13 -6
View File
@@ -18,9 +18,9 @@ template(name="listHeader")
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.count}}
|/#{wipLimit.value})
if showCardsCountForList cards.count
|&nbsp;
span(class="cardCount") {{cardsCount}} {{cardsCountForListIsOne cards.count}}
if showCardsCountForList cards.count
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.count}}
if isMiniScreen
if currentList
if isWatching
@@ -28,7 +28,7 @@ template(name="listHeader")
div.list-header-menu
unless currentUser.isCommentOnly
if canSeeAddCard
a.js-add-card.fa.fa-plus.list-header-plus-icon(title="{{_ 'add-card-to-top-of-list'}}")
a.js-add-card.fa.fa-plus.list-header-plus-top(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
@@ -39,9 +39,9 @@ template(name="listHeader")
div.list-header-menu
unless currentUser.isCommentOnly
//if isBoardAdmin
// a.fa.js-list-star.list-header-plus-icon(class="fa-star{{#unless starred}}-o{{/unless}}")
// a.fa.js-list-star.list-header-plus-top(class="fa-star{{#unless starred}}-o{{/unless}}")
if canSeeAddCard
a.js-add-card.fa.fa-plus.list-header-plus-icon(title="{{_ 'add-card-to-top-of-list'}}")
a.js-add-card.fa.fa-plus.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}")
a.fa.fa-navicon.js-open-list-menu(title="{{_ 'listActionPopup-title'}}")
if currentUser.isBoardAdmin
if isShowDesktopDragHandles
@@ -55,6 +55,13 @@ template(name="editListTitleForm")
a.fa.fa-times-thin.js-close-inlined-form
template(name="listActionPopup")
ul.pop-over-list
li
a.js-add-card.list-header-plus-bottom
i.fa.fa-plus
i.fa.fa-arrow-down
| {{_ 'add-card-to-bottom-of-list'}}
hr
ul.pop-over-list
li
a.js-toggle-watch-list
+9 -1
View File
@@ -101,7 +101,7 @@ BlazeComponent.extendComponent({
this.starred(!this.starred());
},
'click .js-open-list-menu': Popup.open('listAction'),
'click .js-add-card'(event) {
'click .js-add-card.list-header-plus-top'(event) {
const listDom = $(event.target).parents(
`#js-list-${this.currentData()._id}`,
)[0];
@@ -141,6 +141,14 @@ Template.listActionPopup.helpers({
Template.listActionPopup.events({
'click .js-list-subscribe'() {},
'click .js-add-card.list-header-plus-bottom'(event) {
const listDom = $(`#js-list-${this._id}`)[0];
const listComponent = BlazeComponent.getComponentForElement(listDom);
listComponent.openForm({
position: 'bottom',
});
Popup.back();
},
'click .js-set-color-list': Popup.open('setListColor'),
'click .js-select-cards'() {
const cardIds = this.allCards().map(card => card._id);
+2
View File
@@ -1,4 +1,6 @@
template(name="editor")
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
span.copied-tooltip {{_ 'copied'}}
textarea.editor(
dir="auto"
class="{{class}}"
+268 -267
View File
@@ -4,283 +4,284 @@ const specialHandles = [
];
const specialHandleNames = specialHandles.map(m => m.username);
Template.editor.onRendered(() => {
const textareaSelector = 'textarea';
const mentions = [
// User mentions
{
match: /\B@([\w.]*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
callback(
_.union(
currentBoard
.activeMembers()
.map(member => {
const user = Users.findOne(member.userId);
const username = user.username;
const fullName = user.profile && user.profile !== undefined ? user.profile.fullname : "";
return username.includes(term) || fullName.includes(term) ? fullName + "(" + username + ")" : null;
})
.filter(Boolean), [...specialHandleNames])
);
},
template(value) {
return value;
},
replace(username) {
return `@${username} `;
},
index: 1,
},
];
const enableTextarea = function() {
const $textarea = this.$(textareaSelector);
autosize($textarea);
$textarea.escapeableTextComplete(mentions);
};
if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR !== false) {
const isSmall = Utils.isMiniScreen();
const toolbar = isSmall
? [
['view', ['fullscreen']],
['table', ['table']],
['font', ['bold', 'underline']],
//['fontsize', ['fontsize']],
['color', ['color']],
]
: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['fontsize', ['fontsize']],
['fontname', ['fontname']],
['color', ['color']],
['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 :(
['view', ['fullscreen', 'codeview', 'help']],
];
const cleanPastedHTML = function(input) {
const badTags = [
'style',
'script',
'applet',
'embed',
'noframes',
'noscript',
'meta',
'link',
'button',
'form',
].join('|');
const badPatterns = new RegExp(
`(?:${[
`<(${badTags})s*[^>][\\s\\S]*?<\\/\\1>`,
`<(${badTags})[^>]*?\\/>`,
].join('|')})`,
'gi',
);
let output = input;
// remove bad Tags
output = output.replace(badPatterns, '');
// remove attributes ' style="..."'
const badAttributes = new RegExp(
`(?:${[
'on\\S+=([\'"]?).*?\\1',
'href=([\'"]?)javascript:.*?\\2',
'style=([\'"]?).*?\\3',
'target=\\S+',
].join('|')})`,
'gi',
);
output = output.replace(badAttributes, '');
output = output.replace(/(<a )/gi, '$1target=_ '); // always to new target
return output;
};
const editor = '.editor';
const selectors = [
`.js-new-description-form ${editor}`,
`.js-new-comment-form ${editor}`,
`.js-edit-comment ${editor}`,
].join(','); // only new comment and edit comment
const inputs = $(selectors);
if (inputs.length === 0) {
// only enable richereditor to new comment or edit comment no others
enableTextarea();
} else {
const placeholder = inputs.attr('placeholder') || '';
const mSummernotes = [];
const getSummernote = function(input) {
const idx = inputs.index(input);
if (idx > -1) {
return mSummernotes[idx];
}
return undefined;
};
inputs.each(function(idx, input) {
mSummernotes[idx] = $(input).summernote({
placeholder,
callbacks: {
onInit(object) {
const originalInput = this;
$(originalInput).on('submitted', function() {
// when comment is submitted, the original textarea will be set to '', so shall we
if (!this.value) {
const sn = getSummernote(this);
sn && sn.summernote('code', '');
}
});
const jEditor = object && object.editable;
const toolbar = object && object.toolbar;
if (jEditor !== undefined) {
jEditor.escapeableTextComplete(mentions);
}
if (toolbar !== undefined) {
const fBtn = toolbar.find('.btn-fullscreen');
fBtn.on('click', function() {
const $this = $(this),
isActive = $this.hasClass('active');
$('.minicards,#header-quick-access').toggle(!isActive); // mini card is still showing when editor is in fullscreen mode, we hide here manually
});
}
},
onImageUpload(files) {
const $summernote = getSummernote(this);
if (files && files.length > 0) {
const image = files[0];
const currentCard = Utils.getCurrentCard();
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%');
$summernote.summernote('insertNode', img);
};
const processData = function(fileObj) {
Utils.processUploadedAttachment(
currentCard,
fileObj,
attachment => {
if (
attachment &&
attachment._id &&
attachment.isImage()
) {
attachment.one('uploaded', function() {
const maxTry = 3;
const checkItvl = 500;
let retry = 0;
const checkUrl = function() {
// even though uploaded event fired, attachment.url() is still null somehow //TODO
const url = attachment.url();
if (url) {
insertImage(
`${location.protocol}//${location.host}${url}`,
);
} else {
retry++;
if (retry < maxTry) {
setTimeout(checkUrl, checkItvl);
}
BlazeComponent.extendComponent({
onRendered() {
const textareaSelector = 'textarea';
const mentions = [
// User mentions
{
match: /\B@([\w.-]*)$/,
search(term, callback) {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
callback(
_.union(
currentBoard
.activeMembers()
.map(member => {
const user = Users.findOne(member.userId);
const username = user.username;
const fullName = user.profile && user.profile !== undefined && user.profile.fullname ? user.profile.fullname : "";
return username.includes(term) || fullName.includes(term) ? user : null;
})
.filter(Boolean), [...specialHandles])
);
},
template(user) {
if (user.profile && user.profile.fullname) {
return (user.profile.fullname + " (" + user.username + ")");
}
return user.username;
},
replace(user) {
if (user.profile && user.profile.fullname) {
return `@${user.username} (${user.profile.fullname}) `;
}
return `@${user.username} `;
},
index: 1,
},
];
const enableTextarea = function() {
const $textarea = this.$(textareaSelector);
autosize($textarea);
$textarea.escapeableTextComplete(mentions);
};
if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR !== false) {
const isSmall = Utils.isMiniScreen();
const toolbar = isSmall
? [
['view', ['fullscreen']],
['table', ['table']],
['font', ['bold', 'underline']],
//['fontsize', ['fontsize']],
['color', ['color']],
]
: [
['style', ['style']],
['font', ['bold', 'underline', 'clear']],
['fontsize', ['fontsize']],
['fontname', ['fontname']],
['color', ['color']],
['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 :(
['view', ['fullscreen', 'codeview', 'help']],
];
const cleanPastedHTML = function(input) {
const badTags = [
'style',
'script',
'applet',
'embed',
'noframes',
'noscript',
'meta',
'link',
'button',
'form',
].join('|');
const badPatterns = new RegExp(
`(?:${[
`<(${badTags})s*[^>][\\s\\S]*?<\\/\\1>`,
`<(${badTags})[^>]*?\\/>`,
].join('|')})`,
'gi',
);
let output = input;
// remove bad Tags
output = output.replace(badPatterns, '');
// remove attributes ' style="..."'
const badAttributes = new RegExp(
`(?:${[
'on\\S+=([\'"]?).*?\\1',
'href=([\'"]?)javascript:.*?\\2',
'style=([\'"]?).*?\\3',
'target=\\S+',
].join('|')})`,
'gi',
);
output = output.replace(badAttributes, '');
output = output.replace(/(<a )/gi, '$1target=_ '); // always to new target
return output;
};
const editor = '.editor';
const selectors = [
`.js-new-description-form ${editor}`,
`.js-new-comment-form ${editor}`,
`.js-edit-comment ${editor}`,
].join(','); // only new comment and edit comment
const inputs = $(selectors);
if (inputs.length === 0) {
// only enable richereditor to new comment or edit comment no others
enableTextarea();
} else {
const placeholder = inputs.attr('placeholder') || '';
const mSummernotes = [];
const getSummernote = function(input) {
const idx = inputs.index(input);
if (idx > -1) {
return mSummernotes[idx];
}
return undefined;
};
inputs.each(function(idx, input) {
mSummernotes[idx] = $(input).summernote({
placeholder,
callbacks: {
onInit(object) {
const originalInput = this;
$(originalInput).on('submitted', function() {
// when comment is submitted, the original textarea will be set to '', so shall we
if (!this.value) {
const sn = getSummernote(this);
sn && sn.summernote('code', '');
}
});
const jEditor = object && object.editable;
const toolbar = object && object.toolbar;
if (jEditor !== undefined) {
jEditor.escapeableTextComplete(mentions);
}
if (toolbar !== undefined) {
const fBtn = toolbar.find('.btn-fullscreen');
fBtn.on('click', function() {
const $this = $(this),
isActive = $this.hasClass('active');
$('.minicards,#header-quick-access').toggle(!isActive); // mini card is still showing when editor is in fullscreen mode, we hide here manually
});
}
},
onImageUpload(files) {
const $summernote = getSummernote(this);
if (files && files.length > 0) {
const image = files[0];
const currentCard = Utils.getCurrentCard();
const MAX_IMAGE_PIXEL = Utils.MAX_IMAGE_PIXEL;
const COMPRESS_RATIO = Utils.IMAGE_COMPRESS_RATIO;
const processUpload = function(file) {
const uploader = Attachments.insert(
{
file,
meta: Utils.getCommonAttachmentMetaFrom(card),
chunkSize: 'dynamic',
},
false,
);
uploader.on('uploaded', (error, fileRef) => {
if (!error) {
if (fileRef.isImage) {
const img = document.createElement('img');
img.src = fileRef.link();
img.setAttribute('width', '100%');
$summernote.summernote('insertNode', img);
}
}
});
uploader.start();
};
if (MAX_IMAGE_PIXEL) {
const reader = new FileReader();
reader.onload = function(e) {
const dataurl = e && e.target && e.target.result;
if (dataurl !== undefined) {
// need to shrink image
Utils.shrinkImage({
dataurl,
maxSize: MAX_IMAGE_PIXEL,
ratio: COMPRESS_RATIO,
toBlob: true,
callback(blob) {
if (blob !== false) {
blob.name = image.name;
processUpload(blob);
}
};
checkUrl();
},
});
}
},
);
};
if (MAX_IMAGE_PIXEL) {
const reader = new FileReader();
reader.onload = function(e) {
const dataurl = e && e.target && e.target.result;
if (dataurl !== undefined) {
// need to shrink image
Utils.shrinkImage({
dataurl,
maxSize: MAX_IMAGE_PIXEL,
ratio: COMPRESS_RATIO,
toBlob: true,
callback(blob) {
if (blob !== false) {
blob.name = image.name;
processData(blob);
}
},
});
}
};
reader.readAsDataURL(image);
} else {
processData(image);
};
reader.readAsDataURL(image);
} else {
processUpload(image);
}
}
}
},
onPaste(e) {
var clipboardData = e.clipboardData;
var pastedData = clipboardData.getData('Text');
},
onPaste(e) {
var clipboardData = e.clipboardData;
var pastedData = clipboardData.getData('Text');
//if pasted data is an image, exit
if (!pastedData.length) {
e.preventDefault();
return;
}
//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) {
const someNote = getSummernote(object);
// Fix Pasting text into a card is adding a line before and after
// (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');
// == Fix End ==
const original = someNote.summernote('code');
const cleaned = cleanPastedHTML(original); //this is where to call whatever clean function you want. I have mine in a different file, called CleanPastedHTML.
someNote.summernote('code', ''); //clear original
someNote.summernote('pasteHTML', cleaned); //this sets the displayed content editor to the cleaned pasted code.
};
setTimeout(function() {
//this kinda sucks, but if you don't do a setTimeout,
//the function is called before the text is really pasted.
updatePastedText(thisNote);
}, 10);
// clear up unwanted tag info when user pasted in text
const thisNote = this;
const updatePastedText = function(object) {
const someNote = getSummernote(object);
// Fix Pasting text into a card is adding a line before and after
// (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');
// == Fix End ==
const original = someNote.summernote('code');
const cleaned = cleanPastedHTML(original); //this is where to call whatever clean function you want. I have mine in a different file, called CleanPastedHTML.
someNote.summernote('code', ''); //clear original
someNote.summernote('pasteHTML', cleaned); //this sets the displayed content editor to the cleaned pasted code.
};
setTimeout(function() {
//this kinda sucks, but if you don't do a setTimeout,
//the function is called before the text is really pasted.
updatePastedText(thisNote);
}, 10);
},
},
},
dialogsInBody: true,
spellCheck: true,
disableGrammar: false,
disableDragAndDrop: false,
toolbar,
popover: {
image: [
['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
['float', ['floatLeft', 'floatRight', 'floatNone']],
['remove', ['removeMedia']],
],
link: [['link', ['linkDialogShow', 'unlink']]],
table: [
['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
['delete', ['deleteRow', 'deleteCol', 'deleteTable']],
],
air: [
['color', ['color']],
['font', ['bold', 'underline', 'clear']],
],
},
height: 200,
dialogsInBody: true,
spellCheck: true,
disableGrammar: false,
disableDragAndDrop: false,
toolbar,
popover: {
image: [
['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
['float', ['floatLeft', 'floatRight', 'floatNone']],
['remove', ['removeMedia']],
],
link: [['link', ['linkDialogShow', 'unlink']]],
table: [
['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
['delete', ['deleteRow', 'deleteCol', 'deleteTable']],
],
air: [
['color', ['color']],
['font', ['bold', 'underline', 'clear']],
],
},
height: 200,
});
});
});
}
} else {
enableTextarea();
}
} else {
enableTextarea();
},
events() {
return [
{
'click a.fa.fa-copy'(event) {
const $editor = this.$('textarea.editor');
const promise = Utils.copyTextToClipboard($editor[0].value);
const $tooltip = this.$('.copied-tooltip');
Utils.showCopied(promise, $tooltip);
},
}
]
}
});
}).register('editor');
import DOMPurify from 'dompurify';
@@ -339,7 +340,7 @@ Blaze.Template.registerHelper(
}
return member;
}), [...specialHandles]);
const mentionRegex = /\B@([\w.]*)/gi;
const mentionRegex = /\B@([\w.-]*)/gi;
let currentMention;
while ((currentMention = mentionRegex.exec(content)) !== null) {
+7
View File
@@ -0,0 +1,7 @@
.new-comment,
.inlined-form
a.fa.fa-copy
float: right
position: relative
top: 20px
right: 6px
+18
View File
@@ -42,6 +42,24 @@ template(name="globalSearch")
autofocus dir="auto"
)
a.js-new-search.fa.fa-eraser
if debug.get.show
h1 Debug
if debug.get.showSelector
h2 Selector
button.js-copy-debug-selector
= 'Copy'
pre(
id="debug-selector"
)
= sessionData.selector
if debug.get.showProjection
h2 Projection
button.js-copy-debug-projection
= 'Copy'
pre(
id="debug-projection"
)
= sessionData.projection
if searching.get
+spinner
else if hasResults.get
+31
View File
@@ -131,6 +131,9 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
operator_has: TAPi18n.__('operator-has'),
operator_sort: TAPi18n.__('operator-sort'),
operator_limit: TAPi18n.__('operator-limit'),
operator_debug: TAPi18n.__('operator-debug'),
operator_org: TAPi18n.__('operator-org'),
operator_team: TAPi18n.__('operator-team'),
predicate_overdue: TAPi18n.__('predicate-overdue'),
predicate_archived: TAPi18n.__('predicate-archived'),
predicate_all: TAPi18n.__('predicate-all'),
@@ -151,6 +154,8 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
predicate_end: TAPi18n.__('predicate-end'),
predicate_assignee: TAPi18n.__('predicate-assignee'),
predicate_member: TAPi18n.__('predicate-member'),
predicate_selector: TAPi18n.__('predicate-selector'),
predicate_projection: TAPi18n.__('predicate-projection'),
};
let text = '';
@@ -169,6 +174,8 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
['\n- ', 'globalSearch-instructions-operator-member'],
['\n- ', 'globalSearch-instructions-operator-assignee'],
['\n- ', 'globalSearch-instructions-operator-creator'],
['\n- ', 'globalSearch-instructions-operator-org'],
['\n- ', 'globalSearch-instructions-operator-team'],
['\n- ', 'globalSearch-instructions-operator-due'],
['\n- ', 'globalSearch-instructions-operator-created'],
['\n- ', 'globalSearch-instructions-operator-modified'],
@@ -222,6 +229,30 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
);
document.getElementById('global-search-input').focus();
},
'click .js-copy-debug-selector'(evt) {
/* Get the text field */
const selector = document.getElementById("debug-selector");
try {
navigator.clipboard.writeText(selector.textContent);
alert("Selector copied to clipboard");
} catch(err) {
alert("Error copying text: " + err);
}
},
'click .js-copy-debug-projection'(evt) {
/* Get the text field */
const projection = document.getElementById("debug-projection");
try {
navigator.clipboard.writeText(projection.textContent);
alert("Projection copied to clipboard");
} catch(err) {
alert("Error copying text: " + err);
}
},
'click .js-board-title'(evt) {
evt.preventDefault();
const input = document.getElementById('global-search-input');
+3 -3
View File
@@ -38,7 +38,8 @@ template(name="header")
unless currentSetting.customTopLeftCornerLogoLinkUrl
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="{{currentSetting.productName}}" title="{{currentSetting.productName}}")
div#headerIsSettingDatabaseCallDone
img(src="{{pathFor '/logo-header.png'}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}")
span.allBoards
a(href="{{pathFor 'home'}}")
span.fa.fa-home
@@ -94,5 +95,4 @@ template(name="offlineWarning")
i.fa.fa-warning
| {{_ 'app-is-offline'}}
a.app-try-reconnect
{{_ 'app-try-reconnect'}}
a.app-try-reconnect {{_ 'app-try-reconnect'}}
+17
View File
@@ -1,7 +1,24 @@
Meteor.subscribe('user-admin');
Meteor.subscribe('boards');
Meteor.subscribe('setting');
Meteor.subscribe('announcements');
Template.header.onCreated(function(){
const templateInstance = this;
templateInstance.currentSetting = new ReactiveVar();
templateInstance.isLoading = new ReactiveVar(false);
Meteor.subscribe('setting', {
onReady() {
templateInstance.currentSetting.set(Settings.findOne());
let currSetting = templateInstance.currentSetting.curValue;
if(currSetting && currSetting !== undefined && currSetting.customLoginLogoImageUrl !== undefined && document.getElementById("headerIsSettingDatabaseCallDone") != null)
document.getElementById("headerIsSettingDatabaseCallDone").style.display = 'none';
else if(document.getElementById("headerIsSettingDatabaseCallDone") != null)
document.getElementById("headerIsSettingDatabaseCallDone").style.display = 'block';
return this.stop();
},
});
});
Template.header.helpers({
wrappedHeader() {
return !Session.get('currentBoard');
+4 -1
View File
@@ -99,7 +99,7 @@
height: 28px
font-size: 12px
display: flex
z-index: 21
z-index: 1000
padding: 10px 0px
.allBoards
@@ -250,3 +250,6 @@
p
margin: 7px
padding: 0
#headerIsSettingDatabaseCallDone
display: none;
+8 -1
View File
@@ -1,6 +1,6 @@
head
title
meta(name="viewport" content="maximum-scale=1.0,width=device-width,initial-scale=1.0,user-scalable=0")
meta(name="viewport" content="width=device-width, initial-scale=1")
meta(http-equiv="X-UA-Compatible" content="IE=edge")
//- XXX We should use pathFor in the following `href` to support the case
where the application is deployed with a path prefix, but it seems to be
@@ -48,6 +48,13 @@ template(name="userFormsLayout")
+Template.dynamic(template=content)
if currentSetting.displayAuthenticationMethod
+connectionMethod(authenticationMethod=currentSetting.defaultAuthenticationMethod)
if isLegalNoticeLinkExist
div#legalNoticeDiv
span#legalNoticeSpan {{_ 'acceptance_of_our_legalNotice'}}
a#legalNoticeAtLink.at-link(href="{{currentSetting.legalNotice}}", target="_blank", rel="noopener noreferrer")
| {{_ 'legalNotice'}}
if getLegalNoticeWithWritTraduction
div
div.at-form-lang
select.select-lang.js-userform-set-language
each languages
+46
View File
@@ -53,6 +53,19 @@ Template.userFormsLayout.onCreated(function() {
$('.at-pwd-form').hide();
}
});
Meteor.call('isDisableRegistration', (_, result) => {
if (result) {
$('.at-signup-link').hide();
}
});
Meteor.call('isDisableForgotPassword', (_, result) => {
if (result) {
$('.at-pwd-link').hide();
}
});
});
Template.userFormsLayout.onRendered(() => {
@@ -77,6 +90,27 @@ Template.userFormsLayout.helpers({
// return isSettingDatabaseFctCallDone;
// },
isLegalNoticeLinkExist(){
const currSet = Template.instance().currentSetting.get();
if(currSet && currSet !== undefined && currSet != null){
return currSet.legalNotice !== undefined && currSet.legalNotice.trim() != "";
}
else
return false;
},
getLegalNoticeWithWritTraduction(){
let spanLegalNoticeElt = $("#legalNoticeSpan");
if(spanLegalNoticeElt != null && spanLegalNoticeElt != undefined){
spanLegalNoticeElt.html(TAPi18n.__('acceptance_of_our_legalNotice', {}, T9n.getLanguage() || 'en'));
}
let atLinkLegalNoticeElt = $("#legalNoticeAtLink");
if(atLinkLegalNoticeElt != null && atLinkLegalNoticeElt != undefined){
atLinkLegalNoticeElt.html(TAPi18n.__('legalNotice', {}, T9n.getLanguage() || 'en'));
}
return true;
},
isLoading() {
return Template.instance().isLoading.get();
},
@@ -98,12 +132,18 @@ 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 === 'cs-CZ') {
name = 'čeština (Česká republika)';
} else if (lang.name === 'de-CH') {
name = 'Deutsch (Schweiz)';
} else if (lang.name === 'de-AT') {
name = 'Deutsch (Österreich)';
} else if (lang.name === 'en-BR') {
name = 'English (Brazil)';
} else if (lang.name === 'en-DE') {
name = 'English (Germany)';
} else if (lang.name === 'et-EE') {
name = 'eesti keel (Eesti)';
} else if (lang.name === 'fa-IR') {
// fa-IR = Persian (Iran)
name = 'فارسی/پارسی (ایران‎)';
@@ -159,10 +199,16 @@ Template.userFormsLayout.helpers({
name = 'español de Perú';
} else if (lang.name === 'Español de Puerto Rico') {
name = 'español de Puerto Rico';
} else if (lang.name === 'gl-ES') {
name = 'Galego (España)';
} else if (lang.name === 'oc') {
name = 'Occitan';
} else if (lang.name === 'ru-UA') {
name = 'Русский (Украина)';
} else if (lang.name === 'st') {
name = 'Sãotomense';
} else if (lang.name === 'uk-UA') {
name = 'українська (Україна)';
} else if (lang.name === '繁体中文(台湾)') {
// Traditional Chinese (Taiwan)
name = '繁體中文(台灣)';
+5
View File
@@ -545,3 +545,8 @@ a
#isSettingDatabaseCallDone
display: none;
.at-link
color: #17683a;
text-decoration: underline;
text-decoration-color: #17683a;
+1 -1
View File
@@ -112,7 +112,7 @@
.trigger-item
overflow:auto
padding:10px
height:40px
height:100px
margin-bottom:5px
border-radius: 3px
position: relative
+65 -4
View File
@@ -1,5 +1,5 @@
template(name="adminReports")
.setting-content
.setting-content.admin-reports-content
unless currentUser.isAdmin
| {{_ 'error-notAuthorized'}}
else
@@ -26,6 +26,16 @@ template(name="adminReports")
i.fa.fa-magic
| {{_ 'rulesReportTitle'}}
li
a.js-report-boards(data-id="report-boards")
i.fa.fa-magic
| {{_ 'boardsReportTitle'}}
li
a.js-report-cards(data-id="report-cards")
i.fa.fa-magic
| {{_ 'cardsReportTitle'}}
.main-body
if loading.get
+spinner
@@ -37,6 +47,10 @@ template(name="adminReports")
+orphanedFilesReport
else if showRulesReport.get
+rulesReport
else if showBoardsReport.get
+boardsReport
else if showCardsReport.get
+cardsReport
template(name="brokenCardsReport")
@@ -57,7 +71,7 @@ template(name="rulesReport")
th actionType
th activityType
each rule in rows
each rule in results
tr
td {{ rule.title }}
td {{ rule.boardTitle }}
@@ -78,7 +92,7 @@ template(name="filesReport")
th MD5 Sum
th ID
each att in attachmentFiles
each att in results
tr
td {{ att.filename }}
td.right {{fileSize att.length }}
@@ -100,7 +114,7 @@ template(name="orphanedFilesReport")
th MD5 Sum
th ID
each att in attachmentFiles
each att in results
tr
td {{ att.filename }}
td.right {{fileSize att.length }}
@@ -109,3 +123,50 @@ template(name="orphanedFilesReport")
td {{ att._id.toHexString }}
else
div {{_ 'no-results' }}
template(name="cardsReport")
h1 {{_ 'cardsReportTitle'}}
if resultsCount
table.table
tr
th Card Title
th Board
th Swimlane
th List
th Members
th Assignees
each card in results
tr
td {{abbreviate card.title }}
td {{abbreviate card.board.title }}
td {{abbreviate card.swimlane.title }}
td {{abbreviate card.list.title }}
td {{userNames card.members }}
td {{userNames card.assignees }}
else
div {{_ 'no-results' }}
template(name="boardsReport")
h1 {{_ 'boardsReportTitle'}}
if resultsCount
table.table
tr
th Title
th Id
th Permission
th Archived?
th Members
th Organizations
th Teams
each board in results
tr
td {{abbreviate board.title }}
td {{abbreviate board._id }}
td {{ board.permission }}
td
= yesOrNo(board.archived)
td {{userNames board.members }}
else
div {{_ 'no-results' }}
+97 -46
View File
@@ -1,6 +1,8 @@
import { AttachmentStorage } from '/models/attachments';
import { CardSearchPagedComponent } from '/client/lib/cardSearch';
import SessionData from '/models/usersessiondata';
import { QueryParams } from '/config/query-classes';
import { OPERATOR_LIMIT } from '/config/search-const';
BlazeComponent.extendComponent({
subscription: null,
@@ -8,10 +10,14 @@ BlazeComponent.extendComponent({
showBrokenCardsReport: new ReactiveVar(false),
showOrphanedFilesReport: new ReactiveVar(false),
showRulesReport: new ReactiveVar(false),
showCardsReport: new ReactiveVar(false),
showBoardsReport: new ReactiveVar(false),
sessionId: null,
onCreated() {
this.error = new ReactiveVar('');
this.loading = new ReactiveVar(false);
this.sessionId = SessionData.getSessionId();
},
events() {
@@ -21,6 +27,8 @@ BlazeComponent.extendComponent({
'click a.js-report-files': this.switchMenu,
'click a.js-report-orphaned-files': this.switchMenu,
'click a.js-report-rules': this.switchMenu,
'click a.js-report-cards': this.switchMenu,
'click a.js-report-boards': this.switchMenu,
},
];
},
@@ -32,6 +40,9 @@ BlazeComponent.extendComponent({
this.showFilesReport.set(false);
this.showBrokenCardsReport.set(false);
this.showOrphanedFilesReport.set(false);
this.showRulesReport.set(false)
this.showBoardsReport.set(false);
this.showCardsReport.set(false);
if (this.subscription) {
this.subscription.stop();
}
@@ -64,68 +75,79 @@ BlazeComponent.extendComponent({
this.showRulesReport.set(true);
this.loading.set(false);
});
} else if ('report-boards' === targetID) {
this.subscription = Meteor.subscribe('boardsReport', () => {
this.showBoardsReport.set(true);
this.loading.set(false);
});
} else if ('report-cards' === targetID) {
const qp = new QueryParams();
qp.addPredicate(OPERATOR_LIMIT, 300);
this.subscription = Meteor.subscribe(
'globalSearch',
this.sessionId,
qp.getParams(),
qp.text,
() => {
this.showCardsReport.set(true);
this.loading.set(false);
},
);
}
}
},
}).register('adminReports');
Template.filesReport.helpers({
attachmentFiles() {
class AdminReport extends BlazeComponent {
collection;
results() {
// eslint-disable-next-line no-console
// console.log('attachments:', AttachmentStorage.find());
// console.log('attachments.count:', AttachmentStorage.find().count());
return AttachmentStorage.find();
},
return this.collection.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;
},
yesOrNo(value) {
if (value) {
return TAPi18n.__('yes');
} else {
return TAPi18n.__('no');
}
}
resultsCount() {
return AttachmentStorage.find().count();
},
return this.collection.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();
},
abbreviate(text) {
if (text.length > 30) {
return `${text.substr(0, 29)}...`;
}
return text;
}
}
resultsCount() {
return AttachmentStorage.find().count();
},
(class extends AdminReport {
collection = AttachmentStorage;
}.register('filesReport'));
fileSize(size) {
return Math.round(size / 1024);
},
});
(class extends AdminReport {
collection = AttachmentStorage;
}.register('orphanedFilesReport'));
Template.rulesReport.helpers({
rows() {
(class extends AdminReport {
collection = Rules;
results() {
const rules = [];
Rules.find().forEach(rule => {
@@ -139,14 +161,43 @@ Template.rulesReport.helpers({
});
});
// eslint-disable-next-line no-console
console.log('rows:', rules);
return rules;
},
}
}.register('rulesReport'));
resultsCount() {
return Rules.find().count();
},
});
(class extends AdminReport {
collection = Boards;
userNames(members) {
let text = '';
members.forEach(member => {
const user = Users.findOne(member.userId);
text += text ? ', ' : '';
if (user) {
text += user.username;
} else {
text += member.userId
}
});
return text;
}
}.register('boardsReport'));
(class extends AdminReport {
collection = Cards;
userNames(userIds) {
let text = '';
userIds.forEach(userId => {
const user = Users.findOne(userId);
text += text ? ', ' : '';
text += user.username;
});
return text;
}
}.register('cardsReport'));
class BrokenCardsComponent extends CardSearchPagedComponent {
onCreated() {
@@ -0,0 +1,3 @@
.admin-reports-content
height: auto !important
+46 -45
View File
@@ -65,48 +65,49 @@ template(name='statistics')
tr
th {{_ 'OS_Cpus'}}
td {{statistics.os.cpus.length}}
tr
th {{_ 'Node_heap_total_heap_size'}}
td {{bytesToSize statistics.nodeHeapStats.totalHeapSize}}
tr
th {{_ 'Node_heap_total_heap_size_executable'}}
td {{bytesToSize statistics.nodeHeapStats.totalHeapSizeExecutable}}
tr
th {{_ 'Node_heap_total_physical_size'}}
td {{bytesToSize statistics.nodeHeapStats.totalPhysicalSize}}
tr
th {{_ 'Node_heap_total_available_size'}}
td {{bytesToSize statistics.nodeHeapStats.totalAvailableSize}}
tr
th {{_ 'Node_heap_used_heap_size'}}
td {{bytesToSize statistics.nodeHeapStats.usedHeapSize}}
tr
th {{_ 'Node_heap_heap_size_limit'}}
td {{bytesToSize statistics.nodeHeapStats.heapSizeLimit}}
tr
th {{_ 'Node_heap_malloced_memory'}}
td {{bytesToSize statistics.nodeHeapStats.mallocedMemory}}
tr
th {{_ 'Node_heap_peak_malloced_memory'}}
td {{bytesToSize statistics.nodeHeapStats.peakMallocedMemory}}
tr
th {{_ 'Node_heap_does_zap_garbage'}}
td {{statistics.nodeHeapStats.doesZapGarbage}}
tr
th {{_ 'Node_heap_number_of_native_contexts'}}
td {{statistics.nodeHeapStats.numberOfNativeContexts}}
tr
th {{_ 'Node_heap_number_of_detached_contexts'}}
td {{statistics.nodeHeapStats.numberOfDetachedContexts}}
tr
th {{_ 'Node_memory_usage_rss'}}
td {{bytesToSize statistics.nodeMemoryUsage.rss}}
tr
th {{_ 'Node_memory_usage_heap_total'}}
td {{bytesToSize statistics.nodeMemoryUsage.heapTotal}}
tr
th {{_ 'Node_memory_usage_heap_used'}}
td {{bytesToSize statistics.nodeMemoryUsage.heapUsed}}
tr
th {{_ 'Node_memory_usage_external'}}
td {{bytesToSize statistics.nodeMemoryUsage.external}}
unless isSandstorm
tr
th {{_ 'Node_heap_total_heap_size'}}
td {{bytesToSize statistics.nodeHeapStats.totalHeapSize}}
tr
th {{_ 'Node_heap_total_heap_size_executable'}}
td {{bytesToSize statistics.nodeHeapStats.totalHeapSizeExecutable}}
tr
th {{_ 'Node_heap_total_physical_size'}}
td {{bytesToSize statistics.nodeHeapStats.totalPhysicalSize}}
tr
th {{_ 'Node_heap_total_available_size'}}
td {{bytesToSize statistics.nodeHeapStats.totalAvailableSize}}
tr
th {{_ 'Node_heap_used_heap_size'}}
td {{bytesToSize statistics.nodeHeapStats.usedHeapSize}}
tr
th {{_ 'Node_heap_heap_size_limit'}}
td {{bytesToSize statistics.nodeHeapStats.heapSizeLimit}}
tr
th {{_ 'Node_heap_malloced_memory'}}
td {{bytesToSize statistics.nodeHeapStats.mallocedMemory}}
tr
th {{_ 'Node_heap_peak_malloced_memory'}}
td {{bytesToSize statistics.nodeHeapStats.peakMallocedMemory}}
tr
th {{_ 'Node_heap_does_zap_garbage'}}
td {{statistics.nodeHeapStats.doesZapGarbage}}
tr
th {{_ 'Node_heap_number_of_native_contexts'}}
td {{statistics.nodeHeapStats.numberOfNativeContexts}}
tr
th {{_ 'Node_heap_number_of_detached_contexts'}}
td {{statistics.nodeHeapStats.numberOfDetachedContexts}}
tr
th {{_ 'Node_memory_usage_rss'}}
td {{bytesToSize statistics.nodeMemoryUsage.rss}}
tr
th {{_ 'Node_memory_usage_heap_total'}}
td {{bytesToSize statistics.nodeMemoryUsage.heapTotal}}
tr
th {{_ 'Node_memory_usage_heap_used'}}
td {{bytesToSize statistics.nodeMemoryUsage.heapUsed}}
tr
th {{_ 'Node_memory_usage_external'}}
td {{bytesToSize statistics.nodeMemoryUsage.external}}
+32 -32
View File
@@ -148,30 +148,30 @@ template(name="newUserRow")
template(name="orgRow")
tr
if orgData.orgIsActive
td <s>{{ orgData.orgDisplayName }}</s>
else
td {{ orgData.orgDisplayName }}
if orgData.orgIsActive
td <s>{{ orgData.orgDesc }}</s>
else
td <s>{{ orgData.orgDisplayName }}</s>
if orgData.orgIsActive
td {{ orgData.orgDesc }}
if orgData.orgIsActive
td <s>{{ orgData.orgShortName }}</s>
else
td <s>{{ orgData.orgDesc }}</s>
if orgData.orgIsActive
td {{ orgData.orgShortName }}
if orgData.orgIsActive
td <s>{{ orgData.orgWebsite }}</s>
else
td <s>{{ orgData.orgShortName }}</s>
if orgData.orgIsActive
td {{ orgData.orgWebsite }}
if orgData.orgIsActive
td <s>{{ moment orgData.createdAt 'LLL' }}</s>
else
td <s>{{ orgData.orgWebsite }}</s>
if orgData.orgIsActive
td {{ moment orgData.createdAt 'LLL' }}
else
td <s>{{ moment orgData.createdAt 'LLL' }}</s>
td
if orgData.orgIsActive
| {{_ 'no'}}
else
| {{_ 'yes'}}
else
| {{_ 'no'}}
td
a.edit-org
i.fa.fa-edit
@@ -182,30 +182,30 @@ template(name="orgRow")
template(name="teamRow")
tr
if teamData.teamIsActive
td <s>{{ teamData.teamDisplayName }}</s>
else
td {{ teamData.teamDisplayName }}
if teamData.teamIsActive
td <s>{{ teamData.teamDesc }}</s>
else
td <s>{{ teamData.teamDisplayName }}</s>
if teamData.teamIsActive
td {{ teamData.teamDesc }}
if teamData.teamIsActive
td <s>{{ teamData.teamShortName }}</s>
else
td <s>{{ teamData.teamDesc }}</s>
if teamData.teamIsActive
td {{ teamData.teamShortName }}
if teamData.teamIsActive
td <s>{{ teamData.teamWebsite }}</s>
else
td <s>{{ teamData.teamShortName }}</s>
if teamData.teamIsActive
td {{ teamData.teamWebsite }}
if teamData.teamIsActive
td <s>{{ moment teamData.createdAt 'LLL' }}</s>
else
td <s>{{ teamData.teamWebsite }}</s>
if teamData.teamIsActive
td {{ moment teamData.createdAt 'LLL' }}
else
td <s>{{ moment teamData.createdAt 'LLL' }}</s>
td
if teamData.teamIsActive
| {{_ 'no'}}
else
| {{_ 'yes'}}
else
| {{_ 'no'}}
td
a.edit-team
i.fa.fa-edit
@@ -313,8 +313,8 @@ template(name="editOrgPopup")
label
| {{_ 'active'}}
select.select-active.js-org-isactive
option(value="false") {{_ 'yes'}}
option(value="true" selected="{{org.orgIsActive}}") {{_ 'no'}}
option(value="false") {{_ 'no'}}
option(value="true" selected="{{org.orgIsActive}}") {{_ 'yes'}}
hr
div.buttonsContainer
input.primary.wide(type="submit" value="{{_ 'save'}}")
@@ -339,8 +339,8 @@ template(name="editTeamPopup")
label
| {{_ 'active'}}
select.select-active.js-team-isactive
option(value="false") {{_ 'yes'}}
option(value="true" selected="{{team.teamIsActive}}") {{_ 'no'}}
option(value="false") {{_ 'no'}}
option(value="true" selected="{{team.teamIsActive}}") {{_ 'yes'}}
hr
div.buttonsContainer
input.primary.wide(type="submit" value="{{_ 'save'}}")
@@ -442,8 +442,8 @@ template(name="newOrgPopup")
label
| {{_ 'active'}}
select.select-active.js-org-isactive
option(value="false" selected="selected") {{_ 'yes'}}
option(value="true") {{_ 'no'}}
option(value="false" selected="selected") {{_ 'no'}}
option(value="true") {{_ 'yes'}}
hr
div.buttonsContainer
input.primary.wide(type="submit" value="{{_ 'save'}}")
@@ -466,8 +466,8 @@ template(name="newTeamPopup")
label
| {{_ 'active'}}
select.select-active.js-team-isactive
option(value="false" selected="selected") {{_ 'yes'}}
option(value="true") {{_ 'no'}}
option(value="false" selected="selected") {{_ 'no'}}
option(value="true") {{_ 'yes'}}
hr
div.buttonsContainer
input.primary.wide(type="submit" value="{{_ 'save'}}")
+8 -5
View File
@@ -144,6 +144,7 @@ BlazeComponent.extendComponent({
},
orgList() {
const orgs = Org.find(this.findOrgsOptions.get(), {
sort: { orgDisplayName: 1 },
fields: { _id: true },
});
this.numberOrgs.set(orgs.count(false));
@@ -151,6 +152,7 @@ BlazeComponent.extendComponent({
},
teamList() {
const teams = Team.find(this.findTeamsOptions.get(), {
sort: { teamDisplayName: 1 },
fields: { _id: true },
});
this.numberTeams.set(teams.count(false));
@@ -158,6 +160,7 @@ BlazeComponent.extendComponent({
},
peopleList() {
const users = Users.find(this.findUsersOptions.get(), {
sort: { username: 1 },
fields: { _id: true },
});
this.numberPeople.set(users.count(false));
@@ -251,10 +254,10 @@ Template.editUserPopup.helpers({
return Template.instance().authenticationMethods.get();
},
orgsDatas() {
return Org.find({}, {sort: { createdAt: -1 }});
return Org.find({}, {sort: { orgDisplayName: 1 }});
},
teamsDatas() {
return Team.find({}, {sort: { createdAt: -1 }});
return Team.find({}, {sort: { teamDisplayName: 1 }});
},
isSelected(match) {
const userId = Template.instance().data.userId;
@@ -324,10 +327,10 @@ Template.newUserPopup.helpers({
return Template.instance().authenticationMethods.get();
},
orgsDatas() {
return Org.find({}, {sort: { createdAt: -1 }});
return Org.find({}, {sort: { orgDisplayName: 1 }});
},
teamsDatas() {
return Team.find({}, {sort: { createdAt: -1 }});
return Team.find({}, {sort: { teamDisplayName: 1 }});
},
isSelected(match) {
const userId = Template.instance().data.userId;
@@ -417,7 +420,7 @@ BlazeComponent.extendComponent({
BlazeComponent.extendComponent({
onCreated() {},
teamsDatas() {
return Team.find({}, {sort: { createdAt: -1 }});
return Team.find({}, {sort: { teamDisplayName: 1 }});
},
events() {
return [
@@ -63,6 +63,11 @@ template(name="webhookSettings")
template(name="general")
ul#registration-setting.setting-detail
li
a.flex.js-toggle-forgot-password
.materialCheckBox(class="{{#if currentSetting.disableForgotPassword}}is-checked{{/if}}")
span {{_ 'disable-forgot-password'}}
li
a.flex.js-toggle-registration
.materialCheckBox(class="{{#if currentSetting.disableRegistration}}is-checked{{/if}}")
@@ -188,6 +193,10 @@ template(name='layoutSettings')
.title {{_ 'can-invite-if-same-mailDomainName'}}
.form-group
input.wekan-form-control#mailDomainNamevalue(type="text", placeholder="" value="{{currentSetting.mailDomainName}}")
li.layout-form
.title {{_ 'custom-legal-notice-link-url'}}
.form-group
input.wekan-form-control#legalNoticevalue(type="text", placeholder="" value="{{currentSetting.legalNotice}}")
li.layout-form
.title {{_ 'display-authentication-method'}}
.form-group.flex
+17
View File
@@ -4,6 +4,7 @@ BlazeComponent.extendComponent({
onCreated() {
this.error = new ReactiveVar('');
this.loading = new ReactiveVar(false);
this.forgotPasswordSetting = new ReactiveVar(true);
this.generalSetting = new ReactiveVar(true);
this.emailSetting = new ReactiveVar(false);
this.accountSetting = new ReactiveVar(false);
@@ -56,6 +57,14 @@ BlazeComponent.extendComponent({
},
);
},
toggleForgotPassword() {
this.setLoading(true);
const forgotPasswordClosed = this.currentSetting().disableForgotPassword;
Settings.update(Settings.findOne()._id, {
$set: { disableForgotPassword: !forgotPasswordClosed },
});
this.setLoading(false);
},
toggleRegistration() {
this.setLoading(true);
const registrationClosed = this.currentSetting().disableRegistration;
@@ -84,6 +93,7 @@ BlazeComponent.extendComponent({
$('.side-menu li.active').removeClass('active');
target.parent().addClass('active');
const targetID = target.data('id');
this.forgotPasswordSetting.set('forgot-password-setting' === targetID);
this.generalSetting.set('registration-setting' === targetID);
this.emailSetting.set('email-setting' === targetID);
this.accountSetting.set('account-setting' === targetID);
@@ -210,6 +220,11 @@ BlazeComponent.extendComponent({
)
.val()
.trim();
const legalNotice = $(
'#legalNoticevalue',
)
.val()
.trim();
const hideLogoChange = $('input[name=hideLogo]:checked').val() === 'true';
const displayAuthenticationMethod =
$('input[name=displayAuthenticationMethod]:checked').val() === 'true';
@@ -234,6 +249,7 @@ BlazeComponent.extendComponent({
spinnerName,
oidcBtnText,
mailDomainName,
legalNotice,
},
});
} catch (e) {
@@ -261,6 +277,7 @@ BlazeComponent.extendComponent({
events() {
return [
{
'click a.js-toggle-forgot-password': this.toggleForgotPassword,
'click a.js-toggle-registration': this.toggleRegistration,
'click a.js-toggle-tls': this.toggleTLS,
'click a.js-setting-menu': this.switchMenu,
@@ -88,6 +88,8 @@
&.is-checked
background #fff
input[type=radio]
margin: 4px
.option
@extends .flex
+6
View File
@@ -203,6 +203,12 @@ template(name="boardCardSettingsPopup")
span
i.fa.fa-sort
| {{_ 'card-sorting-by-number'}}
div.check-div
a.flex.js-field-has-card-show-lists(class="{{#if allowsShowLists}}is-checked{{/if}}")
.materialCheckBox(class="{{#if allowsShowLists}}is-checked{{/if}}")
span
i.fa.fa-list
| {{_ 'card-show-lists'}}
div.check-div
a.flex.js-field-has-labels(class="{{#if allowsLabels}}is-checked{{/if}}")
.materialCheckBox(class="{{#if allowsLabels}}is-checked{{/if}}")
+22 -3
View File
@@ -827,6 +827,10 @@ BlazeComponent.extendComponent({
return this.currentBoard.allowsCardSortingByNumber;
},
allowsShowLists() {
return this.currentBoard.allowsShowLists;
},
allowsLabels() {
return this.currentBoard.allowsLabels;
},
@@ -1061,6 +1065,22 @@ BlazeComponent.extendComponent({
this.currentBoard.allowsCardSortingByNumber,
);
},
'click .js-field-has-card-show-lists'(evt) {
evt.preventDefault();
this.currentBoard.allowsShowLists = !this.currentBoard
.allowsShowLists;
this.currentBoard.setAllowsShowLists(
this.currentBoard.allowsShowLists,
);
$(`.js-field-has-card-show-lists ${MCB}`).toggleClass(
CKCLS,
this.currentBoard.allowsShowLists,
);
$('.js-field-has-card-show-lists').toggleClass(
CKCLS,
this.currentBoard.allowsShowLists,
);
},
'click .js-field-has-labels'(evt) {
evt.preventDefault();
this.currentBoard.allowsLabels = !this.currentBoard.allowsLabels;
@@ -1325,8 +1345,7 @@ BlazeComponent.extendComponent({
Template.addBoardOrgPopup.helpers({
orgsDatas() {
// return Org.find({}, {sort: { createdAt: -1 }});
let orgs = Org.find({}, {sort: { createdAt: -1 }});
let orgs = Org.find({}, {sort: { orgDisplayName: 1 }});
return orgs;
},
});
@@ -1499,7 +1518,7 @@ BlazeComponent.extendComponent({
Template.addBoardTeamPopup.helpers({
teamsDatas() {
let teams = Team.find({}, {sort: { createdAt: -1 }});
let teams = Team.find({}, {sort: { teamDisplayName: 1 }});
return teams;
},
});
+2 -2
View File
@@ -1,4 +1,4 @@
archivedRequested = false;
//archivedRequested = false;
const subManager = new SubsManager();
BlazeComponent.extendComponent({
@@ -13,7 +13,7 @@ BlazeComponent.extendComponent({
const currentBoardId = Session.get('currentBoard');
if (!currentBoardId) return;
const handle = subManager.subscribe('board', currentBoardId, true);
archivedRequested = true;
//archivedRequested = true;
Tracker.nonreactive(() => {
Tracker.autorun(() => {
this.isArchiveReady.set(handle.ready());
+2 -2
View File
@@ -99,14 +99,14 @@ BlazeComponent.extendComponent({
}).register('filterSidebar');
function mutateSelectedCards(mutationName, ...args) {
Cards.find(MultiSelection.getMongoSelector()).forEach(card => {
Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).forEach(card => {
card[mutationName](...args);
});
}
BlazeComponent.extendComponent({
mapSelection(kind, _id) {
return Cards.find(MultiSelection.getMongoSelector()).map(card => {
return Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).map(card => {
const methodName = kind === 'label' ? 'hasLabel' : 'isAssigned';
return card[methodName](_id);
});
@@ -53,6 +53,7 @@ template(name="addListForm")
autocomplete="off" autofocus)
.edit-controls.clearfix
button.primary.confirm(type="submit") {{_ 'save'}}
.fa.fa-times-thin.js-close-inlined-form
unless currentBoard.isTemplatesBoard
unless currentBoard.isTemplateBoard
span.quiet
+7 -5
View File
@@ -54,13 +54,15 @@ function initSortable(boardComponent, $listsDom) {
};
$listsDom.sortable({
connectWith: '.board-canvas',
tolerance: 'pointer',
helper: 'clone',
items: '.js-list:not(.js-list-composer)',
placeholder: 'list placeholder',
placeholder: 'js-list placeholder',
distance: 7,
start(evt, ui) {
ui.placeholder.height(ui.helper.height());
ui.placeholder.width(ui.helper.width());
EscapeActions.executeUpTo('popup-close');
boardComponent.setIsDragging(true);
},
@@ -148,8 +150,8 @@ BlazeComponent.extendComponent({
},
visible(list) {
if (list.archived) {
// Show archived list only when filter archive is on or archive is selected
if (!(Filter.archive.isSelected() || archivedRequested)) {
// Show archived list only when filter archive is on
if (!Filter.archive.isSelected()) {
return false;
}
}
@@ -280,8 +282,8 @@ BlazeComponent.extendComponent({
},
visible(list) {
if (list.archived) {
// Show archived list only when filter archive is on or archive is selected
if (!(Filter.archive.isSelected() || archivedRequested)) {
// Show archived list only when filter archive is on
if (!Filter.archive.isSelected()) {
return false;
}
}
@@ -36,6 +36,11 @@
// Minimize swimlanes end https://www.w3schools.com/howto/howto_js_accordion.asp
*/
@media screen and (min-width: 801px)
.swimlane.ui-sortable
// swimlane must have max width, otherwise lists are not sortable if there are too much lists and the swimlane "scrollable"
width: max-content
[class=swimlane]
position: sticky
left: 0
+2 -2
View File
@@ -85,7 +85,7 @@ template(name="changeAvatarPopup")
each uploadedAvatars
li: a.js-select-avatar
.member
img.avatar.avatar-image(src="{{url avatarUrlOptions}}")
img.avatar.avatar-image(src="{{link}}?auth=false&brokenIsFine=true")
| {{_ 'uploaded-avatar'}}
if isSelected
i.fa.fa-check
@@ -93,7 +93,7 @@ template(name="changeAvatarPopup")
unless isSelected
a.js-delete-avatar {{_ 'delete'}}
| -
= original.name
= name
li: a.js-select-initials
.member
+userAvatarInitials(userId=currentUser._id)
+24 -32
View File
@@ -3,6 +3,7 @@ import Avatars from '/models/avatars';
import Users from '/models/users';
import Org from '/models/org';
import Team from '/models/team';
import { formatFleURL } from 'meteor/ostrio:files/lib';
Template.userAvatar.helpers({
userData() {
@@ -181,21 +182,14 @@ BlazeComponent.extendComponent({
Meteor.subscribe('my-avatars');
},
avatarUrlOptions() {
return {
auth: false,
brokenIsFine: true,
};
},
uploadedAvatars() {
return Avatars.find({ userId: Meteor.userId() });
return Avatars.find({ userId: Meteor.userId() }).each();
},
isSelected() {
const userProfile = Meteor.user().profile;
const avatarUrl = userProfile && userProfile.avatarUrl;
const currentAvatarUrl = this.currentData().url(this.avatarUrlOptions());
const currentAvatarUrl = `${this.currentData().link()}?auth=false&brokenIsFine=true`;
return avatarUrl === currentAvatarUrl;
},
@@ -220,32 +214,30 @@ BlazeComponent.extendComponent({
this.$('.js-upload-avatar-input').click();
},
'change .js-upload-avatar-input'(event) {
let file, fileUrl;
FS.Utility.eachFile(event, f => {
try {
file = Avatars.insert(new FS.File(f));
fileUrl = file.url(this.avatarUrlOptions());
} catch (e) {
this.setError('avatar-too-big');
}
});
if (fileUrl) {
this.setError('');
const fetchAvatarInterval = window.setInterval(() => {
$.ajax({
url: fileUrl,
success: () => {
this.setAvatar(file.url(this.avatarUrlOptions()));
window.clearInterval(fetchAvatarInterval);
},
});
}, 100);
const self = this;
if (event.currentTarget.files && event.currentTarget.files[0]) {
const uploader = Avatars.insert(
{
file: event.currentTarget.files[0],
chunkSize: 'dynamic',
},
false,
);
uploader.on('uploaded', (error, fileRef) => {
if (!error) {
self.setAvatar(
`${formatFleURL(fileRef)}?auth=false&brokenIsFine=true`,
);
}
});
uploader.on('error', (error, fileData) => {
self.setError(error.reason);
});
uploader.start();
}
},
'click .js-select-avatar'() {
const avatarUrl = this.currentData().url(this.avatarUrlOptions());
const avatarUrl = `${this.currentData().link()}?auth=false&brokenIsFine=true`;
this.setAvatar(avatarUrl);
},
'click .js-select-initials'() {
+12
View File
@@ -266,12 +266,18 @@ Template.changeLanguagePopup.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 === 'cs-CZ') {
name = 'čeština (Česká republika)';
} else if (lang.name === 'de-CH') {
name = 'Deutsch (Schweiz)';
} else if (lang.name === 'de-AT') {
name = 'Deutsch (Österreich)';
} else if (lang.name === 'en-BR') {
name = 'English (Brazil)';
} else if (lang.name === 'en-DE') {
name = 'English (Germany)';
} else if (lang.name === 'et-EE') {
name = 'eesti keel (Eesti)';
} else if (lang.name === 'fa-IR') {
// fa-IR = Persian (Iran)
name = 'فارسی/پارسی (ایران‎)';
@@ -327,10 +333,16 @@ Template.changeLanguagePopup.helpers({
name = 'español de Perú';
} else if (lang.name === 'Español de Puerto Rico') {
name = 'español de Puerto Rico';
} else if (lang.name === 'gl-ES') {
name = 'Galego (España)';
} else if (lang.name === 'oc') {
name = 'Occitan';
} else if (lang.name === 'ru-UA') {
name = 'Русский (Украина)';
} else if (lang.name === 'st') {
name = 'Sãotomense';
} else if (lang.name === 'uk-UA') {
name = 'українська (Україна)';
} else if (lang.name === '繁体中文(台湾)') {
// Traditional Chinese (Taiwan)
name = '繁體中文(台灣)';
+19 -9
View File
@@ -1,5 +1,7 @@
import Cards from '../../models/cards';
import SessionData from '../../models/usersessiondata';
import {QueryDebug} from "../../config/query-classes";
import {OPERATOR_DEBUG} from "../../config/search-const";
export class CardSearchPagedComponent extends BlazeComponent {
onCreated() {
@@ -19,6 +21,8 @@ export class CardSearchPagedComponent extends BlazeComponent {
this.sessionId = SessionData.getSessionId();
this.subscriptionHandle = null;
this.serverError = new ReactiveVar(false);
this.sessionData = null;
this.debug = new ReactiveVar(new QueryDebug());
const that = this;
this.subscriptionCallbacks = {
@@ -52,6 +56,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
this.resultsCount = 0;
this.totalHits = 0;
this.queryErrors = null;
this.debug.set(new QueryDebug());
}
getSessionData(sessionId) {
@@ -63,30 +68,34 @@ export class CardSearchPagedComponent extends BlazeComponent {
getResults() {
// eslint-disable-next-line no-console
// console.log('getting results');
const sessionData = this.getSessionData();
this.sessionData = this.getSessionData();
// eslint-disable-next-line no-console
console.log('session data:', sessionData);
console.log('session data:', this.sessionData);
const cards = [];
sessionData.cards.forEach(cardId => {
this.sessionData.cards.forEach(cardId => {
cards.push(Cards.findOne({ _id: cardId }));
});
this.queryErrors = sessionData.errors;
this.queryErrors = this.sessionData.errors;
if (this.queryErrors.length) {
// console.log('queryErrors:', this.queryErrorMessages());
this.hasQueryErrors.set(true);
// return null;
}
this.debug.set(new QueryDebug(this.sessionData.debug));
console.log('debug:', this.debug.get().get());
console.log('debug.show():', this.debug.get().show());
console.log('debug.showSelector():', this.debug.get().showSelector());
if (cards) {
this.totalHits = sessionData.totalHits;
this.totalHits = this.sessionData.totalHits;
this.resultsCount = cards.length;
this.resultsStart = sessionData.lastHit - this.resultsCount + 1;
this.resultsEnd = sessionData.lastHit;
this.resultsStart = this.sessionData.lastHit - this.resultsCount + 1;
this.resultsEnd = this.sessionData.lastHit;
this.resultsHeading.set(this.getResultsHeading());
this.results.set(cards);
this.hasNextPage.set(sessionData.lastHit < sessionData.totalHits);
this.hasNextPage.set(this.sessionData.lastHit < this.sessionData.totalHits);
this.hasPreviousPage.set(
sessionData.lastHit - sessionData.resultsCount > 0,
this.sessionData.lastHit - this.sessionData.resultsCount > 0,
);
return cards;
}
@@ -113,6 +122,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
runGlobalSearch(queryParams) {
this.searching.set(true);
this.debug.set(new QueryDebug());
this.stopSubscription();
this.subscriptionHandle = this.getSubscription(queryParams);
}
+20
View File
@@ -0,0 +1,20 @@
// https://bugs.jqueryui.com/ticket/15020
// required for sortable
require('jquery-ui/ui/widget')
require('jquery-ui/ui/scroll-parent')
require('jquery-ui/ui/data')
require('jquery-ui/ui/widgets/mouse')
require('jquery-ui/ui/ie')
require('jquery-ui/ui/widgets/sortable')
// required for draggable
require('jquery-ui/ui/plugin')
require('jquery-ui/ui/safe-active-element')
require('jquery-ui/ui/safe-blur')
require('jquery-ui/ui/widgets/draggable')
// everything already required for droppable
require('jquery-ui/ui/widgets/droppable')
// enable touch on mobile
require('jquery-ui-touch-punch')
+70 -1
View File
@@ -8,7 +8,7 @@ function getHoveredCardId() {
}
function getSelectedCardId() {
return Session.get('selectedCard') || getHoveredCardId();
return Session.get('currentCard') || Session.get('selectedCard') || getHoveredCardId();
}
Mousetrap.bind('?', () => {
@@ -68,6 +68,67 @@ Mousetrap.bind(['down', 'up'], (evt, key) => {
}
});
numbArray = _.range(1,10).map(x => 'shift+'+String(x))
Mousetrap.bind(numbArray, (evt, key) => {
num = parseInt(key.substr(6, key.length));
const currentUserId = Meteor.userId();
if (currentUserId === null) {
return;
}
const currentBoardId = Session.get('currentBoard');
board = Boards.findOne(currentBoardId);
labels = board.labels;
if(MultiSelection.isActive())
{
const cardIds = MultiSelection.getSelectedCardIds();
for (const cardId of cardIds)
{
card = Cards.findOne(cardId);
if(num <= board.labels.length)
{
card.removeLabel(labels[num-1]["_id"]);
}
}
}
});
numArray = _.range(1,10).map(x => String(x))
Mousetrap.bind(numArray, (evt, key) => {
num = parseInt(key);
const currentUserId = Meteor.userId();
const currentBoardId = Session.get('currentBoard');
if (currentUserId === null) {
return;
}
board = Boards.findOne(currentBoardId);
labels = board.labels;
if(MultiSelection.isActive() && Meteor.user().isBoardMember())
{
const cardIds = MultiSelection.getSelectedCardIds();
for (const cardId of cardIds)
{
card = Cards.findOne(cardId);
if(num <= board.labels.length)
{
card.addLabel(labels[num-1]["_id"]);
}
}
return;
}
const cardId = getSelectedCardId();
if (!cardId) {
return;
}
if (Meteor.user().isBoardMember()) {
const card = Cards.findOne(cardId);
if(num <= board.labels.length)
{
card.toggleLabel(labels[num-1]["_id"]);
}
}
});
Mousetrap.bind('space', evt => {
const cardId = getSelectedCardId();
if (!cardId) {
@@ -154,5 +215,13 @@ Template.keyboardShortcuts.helpers({
keys: ['c'],
action: 'archive-card',
},
{
keys: ['number keys 1-9'],
action: 'toggle-labels'
},
{
keys: ['shift + number keys 1-9'],
action: 'remove-labels-multiselect'
},
],
});
+3
View File
@@ -83,6 +83,9 @@ MultiSelection = {
isEmpty() {
return this.count() === 0;
},
getSelectedCardIds(){
return this._selectedCards.curValue;
},
activate() {
if (!this.isActive()) {
-12
View File
@@ -163,18 +163,6 @@ describe('Utils', function() {
it('has no tests yet');
});
describe(Utils.isTouchDevice.name, function() {
it('has no tests yet');
});
describe(Utils.calculateTouchDistance.name, function() {
it('has no tests yet');
});
describe(Utils.enableClickOnTouch.name, function() {
it('has no tests yet');
});
describe(Utils.manageCustomUI.name, function() {
it('has no tests yet');
});
+69 -86
View File
@@ -162,33 +162,21 @@ Utils = {
})
);
},
getCommonAttachmentMetaFrom(card) {
const meta = {};
if (card.isLinkedCard()) {
meta.boardId = Cards.findOne(card.linkedId).boardId;
meta.cardId = card.linkedId;
} else {
meta.boardId = card.boardId;
meta.swimlaneId = card.swimlaneId;
meta.listId = card.listId;
meta.cardId = card._id;
}
return meta;
},
MAX_IMAGE_PIXEL: Meteor.settings.public.MAX_IMAGE_PIXEL,
COMPRESS_RATIO: Meteor.settings.public.IMAGE_COMPRESS_RATIO,
processUploadedAttachment(card, fileObj, callback) {
const next = attachment => {
if (typeof callback === 'function') {
callback(attachment);
}
};
if (!card) {
return next();
}
const file = new FS.File(fileObj);
if (card.isLinkedCard()) {
file.boardId = Cards.findOne(card.linkedId).boardId;
file.cardId = card.linkedId;
} else {
file.boardId = card.boardId;
file.swimlaneId = card.swimlaneId;
file.listId = card.listId;
file.cardId = card._id;
}
file.userId = Meteor.userId();
if (file.original) {
file.original.name = fileObj.name;
}
return next(Attachments.insert(file));
},
shrinkImage(options) {
// shrink image to certain size
const dataurl = options.dataurl,
@@ -364,67 +352,6 @@ Utils = {
};
},
// Detect touch device
isTouchDevice() {
const isTouchable = (() => {
const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
const mq = function(query) {
return window.matchMedia(query).matches;
};
if (
'ontouchstart' in window ||
(window.DocumentTouch && document instanceof window.DocumentTouch)
) {
return true;
}
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
// https://git.io/vznFH
const query = [
'(',
prefixes.join('touch-enabled),('),
'heartz',
')',
].join('');
return mq(query);
})();
Utils.isTouchDevice = () => isTouchable;
return isTouchable;
},
calculateTouchDistance(touchA, touchB) {
return Math.sqrt(
Math.pow(touchA.screenX - touchB.screenX, 2) +
Math.pow(touchA.screenY - touchB.screenY, 2),
);
},
enableClickOnTouch(selector) {
let touchStart = null;
let lastTouch = null;
$(document).on('touchstart', selector, function(e) {
touchStart = e.originalEvent.touches[0];
});
$(document).on('touchmove', selector, function(e) {
const touches = e.originalEvent.touches;
lastTouch = touches[touches.length - 1];
});
$(document).on('touchend', selector, function(e) {
if (
touchStart &&
lastTouch &&
Utils.calculateTouchDistance(touchStart, lastTouch) <= 20
) {
e.preventDefault();
const clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent('click', true, true);
e.target.dispatchEvent(clickEvent);
}
});
},
manageCustomUI() {
Meteor.call('getCustomUI', (err, data) => {
if (err && err.error[0] === 'var-not-exist') {
@@ -526,6 +453,62 @@ Utils = {
}
return finalString;
},
fallbackCopyTextToClipboard(text) {
var textArea = document.createElement("textarea");
textArea.value = text;
// Avoid scrolling to bottom
textArea.style.top = "0";
textArea.style.left = "0";
textArea.style.position = "fixed";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand('copy');
return Promise.resolve(true);
} catch (e) {
return Promise.reject(false);
} finally {
document.body.removeChild(textArea);
}
},
/** copy the text to the clipboard
* @see https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript/30810322#30810322
* @param string copy this text to the clipboard
* @return Promise
*/
copyTextToClipboard(text) {
let ret;
if (navigator.clipboard) {
ret = navigator.clipboard.writeText(text).then(function() {
}, function(err) {
console.error('Async: Could not copy text: ', err);
});
} else {
ret = Utils.fallbackCopyTextToClipboard(text);
}
return ret;
},
/** show the "copied!" message
* @param promise the promise of Utils.copyTextToClipboard
* @param $tooltip jQuery tooltip element
*/
showCopied(promise, $tooltip) {
if (promise) {
promise.then(() => {
$tooltip.show(100);
setTimeout(() => $tooltip.hide(100), 1000);
}, (err) => {
console.error("error: ", err);
});
}
},
};
// A simple tracker dependency that we invalidate every time the window is
+42 -4
View File
@@ -1,5 +1,32 @@
const passwordField = AccountsTemplates.removeField('password');
const emailField = AccountsTemplates.removeField('email');
let disableRegistration = false;
let disableForgotPassword = false;
let passwordLoginDisabled = false;
Meteor.call('isPasswordLoginDisabled', (_, result) => {
if (result) {
passwordLoginDisabled = true;
//console.log('passwordLoginDisabled');
//console.log(result);
}
});
Meteor.call('isDisableRegistration', (_, result) => {
if (result) {
disableRegistration = true;
//console.log('disableRegistration');
//console.log(result);
}
});
Meteor.call('isDisableForgotPassword', (_, result) => {
if (result) {
disableForgotPassword = true;
//console.log('disableForgotPassword');
//console.log(result);
}
});
AccountsTemplates.addFields([
{
@@ -27,7 +54,8 @@ AccountsTemplates.configure({
confirmPassword: true,
enablePasswordChange: true,
sendVerificationEmail: true,
showForgotPasswordLink: true,
showForgotPasswordLink: !disableForgotPassword,
forbidClientAccountCreation: disableRegistration,
onLogoutHook() {
const homePage = 'home';
if (FlowRouter.getRouteName() === homePage) {
@@ -38,11 +66,21 @@ AccountsTemplates.configure({
},
});
if (!disableForgotPassword) {
[
'forgotPwd',
'resetPwd',
].forEach(routeName => AccountsTemplates.configureRoute(routeName));
}
if (!disableRegistration) {
[
'signUp',
].forEach(routeName => AccountsTemplates.configureRoute(routeName));
}
[
'signIn',
'signUp',
'resetPwd',
'forgotPwd',
'enrollAccount',
].forEach(routeName => AccountsTemplates.configureRoute(routeName));
+8
View File
@@ -49,6 +49,14 @@ export const TYPE_LINKED_BOARD = 'cardType-linkedBoard';
export const TYPE_LINKED_CARD = 'cardType-linkedCard';
export const TYPE_TEMPLATE_BOARD = 'template-board';
export const TYPE_TEMPLATE_CONTAINER = 'template-container';
export const TYPE_TEMPLATE_CARD = 'template-card';
export const TYPE_TEMPLATE_LIST = 'template-list';
export const CARD_TYPES = [
TYPE_CARD,
TYPE_LINKED_CARD,
TYPE_LINKED_BOARD,
TYPE_TEMPLATE_CARD
];
export const ALLOWED_WAIT_SPINNERS = [
'Bounce',
'Cube',
+122 -45
View File
@@ -4,6 +4,7 @@ import {
OPERATOR_COMMENT,
OPERATOR_CREATED_AT,
OPERATOR_CREATOR,
OPERATOR_DEBUG,
OPERATOR_DUE,
OPERATOR_HAS,
OPERATOR_LABEL,
@@ -11,9 +12,11 @@ import {
OPERATOR_LIST,
OPERATOR_MEMBER,
OPERATOR_MODIFIED_AT,
OPERATOR_ORG,
OPERATOR_SORT,
OPERATOR_STATUS,
OPERATOR_SWIMLANE,
OPERATOR_TEAM,
OPERATOR_UNKNOWN,
OPERATOR_USER,
ORDER_ASCENDING,
@@ -34,8 +37,10 @@ import {
PREDICATE_OPEN,
PREDICATE_OVERDUE,
PREDICATE_PRIVATE,
PREDICATE_PROJECTION,
PREDICATE_PUBLIC,
PREDICATE_QUARTER,
PREDICATE_SELECTOR,
PREDICATE_START_AT,
PREDICATE_WEEK,
PREDICATE_YEAR,
@@ -43,6 +48,46 @@ import {
import Boards from '../models/boards';
import moment from 'moment';
export class QueryDebug {
predicate = null;
constructor(predicate) {
if (predicate) {
this.set(predicate)
}
}
get() {
return this.predicate;
}
set(predicate) {
if ([PREDICATE_ALL, PREDICATE_SELECTOR, PREDICATE_PROJECTION].includes(
predicate
)) {
this.predicate = predicate;
} else {
this.predicate = null;
}
}
show() {
return (this.predicate !== null);
}
showAll() {
return (this.predicate === PREDICATE_ALL);
}
showSelector() {
return (this.predicate === PREDICATE_ALL || this.predicate === PREDICATE_SELECTOR);
}
showProjection() {
return (this.predicate === PREDICATE_ALL || this.predicate === PREDICATE_PROJECTION);
}
}
export class QueryParams {
text = '';
@@ -71,11 +116,14 @@ export class QueryParams {
}
getPredicate(operator) {
if (typeof this.params[operator] === 'object') {
return this.params[operator][0];
} else {
return this.params[operator];
if (this.hasOperator(operator)){
if (typeof this.params[operator] === 'object') {
return this.params[operator][0];
} else {
return this.params[operator];
}
}
return null;
}
getPredicates(operator) {
@@ -115,6 +163,8 @@ export class QueryErrors {
[OPERATOR_ASSIGNEE, 'user-username-not-found'],
[OPERATOR_MEMBER, 'user-username-not-found'],
[OPERATOR_CREATOR, 'user-username-not-found'],
[OPERATOR_ORG, 'org-name-not-found'],
[OPERATOR_TEAM, 'team-name-not-found'],
];
constructor() {
@@ -196,6 +246,10 @@ export class Query {
return this._errors.errors();
}
addError(operator, error) {
this._errors.addError(operator, error)
}
errorMessages() {
return this._errors.errorMessages();
}
@@ -213,6 +267,8 @@ export class Query {
}
buildParams(queryText) {
this.queryParams = new QueryParams();
queryText = queryText.trim();
// eslint-disable-next-line no-console
//console.log('query:', query);
@@ -260,42 +316,51 @@ export class Query {
'operator-has': OPERATOR_HAS,
'operator-sort': OPERATOR_SORT,
'operator-limit': OPERATOR_LIMIT,
'operator-debug': OPERATOR_DEBUG,
'operator-org': OPERATOR_ORG,
'operator-team': OPERATOR_TEAM,
};
const predicates = {
due: {
'predicate-overdue': PREDICATE_OVERDUE,
},
durations: {
'predicate-week': PREDICATE_WEEK,
'predicate-month': PREDICATE_MONTH,
'predicate-quarter': PREDICATE_QUARTER,
'predicate-year': PREDICATE_YEAR,
},
status: {
'predicate-archived': PREDICATE_ARCHIVED,
'predicate-all': PREDICATE_ALL,
'predicate-open': PREDICATE_OPEN,
'predicate-ended': PREDICATE_ENDED,
'predicate-public': PREDICATE_PUBLIC,
'predicate-private': PREDICATE_PRIVATE,
},
sorts: {
'predicate-due': PREDICATE_DUE_AT,
'predicate-created': PREDICATE_CREATED_AT,
'predicate-modified': PREDICATE_MODIFIED_AT,
},
has: {
'predicate-description': PREDICATE_DESCRIPTION,
'predicate-checklist': PREDICATE_CHECKLIST,
'predicate-attachment': PREDICATE_ATTACHMENT,
'predicate-start': PREDICATE_START_AT,
'predicate-end': PREDICATE_END_AT,
'predicate-due': PREDICATE_DUE_AT,
'predicate-assignee': PREDICATE_ASSIGNEES,
'predicate-member': PREDICATE_MEMBERS,
},
};
predicates[OPERATOR_DUE] = {
'predicate-overdue': PREDICATE_OVERDUE,
};
predicates[OPERATOR_STATUS] = {
'predicate-archived': PREDICATE_ARCHIVED,
'predicate-all': PREDICATE_ALL,
'predicate-open': PREDICATE_OPEN,
'predicate-ended': PREDICATE_ENDED,
'predicate-public': PREDICATE_PUBLIC,
'predicate-private': PREDICATE_PRIVATE,
};
predicates[OPERATOR_SORT] = {
'predicate-due': PREDICATE_DUE_AT,
'predicate-created': PREDICATE_CREATED_AT,
'predicate-modified': PREDICATE_MODIFIED_AT,
};
predicates[OPERATOR_HAS] = {
'predicate-description': PREDICATE_DESCRIPTION,
'predicate-checklist': PREDICATE_CHECKLIST,
'predicate-attachment': PREDICATE_ATTACHMENT,
'predicate-start': PREDICATE_START_AT,
'predicate-end': PREDICATE_END_AT,
'predicate-due': PREDICATE_DUE_AT,
'predicate-assignee': PREDICATE_ASSIGNEES,
'predicate-member': PREDICATE_MEMBERS,
};
predicates[OPERATOR_DEBUG] = {
'predicate-all': PREDICATE_ALL,
'predicate-selector': PREDICATE_SELECTOR,
'predicate-projection': PREDICATE_PROJECTION,
};
const predicateTranslations = {};
Object.entries(predicates).forEach(([category, catPreds]) => {
predicateTranslations[category] = {};
@@ -403,7 +468,7 @@ export class Query {
value: moment().format('YYYY-MM-DD'),
};
} else {
this.errors.addError(OPERATOR_DUE, {
this.addError(OPERATOR_DUE, {
tag: 'operator-number-expected',
value: { operator: op, value },
});
@@ -431,27 +496,27 @@ export class Query {
value = m.groups.operator;
negated = true;
}
if (!predicateTranslations.sorts[value]) {
this.errors.addError(OPERATOR_SORT, {
if (!predicateTranslations[OPERATOR_SORT][value]) {
this.addError(OPERATOR_SORT, {
tag: 'operator-sort-invalid',
value,
});
continue;
} else {
value = {
name: predicateTranslations.sorts[value],
name: predicateTranslations[OPERATOR_SORT][value],
order: negated ? ORDER_DESCENDING : ORDER_ASCENDING,
};
}
} else if (operator === OPERATOR_STATUS) {
if (!predicateTranslations.status[value]) {
this.errors.addError(OPERATOR_STATUS, {
if (!predicateTranslations[OPERATOR_STATUS][value]) {
this.addError(OPERATOR_STATUS, {
tag: 'operator-status-invalid',
value,
});
continue;
} else {
value = predicateTranslations.status[value];
value = predicateTranslations[OPERATOR_STATUS][value];
}
} else if (operator === OPERATOR_HAS) {
let negated = false;
@@ -460,22 +525,22 @@ export class Query {
value = m.groups.operator;
negated = true;
}
if (!predicateTranslations.has[value]) {
this.errors.addError(OPERATOR_HAS, {
if (!predicateTranslations[OPERATOR_HAS][value]) {
this.addError(OPERATOR_HAS, {
tag: 'operator-has-invalid',
value,
});
continue;
} else {
value = {
field: predicateTranslations.has[value],
field: predicateTranslations[OPERATOR_HAS][value],
exists: !negated,
};
}
} else if (operator === OPERATOR_LIMIT) {
const limit = parseInt(value, 10);
if (isNaN(limit) || limit < 1) {
this.errors.addError(OPERATOR_LIMIT, {
this.addError(OPERATOR_LIMIT, {
tag: 'operator-limit-invalid',
value,
});
@@ -483,11 +548,21 @@ export class Query {
} else {
value = limit;
}
} else if (operator === OPERATOR_DEBUG) {
if (!predicateTranslations[OPERATOR_DEBUG][value]) {
this.addError(OPERATOR_DEBUG, {
tag: 'operator-debug-invalid',
value,
});
continue;
} else {
value = predicateTranslations[OPERATOR_DEBUG][value];
}
}
this.queryParams.addPredicate(operator, value);
} else {
this.errors.addError(OPERATOR_UNKNOWN, {
this.addError(OPERATOR_UNKNOWN, {
tag: 'operator-unknown-error',
value: op,
});
@@ -509,11 +584,13 @@ export class Query {
}
}
// eslint-disable-next-line no-console
// console.log('text:', text);
this.queryParams.text = text;
// eslint-disable-next-line no-console
//console.log('queryParams:', this.queryParams);
if (this.queryParams.hasOperator(OPERATOR_DEBUG)) {
// eslint-disable-next-line no-console
console.log('text:', this.queryParams.text);
console.log('queryParams:', this.queryParams);
}
}
}
+24
View File
@@ -124,6 +124,30 @@ FlowRouter.route('/shortcuts', {
},
});
FlowRouter.route('/b/templates', {
name: 'template-container',
triggersEnter: [AccountsTemplates.ensureSignedIn],
action() {
Session.set('currentBoard', null);
Session.set('currentList', null);
Session.set('currentCard', null);
Session.set('popupCardId', null);
Session.set('popupCardBoardId', null);
Filter.reset();
Session.set('sortBy', '');
EscapeActions.executeAll();
Utils.manageCustomUI();
Utils.manageMatomo();
BlazeLayout.render('defaultLayout', {
headerBar: 'boardListHeaderBar',
content: 'boardList',
});
},
});
FlowRouter.route('/my-cards', {
name: 'my-cards',
triggersEnter: [AccountsTemplates.ensureSignedIn],
+5
View File
@@ -3,6 +3,7 @@ export const OPERATOR_ASSIGNEE = 'assignees';
export const OPERATOR_COMMENT = 'comment';
export const OPERATOR_CREATED_AT = 'createdAt';
export const OPERATOR_CREATOR = 'userId';
export const OPERATOR_DEBUG = 'debug';
export const OPERATOR_DUE = 'dueAt';
export const OPERATOR_BOARD = 'board';
export const OPERATOR_HAS = 'has';
@@ -11,9 +12,11 @@ export const OPERATOR_LIMIT = 'limit';
export const OPERATOR_LIST = 'list';
export const OPERATOR_MEMBER = 'members';
export const OPERATOR_MODIFIED_AT = 'modifiedAt';
export const OPERATOR_ORG = 'org';
export const OPERATOR_SORT = 'sort';
export const OPERATOR_STATUS = 'status';
export const OPERATOR_SWIMLANE = 'swimlane';
export const OPERATOR_TEAM = 'team';
export const OPERATOR_UNKNOWN = 'unknown';
export const OPERATOR_USER = 'user';
export const ORDER_ASCENDING = 'asc';
@@ -33,9 +36,11 @@ export const PREDICATE_MODIFIED_AT = 'modifiedAt';
export const PREDICATE_MONTH = 'month';
export const PREDICATE_OPEN = 'open';
export const PREDICATE_OVERDUE = 'overdue';
export const PREDICATE_PROJECTION = 'projection';
export const PREDICATE_PRIVATE = 'private';
export const PREDICATE_PUBLIC = 'public';
export const PREDICATE_QUARTER = 'quarter';
export const PREDICATE_SELECTOR = 'selector';
export const PREDICATE_START_AT = 'startAt';
export const PREDICATE_SYSTEM = 'system';
export const PREDICATE_WEEK = 'week';
+10 -4
View File
@@ -174,6 +174,12 @@ services:
#- MAIL_SERVICE_USER=firstname.lastname@hotmail.com
#- MAIL_SERVICE_PASSWORD=SecretPassword
#---------------------------------------------------------------
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
# Add more Node heap, this is done by default at Dockerfile:
# - NODE_OPTIONS="--max_old_space_size=4096"
# Add more stack, this is done at Dockerfile:
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
#---------------------------------------------------------------
# ==== OPTIONAL: MONGO OPLOG SETTINGS =====
# https://github.com/wekan/wekan-mongodb/issues/2#issuecomment-378343587
# We've fixed our CPU usage problem today with an environment
@@ -241,10 +247,6 @@ services:
# Defaults below. Uncomment to change. wekan/server/accounts-common.js
# - ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS=90
#---------------------------------------------------------------
# ==== STORE ATTACHMENT ON SERVER FILESYSTEM INSTEAD OF MONGODB ====
# https://github.com/wekan/wekan/pull/2603
#- ATTACHMENTS_STORE_PATH = <pathname> # pathname can be relative or fullpath
#---------------------------------------------------------------
# ==== RICH TEXT EDITOR IN CARD COMMENTS ====
# https://github.com/wekan/wekan/pull/2560
- RICHER_CARD_COMMENT_EDITOR=false
@@ -323,6 +325,9 @@ services:
# When browser policy is enabled, HTML code at this Trusted URL can have iframe that embeds Wekan inside.
#- TRUSTED_URL=https://intra.example.com
#-----------------------------------------------------------------
# ==== WRITEABLE PATH FOR FILE UPLOADS ====
- WRITABLE_PATH=/data
#-----------------------------------------------------------------
# ==== OUTGOING WEBHOOKS ====
# What to send to Outgoing Webhook, or leave out. If commented out the default values will be: cardId,listId,oldListId,boardId,comment,user,card,commentId,swimlaneId,customerField,customFieldValue
#- WEBHOOKS_ATTRIBUTES=cardId,listId,oldListId,boardId,comment,user,card,commentId
@@ -668,6 +673,7 @@ services:
- wekandb
volumes:
- /etc/localtime:/etc/localtime:ro
- ./volumes/data:/data
#---------------------------------------------------------------------------------
# ==== OPTIONAL: SHARE DATABASE TO OFFICE LAN AND REMOTE VPN ====
-914
View File
@@ -1,914 +0,0 @@
(function () {
/* Imports */
var Meteor = Package.meteor.Meteor;
var global = Package.meteor.global;
var meteorEnv = Package.meteor.meteorEnv;
var FS = Package['wekan-cfs-base-package'].FS;
var check = Package.check.check;
var Match = Package.check.Match;
var EJSON = Package.ejson.EJSON;
var HTTP = Package['wekan-cfs-http-methods'].HTTP;
/* Package-scope variables */
var rootUrlPathPrefix, baseUrl, getHeaders, getHeadersByCollection, _existingMountPoints, mountUrls;
(function(){
///////////////////////////////////////////////////////////////////////
// //
// packages/cfs_access-point/packages/cfs_access-point.js //
// //
///////////////////////////////////////////////////////////////////////
//
(function () {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// packages/wekan-cfs-access-point/access-point-common.js //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
rootUrlPathPrefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || ""; // 1
// Adjust the rootUrlPathPrefix if necessary // 2
if (rootUrlPathPrefix.length > 0) { // 3
if (rootUrlPathPrefix.slice(0, 1) !== '/') { // 4
rootUrlPathPrefix = '/' + rootUrlPathPrefix; // 5
} // 6
if (rootUrlPathPrefix.slice(-1) === '/') { // 7
rootUrlPathPrefix = rootUrlPathPrefix.slice(0, -1); // 8
} // 9
} // 10
// 11
// prepend ROOT_URL when isCordova // 12
if (Meteor.isCordova) { // 13
rootUrlPathPrefix = Meteor.absoluteUrl(rootUrlPathPrefix.replace(/^\/+/, '')).replace(/\/+$/, ''); // 14
} // 15
// 16
baseUrl = '/cfs'; // 17
FS.HTTP = FS.HTTP || {}; // 18
// 19
// Note the upload URL so that client uploader packages know what it is // 20
FS.HTTP.uploadUrl = rootUrlPathPrefix + baseUrl + '/files'; // 21
// 22
/** // 23
* @method FS.HTTP.setBaseUrl // 24
* @public // 25
* @param {String} newBaseUrl - Change the base URL for the HTTP GET and DELETE endpoints. // 26
* @returns {undefined} // 27
*/ // 28
FS.HTTP.setBaseUrl = function setBaseUrl(newBaseUrl) { // 29
// 30
// Adjust the baseUrl if necessary // 31
if (newBaseUrl.slice(0, 1) !== '/') { // 32
newBaseUrl = '/' + newBaseUrl; // 33
} // 34
if (newBaseUrl.slice(-1) === '/') { // 35
newBaseUrl = newBaseUrl.slice(0, -1); // 36
} // 37
// 38
// Update the base URL // 39
baseUrl = newBaseUrl; // 40
// 41
// Change the upload URL so that client uploader packages know what it is // 42
FS.HTTP.uploadUrl = rootUrlPathPrefix + baseUrl + '/files'; // 43
// 44
// Remount URLs with the new baseUrl, unmounting the old, on the server only. // 45
// If existingMountPoints is empty, then we haven't run the server startup // 46
// code yet, so this new URL will be used at that point for the initial mount. // 47
if (Meteor.isServer && !FS.Utility.isEmpty(_existingMountPoints)) { // 48
mountUrls(); // 49
} // 50
}; // 51
// 52
/* // 53
* FS.File extensions // 54
*/ // 55
// 56
/** // 57
* @method FS.File.prototype.url Construct the file url // 58
* @public // 59
* @param {Object} [options] // 60
* @param {String} [options.store] Name of the store to get from. If not defined, the first store defined in `options.stores` for the collection on the client is used.
* @param {Boolean} [options.auth=null] Add authentication token to the URL query string? By default, a token for the current logged in user is added on the client. Set this to `false` to omit the token. Set this to a string to provide your own token. Set this to a number to specify an expiration time for the token in seconds.
* @param {Boolean} [options.download=false] Should headers be set to force a download? Typically this means that clicking the link with this URL will download the file to the user's Downloads folder instead of displaying the file in the browser.
* @param {Boolean} [options.brokenIsFine=false] Return the URL even if we know it's currently a broken link because the file hasn't been saved in the requested store yet.
* @param {Boolean} [options.metadata=false] Return the URL for the file metadata access point rather than the file itself.
* @param {String} [options.uploading=null] A URL to return while the file is being uploaded. // 66
* @param {String} [options.storing=null] A URL to return while the file is being stored. // 67
* @param {String} [options.filename=null] Override the filename that should appear at the end of the URL. By default it is the name of the file in the requested store.
* // 69
* Returns the HTTP URL for getting the file or its metadata. // 70
*/ // 71
FS.File.prototype.url = function(options) { // 72
var self = this; // 73
options = options || {}; // 74
options = FS.Utility.extend({ // 75
store: null, // 76
auth: null, // 77
download: false, // 78
metadata: false, // 79
brokenIsFine: false, // 80
uploading: null, // return this URL while uploading // 81
storing: null, // return this URL while storing // 82
filename: null // override the filename that is shown to the user // 83
}, options.hash || options); // check for "hash" prop if called as helper // 84
// 85
// Primarily useful for displaying a temporary image while uploading an image // 86
if (options.uploading && !self.isUploaded()) { // 87
return options.uploading; // 88
} // 89
// 90
if (self.isMounted()) { // 91
// See if we've stored in the requested store yet // 92
var storeName = options.store || self.collection.primaryStore.name; // 93
if (!self.hasStored(storeName)) { // 94
if (options.storing) { // 95
return options.storing; // 96
} else if (!options.brokenIsFine) { // 97
// We want to return null if we know the URL will be a broken // 98
// link because then we can avoid rendering broken links, broken // 99
// images, etc. // 100
return null; // 101
} // 102
} // 103
// 104
// Add filename to end of URL if we can determine one // 105
var filename = options.filename || self.name({store: storeName}); // 106
if (typeof filename === "string" && filename.length) { // 107
filename = '/' + filename; // 108
} else { // 109
filename = ''; // 110
} // 111
// 112
// TODO: Could we somehow figure out if the collection requires login? // 113
var authToken = ''; // 114
if (Meteor.isClient && typeof Accounts !== "undefined" && typeof Accounts._storedLoginToken === "function") { // 115
if (options.auth !== false) { // 116
// Add reactive deps on the user // 117
Meteor.userId(); // 118
// 119
var authObject = { // 120
authToken: Accounts._storedLoginToken() || '' // 121
}; // 122
// 123
// If it's a number, we use that as the expiration time (in seconds) // 124
if (options.auth === +options.auth) { // 125
authObject.expiration = FS.HTTP.now() + options.auth * 1000; // 126
} // 127
// 128
// Set the authToken // 129
var authString = JSON.stringify(authObject); // 130
authToken = FS.Utility.btoa(authString); // 131
} // 132
} else if (typeof options.auth === "string") { // 133
// If the user supplies auth token the user will be responsible for // 134
// updating // 135
authToken = options.auth; // 136
} // 137
// 138
// Construct query string // 139
var params = {}; // 140
if (authToken !== '') { // 141
params.token = authToken; // 142
} // 143
if (options.download) { // 144
params.download = true; // 145
} // 146
if (options.store) { // 147
// We use options.store here instead of storeName because we want to omit the queryString // 148
// whenever possible, allowing users to have "clean" URLs if they want. The server will // 149
// assume the first store defined on the server, which means that we are assuming that // 150
// the first on the client is also the first on the server. If that's not the case, the // 151
// store option should be supplied. // 152
params.store = options.store; // 153
} // 154
var queryString = FS.Utility.encodeParams(params); // 155
if (queryString.length) { // 156
queryString = '?' + queryString; // 157
} // 158
// 159
// Determine which URL to use // 160
var area; // 161
if (options.metadata) { // 162
area = '/record'; // 163
} else { // 164
area = '/files'; // 165
} // 166
// 167
// Construct and return the http method url // 168
return rootUrlPathPrefix + baseUrl + area + '/' + self.collection.name + '/' + self._id + filename + queryString; // 169
} // 170
// 171
}; // 172
// 173
// 174
// 175
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}).call(this);
(function () {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// packages/wekan-cfs-access-point/access-point-handlers.js //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
getHeaders = []; // 1
getHeadersByCollection = {}; // 2
// 3
FS.HTTP.Handlers = {}; // 4
// 5
/** // 6
* @method FS.HTTP.Handlers.Del // 7
* @public // 8
* @returns {any} response // 9
* // 10
* HTTP DEL request handler // 11
*/ // 12
FS.HTTP.Handlers.Del = function httpDelHandler(ref) { // 13
var self = this; // 14
var opts = FS.Utility.extend({}, self.query || {}, self.params || {}); // 15
// 16
// If DELETE request, validate with 'remove' allow/deny, delete the file, and return // 17
FS.Utility.validateAction(ref.collection.files._validators['remove'], ref.file, self.userId); // 18
// 19
/* // 20
* From the DELETE spec: // 21
* A successful response SHOULD be 200 (OK) if the response includes an // 22
* entity describing the status, 202 (Accepted) if the action has not // 23
* yet been enacted, or 204 (No Content) if the action has been enacted // 24
* but the response does not include an entity. // 25
*/ // 26
self.setStatusCode(200); // 27
// 28
return { // 29
deleted: !!ref.file.remove() // 30
}; // 31
}; // 32
// 33
/** // 34
* @method FS.HTTP.Handlers.GetList // 35
* @public // 36
* @returns {Object} response // 37
* // 38
* HTTP GET file list request handler // 39
*/ // 40
FS.HTTP.Handlers.GetList = function httpGetListHandler() { // 41
// Not Yet Implemented // 42
// Need to check publications and return file list based on // 43
// what user is allowed to see // 44
}; // 45
// 46
/* // 47
requestRange will parse the range set in request header - if not possible it // 48
will throw fitting errors and autofill range for both partial and full ranges // 49
// 50
throws error or returns the object: // 51
{ // 52
start // 53
end // 54
length // 55
unit // 56
partial // 57
} // 58
*/ // 59
var requestRange = function(req, fileSize) { // 60
if (req) { // 61
if (req.headers) { // 62
var rangeString = req.headers.range; // 63
// 64
// Make sure range is a string // 65
if (rangeString === ''+rangeString) { // 66
// 67
// range will be in the format "bytes=0-32767" // 68
var parts = rangeString.split('='); // 69
var unit = parts[0]; // 70
// 71
// Make sure parts consists of two strings and range is of type "byte" // 72
if (parts.length == 2 && unit == 'bytes') { // 73
// Parse the range // 74
var range = parts[1].split('-'); // 75
var start = Number(range[0]); // 76
var end = Number(range[1]); // 77
// 78
// Fix invalid ranges? // 79
if (range[0] != start) start = 0; // 80
if (range[1] != end || !end) end = fileSize - 1; // 81
// 82
// Make sure range consists of a start and end point of numbers and start is less than end // 83
if (start < end) { // 84
// 85
var partSize = 0 - start + end + 1; // 86
// 87
// Return the parsed range // 88
return { // 89
start: start, // 90
end: end, // 91
length: partSize, // 92
size: fileSize, // 93
unit: unit, // 94
partial: (partSize < fileSize) // 95
}; // 96
// 97
} else { // 98
throw new Meteor.Error(416, "Requested Range Not Satisfiable"); // 99
} // 100
// 101
} else { // 102
// The first part should be bytes // 103
throw new Meteor.Error(416, "Requested Range Unit Not Satisfiable"); // 104
} // 105
// 106
} else { // 107
// No range found // 108
} // 109
// 110
} else { // 111
// throw new Error('No request headers set for _parseRange function'); // 112
} // 113
} else { // 114
throw new Error('No request object passed to _parseRange function'); // 115
} // 116
// 117
return { // 118
start: 0, // 119
end: fileSize - 1, // 120
length: fileSize, // 121
size: fileSize, // 122
unit: 'bytes', // 123
partial: false // 124
}; // 125
}; // 126
// 127
/** // 128
* @method FS.HTTP.Handlers.Get // 129
* @public // 130
* @returns {any} response // 131
* // 132
* HTTP GET request handler // 133
*/ // 134
FS.HTTP.Handlers.Get = function httpGetHandler(ref) { // 135
var self = this; // 136
// Once we have the file, we can test allow/deny validators // 137
// XXX: pass on the "share" query eg. ?share=342hkjh23ggj for shared url access? // 138
FS.Utility.validateAction(ref.collection._validators['download'], ref.file, self.userId /*, self.query.shareId*/); // 139
// 140
var storeName = ref.storeName; // 141
// 142
// If no storeName was specified, use the first defined storeName // 143
if (typeof storeName !== "string") { // 144
// No store handed, we default to primary store // 145
storeName = ref.collection.primaryStore.name; // 146
} // 147
// 148
// Get the storage reference // 149
var storage = ref.collection.storesLookup[storeName]; // 150
// 151
if (!storage) { // 152
throw new Meteor.Error(404, "Not Found", 'There is no store "' + storeName + '"'); // 153
} // 154
// 155
// Get the file // 156
var copyInfo = ref.file.copies[storeName]; // 157
// 158
if (!copyInfo) { // 159
throw new Meteor.Error(404, "Not Found", 'This file was not stored in the ' + storeName + ' store'); // 160
} // 161
// 162
// Set the content type for file // 163
if (typeof copyInfo.type === "string") { // 164
self.setContentType(copyInfo.type); // 165
} else { // 166
self.setContentType('application/octet-stream'); // 167
} // 168
// 169
// Add 'Content-Disposition' header if requested a download/attachment URL // 170
if (typeof ref.download !== "undefined") { // 171
var filename = ref.filename || copyInfo.name; // 172
self.addHeader('Content-Disposition', 'attachment; filename="' + filename + '"'); // 173
} else { // 174
self.addHeader('Content-Disposition', 'inline'); // 175
} // 176
// 177
// Get the contents range from request // 178
var range = requestRange(self.request, copyInfo.size); // 179
// 180
// Some browsers cope better if the content-range header is // 181
// still included even for the full file being returned. // 182
self.addHeader('Content-Range', range.unit + ' ' + range.start + '-' + range.end + '/' + range.size); // 183
// 184
// If a chunk/range was requested instead of the whole file, serve that' // 185
if (range.partial) { // 186
self.setStatusCode(206, 'Partial Content'); // 187
} else { // 188
self.setStatusCode(200, 'OK'); // 189
} // 190
// 191
// Add any other global custom headers and collection-specific custom headers // 192
FS.Utility.each(getHeaders.concat(getHeadersByCollection[ref.collection.name] || []), function(header) { // 193
self.addHeader(header[0], header[1]); // 194
}); // 195
// 196
// Inform clients about length (or chunk length in case of ranges) // 197
self.addHeader('Content-Length', range.length); // 198
// 199
// Last modified header (updatedAt from file info) // 200
self.addHeader('Last-Modified', copyInfo.updatedAt.toUTCString()); // 201
// 202
// Inform clients that we accept ranges for resumable chunked downloads // 203
self.addHeader('Accept-Ranges', range.unit); // 204
// 205
if (FS.debug) console.log('Read file "' + (ref.filename || copyInfo.name) + '" ' + range.unit + ' ' + range.start + '-' + range.end + '/' + range.size);
// 207
var readStream = storage.adapter.createReadStream(ref.file, {start: range.start, end: range.end}); // 208
// 209
readStream.on('error', function(err) { // 210
// Send proper error message on get error // 211
if (err.message && err.statusCode) { // 212
self.Error(new Meteor.Error(err.statusCode, err.message)); // 213
} else { // 214
self.Error(new Meteor.Error(503, 'Service unavailable')); // 215
} // 216
}); // 217
// 218
readStream.pipe(self.createWriteStream()); // 219
}; // 220
const originalHandler = FS.HTTP.Handlers.Get;
FS.HTTP.Handlers.Get = function (ref) {
//console.log(ref.filename);
try {
var userAgent = (this.requestHeaders['user-agent']||'').toLowerCase();
if(userAgent.indexOf('msie') >= 0 || userAgent.indexOf('trident') >= 0 || userAgent.indexOf('chrome') >= 0) {
ref.filename = encodeURIComponent(ref.filename);
} else if(userAgent.indexOf('firefox') >= 0) {
ref.filename = Buffer.from(ref.filename).toString('binary');
} else {
/* safari*/
ref.filename = Buffer.from(ref.filename).toString('binary');
}
} catch (ex){
ref.filename = 'tempfix';
}
return originalHandler.call(this, ref);
};
// 221
/** // 222
* @method FS.HTTP.Handlers.PutInsert // 223
* @public // 224
* @returns {Object} response object with _id property // 225
* // 226
* HTTP PUT file insert request handler // 227
*/ // 228
FS.HTTP.Handlers.PutInsert = function httpPutInsertHandler(ref) { // 229
var self = this; // 230
var opts = FS.Utility.extend({}, self.query || {}, self.params || {}); // 231
// 232
FS.debug && console.log("HTTP PUT (insert) handler"); // 233
// 234
// Create the nice FS.File // 235
var fileObj = new FS.File(); // 236
// 237
// Set its name // 238
fileObj.name(opts.filename || null); // 239
// 240
// Attach the readstream as the file's data // 241
fileObj.attachData(self.createReadStream(), {type: self.requestHeaders['content-type'] || 'application/octet-stream'});
// 243
// Validate with insert allow/deny // 244
FS.Utility.validateAction(ref.collection.files._validators['insert'], fileObj, self.userId); // 245
// 246
// Insert file into collection, triggering readStream storage // 247
ref.collection.insert(fileObj); // 248
// 249
// Send response // 250
self.setStatusCode(200); // 251
// 252
// Return the new file id // 253
return {_id: fileObj._id}; // 254
}; // 255
// 256
/** // 257
* @method FS.HTTP.Handlers.PutUpdate // 258
* @public // 259
* @returns {Object} response object with _id and chunk properties // 260
* // 261
* HTTP PUT file update chunk request handler // 262
*/ // 263
FS.HTTP.Handlers.PutUpdate = function httpPutUpdateHandler(ref) { // 264
var self = this; // 265
var opts = FS.Utility.extend({}, self.query || {}, self.params || {}); // 266
// 267
var chunk = parseInt(opts.chunk, 10); // 268
if (isNaN(chunk)) chunk = 0; // 269
// 270
FS.debug && console.log("HTTP PUT (update) handler received chunk: ", chunk); // 271
// 272
// Validate with insert allow/deny; also mounts and retrieves the file // 273
FS.Utility.validateAction(ref.collection.files._validators['insert'], ref.file, self.userId); // 274
// 275
self.createReadStream().pipe( FS.TempStore.createWriteStream(ref.file, chunk) ); // 276
// 277
// Send response // 278
self.setStatusCode(200); // 279
// 280
return { _id: ref.file._id, chunk: chunk }; // 281
}; // 282
// 283
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}).call(this);
(function () {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// packages/wekan-cfs-access-point/access-point-server.js //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
var path = Npm.require("path"); // 1
// 2
HTTP.publishFormats({ // 3
fileRecordFormat: function (input) { // 4
// Set the method scope content type to json // 5
this.setContentType('application/json'); // 6
if (FS.Utility.isArray(input)) { // 7
return EJSON.stringify(FS.Utility.map(input, function (obj) { // 8
return FS.Utility.cloneFileRecord(obj); // 9
})); // 10
} else { // 11
return EJSON.stringify(FS.Utility.cloneFileRecord(input)); // 12
} // 13
} // 14
}); // 15
// 16
/** // 17
* @method FS.HTTP.setHeadersForGet // 18
* @public // 19
* @param {Array} headers - List of headers, where each is a two-item array in which item 1 is the header name and item 2 is the header value.
* @param {Array|String} [collections] - Which collections the headers should be added for. Omit this argument to add the header for all collections.
* @returns {undefined} // 22
*/ // 23
FS.HTTP.setHeadersForGet = function setHeadersForGet(headers, collections) { // 24
if (typeof collections === "string") { // 25
collections = [collections]; // 26
} // 27
if (collections) { // 28
FS.Utility.each(collections, function(collectionName) { // 29
getHeadersByCollection[collectionName] = headers || []; // 30
}); // 31
} else { // 32
getHeaders = headers || []; // 33
} // 34
}; // 35
// 36
/** // 37
* @method FS.HTTP.publish // 38
* @public // 39
* @param {FS.Collection} collection // 40
* @param {Function} func - Publish function that returns a cursor. // 41
* @returns {undefined} // 42
* // 43
* Publishes all documents returned by the cursor at a GET URL // 44
* with the format baseUrl/record/collectionName. The publish // 45
* function `this` is similar to normal `Meteor.publish`. // 46
*/ // 47
FS.HTTP.publish = function fsHttpPublish(collection, func) { // 48
var name = baseUrl + '/record/' + collection.name; // 49
// Mount collection listing URL using http-publish package // 50
HTTP.publish({ // 51
name: name, // 52
defaultFormat: 'fileRecordFormat', // 53
collection: collection, // 54
collectionGet: true, // 55
collectionPost: false, // 56
documentGet: true, // 57
documentPut: false, // 58
documentDelete: false // 59
}, func); // 60
// 61
FS.debug && console.log("Registered HTTP method GET URLs:\n\n" + name + '\n' + name + '/:id\n'); // 62
}; // 63
// 64
/** // 65
* @method FS.HTTP.unpublish // 66
* @public // 67
* @param {FS.Collection} collection // 68
* @returns {undefined} // 69
* // 70
* Unpublishes a restpoint created by a call to `FS.HTTP.publish` // 71
*/ // 72
FS.HTTP.unpublish = function fsHttpUnpublish(collection) { // 73
// Mount collection listing URL using http-publish package // 74
HTTP.unpublish(baseUrl + '/record/' + collection.name); // 75
}; // 76
// 77
_existingMountPoints = {}; // 78
// 79
/** // 80
* @method defaultSelectorFunction // 81
* @private // 82
* @returns { collection, file } // 83
* // 84
* This is the default selector function // 85
*/ // 86
var defaultSelectorFunction = function() { // 87
var self = this; // 88
// Selector function // 89
// // 90
// This function will have to return the collection and the // 91
// file. If file not found undefined is returned - if null is returned the // 92
// search was not possible // 93
var opts = FS.Utility.extend({}, self.query || {}, self.params || {}); // 94
// 95
// Get the collection name from the url // 96
var collectionName = opts.collectionName; // 97
// 98
// Get the id from the url // 99
var id = opts.id; // 100
// 101
// Get the collection // 102
var collection = FS._collections[collectionName]; // 103
// 104
// Get the file if possible else return null // 105
var file = (id && collection)? collection.findOne({ _id: id }): null; // 106
// 107
// Return the collection and the file // 108
return { // 109
collection: collection, // 110
file: file, // 111
storeName: opts.store, // 112
download: opts.download, // 113
filename: opts.filename // 114
}; // 115
}; // 116
// 117
/* // 118
* @method FS.HTTP.mount // 119
* @public // 120
* @param {array of string} mountPoints mount points to map rest functinality on // 121
* @param {function} selector_f [selector] function returns `{ collection, file }` for mount points to work with // 122
* // 123
*/ // 124
FS.HTTP.mount = function(mountPoints, selector_f) { // 125
// We take mount points as an array and we get a selector function // 126
var selectorFunction = selector_f || defaultSelectorFunction; // 127
// 128
var accessPoint = { // 129
'stream': true, // 130
'auth': expirationAuth, // 131
'post': function(data) { // 132
// Use the selector for finding the collection and file reference // 133
var ref = selectorFunction.call(this); // 134
// 135
// We dont support post - this would be normal insert eg. of filerecord? // 136
throw new Meteor.Error(501, "Not implemented", "Post is not supported"); // 137
}, // 138
'put': function(data) { // 139
// Use the selector for finding the collection and file reference // 140
var ref = selectorFunction.call(this); // 141
// 142
// Make sure we have a collection reference // 143
if (!ref.collection) // 144
throw new Meteor.Error(404, "Not Found", "No collection found"); // 145
// 146
// Make sure we have a file reference // 147
if (ref.file === null) { // 148
// No id supplied so we will create a new FS.File instance and // 149
// insert the supplied data. // 150
return FS.HTTP.Handlers.PutInsert.apply(this, [ref]); // 151
} else { // 152
if (ref.file) { // 153
return FS.HTTP.Handlers.PutUpdate.apply(this, [ref]); // 154
} else { // 155
throw new Meteor.Error(404, "Not Found", 'No file found'); // 156
} // 157
} // 158
}, // 159
'get': function(data) { // 160
// Use the selector for finding the collection and file reference // 161
var ref = selectorFunction.call(this); // 162
// 163
// Make sure we have a collection reference // 164
if (!ref.collection) // 165
throw new Meteor.Error(404, "Not Found", "No collection found"); // 166
// 167
// Make sure we have a file reference // 168
if (ref.file === null) { // 169
// No id supplied so we will return the published list of files ala // 170
// http.publish in json format // 171
return FS.HTTP.Handlers.GetList.apply(this, [ref]); // 172
} else { // 173
if (ref.file) { // 174
return FS.HTTP.Handlers.Get.apply(this, [ref]); // 175
} else { // 176
throw new Meteor.Error(404, "Not Found", 'No file found'); // 177
} // 178
} // 179
}, // 180
'delete': function(data) { // 181
// Use the selector for finding the collection and file reference // 182
var ref = selectorFunction.call(this); // 183
// 184
// Make sure we have a collection reference // 185
if (!ref.collection) // 186
throw new Meteor.Error(404, "Not Found", "No collection found"); // 187
// 188
// Make sure we have a file reference // 189
if (ref.file) { // 190
return FS.HTTP.Handlers.Del.apply(this, [ref]); // 191
} else { // 192
throw new Meteor.Error(404, "Not Found", 'No file found'); // 193
} // 194
} // 195
}; // 196
// 197
var accessPoints = {}; // 198
// 199
// Add debug message // 200
FS.debug && console.log('Registered HTTP method URLs:'); // 201
// 202
FS.Utility.each(mountPoints, function(mountPoint) { // 203
// Couple mountpoint and accesspoint // 204
accessPoints[mountPoint] = accessPoint; // 205
// Remember our mountpoints // 206
_existingMountPoints[mountPoint] = mountPoint; // 207
// Add debug message // 208
FS.debug && console.log(mountPoint); // 209
}); // 210
// 211
// XXX: HTTP:methods should unmount existing mounts in case of overwriting? // 212
HTTP.methods(accessPoints); // 213
// 214
}; // 215
// 216
/** // 217
* @method FS.HTTP.unmount // 218
* @public // 219
* @param {string | array of string} [mountPoints] Optional, if not specified all mountpoints are unmounted // 220
* // 221
*/ // 222
FS.HTTP.unmount = function(mountPoints) { // 223
// The mountPoints is optional, can be string or array if undefined then // 224
// _existingMountPoints will be used // 225
var unmountList; // 226
// Container for the mount points to unmount // 227
var unmountPoints = {}; // 228
// 229
if (typeof mountPoints === 'undefined') { // 230
// Use existing mount points - unmount all // 231
unmountList = _existingMountPoints; // 232
} else if (mountPoints === ''+mountPoints) { // 233
// Got a string // 234
unmountList = [mountPoints]; // 235
} else if (mountPoints.length) { // 236
// Got an array // 237
unmountList = mountPoints; // 238
} // 239
// 240
// If we have a list to unmount // 241
if (unmountList) { // 242
// Iterate over each item // 243
FS.Utility.each(unmountList, function(mountPoint) { // 244
// Check _existingMountPoints to make sure the mount point exists in our // 245
// context / was created by the FS.HTTP.mount // 246
if (_existingMountPoints[mountPoint]) { // 247
// Mark as unmount // 248
unmountPoints[mountPoint] = false; // 249
// Release // 250
delete _existingMountPoints[mountPoint]; // 251
} // 252
}); // 253
FS.debug && console.log('FS.HTTP.unmount:'); // 254
FS.debug && console.log(unmountPoints); // 255
// Complete unmount // 256
HTTP.methods(unmountPoints); // 257
} // 258
}; // 259
// 260
// ### FS.Collection maps on HTTP pr. default on the following restpoints: // 261
// * // 262
// baseUrl + '/files/:collectionName/:id/:filename', // 263
// baseUrl + '/files/:collectionName/:id', // 264
// baseUrl + '/files/:collectionName' // 265
// // 266
// Change/ replace the existing mount point by: // 267
// ```js // 268
// // unmount all existing // 269
// FS.HTTP.unmount(); // 270
// // Create new mount point // 271
// FS.HTTP.mount([ // 272
// '/cfs/files/:collectionName/:id/:filename', // 273
// '/cfs/files/:collectionName/:id', // 274
// '/cfs/files/:collectionName' // 275
// ]); // 276
// ``` // 277
// // 278
mountUrls = function mountUrls() { // 279
// We unmount first in case we are calling this a second time // 280
FS.HTTP.unmount(); // 281
// 282
FS.HTTP.mount([ // 283
baseUrl + '/files/:collectionName/:id/:filename', // 284
baseUrl + '/files/:collectionName/:id', // 285
baseUrl + '/files/:collectionName' // 286
]); // 287
}; // 288
// 289
// Returns the userId from URL token // 290
var expirationAuth = function expirationAuth() { // 291
var self = this; // 292
// 293
// Read the token from '/hello?token=base64' // 294
var encodedToken = self.query.token; // 295
// 296
FS.debug && console.log("token: "+encodedToken); // 297
// 298
if (!encodedToken || !Meteor.users) return false; // 299
// 300
// Check the userToken before adding it to the db query // 301
// Set the this.userId // 302
var tokenString = FS.Utility.atob(encodedToken); // 303
// 304
var tokenObject; // 305
try { // 306
tokenObject = JSON.parse(tokenString); // 307
} catch(err) { // 308
throw new Meteor.Error(400, 'Bad Request'); // 309
} // 310
// 311
// XXX: Do some check here of the object // 312
var userToken = tokenObject.authToken; // 313
if (userToken !== ''+userToken) { // 314
throw new Meteor.Error(400, 'Bad Request'); // 315
} // 316
// 317
// If we have an expiration token we should check that it's still valid // 318
if (tokenObject.expiration != null) { // 319
// check if its too old // 320
var now = Date.now(); // 321
if (tokenObject.expiration < now) { // 322
FS.debug && console.log('Expired token: ' + tokenObject.expiration + ' is less than ' + now); // 323
throw new Meteor.Error(500, 'Expired token'); // 324
} // 325
} // 326
// 327
// We are not on a secure line - so we have to look up the user... // 328
var user = Meteor.users.findOne({ // 329
$or: [ // 330
{'services.resume.loginTokens.hashedToken': Accounts._hashLoginToken(userToken)}, // 331
{'services.resume.loginTokens.token': userToken} // 332
] // 333
}); // 334
// 335
// Set the userId in the scope // 336
return user && user._id; // 337
}; // 338
// 339
HTTP.methods( // 340
{'/cfs/servertime': { // 341
get: function(data) { // 342
return Date.now().toString(); // 343
} // 344
} // 345
}); // 346
// 347
// Unify client / server api // 348
FS.HTTP.now = function() { // 349
return Date.now(); // 350
}; // 351
// 352
// Start up the basic mount points // 353
Meteor.startup(function () { // 354
mountUrls(); // 355
}); // 356
// 357
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}).call(this);
///////////////////////////////////////////////////////////////////////
}).call(this);
/* Exports */
if (typeof Package === 'undefined') Package = {};
Package['wekan-cfs-access-point'] = {};
})();
+2 -2
View File
@@ -1,5 +1,5 @@
apiVersion: v2
appVersion: "5.76"
appVersion: "6.13"
dependencies:
- condition: mongodb.enabled
name: mongodb
@@ -21,4 +21,4 @@ name: wekan
sources:
- https://github.com/wekan/wekan
type: application
version: 1.1.0
version: 1.1.1
+48 -11
View File
@@ -1,12 +1,38 @@
# Helm Chart for Wekan
# WeKan ® - Open Source kanban
## Installing the Chart
To install the chart with the release name `my-release`:
```bash
helm repo add wekan https://wekan.github.io/charts
helm install my-release wekan/wekan
```
These commands deploy Wekan on the Kubernetes cluster in the default configuration.
Tip: List all releases using `helm list`
For all available values see `helm show values wekan/wekan`.
## Uninstalling the Chart
To uninstall/delete the my-release deployment:
```bash
helm delete my-release
```
The command removes all the Kubernetes components associated with the chart and
deletes the release.
## Features
o Uses a MongoDB replica set by default - this allows fault-tolerant
* Uses a MongoDB replica set by default - this allows fault-tolerant
and scalable MongoDB deployment (or just set the replicas to 1 for
a single server install)
o Optional Horizontal Pod Autoscaler (HPA), so that your Wekan pods
* Optional Horizontal Pod Autoscaler (HPA), so that your Wekan pods
will scale automatically with increased CPU load.
## The configurable values (values.yaml)
@@ -19,7 +45,9 @@ Scaling Wekan:
replicaCount: 1
```
**replicaCount** Will set the initial number of replicas for the Wekan pod (and container)
**replicaCount** will set the initial number of replicas for the Wekan pod
(and container)
```yaml
## Configure an horizontal pod autoscaler
@@ -34,13 +62,17 @@ autoscaling:
##
targetCPUUtilizationPercentage: 80
```
This section (if *enabled* is set to **true**) will enable the Kubernetes Horizontal Pod Autoscaler (HPA).
**minReplicas:** this is the minimum number of pods to scale down to (We recommend setting this to the same value as **replicaCount**).
This section (if *enabled* is set to **true**) will enable the Kubernetes
Horizontal Pod Autoscaler (HPA).
**minReplicas:** this is the minimum number of pods to scale down to
(We recommend setting this to the same value as **replicaCount**).
**maxReplicas:** this is the maximum number of pods to scale up to.
**targetCPUUtilizationPercentage:** This is the CPU at which the HPA will scale-out the number of Wekan pods.
**targetCPUUtilizationPercentage:** This is the CPU at which the HPA will
scale-out the number of Wekan pods.
```yaml
mongodb-replicaset:
@@ -55,11 +87,16 @@ mongodb-replicaset:
This section controls the scale of the MongoDB redundant Replica Set.
**replicas:** This is the number of MongoDB instances to include in the set. You can set this to 1 for a single server - this will still allow you to scale-up later with a helm upgrade.
**replicas:** This is the number of MongoDB instances to include in the set.
You can set this to 1 for a single server - this will still allow you to
scale-up later with a helm upgrade.
### Install OCP route
If you use this chart to deploy Wekan on an OCP cluster, you can create route instead of ingress with following command:
``` bash
$ helm template --set route.enabled=true,ingress.enabled=false values.yaml . | oc apply -f-
If you use this chart to deploy Wekan on an OCP cluster, you can create route
instead of ingress with following command:
```bash
helm template --set route.enabled=true,ingress.enabled=false values.yaml . | \
oc apply -f-
```
-1
View File
@@ -1 +0,0 @@
+7 -6
View File
@@ -2,7 +2,8 @@
{{- $fullName := include "wekan.fullname" . -}}
{{- $servicePort := .Values.service.port -}}
{{- $ingressPath := .Values.ingress.path -}}
apiVersion: networking.k8s.io/v1beta1
{{- $ingressPathType := .Values.ingress.pathtype -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ $fullName }}
@@ -27,17 +28,17 @@ spec:
secretName: {{ .secretName }}
{{- end }}
{{- end }}
backend:
serviceName: {{ $fullName }}
servicePort: 8080
rules:
{{- range .Values.ingress.hosts }}
- host: {{ . }}
http:
paths:
- path: {{ $ingressPath }}
pathType: {{ $ingressPathType }}
backend:
serviceName: {{ $fullName }}
servicePort: 8080
service:
name: {{ $fullName }}
port:
number: 8080
{{- end }}
{{- end }}
Loaded 100 of 455 files, more files were not shown because too many files have changed in this diff. Show more