Compare commits

...
180 Commits
Author SHA1 Message Date
Lauri Ojansivu 4879df0244 v4.02 2020-05-15 20:20:29 +03:00
Lauri Ojansivu 3bdeaaf552 Update translations. 2020-05-15 20:08:34 +03:00
Lauri Ojansivu 9c6cd51ca7 Merge branch 'marc1006-fixes' 2020-05-14 01:06:46 +03:00
Lauri Ojansivu ea74a34d72 Add popup and changelog for linked card fixes. 2020-05-14 01:04:52 +03:00
Lauri Ojansivu 28cffc4328 Update translations. 2020-05-14 01:04:21 +03:00
Lauri Ojansivu 0a12319002 Merge branch 'fixes' of https://github.com/marc1006/wekan into marc1006-fixes 2020-05-14 00:22:22 +03:00
Lauri Ojansivu 2f33e3a76b Update ChangeLog. 2020-05-13 23:52:30 +03:00
Lauri Ojansivu 96507e6777 Add Spanish (Chile).
Thanks to isos.

Update translations.
2020-05-13 23:48:53 +03:00
Lauri Ojansivu e6d6b5322e Update translations. 2020-05-13 23:22:32 +03:00
Lauri Ojansivu b8d8081ded Update ChangeLog. 2020-05-13 22:06:39 +03:00
Lauri Ojansivu 0e428233f2 Merge pull request #3088 from krupupakku/master
Swimlanes ID missing in new boards
2020-05-13 22:02:24 +03:00
Lauri Ojansivu fdbc1b5c22 Update translations. 2020-05-13 19:37:37 +03:00
mvolo17 ea0239538a Swimlanes ID missing in new boards
when creating a new card in a new board there were and error on console. Result: card was not created. adding this parenthesis it works now.
Just for info. without this change if you want to create a card you need to change view to swimlines and go back to list view
2020-05-13 12:44:40 +02:00
Lauri Ojansivu aa084b7a7e Merge branch 'brymut-add-more-import-export-options' 2020-05-13 05:27:28 +03:00
Lauri Ojansivu 8a2509007c Fix syntax. Maybe sometime later think about translations.
Thanks to xet7 !
2020-05-13 05:25:04 +03:00
Lauri Ojansivu d0208b2112 Update translations. 2020-05-13 04:25:22 +03:00
Lauri Ojansivu 851bfa53e6 Merge branch 'add-more-import-export-options' of https://github.com/brymut/wekan into brymut-add-more-import-export-options 2020-05-13 03:28:02 +03:00
Lauri Ojansivu ba01ebe05d Update ChangeLog. 2020-05-13 03:20:32 +03:00
Lauri Ojansivu e6a2ffc592 Merge branch 'master' of github.com:wekan/wekan 2020-05-13 03:17:11 +03:00
Lauri Ojansivu f90ca00669 Update translations. 2020-05-13 03:16:58 +03:00
Lauri Ojansivu bbb65ae4e2 Merge pull request #3084 from wackazong/master-patch-1
Create card does not allow an empty member list
2020-05-13 03:16:37 +03:00
Lauri Ojansivu eece32d51b Merge branch 'NicoP-S-master' 2020-05-13 03:07:05 +03:00
Lauri Ojansivu 1865bdbee9 Update translations and fix syntax. 2020-05-13 03:06:04 +03:00
Lauri Ojansivu 85f254da38 Merge branch 'master' of https://github.com/NicoP-S/wekan into NicoP-S-master 2020-05-13 02:57:36 +03:00
Lauri Ojansivu 1fe7394d05 Update ChangeLog. 2020-05-13 02:52:33 +03:00
Lauri Ojansivu 6b9a7a3fc1 Merge branch 'krupupakku-master' 2020-05-13 02:51:04 +03:00
Lauri Ojansivu 8f33517142 Merge branch 'master' of https://github.com/krupupakku/wekan into krupupakku-master 2020-05-13 02:46:57 +03:00
Lauri Ojansivu 0a51ea753f Update ChangeLog. 2020-05-13 02:45:10 +03:00
Lauri Ojansivu 235bedab00 Merge branch 'helioguardabaxo-master' 2020-05-13 02:43:16 +03:00
Lauri Ojansivu 564e1919af Merge branch 'master' of https://github.com/helioguardabaxo/wekan into helioguardabaxo-master 2020-05-13 02:39:38 +03:00
Lauri Ojansivu 1c9dd7233e Update translations. 2020-05-12 21:31:42 +03:00
Lauri Ojansivu 6e7a58b204 Update ChangeLog. 2020-05-12 21:26:19 +03:00
Lauri Ojansivu 75bdd33fda Update dependencies.
Thanks to xet7 !
2020-05-12 21:21:22 +03:00
Lauri Ojansivu 5f915ef966 Add options to rebuild-wekan.sh to run Meteor in development mode
where after file change it rebuilds.

Thanks to xet7 !
2020-05-12 19:05:51 +03:00
Bryan Mutai a570c4a861 add: export board/cards/lists to CSV/TSV 2020-05-10 23:58:15 +03:00
wackazong a797abaa36 Create card does not allow an empty member list
When I create a card via the API I always have the authorId in members, even if I pass an empty string as member list. Workaround: I can empty the member list by passing an empty string in a PUT request. This pull request proposes to not add the authorId to the member list when creating a card and the member list is empty.
2020-05-08 18:55:37 +02:00
Marco Volo 2bb5a31fa4 avatar-image fix 2020-05-08 15:25:31 +02:00
Bryan Mutai 1742bcd9b1 add: import board/cards/lists using CSV/TSV 2020-05-07 01:31:59 +03:00
Nico ec03bbe260 API add boards to json where user is member of 2020-05-03 01:29:28 +02:00
Nico 3cc0a93e0e Card vote options in new fork 2020-05-03 00:33:15 +02:00
helioguardabaxo 079867ff37 Add white-space:normal to copy-to-clipboard button in card details 2020-05-02 14:48:49 -03:00
Lauri Ojansivu 533bc045d0 Update translations. 2020-04-30 07:26:13 +03:00
Lauri Ojansivu b5773232d5 Remove extra file. 2020-04-30 07:09:58 +03:00
Lauri Ojansivu 3042d2ff9a Update ChangeLog. 2020-04-30 07:03:43 +03:00
Lauri Ojansivu 8d5adc0464 Install Wekan to mobile homescreen icon and use fullscreen PWA.
Docs at https://github.com/wekan/wekan/wiki/PWA

Thanks to xet7 !

Closes #2879
2020-04-30 06:54:48 +03:00
Marc Hartmayer 9cba640120 Fix typo 2020-04-30 01:59:57 +02:00
Marc Hartmayer b740381a72 Refuse to delete a card as long as there is link to it
This fixes https://github.com/wekan/wekan/issues/2785.
2020-04-30 01:59:44 +02:00
Marc Hartmayer 2691f033cb Fix creation of card links
Without this fix, orphaned card links are created and therefore this leads to
problems as described in https://github.com/wekan/wekan/issues/2785.
2020-04-30 01:59:04 +02:00
Lauri Ojansivu c7d4a90d5c Update ChangeLog. 2020-04-29 18:33:42 +03:00
Lauri Ojansivu 92dd6bbba2 Update ChangeLog. 2020-04-29 16:34:51 +03:00
Lauri Ojansivu e42adcaed0 Merge pull request #3066 from marc1006/shortcuts
Fix shortcuts list and support card shortcuts when hovering a card
2020-04-29 16:32:59 +03:00
Marc Hartmayer 301d96f392 Support card shortcuts when hovering a card 2020-04-29 15:17:43 +02:00
Marc Hartmayer 1c488cb8a7 Fix shortcuts mapping in the shortcuts list
Shorcuts are case-sensitive therefore let's fix the keys in the shortcuts list.
2020-04-29 15:14:56 +02:00
Lauri Ojansivu 9e33d8cbab Update ChangeLog 2020-04-28 23:56:51 +03:00
Lauri Ojansivu 4c3907bd41 Merge pull request #3061 from marc1006/fix
Fix getStartDayOfWeek once again :)
2020-04-28 23:53:24 +03:00
Marc Hartmayer 153d729544 Fix getStartDayOfWeek function
In case profile.startDayOfWeek is 0 it's evaluated to false and 1 is returned.
Let's fix this by differentiating between undefined and an actual value.

Fixes: 9ae20a3f51
2020-04-28 20:56:11 +02:00
Lauri Ojansivu 3d5abd60cc v4.01 2020-04-28 19:02:42 +03:00
Lauri Ojansivu 1d89e96dd1 Upgrade to Node v12.16.3
Thanks to Node developers and xet7 !
2020-04-28 18:58:01 +03:00
Lauri Ojansivu bc3696b64a Update translations. 2020-04-28 15:22:12 +03:00
Lauri Ojansivu f803520c76 Update ChangeLog. 2020-04-28 15:17:09 +03:00
Lauri Ojansivu 6afc9259f0 Smaller height for Add Board button.
Thanks to xet7 !
2020-04-28 15:14:10 +03:00
Lauri Ojansivu 47df8d6737 Update translations. 2020-04-28 03:57:28 +03:00
Lauri Ojansivu d2dfd9c3b9 Update ChangeLog. 2020-04-28 03:53:43 +03:00
Lauri Ojansivu 63f501c574 Merge pull request #3056 from marc1006/header_height_fix
Fix list header height when cards count is shown
2020-04-28 03:51:18 +03:00
Lauri Ojansivu 6aa0aa50dc Update ChangeLog. 2020-04-28 03:38:27 +03:00
Lauri Ojansivu 9ae20a3f51 Fix Cards and Users docs not generated because of syntax error and new Javascript syntax.
Wekan uses wekan/releases/generate-docs*.sh Python code to generate OpenAPI docs,
it did not show any errors while generating docs, only left out parts of API docs.

Thanks to pvcon13 and xet7 !
2020-04-28 03:24:18 +03:00
Lauri Ojansivu 280e66947e Fix Docker builds.
Thanks to xet7 !
2020-04-27 16:14:02 +03:00
Marc Hartmayer 9b9e3c9e0c Fix list header height when cards count is shown 2020-04-27 14:22:26 +02:00
Lauri Ojansivu 1696bd688e v4.00 2020-04-27 03:35:38 +03:00
Lauri Ojansivu 63ad79a784 Merge pull request #3052 from marc1006/360px
Make sure that the board header buttons fit into one line
2020-04-27 03:29:27 +03:00
Marc Hartmayer f7a0d15db7 Make sure that the board header buttons fit into one line
...even for devices with 360px width resolution.
2020-04-27 02:21:48 +02:00
Lauri Ojansivu 6a7cb809f4 v3.99 2020-04-27 03:20:36 +03:00
Lauri Ojansivu 3244c3c32b Update translations. 2020-04-27 03:12:24 +03:00
Lauri Ojansivu 09666585e2 Revert part 2, related https://github.com/wekan/wekan/pull/3048 2020-04-27 02:56:11 +03:00
Lauri Ojansivu ee106d1cb4 Revert In Progress additional vote features. Translations are not removed.
Thanks to xet7 !

Related https://github.com/wekan/wekan/pull/3048
2020-04-27 02:54:40 +03:00
Lauri Ojansivu 8ef435c83e Update translations related to vote feature. Code variables not changed.
Thanks to xet7 !

Related https://github.com/wekan/wekan/pull/3048
2020-04-27 02:37:33 +03:00
Lauri Ojansivu 3a74b88294 Update ChangeLog. 2020-04-27 02:27:28 +03:00
Lauri Ojansivu c5079096b5 Merge branch 'master' of github.com:wekan/wekan 2020-04-27 02:23:42 +03:00
Lauri Ojansivu 927e43ab3f Merge pull request #3051 from marc1006/3049
Reactivate the touch event fix for the boards list
2020-04-27 02:23:00 +03:00
Marc Hartmayer eddcb2260b Reactivate the touch event fix for the boards list
This fixes https://github.com/wekan/wekan/issues/3049.
2020-04-27 01:16:13 +02:00
Lauri Ojansivu ff73aa4566 Merge branch 'NicoP-S-master' 2020-04-26 17:18:41 +03:00
Nico de993a079d Remove old code 2020-04-26 02:44:14 +02:00
Nico 7bb0aa7488 Additional vote features 2020-04-26 02:41:26 +02:00
Nico fe7398faef Put checkbox and label in same row 2020-04-26 02:37:18 +02:00
NicoP-S 8e709c1b79 Merge pull request #6 from wekan/master
Update
2020-04-26 00:37:30 +02:00
Lauri Ojansivu 3908fe0ab8 v3.98 2020-04-25 16:44:45 +03:00
Lauri Ojansivu 5d2ff89e9b Update ChangeLog. 2020-04-25 15:26:46 +03:00
Lauri Ojansivu 7f38bc7b95 Merge pull request #3046 from marc1006/3041
Partially fixes https://github.com/wekan/wekan/issues/3041
2020-04-25 15:21:50 +03:00
Marc Hartmayer ed0c64a270 Allow words in title/description to be able to break and wrap onto the next line 2020-04-25 13:34:30 +02:00
Marc Hartmayer e63e7b1131 Allow variable height for board list items
This fixes https://github.com/wekan/wekan/issues/3041.
2020-04-25 13:34:30 +02:00
Lauri Ojansivu 3f7d9fd42c Update ChangeLog. 2020-04-25 14:23:29 +03:00
Lauri Ojansivu 867344f070 Update translations. 2020-04-25 14:19:26 +03:00
Lauri Ojansivu a84195179e Merge pull request #3045 from marc1006/mobile_followup
Follow-up for https://github.com/wekan/wekan/pull/3040
2020-04-25 14:15:58 +03:00
Marc Hartmayer f1b18d79cd Don't interpret dragging an element as a click
Remove `enableClickOnTouch` as this behavior is not intuitive.
2020-04-25 09:49:41 +02:00
Marc Hartmayer 6d1cdebfe2 Make it compatible with newer and older versions of jQuery sortable
While at it, fix comments and prettify it.
2020-04-25 09:49:10 +02:00
Lauri Ojansivu 7cf8487f57 Merge branch 'master' of github.com:wekan/wekan 2020-04-25 04:16:45 +03:00
Lauri Ojansivu 5403027c9d Update ChangeLog. 2020-04-25 04:16:29 +03:00
Lauri Ojansivu daf397a1ba Merge pull request #3044 from VictorioBerra/patch-1
Fix comment typo in docker-compose.yml
2020-04-25 04:11:07 +03:00
Lauri Ojansivu 6104c1711f Update translations. 2020-04-25 03:58:48 +03:00
Lauri Ojansivu db41e41d90 Update ChangeLog. 2020-04-25 03:53:16 +03:00
Lauri Ojansivu 1235363465 Fix Wekan not load at all in Firefox v.68 for Android.
Thanks to xet7 !

Closes #3021
2020-04-25 03:47:44 +03:00
Lauri Ojansivu 7263d7497f Merge branch 'marc1006-mobile' 2020-04-25 01:41:37 +03:00
Lauri Ojansivu 666186fee8 Merge branch 'mobile' of https://github.com/marc1006/wekan into marc1006-mobile 2020-04-25 01:41:04 +03:00
Victorio Berra 27d1b5acca Fix comment typo in docker-compose.yml
webbroser -> web browser.
2020-04-24 09:07:32 -05:00
Lauri Ojansivu 5eb5ca5752 Update translations. 2020-04-23 18:38:57 +03:00
Lauri Ojansivu 16d371b814 Update ChangeLog. 2020-04-23 14:21:06 +03:00
Lauri Ojansivu df9b4db49d Merge branch 'marc1006-one_apply' 2020-04-23 14:17:57 +03:00
Lauri Ojansivu 2e8e58004d Merge branch 'one_apply' of https://github.com/marc1006/wekan into marc1006-one_apply 2020-04-23 14:17:35 +03:00
Lauri Ojansivu a83aa6162b Update ChangeLog. 2020-04-23 14:16:27 +03:00
Lauri Ojansivu 07c915ccf0 Merge pull request #3038 from marc1006/fix
Fix getStartDayOfWeek function
2020-04-23 14:14:09 +03:00
Marc Hartmayer 405f176bbb Fix getStartDayOfWeek function
In case profile.startDayOfWeek is 0 it's evaluated to false and 1 is returned.
Let's fix this by differentiating between undefined and an actual value.
2020-04-23 10:40:53 +02:00
Marc Hartmayer 6476503137 Fix drag-and-drop and scrolling on mobile devices
Use drag handles on "miniscreens" whenever useful, this is especially useful on
mobile device. This should hopefully fix https://github.com/wekan/wekan/issues/2947.
While at it, simplify the condition

 Utils.isMiniScreen() ||
   (!Utils.isMiniScreen() && showDesktopDragHandles)

 to

  Utils.isMiniScreen() || showDesktopDragHandle
2020-04-23 03:02:03 +02:00
Marc Hartmayer 981ed546f1 Newer versions of jQuery sortable use uiSortable key
Newer versions of jQuery sortable use `uiSortable` as key to store the data.
Let's adapt the code. While at it, refactor the code.
2020-04-23 02:55:33 +02:00
Marc Hartmayer c1287248a6 Mobile device layout fix 2020-04-23 02:55:24 +02:00
Marc Hartmayer 52f884f2b1 Use only one 'Apply' button for applying the user settings 2020-04-23 00:20:16 +02:00
Lauri Ojansivu 4550e10fbe Revert Snap MongoDB changes.
Thanks to xet7 !
2020-04-22 22:43:20 +03:00
Lauri Ojansivu 2efe974195 Update ChangeLog. 2020-04-22 21:50:35 +03:00
Lauri Ojansivu 6b808dd74b Try to upgrade MongoDB version in Snap.
Thanks to xet7 !
2020-04-22 21:48:46 +03:00
Lauri Ojansivu 8a917e0efc Update ChangeLog. 2020-04-22 21:37:33 +03:00
Lauri Ojansivu d1f98d0c47 Upgrade to Meteor 1.10.2
Thanks to Meteor developers and xet7 !
2020-04-22 21:35:13 +03:00
Lauri Ojansivu 323de77a83 Update ChangeLog. 2020-04-22 21:29:53 +03:00
Lauri Ojansivu 738e7f9ebc Merge branch 'boeserwolf-feature-add-babel' 2020-04-22 21:26:06 +03:00
Lauri Ojansivu b5b4af73a9 Merge branch 'feature-add-babel' of https://github.com/boeserwolf/wekan into boeserwolf-feature-add-babel 2020-04-22 21:25:49 +03:00
Lauri Ojansivu ab1014b7d8 Update ChangeLog. 2020-04-22 21:24:13 +03:00
Lauri Ojansivu 12964aa742 Update translations. 2020-04-22 21:16:28 +03:00
Lauri Ojansivu e4b1106acd Update ChangeLog. 2020-04-22 21:07:49 +03:00
Lauri Ojansivu d0524532a4 Merge branch 'master' of github.com:wekan/wekan 2020-04-22 21:05:58 +03:00
Lauri Ojansivu 7de18eccea - Set Snap MongoDB compatibility to 4.2 according to Meteor ChangeLog.
Thanks to xet7 !
2020-04-22 21:05:34 +03:00
Lauri Ojansivu f9747bc908 - Set Snap MongoDB compatibility to 4.2.5 according to Meteor ChangeLog.
Thanks to xet7 !
2020-04-22 21:03:47 +03:00
Lauri Ojansivu 6fd827792a Update ChangeLog. 2020-04-22 21:03:01 +03:00
Lauri Ojansivu 9e95c06415 Fix lint errors in lint error fix.
Thanks to xet7 !
2020-04-22 21:00:31 +03:00
Lauri Ojansivu e7603298d7 Merge branch 'marc1006-week_start' 2020-04-22 20:36:28 +03:00
Marc Hartmayer 8e14459cff Implement option to change the first day of week in user settings
Implements #2535.
2020-04-22 19:16:05 +02:00
Marc Hartmayer 3ac5dba243 Set first day of the week to Monday 2020-04-22 19:12:34 +02:00
Lauri Ojansivu 9969c89b1c Update ChangeLog. 2020-04-22 20:09:07 +03:00
Lauri Ojansivu 5a5b19d4fc Merge pull request #3031 from marc1006/style_issues
Multiple lint issue fixes
2020-04-22 20:06:50 +03:00
Lauri Ojansivu 4d48fa4d95 Update ChangeLog. 2020-04-22 16:43:47 +03:00
boeserwolf 57545f66d2 Add babel to build chain and linter
Enables fancy Javascript language features like optional chaining,
for developer happiness.
2020-04-22 15:16:30 +02:00
Lauri Ojansivu 8586c843a4 Merge pull request #3030 from boeserwolf/master
Pre-fill the title of checklists (Trello-style)
2020-04-22 16:08:06 +03:00
Marc Hartmayer b2acc3ba45 Multiple lint issue fixes
Found by using the command `meteor npm run lint:eslint:fix`.
2020-04-21 18:15:29 +02:00
boeserwolf 9f0273aa44 Pre-fill the title of checklists (Trello-style) 2020-04-21 00:58:15 +03:00
Lauri Ojansivu 3407b0e65b Add links to FAQ. 2020-04-20 16:22:29 +03:00
Lauri Ojansivu 6cd92ab2c6 v3.97 2020-04-19 17:05:41 +03:00
Lauri Ojansivu e92ebe5151 Update ChangeLog. 2020-04-19 16:52:06 +03:00
Lauri Ojansivu 8cb838c0de Merge branch 'boeserwolf-feature-sortable-boards' 2020-04-19 16:31:12 +03:00
Lauri Ojansivu 6cae14d6e9 Merge branch 'feature-sortable-boards' of https://github.com/boeserwolf/wekan into boeserwolf-feature-sortable-boards 2020-04-19 16:30:27 +03:00
boeserwolf b42d8346cd Insert new boards at last position 2020-04-19 15:53:13 +03:00
boeserwolf 1a065ff351 Refactor variable names 2020-04-19 15:52:43 +03:00
boeserwolf 3565ff2700 Export sort field 2020-04-19 15:52:06 +03:00
boeserwolf e354715a9d Remove sorting by _id 2020-04-19 15:51:29 +03:00
Lauri Ojansivu e7002f417b Update translations. 2020-04-19 14:00:24 +03:00
boeserwolf ef5f38f431 Make boards sortable 2020-04-19 13:49:10 +03:00
boeserwolf b3efa71d13 Add move function to boards mutations 2020-04-19 13:49:10 +03:00
boeserwolf 10fcc19b7f Add sortDefault helper for sorting boards 2020-04-19 13:49:07 +03:00
Lauri Ojansivu 948f05fecb Update ChangeLog. 2020-04-19 12:23:29 +03:00
Lauri Ojansivu 927bb83813 Merge pull request #3025 from boeserwolf/master
Make linked card clickable
2020-04-19 12:14:48 +03:00
boeserwolf 9f396e9038 Add a migration to add a sort field to the boards model 2020-04-19 10:51:58 +03:00
boeserwolf 2400c91013 Add sort field to boards model 2020-04-19 10:48:44 +03:00
boeserwolf f583645744 Make linked card clickable 2020-04-19 10:33:41 +03:00
Lauri Ojansivu 42b3cff99f Update ChangeLog. 2020-04-17 22:14:09 +03:00
Lauri Ojansivu 960fe5163b Remove old warning from Sandstorm import board data loss, because bug has been already fixed.
Thanks to aputsiaq and xet7 !
2020-04-17 21:58:19 +03:00
Lauri Ojansivu 41665c079d Update ChangeLog. 2020-04-17 21:48:06 +03:00
Lauri Ojansivu 8a0defc988 Merge pull request #3024 from marc1006/card_layout_fix
Improve card layout on mobile devices
2020-04-17 21:38:50 +03:00
Marc Hartmayer d7e0350ecf Improve card layout on mobile devices 2020-04-17 19:49:43 +02:00
Lauri Ojansivu bf15fa988d Rename Dockerfile.amd64 back to Dockerfile, because automatic builds did not work.
Thanks to xet7 !
2020-04-17 18:34:41 +03:00
Lauri Ojansivu db2d59181c Update ChangeLog. 2020-04-17 10:21:41 +03:00
Lauri Ojansivu dcc9a0d498 Merge branch 'brokencode64-arm64-dockerfile' 2020-04-17 10:18:53 +03:00
Lauri Ojansivu 936dea591a Merge branch 'arm64-dockerfile' of https://github.com/brokencode64/wekan into brokencode64-arm64-dockerfile 2020-04-17 10:18:30 +03:00
Lauri Ojansivu cf7e5472ba Update translations. 2020-04-17 10:10:40 +03:00
Lauri Ojansivu 5c61119716 Update ChangeLog. 2020-04-17 10:08:45 +03:00
Lauri Ojansivu 3558d711ff Merge pull request #3020 from ckavili/master
oidc server is updated to work with OCP OAuth
2020-04-17 10:02:38 +03:00
thewoosterisroot 72c1c49da3 Adding dockerfiles for multi-arch builds and manifest. 2020-04-16 19:30:50 +02:00
Cansu Kavili 93f8ff946f updated with env and annotation parameters 2020-04-15 09:54:22 +02:00
Cansu Kavili 61d582ffd9 updated with env and annotation parameters 2020-04-15 09:52:34 +02:00
Cansu Kavili 60384be5ff add annotations if specified in values file 2020-04-15 09:50:30 +02:00
Cansu Kavili 8ac305778a Add env parameters if specified in values file 2020-04-15 09:50:07 +02:00
Lauri Ojansivu 5be93741ee Update ChangeLog. 2020-04-15 03:44:30 +03:00
Lauri Ojansivu c2f91baaf9 Merge pull request #3019 from devinsm/mobile-friendly-checklist
Allows for use of checklist on mobile
2020-04-15 03:40:14 +03:00
Devin McAllester 9df5c0e2de Allows for use of checklist on mobile 2020-04-14 17:05:58 -07:00
Cansu Kavili 2c792363bf ocp hack added 2020-04-13 14:03:19 +02:00
160 changed files with 48349 additions and 40998 deletions

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
{
"presets": [
"@babel/preset-stage-3"
]
}
+3 -3
View File
@@ -1,4 +1,4 @@
FROM ubuntu:disco
FROM ubuntu:rolling
LABEL maintainer="sgr"
ENV BUILD_DEPS="gnupg gosu bsdtar wget curl bzip2 g++ build-essential python git ca-certificates iproute2"
@@ -6,8 +6,8 @@ ENV DEBIAN_FRONTEND=noninteractive
ENV \
DEBUG=false \
NODE_VERSION=8.17.0 \
METEOR_RELEASE=1.8.1 \
NODE_VERSION=12.16.3 \
METEOR_RELEASE=1.10.2 \
USE_EDGE=false \
METEOR_EDGE=1.5-beta.17 \
NPM_VERSION=latest \
+1
View File
@@ -11,6 +11,7 @@
"browser": true,
"meteor": true
},
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
+257
View File
@@ -0,0 +1,257 @@
name: wekan
version: 0
version-script: git describe --tags | cut -c 2-
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
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://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1604-4.2.6.tgz
plugin: dump
stage-packages: [libssl1.0.0, libcurl3]
filesets:
mongo:
- usr
- bin
- lib
stage:
- $mongo
prime:
- $mongo
wekan:
source: .
plugin: nodejs
node-engine: 12.16.3
node-packages:
- node-gyp
- node-pre-gyp
- fibers
build-packages:
- ca-certificates
- apt-utils
- 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
# Create the OpenAPI specification
rm -rf .build
## Use Meteor 1.8.x on Snap
#rm -rf .meteor
#mv .snap-meteor-1.8/.meteor .
#mv .snap-meteor-1.8/package.json .
#mv .snap-meteor-1.8/package-lock.json .
## Meteor 1.9.x has changes to Buffer() => Buffer.alloc(), so reverting those
#mv .snap-meteor-1.8/cfs_access-point.txt fix-download-unicode/
#mv .snap-meteor-1.8/export.js models/
#mv .snap-meteor-1.8/wekanCreator.js models/
#mv .snap-meteor-1.8/ldap.js packages/wekan-ldap/server/ldap.js
#mv .snap-meteor-1.8/oidc_server.js packages/wekan-oidc/oidc_server.js
rm -rf .snap-meteor-1.8
#mkdir -p .build/python
#cd .build/python
#git clone --depth 1 -b master https://github.com/Kronuz/esprima-python
#cd esprima-python
#python3 setup.py install
#cd ../../..
#mkdir -p ./public/api
#python3 ./openapi/generate_openapi.py --release $(git describe --tags --abbrev=0) > ./public/api/wekan.yml
# we temporary need api2html and mkdirp
#npm install -g api2html@0.3.0
#npm install -g mkdirp
#api2html -c ./public/logo-header.png -o ./public/api/wekan.html ./public/api/wekan.yml
#npm uninstall -g mkdirp
#npm uninstall -g api2html
# Node Fibers 100% CPU usage issue:
# https://github.com/wekan/wekan-mongodb/issues/2#issuecomment-381453161
# https://github.com/meteor/meteor/issues/9796#issuecomment-381676326
# https://github.com/sandstorm-io/sandstorm/blob/0f1fec013fe7208ed0fd97eb88b31b77e3c61f42/shell/server/00-startup.js#L99-L129
# Also see beginning of wekan/server/authentication.js
# import Fiber from "fibers";
# Fiber.poolSize = 1e9;
# OLD: Download node version 8.12.0 prerelease build => Official node 8.12.0 has been released
# Description at https://releases.wekan.team/node.txt
##echo "375bd8db50b9c692c0bbba6e96d4114cd29bee3770f901c1ff2249d1038f1348 node" >> node-SHASUMS256.txt.asc
##curl https://releases.wekan.team/node -o node
# Verify Fibers patched node authenticity
##echo "Fibers 100% CPU issue patched node authenticity:"
##grep node node-SHASUMS256.txt.asc | shasum -a 256 -c -
##rm -f node-SHASUMS256.txt.asc
##chmod +x node
##mv node `which node`
# DOES NOT WORK: paxctl fix.
# Removed from build-packages: - paxctl
#echo "Applying paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303"
#paxctl -mC `which node`
#echo "Installing npm"
#curl -L https://www.npmjs.com/install.sh | sh
echo "Installing meteor"
curl https://install.meteor.com/ -o install_meteor.sh
#sed -i "s|RELEASE=.*|RELEASE=\"1.8.1-beta.0\"|g" install_meteor.sh
chmod +x install_meteor.sh
sh install_meteor.sh
rm install_meteor.sh
# REPOS BELOW ARE INCLUDED TO WEKAN REPO
#if [ ! -d "packages" ]; then
# mkdir packages
#fi
#if [ ! -d "packages/kadira-flow-router" ]; then
# cd packages
# git clone --depth 1 -b master https://github.com/wekan/flow-router.git kadira-flow-router
# cd ..
#fi
#if [ ! -d "packages/meteor-useraccounts-core" ]; then
# cd packages
# git clone --depth 1 -b master https://github.com/meteor-useraccounts/core.git meteor-useraccounts-core
# sed -i 's/api\.versionsFrom/\/\/api.versionsFrom/' meteor-useraccounts-core/package.js
# cd ..
#fi
#if [ ! -d "packages/meteor-accounts-cas" ]; then
# cd packages
# git clone --depth 1 -b master https://github.com/wekan/meteor-accounts-cas.git meteor-accounts-cas
# cd ..
#fi
#if [ ! -d "packages/wekan-ldap" ]; then
# cd packages
# git clone --depth 1 -b master https://github.com/wekan/wekan-ldap.git
# cd ..
#fi
#if [ ! -d "packages/wekan-scrollbar" ]; then
# cd packages
# git clone --depth 1 -b master https://github.com/wekan/wekan-scrollbar.git
# cd ..
#fi
#if [ ! -d "packages/wekan_accounts-oidc" ]; then
# cd packages
# git clone --depth 1 -b master https://github.com/wekan/meteor-accounts-oidc.git
# mv meteor-accounts-oidc/packages/switch_accounts-oidc wekan-accounts-oidc
# mv meteor-accounts-oidc/packages/switch_oidc wekan-oidc
# rm -rf meteor-accounts-oidc
# cd ..
#fi
#if [ ! -d "packages/markdown" ]; then
# cd packages
# git clone --depth 1 -b master --recurse-submodules https://github.com/wekan/markdown.git
# cd ..
#fi
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
#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
#cd .build/bundle/programs/server/npm/node_modules/meteor/npm-bcrypt
#rm -rf node_modules/bcrypt
#meteor npm install --save bcrypt
# Change from npm-bcrypt directory back to .build/bundle/programs/server directory.
#cd ../../../../
# Change to directory .build/bundle/programs/server
cd .build/bundle/programs/server
npm install
npm install --allow-superuser --save babel-runtime
#meteor npm install --save bcrypt
# 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
# Meteor 1.8.x additional .swp remove
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
+1 -1
View File
@@ -83,7 +83,7 @@ parts:
wekan:
source: .
plugin: nodejs
node-engine: 12.14.1
node-engine: 12.14.3
node-packages:
- node-gyp
- node-pre-gyp
+3 -3
View File
@@ -6,7 +6,7 @@
meteor-base@1.4.0
# Build system
ecmascript@0.14.2
ecmascript@0.14.3
standard-minifier-css@1.6.0
standard-minifier-js@2.6.0
mquandalle:jade
@@ -23,7 +23,7 @@ dburles:collection-helpers
idmontie:migrations
matb33:collection-hooks
matteodem:easy-search
mongo@1.9.0
mongo@1.10.0
mquandalle:collection-mutations
# Account system
@@ -72,7 +72,7 @@ simple:rest-accounts-password
useraccounts:core
email@1.2.3
horka:swipebox
dynamic-import@0.5.1
dynamic-import@0.5.2
staringatlights:fast-render
accounts-password@1.6.0
+1 -1
View File
@@ -1 +1 @@
METEOR@1.10.1
METEOR@1.10.2
+7 -7
View File
@@ -104,13 +104,13 @@ meteorspark:util@0.2.0
minifier-css@1.5.0
minifier-js@2.6.0
minifiers@1.1.8-faster-rebuild.0
minimongo@1.5.0
minimongo@1.6.0
mobile-status-bar@1.1.0
modern-browsers@0.1.5
modules@0.15.0
modules-runtime@0.12.0
momentjs:moment@2.24.0
mongo@1.9.1
momentjs:moment@2.25.2
mongo@1.10.0
mongo-decimal@0.1.1
mongo-dev-server@1.1.0
mongo-id@1.0.7
@@ -127,7 +127,7 @@ mquandalle:mousetrap-bindglobal@0.0.1
mquandalle:perfect-scrollbar@0.6.5_2
msavin:usercache@1.8.0
npm-bcrypt@0.9.3
npm-mongo@3.7.0
npm-mongo@3.7.1
oauth@1.3.0
oauth2@1.3.0
observe-sequence@1.0.16
@@ -162,11 +162,11 @@ simple:json-routes@2.1.0
simple:rest-accounts-password@1.1.2
simple:rest-bearer-token-parser@1.0.1
simple:rest-json-error-handler@1.0.1
socket-stream-client@0.2.3
socket-stream-client@0.3.0
softwarerero:accounts-t9n@1.3.11
spacebars@1.0.15
spacebars-compiler@1.1.3
srp@1.0.12
srp@1.1.0
standard-minifier-css@1.6.0
standard-minifier-js@2.6.0
staringatlights:fast-render@3.2.0
@@ -181,7 +181,7 @@ tracker@1.2.0
twbs:bootstrap@3.3.6
ui@1.0.13
underscore@1.0.10
url@1.2.0
url@1.3.0
useraccounts:core@1.14.2
useraccounts:flow-routing@1.14.2
useraccounts:unstyled@1.14.2
+2 -2
View File
@@ -1,9 +1,9 @@
dist: eoan
dist: focal
sudo: required
env:
TRAVIS_DOCKER_COMPOSE_VERSION: 1.24.0
TRAVIS_NODE_VERSION: 12.16.2
TRAVIS_NODE_VERSION: 12.16.3
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 = bg_BG:bg, en_GB:en-GB, es_AR:es-AR, el_GR:el, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, no:nb, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, sl_SI:sl, zh_CN:zh-CN, zh_TW:zh-TW, zh_HK:zh-HK
lang_map = bg_BG:bg, en_GB:en-GB, es_AR:es-AR, es_CL:es-CL, el_GR:el, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, no:nb, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, sl_SI:sl, zh_CN:zh-CN, zh_TW:zh-TW, zh_HK:zh-HK
[wekan.application]
file_filter = i18n/<lang>.i18n.json
+171
View File
@@ -1,3 +1,174 @@
# v4.02 2020-05-15 Wekan release
This release adds the following server platforms:
- [Android arm64/x64](https://github.com/wekan/wekan/wiki/Android).
Thanks to xet7.
and adds the following features:
- [Install Wekan to mobile homescreen icon and use fullscreen
PWA](https://github.com/wekan/wekan/commit/8d5adc04645e3e71423f16869f39b8d79969bccd).
[Docs for iOS and Android at wiki PWA page](https://github.com/wekan/wekan/wiki/PWA).
Thanks to xet7.
- [Add options to rebuild-wekan.sh to run Meteor in development mode where after
file change it rebuilds](https://github.com/wekan/wekan/commit/5f915ef966170ea7baca7ddeb11319bc08a26fef).
Thanks to xet7.
and adds the following updates:
- [Update dependencies](https://github.com/wekan/wekan/commit/75bdd33fda58ea0233f5b38c466bcb1a9b0406ab).
Thanks to xet7.
and adds the following translations:
- [Add Spanish (Chile)](https://github.com/wekan/wekan/commit/96507e6777ed77a324eaec9799c5b46b0d25ad26).
Thanks to isos, Transifex user.
and fixes the following bugs:
- [Fix Deleting linked card makes board not load](https://github.com/wekan/wekan/issues/2785).
Thanks to marc1006 and xet7.
- [Fix getStartDayOfWeek once again](https://github.com/wekan/wekan/pull/3061).
Thanks to marc1006.
- [Fix shortcuts list and support card shortcuts when hovering
a card](https://github.com/wekan/wekan/pull/3066).
Thanks to marc1006.
- [Add white-space:normal to copy-to-clipboard button in card
details](https://github.com/wekan/wekan/pull/3075).
Thanks to helioguardabaxo.
- [Fix avatar-image class](https://github.com/wekan/wekan/pull/3083).
Thanks to krupupakku.
- [Fix Swimlanes ID missing in new boards](https://github.com/wekan/wekan/pull/3088).
Thanks to krupupakku.
- [Fix REST API so Create card does now allow an empty member
list](https://github.com/wekan/wekan/pull/3084).
Thanks to wackazong.
Thanks to above GitHub users for their contributions and translators for their translations.
# v4.01 2020-04-28 Wekan release
This release adds the following updates:
- [Upgrade to Node v12.16.3](https://github.com/wekan/wekan/commit/1d89e96dd101c11913f1acdd6d16b5650eaf18a7).
Thanks to Node developers and xet7.
and fixes the following bugs:
- [Fix Docker builds](https://github.com/wekan/wekan/commit/280e66947e3afa878c41e876cf827ebcec81a2c6).
Thanks to xet7.
- [Fix Cards and Users API docs at https://wekan.github.io/api/ not generated because of
syntax error and new Javascript syntax](https://github.com/wekan/wekan/commit/9ae20a3f51e63c29f536e2f5b3e66a2c7d88c691).
Wekan uses wekan/releases/generate-docs*.sh Python code to generate OpenAPI docs,
it did not show any errors while generating docs, only left out parts of API docs.
This affected Wekan versions v3.94-v4.00.
Thanks to pvcon13 and xet7.
- [Fix list header height when cards count is shown](https://github.com/wekan/wekan/pull/3056).
Thanks to marc1006.
- [Smaller height for Add Board button](https://github.com/wekan/wekan/commit/6afc9259f084717a0cc3ce6d66979fd7c1471939).
Thanks to xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v4.00 2020-04-27 Wekan release
This release fixes the following bugs:
- [Make sure that the board header buttons fit into one line even for devices with 360px width
resolution](https://github.com/wekan/wekan/pull/3052).
Thanks to marc1006.
Thanks to above GitHub users for their contributions and translators for their translations.
# v3.99 2020-04-27 Wekan release
This release fixes the following bugs:
- [Fix Boards are very hard to tap in mobile](https://github.com/wekan/wekan/pull/3051).
Thanks to marc1006.
Thanks to above GitHub users for their contributions and translators for their translations.
# v3.98 2020-04-25 Wekan release
News:
- There is now many mobile and desktop webbrowser fixes. Please test does your
favourite Javascript enabled webbrowser work, and add issues if something
does not work, and there is no existing issue about that yet.
- Desktop browser mode has setting for Show/Hide drag handles:
top right click username / Change Settings / Show desktop drag handles.
You can request desktop website also at mobile webbrowsers on Android.
At iOS requesting desktop website did not seem to work yet.
- At iOS Safari and Chrome, to see swimlane buttons you need to scroll to right.
Fixes to this and other issues are welcome as pull request.
This release adds the following new features:
- [Pre-fill the title of checklists (Trello-style)](https://github.com/wekan/wekan/pull/3030).
Thanks to boeserwolf.
- [Implement option to change the first day of the week in user settings](https://github.com/wekan/wekan/pull/3032).
Thanks to marc1006.
- [Add babel to build chain and linter. Enables fancy Javascript language
features like optional chaining, for developer happiness](https://github.com/wekan/wekan/pull/3034).
Thanks to boeserwolf.
- [Use only one 'Apply' button for applying the user settings](https://github.com/wekan/wekan/pull/3039).
Thanks to marc1006.
- [Allow variable height for board list items. Allow words in title/description to be able to break
and wrap onto the next line](https://github.com/wekan/wekan/pull/3046).
Thanks to marc1006.
and adds the following updates:
- [Upgrade to Meteor 1.10.2](https://github.com/wekan/wekan/commit/d1f98d0c472fb41e25fb29a9a6f6dae7db003f6f).
Thanks to Meteor developers and xet7.
- [Set Snap MongoDB compatibility to 4.2 according to Meteor ChangeLog](https://github.com/wekan/wekan/commit/7de18eccea3854db3be6197bf21afbfd3ddb65a6).
Thanks to xet7.
and fixes the following bugs:
- [Multiple lint issue fixes](https://github.com/wekan/wekan/pull/3031).
Thanks to marc1006.
- [Fix lint errors in lint error fix](https://github.com/wekan/wekan/commit/9e95c06415e614e587d684ff9660cc53c5f8c8d3).
Thanks to xet7.
- [Fix getStartDayOfWeek function](https://github.com/wekan/wekan/pull/3038).
Thanks to marc1006 and boeserwolf.
- Improve mobile devices support [Part1](https://github.com/wekan/wekan/pull/3040) and [Part2](https://github.com/wekan/wekan/pull/3045).
Thanks to marc1006.
- [Fix Wekan not load at all in Firefox v.68 for Android](https://github.com/wekan/wekan/commit/1235363465b824d26129d4aa74a4445f362c1a73).
Thanks to xet7.
- [Fix comment typo in docker-compose.yml](https://github.com/wekan/wekan/pull/3044).
Thanks to VictorioBerra.
Thanks to above GitHub users for their contributions and translators for their translations.
# v3.97 2020-04-19 Wekan release
This release adds the following new features:
- [Sortable boards](https://github.com/wekan/wekan/pull/3027).
Thanks to boeserwolf.
- [Added dockerfiles for multi-arch builds and manifest](https://github.com/wekan/wekan/pull/3023).
[In Progress](https://github.com/wekan/wekan/issues/2999).
Thanks to brokencode64.
- [Make linked card clickable](https://github.com/wekan/wekan/pull/3025).
Thanks to boeserwolf.
and fixes the following bugs:
- [Fix using checklists on mobile and iPad](https://github.com/wekan/wekan/pull/3019).
Thanks to devinsm.
- [Improve card layout on mobile devices](https://github.com/wekan/wekan/pull/3024).
Thanks to marc1006.
- [Make OCP OAuth work with Openshift 4.x](https://github.com/wekan/wekan/pull/3020).
Thanks to ckavili.
- [Remove old warning from Sandstorm import board data loss, because bug has been already
fixed](https://github.com/wekan/wekan/commit/960fe5163b6a2f7c3dca03b5e31d69611b49f079).
Thanks to aputsiaq and xet7.
Thanks to above GitHub users for their contributions and translators for their translations.
# v3.96 2020-04-15 Wekan release
This release adds the following Sandstorm updates:
+6 -2
View File
@@ -4,10 +4,12 @@ LABEL maintainer="wekan"
# Set the environment variables (defaults where required)
# DOES NOT WORK: paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
# ENV BUILD_DEPS="paxctl"
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.16.2 \
METEOR_RELEASE=1.10-rc.2 \
NODE_VERSION=v12.16.3 \
METEOR_RELEASE=1.10.2 \
USE_EDGE=false \
METEOR_EDGE=1.5-beta.17 \
NPM_VERSION=latest \
@@ -271,6 +273,8 @@ RUN \
cd /home/wekan/app_build/bundle/programs/server/ && \
gosu wekan:wekan npm install && \
#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 && \
mv /home/wekan/app_build/bundle /build && \
\
# Put back the original tar
+77
View File
@@ -0,0 +1,77 @@
FROM amd64/alpine:3.7 AS builder
# Set the environment variables for builder
ENV QEMU_VERSION=v4.2.0-6 \
QEMU_ARCHITECTURE=aarch64 \
NODE_ARCHITECTURE=linux-arm64 \
NODE_VERSION=v12.16.3 \
WEKAN_VERSION=3.96 \
WEKAN_ARCHITECTURE=arm64
# Install dependencies
RUN apk update && apk add ca-certificates outils-sha1 && \
\
# Download qemu static for our architecture
wget https://github.com/multiarch/qemu-user-static/releases/download/${QEMU_VERSION}/qemu-${QEMU_ARCHITECTURE}-static.tar.gz -O - | tar -xz && \
\
# Download wekan and shasum
wget https://releases.wekan.team/raspi3/wekan-${WEKAN_VERSION}-${WEKAN_ARCHITECTURE}.zip && \
wget https://releases.wekan.team/raspi3/SHA256SUMS.txt && \
# Verify wekan
grep wekan-${WEKAN_VERSION}-${WEKAN_ARCHITECTURE}.zip SHA256SUMS.txt | sha256sum -c - && \
\
# Unzip wekan
unzip wekan-${WEKAN_VERSION}-${WEKAN_ARCHITECTURE}.zip && \
\
# Download node and shasums
wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-${NODE_ARCHITECTURE}.tar.gz && \
wget https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt.asc && \
\
# Verify nodejs authenticity
grep node-${NODE_VERSION}-${NODE_ARCHITECTURE}.tar.gz SHASUMS256.txt.asc | sha256sum -c - && \
\
# Extract node and remove tar.gz
tar xvzf node-${NODE_VERSION}-${NODE_ARCHITECTURE}.tar.gz
# Build wekan dockerfile
FROM arm64v8/ubuntu:19.10
LABEL maintainer="wekan"
# Set the environment variables (defaults where required)
ENV QEMU_ARCHITECTURE=aarch64 \
NODE_ARCHITECTURE=linux-arm64 \
NODE_VERSION=v12.16.1 \
NODE_ENV=production \
NPM_VERSION=latest \
WITH_API=true \
PORT=8080 \
ROOT_URL=http://localhost \
MONGO_URL=mongodb://127.0.0.1:27017/wekan
# Copy qemu-static to image
COPY --from=builder qemu-${QEMU_ARCHITECTURE}-static /usr/bin
# Copy the app to the image
COPY --from=builder bundle /home/wekan/bundle
# Copy
COPY --from=builder node-${NODE_VERSION}-${NODE_ARCHITECTURE} /opt/nodejs
RUN \
set -o xtrace && \
# Add non-root user wekan
useradd --user-group --system --home-dir /home/wekan wekan && \
\
# Install Node
ln -s /opt/nodejs/bin/node /usr/bin/node && \
ln -s /opt/nodejs/bin/npm /usr/bin/npm && \
mkdir -p /opt/nodejs/lib/node_modules/fibers/.node-gyp /root/.node-gyp/8.16.1 /home/wekan/.config && \
chown wekan --recursive /home/wekan/.config && \
\
# Install Node dependencies
npm install -g npm@${NPM_VERSION}
EXPOSE $PORT
USER wekan
CMD ["node", "/home/wekan/bundle/main.js"]
+1 -1
View File
@@ -34,7 +34,7 @@ and PWA app that can be added as icon on Android and bookmark on iOS, used like
**NOTE**:
- Please read the [FAQ](https://github.com/wekan/wekan/wiki/FAQ) first
- Please don't feed the trolls and spammers that are mentioned in the FAQ :)
- Please don't feed the [trolls](https://github.com/wekan/wekan/wiki/FAQ#why-am-i-called-a-troll) and [spammers](https://github.com/wekan/wekan/wiki/FAQ#why-am-i-called-a-spammer) that are mentioned in the FAQ :)
## About Wekan
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v3.96.0"
appVersion: "v4.02.0"
files:
userUploads:
- README.md
+6
View File
@@ -0,0 +1,6 @@
// PWA
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/pwa-service-worker.js');
});
}
+1 -1
View File
@@ -7,7 +7,7 @@ BlazeComponent.extendComponent({
return Boards.find(
{ archived: true },
{
sort: ['title'],
sort: { sort: 1 /* boards default sorting */ },
},
);
},
+3 -7
View File
@@ -1,7 +1,7 @@
import { Cookies } from 'meteor/ostrio:cookies';
const cookies = new Cookies();
const subManager = new SubsManager();
const { calculateIndex, enableClickOnTouch } = Utils;
const { calculateIndex } = Utils;
const swimlaneWhileSortingHeight = 150;
BlazeComponent.extendComponent({
@@ -191,9 +191,6 @@ BlazeComponent.extendComponent({
},
});
// ugly touch event hotfix
enableClickOnTouch('.js-swimlane:not(.placeholder)');
this.autorun(() => {
let showDesktopDragHandles = false;
currentUser = Meteor.user();
@@ -205,7 +202,7 @@ BlazeComponent.extendComponent({
} else {
showDesktopDragHandles = false;
}
if (!Utils.isMiniScreen() && showDesktopDragHandles) {
if (Utils.isMiniScreen() || showDesktopDragHandles) {
$swimlanesDom.sortable({
handle: '.js-swimlane-header-handle',
});
@@ -215,9 +212,8 @@ BlazeComponent.extendComponent({
});
}
// Disable drag-dropping if the current user is not a board member or is miniscreen
// Disable drag-dropping if the current user is not a board member
$swimlanesDom.sortable('option', 'disabled', !userIsMember());
$swimlanesDom.sortable('option', 'disabled', Utils.isMiniScreen());
});
function userIsMember() {
+2 -2
View File
@@ -1,10 +1,10 @@
template(name="boardList")
.wrapper
ul.board-list.clearfix
ul.board-list.clearfix.js-boards
li.js-add-board
a.board-list-item.label {{_ 'add-board'}}
each boards
li(class="{{#if isStarred}}starred{{/if}}" class=colorClass)
li(class="{{#if isStarred}}starred{{/if}}" class=colorClass).js-board
if isInvited
.board-list-item
span.details
+63 -12
View File
@@ -1,4 +1,5 @@
const subManager = new SubsManager();
const { calculateIndex, enableClickOnTouch } = Utils;
Template.boardListHeaderBar.events({
'click .js-open-archived-board'() {
@@ -7,8 +8,8 @@ Template.boardListHeaderBar.events({
});
Template.boardListHeaderBar.helpers({
title(){
return FlowRouter.getRouteName() == 'home' ? 'my-boards' :'public';
title() {
return FlowRouter.getRouteName() === 'home' ? 'my-boards' : 'public';
},
templatesBoardId() {
return Meteor.user() && Meteor.user().getTemplatesBoardId();
@@ -23,20 +24,70 @@ BlazeComponent.extendComponent({
Meteor.subscribe('setting');
},
onRendered() {
function userIsAllowedToMove() {
return Meteor.user();
}
const itemsSelector = '.js-board:not(.placeholder)';
const $boards = this.$('.js-boards');
$boards.sortable({
connectWith: '.js-boards',
tolerance: 'pointer',
appendTo: '.board-list',
helper: 'clone',
distance: 7,
items: itemsSelector,
placeholder: 'board-wrapper placeholder',
start(evt, ui) {
ui.helper.css('z-index', 1000);
ui.placeholder.height(ui.helper.height());
EscapeActions.executeUpTo('popup-close');
},
stop(evt, ui) {
// To attribute the new index number, we need to get the DOM element
// 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 boardDomElement = ui.item.get(0);
const board = Blaze.getData(boardDomElement);
// Normally the jquery-ui sortable library moves the dragged DOM element
// to its new position, which disrupts Blaze reactive updates mechanism
// (especially when we move the last card of a list, or when multiple
// users move some cards at the same time). To prevent these UX glitches
// we ask sortable to gracefully cancel the move, and to put back the
// DOM in its initial state. The card move is then handled reactively by
// Blaze with the below query.
$boards.sortable('cancel');
board.move(sortIndex.base);
},
});
// ugly touch event hotfix
enableClickOnTouch(itemsSelector);
// Disable drag-dropping if the current user is not a board member or is comment only
this.autorun(() => {
$boards.sortable('option', 'disabled', !userIsAllowedToMove());
});
},
boards() {
let query = {
const query = {
archived: false,
type: 'board',
}
if (FlowRouter.getRouteName() == 'home')
query['members.userId'] = Meteor.userId()
else
query.permission = 'public'
};
if (FlowRouter.getRouteName() === 'home')
query['members.userId'] = Meteor.userId();
else query.permission = 'public';
return Boards.find(
query,
{ sort: ['title'] },
);
return Boards.find(query, {
sort: { sort: 1 /* boards default sorting */ },
});
},
isStarred() {
const user = Meteor.user();
+17 -3
View File
@@ -11,6 +11,19 @@ $spaceBetweenTiles = 16px
box-sizing: border-box
position: relative
&.placeholder:after
content: '';
display: block;
background: darken(white, 20%)
border-radius: 3px;
height: 106px;
margin: 8px;
&.ui-sortable-helper
cursor: grabbing
transform: rotate(4deg)
display: block !important
&.starred
.fa-star,
.fa-star-o
@@ -20,7 +33,7 @@ $spaceBetweenTiles = 16px
overflow: hidden;
background-color: #999
color: #f6f6f6
height: 90px
height: auto
font-size: 16px
line-height: 22px
border-radius: 3px
@@ -31,6 +44,7 @@ $spaceBetweenTiles = 16px
margin: ($spaceBetweenTiles/2)
position: relative
text-decoration: none
word-wrap: break-word
&.tile
background-size: auto
@@ -55,7 +69,7 @@ $spaceBetweenTiles = 16px
.label
font-weight: normal
line-height:90px
line-height: 56px
:hover
background-color:#939393
@@ -183,7 +197,7 @@ $spaceBetweenTiles = 16px
overflow: scroll
li
width: 50%
width: 50%
.board-list-item
overflow: hidden
+27
View File
@@ -386,3 +386,30 @@ CardEndDate.register('cardEndDate');
return this.date.get().format('l');
}
}.register('minicardEndDate'));
class VoteEndDate extends CardDate {
onCreated() {
super.onCreated();
const self = this;
self.autorun(() => {
self.date.set(moment(self.data().getVoteEnd()));
});
}
classes() {
const classes = 'end-date' + ' ';
return classes;
}
showDate() {
return this.date.get().format('l LT');
}
showTitle() {
return `${TAPi18n.__('card-end-on')} ${this.date.get().format('LLLL')}`;
}
events() {
return super.events().concat({
'click .js-edit-date': Popup.open('editVoteEndDate'),
});
}
}
VoteEndDate.register('voteEndDate');
+51 -32
View File
@@ -32,7 +32,7 @@ template(name="cardDetails")
// else
{{_ 'top-level-card'}}
if isLinkedCard
h3.linked-card-location
a.linked-card-location.js-go-to-linked-card
+viewer
| {{getBoardTitle}} > {{getTitle}}
@@ -202,9 +202,12 @@ template(name="cardDetails")
if getVoteQuestion
hr
.vote-title
h3
i.fa.fa-thumbs-up
card-details-item-title {{_ 'vote-question'}}
div.flex
h3
i.fa.fa-thumbs-up
| {{_ 'vote-question'}}
if getVoteEnd
+voteEndDate
.vote-result
if votePublic
a.card-label.card-label-green.js-show-positive-votes {{ voteCountPositive }}
@@ -212,10 +215,13 @@ template(name="cardDetails")
else
.card-label.card-label-green {{ voteCountPositive }}
.card-label.card-label-red {{ voteCountNegative }}
unless ($and currentBoard.isPublic voteAllowNonBoardMembers )
.card-label.card-label-gray {{ voteCount }} {{_ 'r-of' }} {{ currentBoard.activeMembers.length }}
+viewer
= getVoteQuestion
button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}") {{_ 'vote-for-it'}}
button.card-details-red.js-vote.js-vote-negative(class="{{#if $eq voteState false}}voted{{/if}}") {{_ 'vote-against'}}
if showVotingButtons
button.card-details-green.js-vote.js-vote-positive(class="{{#if voteState}}voted{{/if}}") {{_ 'vote-for-it'}}
button.card-details-red.js-vote.js-vote-negative(class="{{#if $eq voteState false}}voted{{/if}}") {{_ 'vote-against'}}
//- XXX We should use "editable" to avoid repetiting ourselves
if canModifyCard
@@ -333,16 +339,10 @@ template(name="cardDetailsActionsPopup")
//li: a.js-members {{_ 'card-edit-members'}}
//li: a.js-labels {{_ 'card-edit-labels'}}
//li: a.js-attachments {{_ 'card-edit-attachments'}}
if getVoteQuestion
li
a.js-cancel-voting
i.fa.fa-thumbs-up
| {{_ 'card-cancel-voting'}}
else
li
a.js-start-voting
i.fa.fa-thumbs-up
| {{_ 'card-start-voting'}}
li
a.js-start-voting
i.fa.fa-thumbs-up
| {{_ 'card-edit-voting'}}
li
a.js-custom-fields
i.fa.fa-list-alt
@@ -465,14 +465,14 @@ template(name="cardAssigneesPopup")
i.fa.fa-check
if currentUser.isWorker
ul.pop-over-list.js-card-assignee-list
li.item(class="{{#if currentUser.isCardAssignee}}active{{/if}}")
a.name.js-select-assignee(href="#")
+userAvatar(userId=currentUser._id)
span.full-name
= currentUser.profile.fullname
| (<span class="username">{{ currentUser.username }}</span>)
if currentUser.isCardAssignee
i.fa.fa-check
li.item(class="{{#if currentUser.isCardAssignee}}active{{/if}}")
a.name.js-select-assignee(href="#")
+userAvatar(userId=currentUser._id)
span.full-name
= currentUser.profile.fullname
| (<span class="username">{{ currentUser.username }}</span>)
if currentUser.isCardAssignee
i.fa.fa-check
template(name="userAvatarAssignee")
a.assignee.js-assignee(title="{{userData.profile.fullname}} ({{userData.username}})")
@@ -519,7 +519,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="{{ absoluteUrl }}" autofocus="autofocus")
button.js-copy-card-link-to-clipboard(class="btn") {{_ 'copy-card-link-to-clipboard'}}
button.js-copy-card-link-to-clipboard(class="btn" id="clipboard") {{_ 'copy-card-link-to-clipboard'}}
span.clearfix
br
h2 {{_ 'change-card-parent'}}
@@ -564,20 +564,39 @@ template(name="setCardColorPopup")
template(name="cardDeletePopup")
p {{_ "card-delete-pop"}}
unless archived
p {{_ "card-delete-suggest-archive"}}
p {{_ "card-delete-suggest-archive"}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
template(name="deleteVotePopup")
p {{_ "vote-delete-pop"}}
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
template(name="cardStartVotingPopup")
form.edit-vote-question
.fields
label(for="vote") {{_ 'vote-question'}}
input.js-vote-field#vote(type="text" name="vote" value="{{card.getVoteQuestion}}" autofocus)
label(for="vote-public") {{_ 'vote-public'}}
a.js-toggle-vote-public
.materialCheckBox#vote-public(name="vote-public")
input.js-vote-field#vote(type="text" name="vote" value="{{getVoteQuestion}}" autofocus disabled="{{#if getVoteQuestion}}disabled{{/if}}")
.check-div
a.flex(class="{{#if getVoteQuestion}}is-disabled{{else}}js-toggle-vote-allow-non-members{{/if}}")
.materialCheckBox#vote-allow-non-members(name="vote-allow-non-members" class="{{#if voteAllowNonBoardMembers}}is-checked{{/if}}")
span {{_ 'allowNonBoardMembers'}}
.check-div
a.flex(class="{{#if getVoteQuestion}}is-disabled{{else}}js-toggle-vote-public{{/if}}")
.materialCheckBox#vote-public(name="vote-public" class="{{#if votePublic}}is-checked{{/if}}")
span {{_ 'vote-public'}}
.check-div.flex
i.fa.fa-hourglass-end
a.js-end-date
span
| {{_ 'card-end'}}
unless getVoteEnd
i.fa.fa-plus
if getVoteEnd
+voteEndDate
button.primary.confirm.js-submit {{_ 'save'}}
//- button.js-remove-color.negate.wide.right {{_ 'delete'}}
button.primary.js-submit {{_ 'save'}}
if getVoteQuestion
button.js-remove-vote.negate.wide.right {{_ 'delete'}}
template(name="positiveVoteMembersPopup")
ul.pop-over-list.js-card-member-list
+121 -51
View File
@@ -1,5 +1,5 @@
const subManager = new SubsManager();
const { calculateIndexData, enableClickOnTouch } = Utils;
const { calculateIndexData } = Utils;
let cardColors;
Meteor.startup(() => {
@@ -54,22 +54,6 @@ BlazeComponent.extendComponent({
}
return null;
},
votePublic() {
const card = this.currentData();
if (card.vote)
return card.vote.public
return null
},
voteCountPositive() {
const card = this.currentData();
if (card.vote && card.vote.positive) return card.vote.positive.length;
return null;
},
voteCountNegative() {
const card = this.currentData();
if (card.vote && card.vote.negative) return card.vote.negative.length;
return null;
},
isWatching() {
const card = this.currentData();
return card.findWatcher(Meteor.userId());
@@ -149,6 +133,15 @@ BlazeComponent.extendComponent({
return result;
},
showVotingButtons() {
const card = this.currentData();
return (
(currentUser.isBoardMember() ||
(currentUser && card.voteAllowNonBoardMembers())) &&
!card.expiredVote()
);
},
onRendered() {
if (Meteor.settings.public.CARD_OPENED_WEBHOOK_ENABLED) {
// Send Webhook but not create Activities records ---
@@ -232,9 +225,6 @@ BlazeComponent.extendComponent({
},
});
// ugly touch event hotfix
enableClickOnTouch('.card-checklist-items .js-checklist');
const $subtasksDom = this.$('.card-subtasks-items');
$subtasksDom.sortable({
@@ -270,26 +260,21 @@ BlazeComponent.extendComponent({
},
});
// ugly touch event hotfix
enableClickOnTouch('.card-subtasks-items .js-subtasks');
function userIsMember() {
return Meteor.user() && Meteor.user().isBoardMember();
}
// Disable sorting if the current user is not a board member
this.autorun(() => {
if ($checklistsDom.data('sortable')) {
$checklistsDom.sortable('option', 'disabled', !userIsMember());
const disabled = !userIsMember() || Utils.isMiniScreen();
if (
$checklistsDom.data('uiSortable') ||
$checklistsDom.data('sortable')
) {
$checklistsDom.sortable('option', 'disabled', disabled);
}
if ($subtasksDom.data('sortable')) {
$subtasksDom.sortable('option', 'disabled', !userIsMember());
}
if ($checklistsDom.data('sortable')) {
$checklistsDom.sortable('option', 'disabled', Utils.isMiniScreen());
}
if ($subtasksDom.data('sortable')) {
$subtasksDom.sortable('option', 'disabled', Utils.isMiniScreen());
if ($subtasksDom.data('uiSortable') || $subtasksDom.data('sortable')) {
$subtasksDom.sortable('option', 'disabled', disabled);
}
});
},
@@ -379,6 +364,9 @@ BlazeComponent.extendComponent({
this.data().setRequestedBy('');
}
},
'click .js-go-to-linked-card'() {
Utils.goCardId(this.data().linkedId);
},
'click .js-member': Popup.open('cardMember'),
'click .js-add-members': Popup.open('cardMembers'),
'click .js-assignee': Popup.open('cardAssignee'),
@@ -388,7 +376,7 @@ BlazeComponent.extendComponent({
'click .js-start-date': Popup.open('editCardStartDate'),
'click .js-due-date': Popup.open('editCardDueDate'),
'click .js-end-date': Popup.open('editCardEndDate'),
'click .js-show-positive-votes':Popup.open('positiveVoteMembers'),
'click .js-show-positive-votes': Popup.open('positiveVoteMembers'),
'click .js-show-negative-votes': Popup.open('negativeVoteMembers'),
'mouseenter .js-card-details'() {
const parentComponent = this.parentComponent().parentComponent();
@@ -417,9 +405,9 @@ BlazeComponent.extendComponent({
const forIt = $(e.target).hasClass('js-vote-positive');
let newState = null;
if (
this.voteState() == null ||
(this.voteState() == false && forIt) ||
(this.voteState() == true && !forIt)
this.voteState() === null ||
(this.voteState() === false && forIt) ||
(this.voteState() === true && !forIt)
) {
newState = forIt;
}
@@ -617,11 +605,6 @@ Template.cardDetailsActionsPopup.events({
'click .js-copy-card': Popup.open('copyCard'),
'click .js-copy-checklist-cards': Popup.open('copyChecklistToManyCards'),
'click .js-set-card-color': Popup.open('setCardColor'),
'click .js-cancel-voting'(event) {
event.preventDefault();
this.unsetVote();
Popup.close();
},
'click .js-move-card-to-top'(event) {
event.preventDefault();
const minOrder = _.min(
@@ -655,7 +638,7 @@ Template.cardDetailsActionsPopup.events({
},
});
Template.editCardTitleForm.onRendered(function () {
Template.editCardTitleForm.onRendered(function() {
autosize(this.$('.js-edit-card-title'));
});
@@ -669,7 +652,7 @@ Template.editCardTitleForm.events({
},
});
Template.editCardRequesterForm.onRendered(function () {
Template.editCardRequesterForm.onRendered(function() {
autosize(this.$('.js-edit-card-requester'));
});
@@ -682,7 +665,7 @@ Template.editCardRequesterForm.events({
},
});
Template.editCardAssignerForm.onRendered(function () {
Template.editCardAssignerForm.onRendered(function() {
autosize(this.$('.js-edit-card-assigner'));
});
@@ -724,7 +707,7 @@ BlazeComponent.extendComponent({
_id: { $ne: Meteor.user().getTemplatesBoardId() },
},
{
sort: ['title'],
sort: { sort: 1 /* boards default sorting */ },
},
);
return boards;
@@ -822,7 +805,7 @@ Template.copyChecklistToManyCardsPopup.events({
// copy subtasks
cursor = Cards.find({ parentId: oldId });
cursor.forEach(function () {
cursor.forEach(function() {
'use strict';
const subtask = arguments[0];
subtask.parentId = _id;
@@ -900,7 +883,7 @@ BlazeComponent.extendComponent({
},
},
{
sort: ['title'],
sort: { sort: 1 /* boards default sorting */ },
},
);
return boards;
@@ -971,9 +954,25 @@ BlazeComponent.extendComponent({
}
}
},
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
'click .js-delete': Popup.afterConfirm('cardDelete', function() {
Popup.close();
Cards.remove(this._id);
// verify that there are no linked cards
if (Cards.find({ linkedId: this._id }).count() === 0) {
Cards.remove(this._id);
} else {
// TODO: Maybe later we can list where the linked cards are.
// Now here is popup with a hint that the card cannot be deleted
// as there are linked cards.
// Related:
// client/components/lists/listHeader.js about line 248
// https://github.com/wekan/wekan/issues/2785
const message = `${TAPi18n.__(
'delete-linked-card-before-this-card',
)} linkedId: ${
this._id
} at client/components/cards/cardDetails.js and https://github.com/wekan/wekan/issues/2785`;
alert(message);
}
Utils.goBoardId(this.boardId);
}),
'change .js-field-parent-board'(event) {
@@ -1006,22 +1005,93 @@ BlazeComponent.extendComponent({
events() {
return [
{
'click .js-end-date': Popup.open('editVoteEndDate'),
'submit .edit-vote-question'(evt) {
evt.preventDefault();
const voteQuestion = evt.target.vote.value;
const publicVote = $('#vote-public').hasClass('is-checked');
this.currentCard.setVoteQuestion(voteQuestion, publicVote);
const allowNonBoardMembers = $('#vote-allow-non-members').hasClass(
'is-checked',
);
const endString = this.currentCard.getVoteEnd();
this.currentCard.setVoteQuestion(
voteQuestion,
publicVote,
allowNonBoardMembers,
);
if (endString) {
this.currentCard.setVoteEnd(endString);
}
Popup.close();
},
'click .js-remove-vote': Popup.afterConfirm('deleteVote', () => {
event.preventDefault();
this.currentCard.unsetVote();
Popup.close();
}),
'click a.js-toggle-vote-public'(event) {
event.preventDefault();
$('#vote-public').toggleClass('is-checked');
},
'click a.js-toggle-vote-allow-non-members'(event) {
event.preventDefault();
$('#vote-allow-non-members').toggleClass('is-checked');
},
},
];
},
}).register('cardStartVotingPopup');
// editVoteEndDatePopup
(class extends DatePicker {
onCreated() {
super.onCreated(moment().format('YYYY-MM-DD HH:mm'));
this.data().getVoteEnd() && this.date.set(moment(this.data().getVoteEnd()));
}
events() {
return [
{
'submit .edit-date'(evt) {
evt.preventDefault();
// if no time was given, init with 12:00
const time =
evt.target.time.value ||
moment(new Date().setHours(12, 0, 0)).format('LT');
const dateString = `${evt.target.date.value} ${time}`;
const newDate = moment(dateString, 'L LT', true);
if (newDate.isValid()) {
// if active vote - store it
if (this.currentData().getVoteQuestion()) {
this._storeDate(newDate.toDate());
Popup.close();
} else {
this.currentData().vote = { end: newDate.toDate() }; // set vote end temp
Popup.back();
}
} else {
this.error.set('invalid-date');
evt.target.date.focus();
}
},
'click .js-delete-date'(evt) {
evt.preventDefault();
this._deleteDate();
Popup.close();
},
},
];
}
_storeDate(newDate) {
this.card.setVoteEnd(newDate);
}
_deleteDate() {
this.card.unsetVoteEnd();
}
}.register('editVoteEndDatePopup'));
// Close the card details pane by pressing escape
EscapeActions.register(
'detailsPane',
+11
View File
@@ -10,6 +10,9 @@ avatar-radius = 50%
left: -2000px
top: 0px
#clipboard
white-space: normal
.assignee
border-radius: 3px
display: block
@@ -37,6 +40,8 @@ avatar-radius = 50%
position: absolute
&.avatar-image
object-fit: cover;
object-position: center;
height: 100%
width: @height
@@ -94,6 +99,7 @@ avatar-radius = 50%
animation: flexGrowIn 0.1s
box-shadow: 0 0 7px 0 darken(white, 30%)
transition: flex-basis 0.1s
box-sizing: border-box
.mCustomScrollBox
padding-left: 0
@@ -336,6 +342,11 @@ card-details-color(background, color...)
.vote-title
display: flex
justify-content: space-between
.js-edit-date
align-self: baseline
margin-left: 5px
.vote-result
display: flex
.js-show-positive-votes
+2 -1
View File
@@ -88,7 +88,8 @@ template(name="checklistItems")
template(name='checklistItemDetail')
.js-checklist-item.checklist-item
if canModifyCard
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
.check-box-container
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}")
+viewer
= item.title
+20 -11
View File
@@ -1,4 +1,4 @@
const { calculateIndexData, enableClickOnTouch } = Utils;
const { calculateIndexData, capitalize } = Utils;
function initSorting(items) {
items.sortable({
@@ -36,9 +36,6 @@ function initSorting(items) {
checklistItem.move(checklistId, sortIndex.base);
},
});
// ugly touch event hotfix
enableClickOnTouch('.js-checklist-item:not(.placeholder)');
}
BlazeComponent.extendComponent({
@@ -54,14 +51,15 @@ BlazeComponent.extendComponent({
return Meteor.user() && Meteor.user().isBoardMember();
}
// Disable sorting if the current user is not a board member
// Disable sorting if the current user is not a board member or is a miniscreen
self.autorun(() => {
const $itemsDom = $(self.itemsDom);
if ($itemsDom.data('sortable')) {
$(self.itemsDom).sortable('option', 'disabled', !userIsMember());
}
if ($itemsDom.data('sortable')) {
$(self.itemsDom).sortable('option', 'disabled', Utils.isMiniScreen());
if ($itemsDom.data('uiSortable') || $itemsDom.data('sortable')) {
$(self.itemsDom).sortable(
'option',
'disabled',
!userIsMember() || Utils.isMiniScreen(),
);
}
});
},
@@ -177,6 +175,16 @@ BlazeComponent.extendComponent({
}
},
focusChecklistItem(event) {
// If a new checklist is created, pre-fill the title and select it.
const checklist = this.currentData().checklist;
if (!checklist) {
const textarea = event.target;
textarea.value = capitalize(TAPi18n.__('r-checklist'));
textarea.select();
}
},
events() {
const events = {
'click .toggle-delete-checklist-dialog'(event) {
@@ -196,6 +204,7 @@ BlazeComponent.extendComponent({
'submit .js-edit-checklist-item': this.editChecklistItem,
'click .js-delete-checklist-item': this.deleteItem,
'click .confirm-checklist-delete': this.deleteChecklist,
'focus .js-add-checklist-item': this.focusChecklistItem,
keydown: this.pressKey,
},
];
@@ -250,7 +259,7 @@ BlazeComponent.extendComponent({
events() {
return [
{
'click .js-checklist-item .check-box': this.toggleItem,
'click .js-checklist-item .check-box-container': this.toggleItem,
},
];
},
+4 -1
View File
@@ -113,6 +113,9 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
&:hover
background-color: darken(white, 8%)
.check-box-container
padding-right: 1px;
.check-box
margin: 0.1em 0 0 0;
&.is-checked
@@ -121,7 +124,7 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
.item-title
flex: 1
padding-left: 10px;
margin-left: 10px;
&.is-checked
color: #8c8c8c
font-style: italic
+4 -2
View File
@@ -4,8 +4,8 @@ template(name="minicard")
class="{{#if isLinkedBoard}}linked-board{{/if}}"
class="minicard-{{colorClass}}")
if isMiniScreen
//.handle
// .fa.fa-arrows
.handle
.fa.fa-arrows
unless isMiniScreen
if showDesktopDragHandles
.handle
@@ -103,7 +103,9 @@ template(name="minicard")
if getVoteQuestion
.badge.badge-state-image-only(title=getVoteQuestion)
span.badge-icon.fa.fa-thumbs-up
span.badge-text {{ voteCountPositive }}
span.badge-icon.fa.fa-thumbs-down
span.badge-text {{ voteCountNegative }}
if attachments.count
.badge
span.badge-icon.fa.fa-paperclip
@@ -0,0 +1,37 @@
export function getMembersToMap(data) {
// we will work on the list itself (an ordered array of objects) when a
// mapping is done, we add a 'wekan' field to the object representing the
// imported member
const membersToMap = [];
const importedMembers = [];
let membersIndex;
for (let i = 0; i < data[0].length; i++) {
if (data[0][i].toLowerCase() === 'members') {
membersIndex = i;
}
}
for (let i = 1; i < data.length; i++) {
if (data[i][membersIndex]) {
for (const importedMember of data[i][membersIndex].split(' ')) {
if (importedMember && importedMembers.indexOf(importedMember) === -1) {
importedMembers.push(importedMember);
}
}
}
}
for (let importedMember of importedMembers) {
importedMember = {
username: importedMember,
id: importedMember,
};
const wekanUser = Users.findOne({ username: importedMember.username });
if (wekanUser) importedMember.wekanId = wekanUser._id;
membersToMap.push(importedMember);
}
return membersToMap;
}
+1 -4
View File
@@ -13,11 +13,8 @@ template(name="import")
template(name="importTextarea")
form
p: label(for='import-textarea') {{_ instruction}} {{_ 'import-board-instruction-about-errors'}}
textarea.js-import-json(placeholder="{{_ 'import-json-placeholder'}}" autofocus)
textarea.js-import-json(placeholder="{{_ importPlaceHolder}}" autofocus)
| {{jsonText}}
if isSandstorm
h1.warning {{_ 'import-sandstorm-backup-warning'}}
p.warning {{_ 'import-sandstorm-warning'}}
input.primary.wide(type="submit" value="{{_ 'import'}}")
template(name="importMapMembers")
+40 -12
View File
@@ -1,5 +1,8 @@
import trelloMembersMapper from './trelloMembersMapper';
import wekanMembersMapper from './wekanMembersMapper';
import csvMembersMapper from './csvMembersMapper';
const Papa = require('papaparse');
BlazeComponent.extendComponent({
title() {
@@ -30,20 +33,30 @@ BlazeComponent.extendComponent({
}
},
importData(evt) {
importData(evt, dataSource) {
evt.preventDefault();
const dataJson = this.find('.js-import-json').value;
try {
const dataObject = JSON.parse(dataJson);
this.setError('');
this.importedData.set(dataObject);
const membersToMap = this._prepareAdditionalData(dataObject);
// store members data and mapping in Session
// (we go deep and 2-way, so storing in data context is not a viable option)
const input = this.find('.js-import-json').value;
if (dataSource === 'csv') {
const csv = input.indexOf('\t') > 0 ? input.replace(/(\t)/g, ',') : input;
const ret = Papa.parse(csv);
if (ret && ret.data && ret.data.length) this.importedData.set(ret.data);
else throw new Meteor.Error('error-csv-schema');
const membersToMap = this._prepareAdditionalData(ret.data);
this.membersToMap.set(membersToMap);
this.nextStep();
} catch (e) {
this.setError('error-json-malformed');
} else {
try {
const dataObject = JSON.parse(input);
this.setError('');
this.importedData.set(dataObject);
const membersToMap = this._prepareAdditionalData(dataObject);
// store members data and mapping in Session
// (we go deep and 2-way, so storing in data context is not a viable option)
this.membersToMap.set(membersToMap);
this.nextStep();
} catch (e) {
this.setError('error-json-malformed');
}
}
},
@@ -91,6 +104,9 @@ BlazeComponent.extendComponent({
case 'wekan':
membersToMap = wekanMembersMapper.getMembersToMap(dataObject);
break;
case 'csv':
membersToMap = csvMembersMapper.getMembersToMap(dataObject);
break;
}
return membersToMap;
},
@@ -109,11 +125,23 @@ BlazeComponent.extendComponent({
return `import-board-instruction-${Session.get('importSource')}`;
},
importPlaceHolder() {
const importSource = Session.get('importSource');
if (importSource === 'csv') {
return 'import-csv-placeholder';
} else {
return 'import-json-placeholder';
}
},
events() {
return [
{
submit(evt) {
return this.parentComponent().importData(evt);
return this.parentComponent().importData(
evt,
Session.get('importSource'),
);
},
},
];
+4 -18
View File
@@ -1,6 +1,6 @@
import { Cookies } from 'meteor/ostrio:cookies';
const cookies = new Cookies();
const { calculateIndex, enableClickOnTouch } = Utils;
const { calculateIndex } = Utils;
BlazeComponent.extendComponent({
// Proxy
@@ -114,9 +114,6 @@ BlazeComponent.extendComponent({
},
});
// ugly touch event hotfix
enableClickOnTouch(itemsSelector);
this.autorun(() => {
let showDesktopDragHandles = false;
currentUser = Meteor.user();
@@ -129,7 +126,7 @@ BlazeComponent.extendComponent({
showDesktopDragHandles = false;
}
if (!Utils.isMiniScreen() && showDesktopDragHandles) {
if (Utils.isMiniScreen() || showDesktopDragHandles) {
$cards.sortable({
handle: '.handle',
});
@@ -139,27 +136,16 @@ BlazeComponent.extendComponent({
});
}
if ($cards.data('sortable')) {
if ($cards.data('uiSortable') || $cards.data('sortable')) {
$cards.sortable(
'option',
'disabled',
// Disable drag-dropping when user is not member/is miniscreen
// Disable drag-dropping when user is not member
!userIsMember(),
// Not disable drag-dropping while in multi-selection mode
// MultiSelection.isActive() || !userIsMember(),
);
}
if ($cards.data('sortable')) {
$cards.sortable(
'option',
'disabled',
// Disable drag-dropping when user is not member/is miniscreen
Utils.isMiniScreen(),
// Not disable drag-dropping while in multi-selection mode
// MultiSelection.isActive() || !userIsMember(),
);
}
});
// We want to re-run this function any time a card is added.
+3 -3
View File
@@ -43,9 +43,6 @@
background: white
margin: -3px 0 8px
.list-header-card-count
height: 35px
.list-header-add
flex: 0 0 auto
padding: 20px 12px 4px
@@ -60,6 +57,9 @@
background-color: #e4e4e4;
border-bottom: 6px solid #e4e4e4;
&.list-header-card-count
min-height: 35px
height: auto
&.ui-sortable-handle
cursor: grab
+5 -8
View File
@@ -77,7 +77,7 @@ BlazeComponent.extendComponent({
else if (
Utils.boardView() === 'board-view-lists' ||
Utils.boardView() === 'board-view-cal' ||
!Utils.boardView
!Utils.boardView()
)
swimlaneId = board.getDefaultSwimline()._id;
@@ -411,7 +411,7 @@ BlazeComponent.extendComponent({
type: 'board',
},
{
sort: ['title'],
sort: { sort: 1 /* boards default sorting */ },
},
);
return boards;
@@ -597,7 +597,7 @@ BlazeComponent.extendComponent({
type: 'board',
},
{
sort: ['title'],
sort: { sort: 1 /* boards default sorting */ },
},
);
return boards;
@@ -658,10 +658,7 @@ BlazeComponent.extendComponent({
_id = element.copy(this.boardId, this.swimlaneId, this.listId);
// 1.B Linked card
} else {
delete element._id;
element.type = 'cardType-linkedCard';
element.linkedId = element.linkedId || element._id;
_id = Cards.insert(element);
_id = element.link(this.boardId, this.swimlaneId, this.listId);
}
Filter.addException(_id);
// List insertion
@@ -675,7 +672,7 @@ BlazeComponent.extendComponent({
element.sort = Boards.findOne(this.boardId)
.swimlanes()
.count();
element.type = 'swimlalne';
element.type = 'swimlane';
_id = element.copy(this.boardId);
} else if (this.isBoardTemplateSearch) {
board = Boards.findOne(element.linkedId);
+1 -2
View File
@@ -30,10 +30,9 @@ template(name="listHeader")
if canSeeAddCard
a.js-add-card.fa.fa-plus.list-header-plus-icon
a.fa.fa-navicon.js-open-list-menu
//a.list-header-handle.handle.fa.fa-arrows.js-list-handle
else
a.list-header-menu-icon.fa.fa-angle-right.js-select-list
//a.list-header-handle.handle.fa.fa-arrows.js-list-handle
a.list-header-handle.handle.fa.fa-arrows.js-list-handle
else if currentUser.isBoardMember
if isWatching
i.list-header-watch-icon.fa.fa-eye
+29 -2
View File
@@ -223,8 +223,35 @@ BlazeComponent.extendComponent({
Template.listMorePopup.events({
'click .js-delete': Popup.afterConfirm('listDelete', function() {
Popup.close();
this.allCards().map(card => Cards.remove(card._id));
Lists.remove(this._id);
// TODO how can we avoid the fetch call?
const allCards = this.allCards().fetch();
const allCardIds = _.pluck(allCards, '_id');
// it's okay if the linked cards are on the same list
if (
Cards.find({
$and: [
{ listId: { $ne: this._id } },
{ linkedId: { $in: allCardIds } },
],
}).count() === 0
) {
allCardIds.map(_id => Cards.remove(_id));
Lists.remove(this._id);
} else {
// TODO: Figure out more informative message.
// Popup with a hint that the list cannot be deleted as there are
// linked cards. We can adapt the query above so we can list the linked
// cards.
// Related:
// client/components/cards/cardDetails.js about line 969
// https://github.com/wekan/wekan/issues/2785
const message = `${TAPi18n.__(
'delete-linked-cards-before-this-list',
)} linkedId: ${
this._id
} at client/components/lists/listHeader.js and https://github.com/wekan/wekan/issues/2785`;
alert(message);
}
Utils.goBoardId(this.boardId);
}),
});
+1 -1
View File
@@ -330,7 +330,7 @@ Template.viewer.events({
// the corresponding text). Clicking a link shouldn't fire these actions, stop
// we stop these event at the viewer component level.
'click a'(event, templateInstance) {
let prevent = true;
const prevent = true;
const userId = event.currentTarget.dataset.userid;
if (userId) {
Popup.open('member').call({ userId }, event, templateInstance);
+1 -1
View File
@@ -175,7 +175,7 @@
.board-header-btn
height: 32px
line-height: @height
font-size: 16px
font-size: 15px
i.fa
line-height: 32px
+10 -4
View File
@@ -6,10 +6,16 @@ head
where the application is deployed with a path prefix, but it seems to be
difficult to do that cleanly with Blaze -- at least without adding extra
packages.
link(rel="shortcut icon" href="/wekan-favicon.png")
link(rel="apple-touch-icon" href="/wekan-favicon.png")
link(rel="mask-icon" href="/wekan-logo-150.svg")
link(rel="manifest" href="/wekan-manifest.json")
link(rel="shortcut icon" type="image/x-icon" href="/favicon.ico")
link(rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png")
link(rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png")
link(rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png")
link(rel="manifest" href="/site.webmanifest")
link(rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5")
meta(name="apple-mobile-web-app-title" content="Wekan")
meta(name="application-name" content="Wekan")
meta(name="msapplication-TileColor" content="#00aba9")
meta(name="theme-color" content="#ffffff")
template(name="userFormsLayout")
section.auth-layout
+5
View File
@@ -135,6 +135,10 @@ $popupWidth = 300px
margin-bottom: 8px
.pop-over-list
li
display: block
clear: both
li > a
clear: both
cursor: pointer
@@ -316,6 +320,7 @@ $popupWidth = 300px
input[type="file"]
margin: 4px 0 12px
width: 100%
box-sizing: border-box
.pop-over-list
li > a
@@ -11,7 +11,7 @@ BlazeComponent.extendComponent({
},
},
{
sort: ['title'],
sort: { sort: 1 /* boards default sorting */ },
},
);
return boards;
+1 -1
View File
@@ -48,7 +48,7 @@ BlazeComponent.extendComponent({
'members.isAdmin': true,
},
{
sort: ['title'],
sort: { sort: 1 /* boards default sorting */ },
},
);
},
+18 -1
View File
@@ -230,6 +230,8 @@ template(name="chooseBoardSource")
a(href="{{pathFor '/import/trello'}}") {{_ 'from-trello'}}
li
a(href="{{pathFor '/import/wekan'}}") {{_ 'from-wekan'}}
li
a(href="{{pathFor '/import/csv'}}") {{_ 'from-csv'}}
template(name="archiveBoardPopup")
p {{_ 'close-board-pop'}}
@@ -300,7 +302,7 @@ template(name="boardMenuPopup")
ul.pop-over-list
if withApi
li
a(href="{{exportUrl}}", download="{{exportFilename}}")
a.js-export-board
i.fa.fa-share-alt
| {{_ 'export-board'}}
li
@@ -360,6 +362,21 @@ template(name="boardMenuPopup")
i.fa.fa-sitemap
| {{_ 'subtask-settings'}}
template(name="exportBoard")
ul.pop-over-list
li
a(href="{{exportUrl}}", download="{{exportJsonFilename}}")
i.fa.fa-share-alt
| {{_ 'export-board-json'}}
li
a(href="{{exportCsvUrl}}", download="{{exportCsvFilename}}")
i.fa.fa-share-alt
| {{_ 'export-board-csv'}}
li
a(href="{{exportTsvUrl}}", download="{{exportTsvFilename}}")
i.fa.fa-share-alt
| {{_ 'export-board-tsv'}}
template(name="labelsWidget")
.board-widget.board-widget-labels
h3
+69 -12
View File
@@ -196,14 +196,14 @@ Template.boardMenuPopup.events({
},
'click .js-change-board-color': Popup.open('boardChangeColor'),
'click .js-change-language': Popup.open('changeLanguage'),
'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function () {
'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
currentBoard.archive();
// XXX We should have some kind of notification on top of the page to
// confirm that the board was successfully archived.
FlowRouter.go('home');
}),
'click .js-delete-board': Popup.afterConfirm('deleteBoard', function () {
'click .js-delete-board': Popup.afterConfirm('deleteBoard', function() {
const currentBoard = Boards.findOne(Session.get('currentBoard'));
Popup.close();
Boards.remove(currentBoard._id);
@@ -213,19 +213,19 @@ Template.boardMenuPopup.events({
'click .js-import-board': Popup.open('chooseBoardSource'),
'click .js-subtask-settings': Popup.open('boardSubtaskSettings'),
'click .js-card-settings': Popup.open('boardCardSettings'),
'click .js-export-board': Popup.open('exportBoard'),
});
Template.boardMenuPopup.onCreated(function () {
Template.boardMenuPopup.onCreated(function() {
this.apiEnabled = new ReactiveVar(false);
Meteor.call('_isApiEnabled', (e, result) => {
this.apiEnabled.set(result)
})
})
this.apiEnabled.set(result);
});
});
Template.boardMenuPopup.helpers({
withApi() {
return Template.instance().apiEnabled.get()
return Template.instance().apiEnabled.get();
},
exportUrl() {
const params = {
@@ -248,7 +248,7 @@ Template.memberPopup.events({
Popup.close();
},
'click .js-change-role': Popup.open('changePermissions'),
'click .js-remove-member': Popup.afterConfirm('removeMember', function () {
'click .js-remove-member': Popup.afterConfirm('removeMember', function() {
const boardId = Session.get('currentBoard');
const memberId = this.userId;
Cards.find({ boardId, members: memberId }).forEach(card => {
@@ -406,6 +406,63 @@ BlazeComponent.extendComponent({
},
}).register('chooseBoardSourcePopup');
BlazeComponent.extendComponent({
template() {
return 'exportBoard';
},
withApi() {
return Template.instance().apiEnabled.get();
},
exportUrl() {
const params = {
boardId: Session.get('currentBoard'),
};
const queryParams = {
authToken: Accounts._storedLoginToken(),
};
return FlowRouter.path('/api/boards/:boardId/export', params, queryParams);
},
exportCsvUrl() {
const params = {
boardId: Session.get('currentBoard'),
};
const queryParams = {
authToken: Accounts._storedLoginToken(),
};
return FlowRouter.path(
'/api/boards/:boardId/export/csv',
params,
queryParams,
);
},
exportTsvUrl() {
const params = {
boardId: Session.get('currentBoard'),
};
const queryParams = {
authToken: Accounts._storedLoginToken(),
delimiter: '\t',
};
return FlowRouter.path(
'/api/boards/:boardId/export/csv',
params,
queryParams,
);
},
exportJsonFilename() {
const boardId = Session.get('currentBoard');
return `wekan-export-board-${boardId}.json`;
},
exportCsvFilename() {
const boardId = Session.get('currentBoard');
return `wekan-export-board-${boardId}.csv`;
},
exportTsvFilename() {
const boardId = Session.get('currentBoard');
return `wekan-export-board-${boardId}.tsv`;
},
}).register('exportBoardPopup');
Template.labelsWidget.events({
'click .js-label': Popup.open('editLabel'),
'click .js-add-label': Popup.open('createLabel'),
@@ -510,7 +567,7 @@ BlazeComponent.extendComponent({
'members.userId': Meteor.userId(),
},
{
sort: ['title'],
sort: { sort: 1 /* boards default sorting */ },
},
);
},
@@ -589,7 +646,7 @@ BlazeComponent.extendComponent({
'subtext-with-parent',
'no-parent',
];
options.forEach(function (element) {
options.forEach(function(element) {
if (element !== value) {
$(`#${element} ${MCB}`).toggleClass(CKCLS, false);
$(`#${element}`).toggleClass(CKCLS, false);
@@ -688,7 +745,7 @@ BlazeComponent.extendComponent({
'members.userId': Meteor.userId(),
},
{
sort: ['title'],
sort: { sort: 1 /* boards default sorting */ },
},
);
},
+6 -32
View File
@@ -1,6 +1,6 @@
import { Cookies } from 'meteor/ostrio:cookies';
const cookies = new Cookies();
const { calculateIndex, enableClickOnTouch } = Utils;
const { calculateIndex } = Utils;
function currentListIsInThisSwimlane(swimlaneId) {
const currentList = Lists.findOne(Session.get('currentList'));
@@ -87,9 +87,6 @@ function initSortable(boardComponent, $listsDom) {
},
});
// ugly touch event hotfix
enableClickOnTouch('.js-list:not(.js-list-composer)');
function userIsMember() {
return (
Meteor.user() &&
@@ -111,7 +108,7 @@ function initSortable(boardComponent, $listsDom) {
showDesktopDragHandles = false;
}
if (!Utils.isMiniScreen() && showDesktopDragHandles) {
if (Utils.isMiniScreen() || showDesktopDragHandles) {
$listsDom.sortable({
handle: '.js-list-handle',
});
@@ -122,34 +119,12 @@ function initSortable(boardComponent, $listsDom) {
}
const $listDom = $listsDom;
if ($listDom.data('sortable')) {
if ($listDom.data('uiSortable') || $listDom.data('sortable')) {
$listsDom.sortable(
'option',
'disabled',
// Disable drag-dropping when user is not member/is worker/is miniscreen
!userIsMember(),
// Not disable drag-dropping while in multi-selection mode
// MultiSelection.isActive() || !userIsMember(),
);
}
if ($listDom.data('sortable')) {
$listsDom.sortable(
'option',
'disabled',
// Disable drag-dropping when user is not member/is worker/is miniscreen
Meteor.user().isWorker(),
// Not disable drag-dropping while in multi-selection mode
// MultiSelection.isActive() || !userIsMember(),
);
}
if ($listDom.data('sortable')) {
$listsDom.sortable(
'option',
'disabled',
// Disable drag-dropping when user is not member/is worker/is miniscreen
Utils.isMiniScreen(),
// Disable drag-dropping when user is not member/is worker
!userIsMember() || Meteor.user().isWorker(),
// Not disable drag-dropping while in multi-selection mode
// MultiSelection.isActive() || !userIsMember(),
);
@@ -210,8 +185,7 @@ BlazeComponent.extendComponent({
}
const noDragInside = ['a', 'input', 'textarea', 'p'].concat(
Utils.isMiniScreen() ||
(!Utils.isMiniScreen() && showDesktopDragHandles)
Utils.isMiniScreen() || showDesktopDragHandles
? ['.js-list-handle', '.js-swimlane-header-handle']
: ['.js-list-header'],
);
+2
View File
@@ -29,6 +29,8 @@ avatar-radius = 50%
position: absolute
&.avatar-image
object-fit: cover;
object-position: center;
height: 100%
width: @height
+11 -2
View File
@@ -112,11 +112,20 @@ template(name="changeSettingsPopup")
i.fa.fa-check
unless currentUser.isWorker
li
label.bold
label.bold.clear
i.fa.fa-sort-numeric-asc
| {{_ 'show-cards-minimum-count'}}
input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="0" max="99" onkeydown="return false")
input.js-apply-show-cards-at.left(type="submit" value="{{_ 'apply'}}")
label.bold.clear
i.fa.fa-calendar
| {{_ 'start-day-of-week'}}
select#start-day-of-week.inline-input.left
each day in weekDays startDayOfWeek
if day.isSelected
option(selected="true", value="#{day.value}") #{day.name}
else
option(value="#{day.value}") #{day.name}
input.js-apply-user-settings.left(type="submit" value="{{_ 'apply'}}")
template(name="userDeletePopup")
unless currentUser.isWorker
+35 -3
View File
@@ -224,6 +224,27 @@ Template.changeSettingsPopup.helpers({
return cookies.get('limitToShowCardsCount');
}
},
weekDays(startDay) {
return [
TAPi18n.__('sunday'),
TAPi18n.__('monday'),
TAPi18n.__('tuesday'),
TAPi18n.__('wednesday'),
TAPi18n.__('thursday'),
TAPi18n.__('friday'),
TAPi18n.__('saturday'),
].map(function(day, index) {
return { name: day, value: index, isSelected: index === startDay };
});
},
startDayOfWeek() {
currentUser = Meteor.user();
if (currentUser) {
return currentUser.getStartDayOfWeek();
} else {
return cookies.get('startDayOfWeek');
}
},
});
Template.changeSettingsPopup.events({
@@ -247,20 +268,31 @@ Template.changeSettingsPopup.events({
cookies.set('hasHiddenSystemMessages', 'true');
}
},
'click .js-apply-show-cards-at'(event, templateInstance) {
'click .js-apply-user-settings'(event, templateInstance) {
event.preventDefault();
const minLimit = parseInt(
templateInstance.$('#show-cards-count-at').val(),
10,
);
const startDay = parseInt(
templateInstance.$('#start-day-of-week').val(),
10,
);
const currentUser = Meteor.user();
if (!isNaN(minLimit)) {
currentUser = Meteor.user();
if (currentUser) {
Meteor.call('changeLimitToShowCardsCount', minLimit);
} else {
cookies.set('limitToShowCardsCount', minLimit);
}
Popup.back();
}
if (!isNaN(startDay)) {
if (currentUser) {
Meteor.call('changeStartDayOfWeek', startDay);
} else {
cookies.set('startDayOfWeek', startDay);
}
}
Popup.back();
},
});
+10
View File
@@ -10,12 +10,22 @@ DatePicker = BlazeComponent.extendComponent({
this.defaultTime = defaultTime;
},
startDayOfWeek() {
const currentUser = Meteor.user();
if (currentUser) {
return currentUser.getStartDayOfWeek();
} else {
return 1;
}
},
onRendered() {
const $picker = this.$('.js-datepicker')
.datepicker({
todayHighlight: true,
todayBtn: 'linked',
language: TAPi18n.getLanguage(),
weekStart: this.startDayOfWeek(),
})
.on(
'changeDate',
+21 -11
View File
@@ -1,6 +1,16 @@
// XXX There is no reason to define these shortcuts globally, they should be
// attached to a template (most of them will go in the `board` template).
function getHoveredCardId() {
const card = $('.js-minicard:hover').get(0);
if (!card) return null;
return Blaze.getData(card)._id;
}
function getSelectedCardId() {
return Session.get('selectedCard') || getHoveredCardId();
}
Mousetrap.bind('?', () => {
FlowRouter.go('shortcuts');
});
@@ -50,9 +60,9 @@ Mousetrap.bind(['down', 'up'], (evt, key) => {
}
});
// XXX This shortcut should also work when hovering over a card in board view
Mousetrap.bind('space', evt => {
if (!Session.get('currentCard')) {
const cardId = getSelectedCardId();
if (!cardId) {
return;
}
@@ -62,7 +72,7 @@ Mousetrap.bind('space', evt => {
}
if (Meteor.user().isBoardMember()) {
const card = Cards.findOne(Session.get('currentCard'));
const card = Cards.findOne(cardId);
card.toggleMember(currentUserId);
// We should prevent scrolling in card when spacebar is clicked
// This should do it according to Mousetrap docs, but it doesn't
@@ -70,9 +80,9 @@ Mousetrap.bind('space', evt => {
}
});
// XXX This shortcut should also work when hovering over a card in board view
Mousetrap.bind('c', evt => {
if (!Session.get('currentCard')) {
const cardId = getSelectedCardId();
if (!cardId) {
return;
}
@@ -86,7 +96,7 @@ Mousetrap.bind('c', evt => {
!Meteor.user().isCommentOnly() &&
!Meteor.user().isWorker()
) {
const card = Cards.findOne(Session.get('currentCard'));
const card = Cards.findOne(cardId);
card.archive();
// We should prevent scrolling in card when spacebar is clicked
// This should do it according to Mousetrap docs, but it doesn't
@@ -97,19 +107,19 @@ Mousetrap.bind('c', evt => {
Template.keyboardShortcuts.helpers({
mapping: [
{
keys: ['W'],
keys: ['w'],
action: 'shortcut-toggle-sidebar',
},
{
keys: ['Q'],
keys: ['q'],
action: 'shortcut-filter-my-cards',
},
{
keys: ['F'],
keys: ['f'],
action: 'shortcut-toggle-filterbar',
},
{
keys: ['X'],
keys: ['x'],
action: 'shortcut-clear-filters',
},
{
@@ -129,7 +139,7 @@ Template.keyboardShortcuts.helpers({
action: 'shortcut-assign-self',
},
{
keys: ['C'],
keys: ['c'],
action: 'archive-card',
},
],
+1 -1
View File
@@ -38,7 +38,7 @@ version: '2'
# sudo service docker start
# ----------------------------------------------------------------------------------
# ==== USAGE OF THIS docker-compose.yml ====
# 1) For seeing does Wekan work, try this and check with your webbroser:
# 1) For seeing does Wekan work, try this and check with your web browser:
# docker-compose up
# 2) Stop Wekan and start Wekan in background:
# docker-compose stop
+6
View File
@@ -37,6 +37,12 @@ spec:
value: {{ .Values.root_url | default "https://wekan.local" | quote }}
- name: MONGO_URL
value: "{{ template "mongodb-replicaset.url" . }}"
{{- range $key := .Values.env }}
{{- if .value }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
{{- end }}
livenessProbe:
httpGet:
path: /
+4
View File
@@ -2,6 +2,10 @@
apiVersion: v1
kind: ServiceAccount
metadata:
{{- if .Values.serviceAccounts.annotations }}
annotations:
{{ .Values.serviceAccounts.annotations | indent 4}}
{{- end }}
labels:
app: {{ template "wekan.name" . }}
chart: {{ template "wekan.chart" . }}
+7 -4
View File
@@ -8,6 +8,7 @@
serviceAccounts:
create: true
name: ""
annotations: ""
## Wekan image configuration
##
@@ -29,7 +30,9 @@ credentials:
## Specify additional environmental variables for the Deployment
##
env: {}
env:
- name: ""
value: ""
service:
type: NodePort
@@ -59,10 +62,10 @@ ingress:
# hosts:
# - wekan-example.local
route:
enabled: false
route:
enabled: false
resources:
resources:
requests:
memory: 128Mi
cpu: 300m
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+36 -9
View File
@@ -152,8 +152,6 @@
"card-spent": "Spent Time",
"card-edit-attachments": "Edit attachments",
"card-edit-custom-fields": "Edit custom fields",
"card-start-voting": "Start voting",
"card-cancel-voting": "Delete voting and all votes",
"card-edit-labels": "Edit labels",
"card-edit-members": "Edit members",
"card-labels-title": "Change the labels for the card.",
@@ -166,10 +164,15 @@
"cardStartVotingPopup-title": "Start a vote",
"positiveVoteMembersPopup-title": "Proponents",
"negativeVoteMembersPopup-title": "Opponents",
"card-edit-voting": "Edit voting",
"editVoteEndDatePopup-title": "Change vote end date",
"allowNonBoardMembers": "Allow all logged in users",
"vote-question": "Voting question",
"vote-public": "Public vote",
"vote-public": "Show who voted what",
"vote-for-it": "for it",
"vote-against": "against",
"deleteVotePopup-title": "Delete vote?",
"vote-delete-pop": "Deleting is permanent. You will lose all actions associated with this vote.",
"cardDeletePopup-title": "Delete Card?",
"cardDetailsActionsPopup-title": "Card Actions",
"cardLabelsPopup-title": "Labels",
@@ -306,6 +309,7 @@
"error-board-notAMember": "You need to be a member of this board to do that",
"error-json-malformed": "Your text is not valid JSON",
"error-json-schema": "Your JSON data does not include the proper information in the correct format",
"error-csv-schema": "Your CSV(Comma Separated Values)/TSV (Tab Separated Values) does not include the proper information in the correct format ",
"error-list-doesNotExist": "This list does not exist",
"error-user-doesNotExist": "This user does not exist",
"error-user-notAllowSelf": "You can not invite yourself",
@@ -313,6 +317,11 @@
"error-username-taken": "This username is already taken",
"error-email-taken": "Email has already been taken",
"export-board": "Export board",
"export-board-json": "Export board to JSON",
"export-board-csv": "Export board to CSV",
"export-board-tsv": "Export board to TSV",
"export-board-html": "Export board to HTML",
"exportBoardPopup-title": "Export board",
"sort": "Sort",
"sort-desc": "Click to Sort List",
"list-sort-by": "Sort the List By:",
@@ -348,14 +357,16 @@
"import-board-c": "Import board",
"import-board-title-trello": "Import board from Trello",
"import-board-title-wekan": "Import board from previous export",
"import-sandstorm-backup-warning": "Do not delete data you import from original exported board or Trello before checking does this grain close and open again, or do you get Board not found error, that means data loss.",
"import-sandstorm-warning": "Imported board will delete all existing data on board and replace it with imported board.",
"import-board-title-csv": "Import board from CSV/TSV",
"from-trello": "From Trello",
"from-wekan": "From previous export",
"from-csv": "From CSV/TSV",
"import-board-instruction-trello": "In your Trello board, go to 'Menu', then 'More', 'Print and Export', 'Export JSON', and copy the resulting text.",
"import-board-instruction-csv": "Paste in your Comma Separated Values(CSV)/ Tab Separated Values (TSV) .",
"import-board-instruction-wekan": "In your board, go to 'Menu', then 'Export board', and copy the text in the downloaded file.",
"import-board-instruction-about-errors": "If you get errors when importing board, sometimes importing still works, and board is at All Boards page.",
"import-json-placeholder": "Paste your valid JSON data here",
"import-csv-placeholder": "Paste your valid CSV/TSV data here",
"import-map-members": "Map members",
"import-members-map": "Your imported board has some members. Please map the members you want to import to your users",
"import-show-user-mapping": "Review members mapping",
@@ -388,6 +399,7 @@
"swimlaneActionPopup-title": "Swimlane Actions",
"swimlaneAddPopup-title": "Add a Swimlane below",
"listImportCardPopup-title": "Import a Trello card",
"listImportCardsTsvPopup-title": "Import Excel CSV/TSV",
"listMorePopup-title": "More",
"link-list": "Link to this list",
"list-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the list. There is no undo.",
@@ -643,7 +655,6 @@
"r-when-a-member": "When a member is",
"r-when-the-member": "When the member",
"r-name": "name",
"r-is": "is",
"r-when-a-attach": "When an attachment",
"r-when-a-checklist": "When a checklist is",
"r-when-the-checklist": "When the checklist",
@@ -657,7 +668,6 @@
"r-top-of": "Top of",
"r-bottom-of": "Bottom of",
"r-its-list": "its list",
"r-list": "list",
"r-archive": "Move to Archive",
"r-unarchive": "Restore from Archive",
"r-card": "card",
@@ -677,6 +687,7 @@
"r-of-checklist": "of checklist",
"r-send-email": "Send an email",
"r-to": "to",
"r-of": "of",
"r-subject": "subject",
"r-rule-details": "Rule details",
"r-d-move-to-top-gen": "Move card to top of its list",
@@ -712,7 +723,6 @@
"r-swimlane-name": "swimlane name",
"r-board-note": "Note: leave a field empty to match every possible value. ",
"r-checklist-note": "Note: checklist's items have to be written as comma separated values.",
"r-added-to": "added to",
"r-when-a-card-is-moved": "When a card is moved to another list",
"r-set": "Set",
"r-update": "Update",
@@ -779,5 +789,22 @@
"mark-all-as-read": "Mark all as read",
"remove-all-read": "Remove all read",
"allow-rename": "Allow Rename",
"allowRenamePopup-title": "Allow Rename"
"allowRenamePopup-title": "Allow Rename",
"start-day-of-week": "Set day of the week start",
"monday": "Monday",
"tuesday": "Tuesday",
"wednesday": "Wednesday",
"thursday": "Thursday",
"friday": "Friday",
"saturday": "Saturday",
"sunday": "Sunday",
"status": "Status",
"swimlane": "Swimlane",
"owner": "Owner",
"last-modified-at": "Last modified at",
"last-activity": "Last activity",
"voting": "Voting",
"archived": "Archived",
"delete-linked-card-before-this-card": "You can not delete this card before first deleting linked card that has",
"delete-linked-cards-before-this-list": "You can not delete this list before first deleting linked cards that are pointing to cards in this list"
}
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+810
View File
@@ -0,0 +1,810 @@
{
"accept": "Aceptar",
"act-activity-notify": "Notificación de actividad",
"act-addAttachment": "añadido el adjunto __attachment__ a la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-deleteAttachment": "eliminado el adjunto __attachment__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-addSubtask": "añadida la subtarea __subtask__ a la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-addLabel": "añadida la etiqueta __label__ a la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-addedLabel": "añadida la etiqueta __label__ a la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-removeLabel": "eliminada la etiqueta __label__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-removedLabel": "eliminada la etiqueta __label__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-addChecklist": "añadida la lista de verificación __checklist__ a la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-addChecklistItem": "añadido el elemento __checklistItem__ a la lista de verificación __checklist__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-removeChecklist": "eliminada la lista de verificación __checklist__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-removeChecklistItem": "eliminado el elemento __checklistItem__ de la lista de verificación __checkList__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-checkedItem": "marcado el elemento __checklistItem__ de la lista de verificación __checklist__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-uncheckedItem": "desmarcado el elemento __checklistItem__ de la lista de verificación __checklist__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-completeChecklist": "completada la lista de verificación __checklist__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-uncompleteChecklist": "no completada la lista de verificación __checklist__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-addComment": "comentario en la tarjeta__card__: __comment__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-editComment": "comentario editado en la tarjeta __card__: __comment__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-deleteComment": "comentario eliminado en la tarjeta __card__: __comment__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-createBoard": "creó el tablero __board__",
"act-createSwimlane": "creó el carril de flujo __swimlane__ en el tablero __board__",
"act-createCard": "creada la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-createCustomField": "creado el campo personalizado __customField__ en el tablero __board__",
"act-deleteCustomField": "eliminado el campo personalizado __customField__ del tablero __board__",
"act-setCustomField": "editado el campo personalizado __customField__: __customFieldValue__ en la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-createList": "añadida la lista __list__ al tablero __board__",
"act-addBoardMember": "añadido el mimbro __member__ al tablero __board__",
"act-archivedBoard": "El tablero __board__ se ha archivado",
"act-archivedCard": "La tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__ se ha archivado",
"act-archivedList": "La lista __list__ del carril __swimlane__ del tablero __board__ se ha archivado",
"act-archivedSwimlane": "El carril __swimlane__ del tablero __board__ se ha archivado",
"act-importBoard": "importado el tablero __board__",
"act-importCard": "importada la tarjeta __card__ a la lista __list__ del carrril __swimlane__ del tablero __board__",
"act-importList": "importada la lista __list__ al carril __swimlane__ del tablero __board__",
"act-joinMember": "añadido el miembro __member__ a la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-moveCard": "movida la tarjeta __card__ del tablero __board__ de la lista __oldList__ del carril __oldSwimlane__ a la lista __list__ del carril __swimlane__",
"act-moveCardToOtherBoard": "movida la tarjeta __card__ de la lista __oldList__ del carril __oldSwimlane__ del tablero __oldBoard__ a la lista __list__ del carril __swimlane__ del tablero __board__",
"act-removeBoardMember": "eliminado el miembro __member__ del tablero __board__",
"act-restoredCard": "restaurada la tarjeta __card__ a la lista __list__ del carril __swimlane__ del tablero __board__",
"act-unjoinMember": "eliminado el miembro __member__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"act-withBoardTitle": "__board__",
"act-withCardTitle": "[__board__] __card__",
"actions": "Acciones",
"activities": "Actividades",
"activity": "Actividad",
"activity-added": "ha añadido %s a %s",
"activity-archived": "%s se ha archivado",
"activity-attached": "ha adjuntado %s a %s",
"activity-created": "ha creado %s",
"activity-customfield-created": "creó el campo personalizado %s",
"activity-excluded": "ha excluido %s de %s",
"activity-imported": "ha importado %s a %s desde %s",
"activity-imported-board": "ha importado %s desde %s",
"activity-joined": "se ha unido a %s",
"activity-moved": "ha movido %s de %s a %s",
"activity-on": "en %s",
"activity-removed": "ha eliminado %s de %s",
"activity-sent": "ha enviado %s a %s",
"activity-unjoined": "se ha desvinculado de %s",
"activity-subtask-added": "ha añadido la subtarea a %s",
"activity-checked-item": "marcado %s en la lista de verificación %s de %s",
"activity-unchecked-item": "desmarcado %s en lista %s de %s",
"activity-checklist-added": "ha añadido una lista de verificación a %s",
"activity-checklist-removed": "eliminada una lista de verificación desde %s",
"activity-checklist-completed": "lista de verificación completada %s de %s",
"activity-checklist-uncompleted": "no completado la lista %s de %s",
"activity-checklist-item-added": "ha añadido el elemento de la lista de verificación a '%s' en %s",
"activity-checklist-item-removed": "eliminado un elemento de la lista de verificación desde '%s' en %s",
"add": "Añadir",
"activity-checked-item-card": "marcado %s en la lista de verificación %s",
"activity-unchecked-item-card": "desmarcado %s en la lista de verificación %s",
"activity-checklist-completed-card": "completada la lista de verificación __checklist__ de la tarjeta __card__ de la lista __list__ del carril __swimlane__ del tablero __board__",
"activity-checklist-uncompleted-card": "no completó la lista de verificación %s",
"activity-editComment": "comentario editado",
"activity-deleteComment": "comentario eliminado",
"add-attachment": "Añadir adjunto",
"add-board": "Añadir tablero",
"add-card": "Añadir una tarjeta",
"add-swimlane": "Añadir un carril de flujo",
"add-subtask": "Añadir subtarea",
"add-checklist": "Añadir una lista de verificación",
"add-checklist-item": "Añadir un elemento a la lista de verificación",
"add-cover": "Añadir portada",
"add-label": "Añadir una etiqueta",
"add-list": "Añadir una lista",
"add-members": "Añadir miembros",
"added": "Añadida el",
"addMemberPopup-title": "Miembros",
"admin": "Administrador",
"admin-desc": "Puedes ver y editar tarjetas, eliminar miembros, y cambiar las preferencias del tablero",
"admin-announcement": "Aviso",
"admin-announcement-active": "Activar el aviso para todo el sistema",
"admin-announcement-title": "Aviso del administrador",
"all-boards": "Tableros",
"and-n-other-card": "y __count__ tarjeta más",
"and-n-other-card_plural": "y otras __count__ tarjetas",
"apply": "Aplicar",
"app-is-offline": "Cargando, espera por favor. Refrescar esta página causará pérdida de datos. Si la carga no funciona, por favor comprueba que el servidor no se ha parado.",
"archive": "Archivar",
"archive-all": "Archivar todo",
"archive-board": "Archivar este tablero",
"archive-card": "Archivar esta tarjeta",
"archive-list": "Archivar esta lista",
"archive-swimlane": "Archivar este carril",
"archive-selection": "Archivar esta selección",
"archiveBoardPopup-title": "¿Archivar este tablero?",
"archived-items": "Archivo",
"archived-boards": "Tableros en el Archivo",
"restore-board": "Restaurar el tablero",
"no-archived-boards": "No hay Tableros en el Archivo",
"archives": "Archivo",
"template": "Plantilla",
"templates": "Plantillas",
"assign-member": "Asignar miembros",
"attached": "adjuntado",
"attachment": "Adjunto",
"attachment-delete-pop": "La eliminación de un fichero adjunto es permanente. Esta acción no puede deshacerse.",
"attachmentDeletePopup-title": "¿Eliminar el adjunto?",
"attachments": "Adjuntos",
"auto-watch": "Suscribirse automáticamente a los tableros cuando son creados",
"avatar-too-big": "El avatar es muy grande (70KB máx.)",
"back": "Atrás",
"board-change-color": "Cambiar el color",
"board-nb-stars": "%s destacados",
"board-not-found": "Tablero no encontrado",
"board-private-info": "Este tablero será <strong>privado</strong>.",
"board-public-info": "Este tablero será <strong>público</strong>.",
"boardChangeColorPopup-title": "Cambiar el fondo del tablero",
"boardChangeTitlePopup-title": "Renombrar el tablero",
"boardChangeVisibilityPopup-title": "Cambiar visibilidad",
"boardChangeWatchPopup-title": "Cambiar vigilancia",
"boardMenuPopup-title": "Preferencias del tablero",
"boardChangeViewPopup-title": "Vista del tablero",
"boards": "Tableros",
"board-view": "Vista del tablero",
"board-view-cal": "Calendario",
"board-view-swimlanes": "Carriles",
"board-view-collapse": "Contraer",
"board-view-lists": "Listas",
"bucket-example": "Como “Cosas por hacer” por ejemplo",
"cancel": "Cancelar",
"card-archived": "Se archivó esta tarjeta",
"board-archived": "Se archivó este tablero",
"card-comments-title": "Esta tarjeta tiene %s comentarios.",
"card-delete-notice": "la eliminación es permanente. Perderás todas las acciones asociadas a esta tarjeta.",
"card-delete-pop": "Se eliminarán todas las acciones del historial de actividades y no se podrá volver a abrir la tarjeta. Esta acción no puede deshacerse.",
"card-delete-suggest-archive": "Puedes mover una tarjeta al Archivo para quitarla del tablero y preservar la actividad.",
"card-due": "Vence",
"card-due-on": "Vence el",
"card-spent": "Tiempo consumido",
"card-edit-attachments": "Editar los adjuntos",
"card-edit-custom-fields": "Editar los campos personalizados",
"card-edit-labels": "Editar las etiquetas",
"card-edit-members": "Editar los miembros",
"card-labels-title": "Cambia las etiquetas de la tarjeta",
"card-members-title": "Añadir o eliminar miembros del tablero desde la tarjeta.",
"card-start": "Comienza",
"card-start-on": "Comienza el",
"cardAttachmentsPopup-title": "Adjuntar desde",
"cardCustomField-datePopup-title": "Cambiar la fecha",
"cardCustomFieldsPopup-title": "Editar los campos personalizados",
"cardStartVotingPopup-title": "Comience a votar",
"positiveVoteMembersPopup-title": "Favorables",
"negativeVoteMembersPopup-title": "Contrarios",
"card-edit-voting": "Editar votación",
"editVoteEndDatePopup-title": "Cambie fecha de termino del voto",
"allowNonBoardMembers": "Permitir todos los usuarios autentificados",
"vote-question": "Pregunta de votación",
"vote-public": "Mostrar quien voto que",
"vote-for-it": "por esto",
"vote-against": "contrarios",
"deleteVotePopup-title": "¿Borrar voto?",
"vote-delete-pop": "El Borrado es permanente. Perderá todas las acciones asociadas con este voto.",
"cardDeletePopup-title": "¿Eliminar la tarjeta?",
"cardDetailsActionsPopup-title": "Acciones de la tarjeta",
"cardLabelsPopup-title": "Etiquetas",
"cardMembersPopup-title": "Miembros",
"cardMorePopup-title": "Más",
"cardTemplatePopup-title": "Crear plantilla",
"cards": "Tarjetas",
"cards-count": "Tarjetas",
"casSignIn": "Iniciar sesión con CAS",
"cardType-card": "Tarjeta",
"cardType-linkedCard": "Tarjeta enlazada",
"cardType-linkedBoard": "Tablero enlazado",
"change": "Cambiar",
"change-avatar": "Cambiar el avatar",
"change-password": "Cambiar la contraseña",
"change-permissions": "Cambiar los permisos",
"change-settings": "Cambiar las preferencias",
"changeAvatarPopup-title": "Cambiar el avatar",
"changeLanguagePopup-title": "Cambiar el idioma",
"changePasswordPopup-title": "Cambiar la contraseña",
"changePermissionsPopup-title": "Cambiar los permisos",
"changeSettingsPopup-title": "Cambiar las preferencias",
"subtasks": "Subtareas",
"checklists": "Lista de verificación",
"click-to-star": "Haz clic para destacar este tablero.",
"click-to-unstar": "Haz clic para dejar de destacar este tablero.",
"clipboard": "el portapapeles o con arrastrar y soltar",
"close": "Cerrar",
"close-board": "Cerrar el tablero",
"close-board-pop": "Podrás restaurar el tablero haciendo clic en el botón \"Archivo\" del encabezado de la pantalla inicial.",
"color-black": "negra",
"color-blue": "azul",
"color-crimson": "carmesí",
"color-darkgreen": "verde oscuro",
"color-gold": "oro",
"color-gray": "gris",
"color-green": "verde",
"color-indigo": "añil",
"color-lime": "lima",
"color-magenta": "magenta",
"color-mistyrose": "rosa claro",
"color-navy": "azul marino",
"color-orange": "naranja",
"color-paleturquoise": "turquesa",
"color-peachpuff": "melocotón",
"color-pink": "rosa",
"color-plum": "púrpura",
"color-purple": "violeta",
"color-red": "roja",
"color-saddlebrown": "marrón",
"color-silver": "plata",
"color-sky": "celeste",
"color-slateblue": "azul",
"color-white": "blanco",
"color-yellow": "amarilla",
"unset-color": "Desmarcar",
"comment": "Comentar",
"comment-placeholder": "Escribir comentario",
"comment-only": "Sólo comentarios",
"comment-only-desc": "Solo puedes comentar en las tarjetas.",
"no-comments": "No hay comentarios",
"no-comments-desc": "No se pueden mostrar comentarios ni actividades.",
"worker": "Trabajador",
"worker-desc": "Solo puede mover tarjetas, asignarse a la tarjeta y comentar.",
"computer": "el ordenador",
"confirm-subtask-delete-dialog": "¿Seguro que quieres eliminar la subtarea?",
"confirm-checklist-delete-dialog": "¿Seguro que quieres eliminar la lista de verificación?",
"copy-card-link-to-clipboard": "Copiar el enlace de la tarjeta al portapapeles",
"linkCardPopup-title": "Enlazar tarjeta",
"searchElementPopup-title": "Buscar",
"copyCardPopup-title": "Copiar la tarjeta",
"copyChecklistToManyCardsPopup-title": "Copiar la plantilla de la lista de verificación en varias tarjetas",
"copyChecklistToManyCardsPopup-instructions": "Títulos y descripciones de las tarjetas de destino en formato JSON",
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"Título de la primera tarjeta\", \"description\":\"Descripción de la primera tarjeta\"}, {\"title\":\"Título de la segunda tarjeta\",\"description\":\"Descripción de la segunda tarjeta\"},{\"title\":\"Título de la última tarjeta\",\"description\":\"Descripción de la última tarjeta\"} ]",
"create": "Crear",
"createBoardPopup-title": "Crear tablero",
"chooseBoardSourcePopup-title": "Importar un tablero",
"createLabelPopup-title": "Crear etiqueta",
"createCustomField": "Crear un campo",
"createCustomFieldPopup-title": "Crear un campo",
"current": "actual",
"custom-field-delete-pop": "Se eliminará este campo personalizado de todas las tarjetas y se destruirá su historial. Esta acción no puede deshacerse.",
"custom-field-checkbox": "Casilla de verificación",
"custom-field-date": "Fecha",
"custom-field-dropdown": "Lista desplegable",
"custom-field-dropdown-none": "(nada)",
"custom-field-dropdown-options": "Opciones de la lista",
"custom-field-dropdown-options-placeholder": "Pulsa Intro para añadir más opciones",
"custom-field-dropdown-unknown": "(desconocido)",
"custom-field-number": "Número",
"custom-field-text": "Texto",
"custom-fields": "Campos personalizados",
"date": "Fecha",
"decline": "Declinar",
"default-avatar": "Avatar por defecto",
"delete": "Eliminar",
"deleteCustomFieldPopup-title": "¿Eliminar el campo personalizado?",
"deleteLabelPopup-title": "¿Eliminar la etiqueta?",
"description": "Descripción",
"disambiguateMultiLabelPopup-title": "Desambiguar la acción de etiqueta",
"disambiguateMultiMemberPopup-title": "Desambiguar la acción de miembro",
"discard": "Descartarla",
"done": "Hecho",
"download": "Descargar",
"edit": "Editar",
"edit-avatar": "Cambiar el avatar",
"edit-profile": "Editar el perfil",
"edit-wip-limit": "Cambiar el límite del trabajo en proceso",
"soft-wip-limit": "Límite del trabajo en proceso flexible",
"editCardStartDatePopup-title": "Cambiar la fecha de comienzo",
"editCardDueDatePopup-title": "Cambiar la fecha de vencimiento",
"editCustomFieldPopup-title": "Editar el campo",
"editCardSpentTimePopup-title": "Cambiar el tiempo consumido",
"editLabelPopup-title": "Cambiar la etiqueta",
"editNotificationPopup-title": "Editar las notificaciones",
"editProfilePopup-title": "Editar el perfil",
"email": "Correo electrónico",
"email-enrollAccount-subject": "Cuenta creada en __siteName__",
"email-enrollAccount-text": "Hola __user__,\n\nPara empezar a utilizar el servicio, simplemente haz clic en el siguiente enlace.\n\n__url__\n\nGracias.",
"email-fail": "Error al enviar el correo",
"email-fail-text": "Error al intentar enviar el correo",
"email-invalid": "Correo no válido",
"email-invite": "Invitar vía correo electrónico",
"email-invite-subject": "__inviter__ ha enviado una invitación",
"email-invite-text": "Estimado __user__,\n\n__inviter__ te invita a unirte al tablero '__board__' para colaborar.\n\nPor favor, haz clic en el siguiente enlace:\n\n__url__\n\nGracias.",
"email-resetPassword-subject": "Restablecer tu contraseña en __siteName__",
"email-resetPassword-text": "Hola __user__,\n\nPara restablecer tu contraseña, haz clic en el siguiente enlace.\n\n__url__\n\nGracias.",
"email-sent": "Correo enviado",
"email-verifyEmail-subject": "Verifica tu dirección de correo en __siteName__",
"email-verifyEmail-text": "Hola __user__,\n\nPara verificar tu cuenta de correo electrónico, haz clic en el siguiente enlace.\n\n__url__\n\nGracias.",
"enable-wip-limit": "Habilitar el límite del trabajo en proceso",
"error-board-doesNotExist": "El tablero no existe",
"error-board-notAdmin": "Es necesario ser administrador de este tablero para hacer eso",
"error-board-notAMember": "Es necesario ser miembro de este tablero para hacer eso",
"error-json-malformed": "El texto no es un JSON válido",
"error-json-schema": "Sus datos JSON no incluyen la información apropiada en el formato correcto",
"error-csv-schema": "Su CSV(Valores separados por coma)/TSV(Valores separados por tab) no incluyen la información apropiada en el formato correcto",
"error-list-doesNotExist": "La lista no existe",
"error-user-doesNotExist": "El usuario no existe",
"error-user-notAllowSelf": "No puedes invitarte a ti mismo",
"error-user-notCreated": "El usuario no ha sido creado",
"error-username-taken": "Este nombre de usuario ya está en uso",
"error-email-taken": "Esta dirección de correo ya está en uso",
"export-board": "Exportar el tablero",
"export-board-json": "Exportar tablero a JSON",
"export-board-csv": "Exportar tablero a CSV",
"export-board-tsv": "Exportar tablero a TSV",
"export-board-html": "Export board to HTML",
"exportBoardPopup-title": "Exportar el tablero",
"sort": "Ordenar",
"sort-desc": "Click para ordenar la lista",
"list-sort-by": "Ordenar la lista por:",
"list-label-modifiedAt": "Hora de último acceso",
"list-label-title": "Nombre de la lista",
"list-label-sort": "Tu orden manual",
"list-label-short-modifiedAt": "(L)",
"list-label-short-title": "(N)",
"list-label-short-sort": "(M)",
"filter": "Filtrar",
"filter-cards": "Filtrar tarjetas o listas",
"list-filter-label": "Filtrar listas por título",
"filter-clear": "Limpiar el filtro",
"filter-no-label": "Sin etiqueta",
"filter-no-member": "Sin miembro",
"filter-no-assignee": "No asignado",
"filter-no-custom-fields": "Sin campos personalizados",
"filter-show-archive": "Mostrar las listas archivadas",
"filter-hide-empty": "Ocultar las listas vacías",
"filter-on": "Filtrado activado",
"filter-on-desc": "Estás filtrando tarjetas en este tablero. Haz clic aquí para editar el filtro.",
"filter-to-selection": "Filtrar la selección",
"advanced-filter-label": "Filtrado avanzado",
"advanced-filter-description": "El filtrado avanzado permite escribir una cadena que contiene los siguientes operadores: == != <= >= && || ( ) Se utiliza un espacio como separador entre los operadores. Se pueden filtrar todos los campos personalizados escribiendo sus nombres y valores. Por ejemplo: Campo1 == Valor1. Nota: Si los campos o valores contienen espacios, deben encapsularse entre comillas simples. Por ejemplo: 'Campo 1' == 'Valor 1'. Para omitir los caracteres de control único (' \\/), se usa \\. Por ejemplo: Campo1 = I\\'m. También se pueden combinar múltiples condiciones. Por ejemplo: C1 == V1 || C1 == V2. Normalmente todos los operadores se interpretan de izquierda a derecha. Se puede cambiar el orden colocando paréntesis. Por ejemplo: C1 == V1 && ( C2 == V2 || C2 == V3 ). También se puede buscar en campos de texto usando expresiones regulares: C1 == /Tes.*/i",
"fullname": "Nombre completo",
"header-logo-title": "Volver a tu página de tableros",
"hide-system-messages": "Ocultar las notificaciones de actividad",
"headerBarCreateBoardPopup-title": "Crear tablero",
"home": "Inicio",
"import": "Importar",
"link": "Enlace",
"import-board": "importar un tablero",
"import-board-c": "Importar un tablero",
"import-board-title-trello": "Importar un tablero desde Trello",
"import-board-title-wekan": "Importar tablero desde una exportación previa",
"import-board-title-csv": "Importar tablero desde CSV/TSV",
"from-trello": "Desde Trello",
"from-wekan": "Desde exportación previa",
"from-csv": "Desde CSV/TSV",
"import-board-instruction-trello": "En tu tablero de Trello, ve a 'Menú', luego 'Más' > 'Imprimir y exportar' > 'Exportar JSON', y copia el texto resultante.",
"import-board-instruction-csv": "Pegue en sus Valores separados por coma(CSV)/Valores separados por tab(TSV).",
"import-board-instruction-wekan": "En tu tablero, vete a 'Menú', luego 'Exportar tablero', y copia el texto en el archivo descargado.",
"import-board-instruction-about-errors": "Aunque obtengas errores cuando importes el tablero, a veces la importación funciona igualmente, y el tablero se encontrará en la página de tableros.",
"import-json-placeholder": "Pega tus datos JSON válidos aquí",
"import-csv-placeholder": "Paste your valid CSV/TSV data here",
"import-map-members": "Mapa de miembros",
"import-members-map": "Tu tablero importado tiene algunos miembros. Por favor, mapea los miembros que quieres importar con tus usuarios.",
"import-show-user-mapping": "Revisión de la asignación de miembros",
"import-user-select": "Selecciona el miembro existe que quieres usar como este miembro.",
"importMapMembersAddPopup-title": "Seleccionar miembro",
"info": "Versión",
"initials": "Iniciales",
"invalid-date": "Fecha no válida",
"invalid-time": "Tiempo no válido",
"invalid-user": "Usuario no válido",
"joined": "se ha unido",
"just-invited": "Has sido invitado a este tablero",
"keyboard-shortcuts": "Atajos de teclado",
"label-create": "Crear una etiqueta",
"label-default": "etiqueta %s (por defecto)",
"label-delete-pop": "Se eliminará esta etiqueta de todas las tarjetas y se destruirá su historial. Esta acción no puede deshacerse.",
"labels": "Etiquetas",
"language": "Cambiar el idioma",
"last-admin-desc": "No puedes cambiar roles porque debe haber al menos un administrador.",
"leave-board": "Abandonar el tablero",
"leave-board-pop": "¿Seguro que quieres abandonar __boardTitle__? Serás desvinculado de todas las tarjetas en este tablero.",
"leaveBoardPopup-title": "¿Abandonar el tablero?",
"link-card": "Enlazar a esta tarjeta",
"list-archive-cards": "Archivar todas las tarjetas de esta lista",
"list-archive-cards-pop": "Esto eliminará del tablero todas las tarjetas en esta lista. Para ver las tarjetas en el Archivo y recuperarlas al tablero haga click en \"Menu\" > \"Archivo\"",
"list-move-cards": "Mover todas las tarjetas de esta lista",
"list-select-cards": "Seleccionar todas las tarjetas de esta lista",
"set-color-list": "Cambiar el color",
"listActionPopup-title": "Acciones de la lista",
"swimlaneActionPopup-title": "Acciones del carril de flujo",
"swimlaneAddPopup-title": "Añadir un carril de flujo debajo",
"listImportCardPopup-title": "Importar una tarjeta de Trello",
"listImportCardsTsvPopup-title": "Import Excel CSV/TSV",
"listMorePopup-title": "Más",
"link-list": "Enlazar a esta lista",
"list-delete-pop": "Todas las acciones serán eliminadas del historial de actividades y no se podrá recuperar la lista. Esta acción no puede deshacerse.",
"list-delete-suggest-archive": "Puedes mover una lista al Archivo para quitarla del tablero y preservar la actividad.",
"lists": "Listas",
"swimlanes": "Carriles",
"log-out": "Finalizar la sesión",
"log-in": "Iniciar sesión",
"loginPopup-title": "Iniciar sesión",
"memberMenuPopup-title": "Preferencias de miembro",
"members": "Miembros",
"menu": "Menú",
"move-selection": "Mover la selección",
"moveCardPopup-title": "Mover la tarjeta",
"moveCardToBottom-title": "Mover al final",
"moveCardToTop-title": "Mover al principio",
"moveSelectionPopup-title": "Mover la selección",
"multi-selection": "Selección múltiple",
"multi-selection-on": "Selección múltiple activada",
"muted": "Silenciado",
"muted-info": "No serás notificado de ningún cambio en este tablero",
"my-boards": "Mis tableros",
"name": "Nombre",
"no-archived-cards": "No hay tarjetas archivadas.",
"no-archived-lists": "No hay listas archivadas.",
"no-archived-swimlanes": "No hay carriles archivados.",
"no-results": "Sin resultados",
"normal": "Normal",
"normal-desc": "Puedes ver y editar tarjetas. No puedes cambiar la configuración.",
"not-accepted-yet": "La invitación no ha sido aceptada aún",
"notify-participate": "Recibir actualizaciones de cualquier tarjeta en la que participas como creador o miembro",
"notify-watch": "Recibir actuaizaciones de cualquier tablero, lista o tarjeta que estés vigilando",
"optional": "opcional",
"or": "o",
"page-maybe-private": "Esta página puede ser privada. Es posible que puedas verla al <a href='%s'>iniciar sesión</a>.",
"page-not-found": "Página no encontrada.",
"password": "Contraseña",
"paste-or-dragdrop": "pegar o arrastrar y soltar un fichero de imagen (sólo imagen)",
"participating": "Participando",
"preview": "Previsualizar",
"previewAttachedImagePopup-title": "Previsualizar",
"previewClipboardImagePopup-title": "Previsualizar",
"private": "Privado",
"private-desc": "Este tablero es privado. Sólo las personas añadidas al tablero pueden verlo y editarlo.",
"profile": "Perfil",
"public": "Público",
"public-desc": "Este tablero es público. Es visible para cualquiera a través del enlace, y se mostrará en los buscadores como Google. Sólo las personas añadidas al tablero pueden editarlo.",
"quick-access-description": "Destaca un tablero para añadir un acceso directo en esta barra.",
"remove-cover": "Eliminar portada",
"remove-from-board": "Desvincular del tablero",
"remove-label": "Eliminar la etiqueta",
"listDeletePopup-title": "¿Eliminar la lista?",
"remove-member": "Eliminar miembro",
"remove-member-from-card": "Eliminar de la tarjeta",
"remove-member-pop": "¿Eliminar __name__ (__username__) de __boardTitle__? El miembro será eliminado de todas las tarjetas de este tablero. En ellas se mostrará una notificación.",
"removeMemberPopup-title": "¿Eliminar miembro?",
"rename": "Renombrar",
"rename-board": "Renombrar el tablero",
"restore": "Restaurar",
"save": "Añadir",
"search": "Buscar",
"rules": "Reglas",
"search-cards": "Buscar entre los títulos, las descripciones de las tarjetas/listas y los campos personalizados en este tablero.",
"search-example": "¿Texto a buscar?",
"select-color": "Seleccionar el color",
"set-wip-limit-value": "Cambiar el límite para el número máximo de tareas en esta lista.",
"setWipLimitPopup-title": "Cambiar el límite del trabajo en proceso",
"shortcut-assign-self": "Asignarte a ti mismo a la tarjeta actual",
"shortcut-autocomplete-emoji": "Autocompletar emoji",
"shortcut-autocomplete-members": "Autocompletar miembros",
"shortcut-clear-filters": "Limpiar todos los filtros",
"shortcut-close-dialog": "Cerrar el cuadro de diálogo",
"shortcut-filter-my-cards": "Filtrar mis tarjetas",
"shortcut-show-shortcuts": "Mostrar esta lista de atajos",
"shortcut-toggle-filterbar": "Conmutar la barra lateral del filtro",
"shortcut-toggle-sidebar": "Conmutar la barra lateral del tablero",
"show-cards-minimum-count": "Mostrar recuento de tarjetas si la lista contiene más de",
"sidebar-open": "Abrir la barra lateral",
"sidebar-close": "Cerrar la barra lateral",
"signupPopup-title": "Crear una cuenta",
"star-board-title": "Haz clic para destacar este tablero. Se mostrará en la parte superior de tu lista de tableros.",
"starred-boards": "Tableros destacados",
"starred-boards-description": "Los tableros destacados se mostrarán en la parte superior de tu lista de tableros.",
"subscribe": "Suscribirse",
"team": "Equipo",
"this-board": "este tablero",
"this-card": "esta tarjeta",
"spent-time-hours": "Tiempo consumido (horas)",
"overtime-hours": "Tiempo excesivo (horas)",
"overtime": "Tiempo excesivo",
"has-overtime-cards": "Hay tarjetas con el tiempo excedido",
"has-spenttime-cards": "Se ha excedido el tiempo de las tarjetas",
"time": "Hora",
"title": "Título",
"tracking": "Siguiendo",
"tracking-info": "Serás notificado de cualquier cambio en las tarjetas en las que participas como creador o miembro.",
"type": "Tipo",
"unassign-member": "Desvincular al miembro",
"unsaved-description": "Tienes una descripción por añadir.",
"unwatch": "Dejar de vigilar",
"upload": "Cargar",
"upload-avatar": "Cargar un avatar",
"uploaded-avatar": "Avatar cargado",
"username": "Nombre de usuario",
"view-it": "Verla",
"warn-list-archived": "advertencia: esta tarjeta está en una lista en el Archivo",
"watch": "Vigilar",
"watching": "Vigilando",
"watching-info": "Serás notificado de cualquier cambio en este tablero",
"welcome-board": "Tablero de bienvenida",
"welcome-swimlane": "Hito 1",
"welcome-list1": "Básicos",
"welcome-list2": "Avanzados",
"card-templates-swimlane": "Plantilla de tarjeta",
"list-templates-swimlane": "Listar plantillas",
"board-templates-swimlane": "Plantilla de tablero",
"what-to-do": "¿Qué quieres hacer?",
"wipLimitErrorPopup-title": "El límite del trabajo en proceso no es válido.",
"wipLimitErrorPopup-dialog-pt1": "El número de tareas en esta lista es mayor que el límite del trabajo en proceso que has definido.",
"wipLimitErrorPopup-dialog-pt2": "Por favor, mueve algunas tareas fuera de esta lista, o fija un límite del trabajo en proceso más alto.",
"admin-panel": "Panel del administrador",
"settings": "Preferencias",
"people": "Personas",
"registration": "Registro",
"disable-self-registration": "Deshabilitar autoregistro",
"invite": "Invitar",
"invite-people": "Invitar a personas",
"to-boards": "A el(los) tablero(s)",
"email-addresses": "Direcciones de correo electrónico",
"smtp-host-description": "Dirección del servidor SMTP para gestionar tus correos",
"smtp-port-description": "Puerto usado por el servidor SMTP para mandar correos",
"smtp-tls-description": "Habilitar el soporte TLS para el servidor SMTP",
"smtp-host": "Servidor SMTP",
"smtp-port": "Puerto SMTP",
"smtp-username": "Nombre de usuario",
"smtp-password": "Contraseña",
"smtp-tls": "Soporte TLS",
"send-from": "Desde",
"send-smtp-test": "Enviarte un correo de prueba a ti mismo",
"invitation-code": "Código de Invitación",
"email-invite-register-subject": "__inviter__ te ha enviado una invitación",
"email-invite-register-text": "Querido __user__,\n__inviter__ le invita al tablero kanban para colaborar.\n\nPor favor, siga el siguiente enlace:\n__url__\n\nY tu código de invitación es: __icode__\n\nGracias.",
"email-smtp-test-subject": "Prueba de email SMTP",
"email-smtp-test-text": "El correo se ha enviado correctamente",
"error-invitation-code-not-exist": "El código de invitación no existe",
"error-notAuthorized": "No estás autorizado a ver esta página.",
"webhook-title": "Nombre del Webhook",
"webhook-token": "Token (opcional para la autenticación)",
"outgoing-webhooks": "Webhooks salientes",
"bidirectional-webhooks": "Webhooks de doble sentido",
"outgoingWebhooksPopup-title": "Webhooks salientes",
"boardCardTitlePopup-title": "Filtro de títulos de tarjeta",
"disable-webhook": "Deshabilitar este Webhook",
"global-webhook": "Webhooks globales",
"new-outgoing-webhook": "Nuevo webhook saliente",
"no-name": "(Desconocido)",
"Node_version": "Versión de Node",
"Meteor_version": "Versión de Meteor",
"MongoDB_version": "Versión de MongoDB",
"MongoDB_storage_engine": "Motor de almacenamiento de MongoDB",
"MongoDB_Oplog_enabled": "Oplog de MongoDB habilitado",
"OS_Arch": "Arquitectura del sistema",
"OS_Cpus": "Número de CPUs del sistema",
"OS_Freemem": "Memoria libre del sistema",
"OS_Loadavg": "Carga media del sistema",
"OS_Platform": "Plataforma del sistema",
"OS_Release": "Publicación del sistema",
"OS_Totalmem": "Memoria total del sistema",
"OS_Type": "Tipo de sistema",
"OS_Uptime": "Tiempo activo del sistema",
"days": "días",
"hours": "horas",
"minutes": "minutos",
"seconds": "segundos",
"show-field-on-card": "Mostrar este campo en la tarjeta",
"automatically-field-on-card": "Crear campos automáticamente para todas las tarjetas.",
"showLabel-field-on-card": "Mostrar etiquetas de campos en la minitarjeta.",
"yes": "Sí",
"no": "No",
"accounts": "Cuentas",
"accounts-allowEmailChange": "Permitir cambiar el correo electrónico",
"accounts-allowUserNameChange": "Permitir cambiar el nombre de usuario",
"createdAt": "Fecha de alta",
"verified": "Verificado",
"active": "Activo",
"card-received": "Recibido",
"card-received-on": "Recibido el",
"card-end": "Finalizado",
"card-end-on": "Finalizado el",
"editCardReceivedDatePopup-title": "Cambiar la fecha de recepción",
"editCardEndDatePopup-title": "Cambiar la fecha de finalización",
"setCardColorPopup-title": "Cambiar el color",
"setCardActionsColorPopup-title": "Elegir un color",
"setSwimlaneColorPopup-title": "Elegir un color",
"setListColorPopup-title": "Elegir un color",
"assigned-by": "Asignado por",
"requested-by": "Solicitado por",
"board-delete-notice": "Se eliminarán todas las listas, tarjetas y acciones asociadas a este tablero. Esta acción no puede deshacerse.",
"delete-board-confirm-popup": "Se eliminarán todas las listas, tarjetas, etiquetas y actividades, y no podrás recuperar los contenidos del tablero. Esta acción no puede deshacerse.",
"boardDeletePopup-title": "¿Eliminar el tablero?",
"delete-board": "Eliminar el tablero",
"default-subtasks-board": "Subtareas para el tablero __board__",
"default": "Por defecto",
"queue": "Cola",
"subtask-settings": "Preferencias de las subtareas",
"card-settings": "Preferencias de la tarjeta",
"boardSubtaskSettingsPopup-title": "Preferencias de las subtareas del tablero",
"boardCardSettingsPopup-title": "Preferencias de la tarjeta",
"deposit-subtasks-board": "Depositar subtareas en este tablero:",
"deposit-subtasks-list": "Lista de destino para subtareas depositadas aquí:",
"show-parent-in-minicard": "Mostrar el padre en una minitarjeta:",
"prefix-with-full-path": "Prefijo con ruta completa",
"prefix-with-parent": "Prefijo con el padre",
"subtext-with-full-path": "Subtexto con ruta completa",
"subtext-with-parent": "Subtexto con el padre",
"change-card-parent": "Cambiar la tarjeta padre",
"parent-card": "Tarjeta padre",
"source-board": "Tablero de origen",
"no-parent": "No mostrar la tarjeta padre",
"activity-added-label": "añadida etiqueta %s a %s",
"activity-removed-label": "eliminada etiqueta '%s' desde %s",
"activity-delete-attach": "eliminado un adjunto desde %s",
"activity-added-label-card": "añadida etiqueta '%s'",
"activity-removed-label-card": "eliminada etiqueta '%s'",
"activity-delete-attach-card": "eliminado un adjunto",
"activity-set-customfield": "Cambiar el campo personalizado '%s' a '%s' en %s",
"activity-unset-customfield": "Desmarcar el campo personalizado '%s' en %s",
"r-rule": "Regla",
"r-add-trigger": "Añadir disparador",
"r-add-action": "Añadir acción",
"r-board-rules": "Reglas del tablero",
"r-add-rule": "Añadir regla",
"r-view-rule": "Ver regla",
"r-delete-rule": "Eliminar regla",
"r-new-rule-name": "Nueva título de regla",
"r-no-rules": "No hay reglas",
"r-when-a-card": "Cuando una tarjeta",
"r-is": "es",
"r-is-moved": "es movida",
"r-added-to": "Added to",
"r-removed-from": "eliminado de",
"r-the-board": "el tablero",
"r-list": "la lista",
"set-filter": "Filtrar",
"r-moved-to": "Movido a",
"r-moved-from": "Movido desde",
"r-archived": "Se archivó",
"r-unarchived": "Restaurado del archivo",
"r-a-card": "una tarjeta",
"r-when-a-label-is": "Cuando una etiqueta es",
"r-when-the-label": "Cuando la etiqueta es",
"r-list-name": "Nombre de lista",
"r-when-a-member": "Cuando un miembro es",
"r-when-the-member": "Cuando el miembro",
"r-name": "nombre",
"r-when-a-attach": "Cuando un adjunto",
"r-when-a-checklist": "Cuando una lista de verificación es",
"r-when-the-checklist": "Cuando la lista de verificación",
"r-completed": "Completada",
"r-made-incomplete": "Hecha incompleta",
"r-when-a-item": "Cuando un elemento de la lista de verificación es",
"r-when-the-item": "Cuando el elemento de la lista de verificación es",
"r-checked": "Marcado",
"r-unchecked": "Desmarcado",
"r-move-card-to": "Mover la tarjeta",
"r-top-of": "Arriba de",
"r-bottom-of": "Abajo de",
"r-its-list": "su lista",
"r-archive": "Archivar",
"r-unarchive": "Restaurar del Archivo",
"r-card": "la tarjeta",
"r-add": "Añadir",
"r-remove": "Eliminar",
"r-label": "etiqueta",
"r-member": "miembro",
"r-remove-all": "Eliminar todos los miembros de la tarjeta",
"r-set-color": "Cambiar el color a",
"r-checklist": "lista de verificación",
"r-check-all": "Marcar todo",
"r-uncheck-all": "Desmarcar todo",
"r-items-check": "elementos de la lista de verificación",
"r-check": "Marcar",
"r-uncheck": "Desmarcar",
"r-item": "elemento",
"r-of-checklist": "de la lista de verificación",
"r-send-email": "Enviar un email",
"r-to": "a",
"r-of": "of",
"r-subject": "asunto",
"r-rule-details": "Detalle de la regla",
"r-d-move-to-top-gen": "Mover la tarjeta al inicio de su lista",
"r-d-move-to-top-spec": "Mover la tarjeta al inicio de la lista",
"r-d-move-to-bottom-gen": "Mover la tarjeta al final de su lista",
"r-d-move-to-bottom-spec": "Mover la tarjeta al final de la lista",
"r-d-send-email": "Enviar email",
"r-d-send-email-to": "a",
"r-d-send-email-subject": "asunto",
"r-d-send-email-message": "mensaje",
"r-d-archive": "Archivar la tarjeta",
"r-d-unarchive": "Restaurar tarjeta del Archivo",
"r-d-add-label": "Añadir etiqueta",
"r-d-remove-label": "Eliminar etiqueta",
"r-create-card": "Crear una nueva tarjeta",
"r-in-list": "en la lista",
"r-in-swimlane": "en el carril",
"r-d-add-member": "Añadir miembro",
"r-d-remove-member": "Eliminar miembro",
"r-d-remove-all-member": "Eliminar todos los miembros",
"r-d-check-all": "Marcar todos los elementos de una lista",
"r-d-uncheck-all": "Desmarcar todos los elementos de una lista",
"r-d-check-one": "Marcar elemento",
"r-d-uncheck-one": "Desmarcar elemento",
"r-d-check-of-list": "de la lista de verificación",
"r-d-add-checklist": "Añadir una lista de verificación",
"r-d-remove-checklist": "Eliminar lista de verificación",
"r-by": "por",
"r-add-checklist": "Añadir una lista de verificación",
"r-with-items": "con items",
"r-items-list": "item1,item2,item3",
"r-add-swimlane": "Agregar el carril",
"r-swimlane-name": "nombre del carril",
"r-board-note": "Nota: deje un campo vacío para que coincida con todos los valores posibles",
"r-checklist-note": "Nota: los ítems de la lista tienen que escribirse como valores separados por coma.",
"r-when-a-card-is-moved": "Cuando una tarjeta es movida a otra lista",
"r-set": "Cambiar",
"r-update": "Actualizar",
"r-datefield": "campo de fecha",
"r-df-start-at": "comienza",
"r-df-due-at": "vencimiento",
"r-df-end-at": "finalizado",
"r-df-received-at": "recibido",
"r-to-current-datetime": "a la fecha/hora actual",
"r-remove-value-from": "Eliminar el valor de",
"ldap": "LDAP",
"oauth2": "OAuth2",
"cas": "CAS",
"authentication-method": "Método de autenticación",
"authentication-type": "Tipo de autenticación",
"custom-product-name": "Nombre de producto personalizado",
"layout": "Diseño",
"hide-logo": "Ocultar el logo",
"add-custom-html-after-body-start": "Añade HTML personalizado después de <body>",
"add-custom-html-before-body-end": "Añade HTML personalizado después de </body>",
"error-undefined": "Algo no está bien",
"error-ldap-login": "Ocurrió un error al intentar acceder",
"display-authentication-method": "Mostrar el método de autenticación",
"default-authentication-method": "Método de autenticación por defecto",
"duplicate-board": "Duplicar tablero",
"people-number": "El número de personas es:",
"swimlaneDeletePopup-title": "¿Eliminar el carril de flujo?",
"swimlane-delete-pop": "Todas las acciones serán eliminadas del historial de actividades y no se podrá recuperar el carril de flujo. Esta acción no puede deshacerse.",
"restore-all": "Restaurar todas",
"delete-all": "Borrar todas",
"loading": "Cargando. Por favor, espere.",
"previous_as": "el último tiempo fue",
"act-a-dueAt": "cambiada la hora de vencimiento a \nCuándo: __timeValue__\nDónde: __card__\n el vencimiento anterior fue __timeOldValue__",
"act-a-endAt": "cambiada la hora de finalización a __timeValue__ Fecha anterior: (__timeOldValue__)",
"act-a-startAt": "cambiada la hora de comienzo a __timeValue__ Fecha anterior: (__timeOldValue__)",
"act-a-receivedAt": "cambiada la fecha de recepción a __timeValue__ Fecha anterior: (__timeOldValue__)",
"a-dueAt": "cambiada la hora de vencimiento a",
"a-endAt": "cambiada la hora de finalización a",
"a-startAt": "cambiada la hora de comienzo a",
"a-receivedAt": "cambiada la hora de recepción a",
"almostdue": "está próxima la hora de vencimiento actual %s",
"pastdue": "se sobrepasó la hora de vencimiento actual%s",
"duenow": "la hora de vencimiento actual %s es hoy",
"act-newDue": "__list__/__card__ tiene una 1ra notificación de vencimiento [__board__]",
"act-withDue": "__list__/__card__ notificaciones de vencimiento [__board__]",
"act-almostdue": "se ha notificado que el vencimiento actual (__timeValue__) de __card__ está próximo",
"act-pastdue": "se ha notificado que el vencimiento actual (__timeValue__) de __card__ se sobrepasó",
"act-duenow": "se ha notificado que el vencimiento actual (__timeValue__) de __card__ es ahora",
"act-atUserComment": "Se te mencionó en [__board__] __list__/__card__",
"delete-user-confirm-popup": "¿Seguro que quieres eliminar esta cuenta? Esta acción no puede deshacerse.",
"accounts-allowUserDelete": "Permitir a los usuarios eliminar su cuenta",
"hide-minicard-label-text": "Ocultar el texto de la etiqueta de la minitarjeta",
"show-desktop-drag-handles": "Mostrar los controles de arrastre del escritorio",
"assignee": "Asignado",
"cardAssigneesPopup-title": "Asignado",
"addmore-detail": "Añadir una descripción detallada",
"show-on-card": "Mostrar en la tarjeta",
"new": "Nuevo",
"editUserPopup-title": "Editar el usuario",
"newUserPopup-title": "Nuevo usuario",
"notifications": "Notificaciones",
"view-all": "Ver todo",
"filter-by-unread": "Filtrar por no leído",
"mark-all-as-read": "Marcar todo como leido",
"remove-all-read": "Remove all read",
"allow-rename": "Permitir renombrar",
"allowRenamePopup-title": "Permitir renombrar",
"start-day-of-week": "Set day of the week start",
"monday": "Lunes",
"tuesday": "Martes",
"wednesday": "Miércoles",
"thursday": "Jueves",
"friday": "Viernes",
"saturday": "Sábado",
"sunday": "Domingo",
"status": "Status",
"swimlane": "Swimlane",
"owner": "Owner",
"last-modified-at": "Last modified at",
"last-activity": "Last activity",
"voting": "Voting",
"archived": "Archived",
"delete-linked-card-before-this-card": "You can not delete this card before first deleting linked card that has",
"delete-linked-cards-before-this-list": "You can not delete this list before first deleting linked cards that are pointing to cards in this list"
}
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
+809 -779
View File
File diff suppressed because it is too large. Load diff
Loaded 100 of 160 files, more files were not shown because too many files have changed in this diff. Show more