Compare commits

..

256 Commits

Author SHA1 Message Date
grnd-alt
981d1cbd38 fix: remove deprecated ToolTip
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-14 09:54:43 +02:00
grnd-alt
85af54cd6f fix: do not clean webpack-stats.json from build files
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:38:28 +02:00
grnd-alt
f3a8de2c48 fix: stabilize cypress
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:38:22 +02:00
grnd-alt
1d7bf30e8f bump @nextcloud/dialogs to 7.0.0-rc.1
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:12:31 +02:00
grnd-alt
ee10097c24 fix: adapt NcButtons to nextcloud-vue 9
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:12:31 +02:00
grnd-alt
03d2bd945c fix: remove extra component for NcAction entries
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:12:29 +02:00
grnd-alt
1110a4f125 use correct prop name for nextcloud/vue vue3
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
f4acf38035 replace Vue.set with direct setting
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
30e74a7919 fix: rename parameter names deprecated in vue3
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
b59b2edb37 use v-model instead of value:sync
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
8e805dbec3 fix: use vue3 slot syntax
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
0f1d1181e3 fix: correct syntax for scss variables
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
c32115dea6 vue3-with non-local dependencies and part of the functionality
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
452dc5f230 get deck to build with vue3 with broken functionality
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:38 +02:00
Nextcloud bot
81e2c4768b fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-07-09 00:29:04 +00:00
Luka Trovic
3c917f3b2d Merge pull request #7083 from nextcloud/feat/workflow-auto-update-reuse.yml
ci: update reuse.yml workflow from template
2025-07-08 10:51:19 +02:00
Nextcloud bot
6fd24ffa45 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-07-08 00:29:03 +00:00
Nextcloud bot
a9235e00c7 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-07-06 00:28:13 +00:00
Nextcloud bot
f8ad05b55b fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-07-05 00:28:23 +00:00
Nextcloud bot
be497a741c fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-07-04 00:28:38 +00:00
Luka Trovic
62a9ce3131 fix: add retry and show warning on description saving error (#7070)
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2025-07-03 11:47:28 +02:00
grnd-alt
7799854df4 fix: ensure correct type when filtering events (#7071)
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-03 10:45:42 +02:00
Nextcloud bot
bf961c3de4 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-07-03 00:28:51 +00:00
Nextcloud bot
5f73d97e4e fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-07-02 00:29:11 +00:00
Nextcloud bot
32f0852a23 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-07-01 00:28:28 +00:00
Nextcloud bot
d80c9b3eec fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-30 00:27:42 +00:00
Nextcloud bot
002bac60b1 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-29 00:27:40 +00:00
Nextcloud bot
08756b6c5d fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-28 00:29:06 +00:00
Nextcloud bot
71bb838964 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-28 00:28:03 +00:00
Nextcloud bot
6c55e3cd70 ci: update reuse.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-27 10:14:06 +00:00
Nextcloud bot
8391d843d5 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-27 00:43:49 +00:00
Luka Trovic
7cb9f8b966 Merge pull request #7066 from nextcloud/dependabot/github_actions/shivammathur/setup-php-2.34.1
Chore(deps): Bump shivammathur/setup-php from 2.33.0 to 2.34.1
2025-06-26 11:13:34 +02:00
Nextcloud bot
1dfbec4278 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-26 00:42:57 +00:00
Nextcloud bot
6841d4c068 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-25 00:43:14 +00:00
Nextcloud bot
4e70286629 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-24 00:43:11 +00:00
Nextcloud bot
54a5a1ecb2 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-20 00:42:28 +00:00
Nextcloud bot
4139f8b94a fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-19 00:42:34 +00:00
Julius Knorr
5c21cd2cf5 Merge pull request #7000 from nextcloud/automated/noid/main-update-nextcloud-ocp 2025-06-18 08:34:43 +02:00
Nextcloud bot
af253270aa fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-17 00:40:26 +00:00
Nextcloud bot
6a64b4fc75 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-16 00:40:38 +00:00
nextcloud-command
4b260a047c chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2025-06-15 03:34:29 +00:00
dependabot[bot]
8d41f9730f Chore(deps): Bump shivammathur/setup-php from 2.33.0 to 2.34.1
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.33.0 to 2.34.1.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.33.0...2.34.1)

---
updated-dependencies:
- dependency-name: shivammathur/setup-php
  dependency-version: 2.34.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-14 02:25:16 +00:00
Nextcloud bot
2adacaa39e fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-14 00:40:02 +00:00
Luka Trovic
69fcd9bfdf Merge pull request #7030 from nextcloud/fix-cypress
fix: unstable cypress test
2025-06-12 18:14:49 +02:00
Luka Trovic
c0b3775232 fix: unstable cypress test
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2025-06-12 16:17:02 +02:00
Nextcloud bot
df0e909be4 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-11 00:44:33 +00:00
Julius Knorr
96905c891c Merge pull request #7059 from nextcloud/fix-file-sharing-picker 2025-06-10 17:11:51 +02:00
Nextcloud bot
58c8dd5221 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-10 00:40:10 +00:00
Luka Trovic
e21c82b38e fix: not show Share with a Deck card for unauthorized users
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2025-06-09 12:25:51 +02:00
Julius Knorr
02afc218ff Merge pull request #7043 from nextcloud/dependabot/npm_and_yarn/tar-fs-2.1.3
Chore(deps-dev): Bump tar-fs from 2.1.2 to 2.1.3
2025-06-03 14:41:17 +02:00
dependabot[bot]
50d199dd08 Chore(deps-dev): Bump tar-fs from 2.1.2 to 2.1.3
Bumps [tar-fs](https://github.com/mafintosh/tar-fs) from 2.1.2 to 2.1.3.
- [Commits](https://github.com/mafintosh/tar-fs/commits)

---
updated-dependencies:
- dependency-name: tar-fs
  dependency-version: 2.1.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-03 09:16:36 +00:00
Nextcloud bot
ff74bfbf13 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-06-01 00:39:59 +00:00
Nextcloud bot
a64bec0ecd fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-31 00:40:55 +00:00
Luka Trovic
d66e6408b1 Merge pull request #7027 from nextcloud/purge-deleted-lists
fix: update DeleteCron to remove deleted lists
2025-05-28 17:58:59 +02:00
Luka Trovic
324eb05598 fix: update DeleteCron to remove deleted lists
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2025-05-28 12:03:06 +02:00
Nextcloud bot
9938a6d57f fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-28 00:41:37 +00:00
Nextcloud bot
c2e4165bf7 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-26 00:41:08 +00:00
Nextcloud bot
7de0d6f1c4 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-23 00:40:37 +00:00
Nextcloud bot
5631741b6b fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-22 00:41:20 +00:00
Luka Trovic
724ad74c47 Merge pull request #7012 from nextcloud/update-dependabot
chore: update dependabot.yml
2025-05-21 20:22:13 +02:00
Nextcloud bot
c8897477a7 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-21 00:45:40 +00:00
Luka Trovic
7ac93d311c chore: update dependabot.yml
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2025-05-19 15:48:12 +02:00
Nextcloud bot
be8806102a fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-18 00:41:52 +00:00
Nextcloud bot
f6a5877b85 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-17 00:44:01 +00:00
Nextcloud bot
9360a49d50 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-15 00:44:21 +00:00
Nextcloud bot
3aee848221 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-14 00:41:37 +00:00
Nextcloud bot
2f53f8a1d6 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-13 00:42:47 +00:00
Nextcloud bot
d63764fa78 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-12 00:41:52 +00:00
Nextcloud bot
d06ec0ad98 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-11 00:41:44 +00:00
Nextcloud bot
4bf086b55e fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-10 00:43:58 +00:00
dependabot[bot]
99e2912d7c Merge pull request #6972 from nextcloud/dependabot/npm_and_yarn/main/relative-ci/agent-4.3.1 2025-05-08 14:45:00 +00:00
dependabot[bot]
10aed3660c Chore(deps-dev): Bump @relative-ci/agent from 4.2.14 to 4.3.1
Bumps [@relative-ci/agent](https://github.com/relative-ci/agent) from 4.2.14 to 4.3.1.
- [Release notes](https://github.com/relative-ci/agent/releases)
- [Commits](https://github.com/relative-ci/agent/compare/v4.2.14...v4.3.1)

---
updated-dependencies:
- dependency-name: "@relative-ci/agent"
  dependency-version: 4.3.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-08 16:39:31 +02:00
Nextcloud bot
6628c42eca fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-08 00:43:26 +00:00
Nextcloud bot
dbe1ced6b0 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-07 00:43:32 +00:00
Nextcloud bot
04b4da39c9 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-06 00:43:38 +00:00
Nextcloud bot
530a695e6f fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-05 01:11:34 +00:00
github-actions[bot]
02d7dd469e Merge pull request #6979 from nextcloud/automated/noid/main-update-nextcloud-ocp
[main] Update nextcloud/ocp dependency
2025-05-04 04:36:55 +00:00
nextcloud-command
71340b1217 chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2025-05-04 03:20:39 +00:00
Nextcloud bot
153a9d2b7d fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-04 00:41:43 +00:00
Nextcloud bot
e18f73a333 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-03 00:42:55 +00:00
dependabot[bot]
127f1b2d40 Merge pull request #6861 from nextcloud/dependabot/npm_and_yarn/main/babel/runtime-7.27.0 2025-05-02 16:21:14 +00:00
dependabot[bot]
fe4c8df97e Chore(deps): Bump @babel/runtime from 7.26.10 to 7.27.0
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.26.10 to 7.27.0.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.27.0/packages/babel-runtime)

---
updated-dependencies:
- dependency-name: "@babel/runtime"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-02 18:16:03 +02:00
dependabot[bot]
d5582535d6 Merge pull request #6926 from nextcloud/dependabot/github_actions/shivammathur/setup-php-2.33.0 2025-05-02 15:59:19 +00:00
dependabot[bot]
7ec112ae1d Chore(deps): Bump shivammathur/setup-php from 2.32.0 to 2.33.0
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.32.0 to 2.33.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.32.0...2.33.0)

---
updated-dependencies:
- dependency-name: shivammathur/setup-php
  dependency-version: 2.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-02 17:54:08 +02:00
dependabot[bot]
aa747d7d62 Merge pull request #6938 from nextcloud/dependabot/composer/tests/integration/behat/behat-approx-3.21.1 2025-05-02 15:08:12 +00:00
dependabot[bot]
d97f6c1a5f Chore(deps-dev): Update behat/behat requirement in /tests/integration
Updates the requirements on [behat/behat](https://github.com/Behat/Behat) to permit the latest version.
- [Release notes](https://github.com/Behat/Behat/releases)
- [Changelog](https://github.com/Behat/Behat/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Behat/Behat/compare/v3.18.1...v3.21.1)

---
updated-dependencies:
- dependency-name: behat/behat
  dependency-version: 3.21.1
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-02 17:00:07 +02:00
Nextcloud bot
8e0b585662 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-02 00:43:00 +00:00
Nextcloud bot
c0f7e16463 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-05-01 00:42:07 +00:00
Luka Trovic
71b4700a07 Merge pull request #6872 from nextcloud/board-import-export
feat: add board import and export
2025-04-30 22:41:09 +02:00
Luka Trovic
688649f5a8 Merge pull request #6916 from nextcloud/perf/dont-enrich-calendar-entries
perf: don't enrich cards when finding calendar entries
2025-04-29 13:39:08 +02:00
Luka Trovic
03cdc47540 feat: add board import and export
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2025-04-29 09:53:49 +02:00
Nextcloud bot
9f06a43d4b fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-29 00:42:23 +00:00
grnd-alt
d31e31735d Merge pull request #6933 from nextcloud/fix/label-card-limit
fix: Ensure consistent label mappings
2025-04-28 10:43:20 +02:00
Julius Knorr
4a05762c0a Merge pull request #6950 from nextcloud/automated/noid/main-fix-npm-audit
[main] Fix npm audit
2025-04-28 08:52:07 +02:00
Julius Knorr
a72f48f9ce Merge pull request #6898 from nextcloud/fix/log-spam
fix: Use strings as rich object ids
2025-04-28 08:51:15 +02:00
Nextcloud bot
7e6f23fa82 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-28 00:42:35 +00:00
github-actions[bot]
a72f4e3aa3 Merge pull request #6947 from nextcloud/automated/noid/main-update-nextcloud-ocp
[main] Update nextcloud/ocp dependency
2025-04-27 04:29:11 +00:00
nextcloud-command
ec8945bb54 fix(deps): Fix npm audit
Signed-off-by: GitHub <noreply@github.com>
2025-04-27 03:53:25 +00:00
nextcloud-command
760f771e11 chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2025-04-27 03:15:52 +00:00
Nextcloud bot
f0a443cbb6 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-27 00:42:04 +00:00
Nextcloud bot
69b9c09a14 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-25 00:41:58 +00:00
Nextcloud bot
7c93108172 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-24 00:42:52 +00:00
grnd-alt
899d8a6531 fix: only delete assignments on unshared board (#6932)
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-04-23 11:37:17 +02:00
Julius Knorr
60b34d190a tests: Fix unit test mocking around label checks
Signed-off-by: Julius Knorr <jus@bitgrid.net>
2025-04-23 09:48:02 +02:00
Julius Knorr
438a149304 chore: Add migration step for wrong label mapping
Signed-off-by: Julius Knorr <jus@bitgrid.net>
2025-04-23 09:47:37 +02:00
Nextcloud bot
9a2fcf6925 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-23 00:42:06 +00:00
dependabot[bot]
e3c802c0f3 Merge pull request #6925 from nextcloud/dependabot/github_actions/actions/setup-node-4.4.0 2025-04-22 17:22:42 +00:00
Julius Knorr
ea84743864 fix: Use strings as rich object ids
Signed-off-by: Julius Knorr <jus@bitgrid.net>
2025-04-22 17:01:56 +02:00
Julius Knorr
abd38e0c15 Merge pull request #6928 from nextcloud/dependabot/npm_and_yarn/main/nextcloud/vue-8.25.1
Chore(deps): Bump @nextcloud/vue from 8.24.0 to 8.25.1
2025-04-22 16:43:56 +02:00
Julius Knorr
0ec1f7151c Merge pull request #6843 from nextcloud/automated/noid/main-update-nextcloud-ocp
[main] Update nextcloud/ocp dependency
2025-04-22 16:43:20 +02:00
Julius Knorr
a27cbf8bad Merge pull request #6773 from nextcloud/automated/noid/main-fix-npm-audit
[main] Fix npm audit
2025-04-22 16:42:51 +02:00
Luka Trovic
f4a1424e90 Merge pull request #6930 from nextcloud/dependabot/npm_and_yarn/main/eslint-webpack-plugin-5.0.1
Chore(deps-dev): Bump eslint-webpack-plugin from 4.2.0 to 5.0.1
2025-04-22 15:57:04 +02:00
Julius Härtl
a92dc282a8 fix: Limit label actions to labels of the cards board
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2025-04-22 15:41:39 +02:00
nextcloud-command
e3ffbf73c3 fix(deps): Fix npm audit
Signed-off-by: GitHub <noreply@github.com>
2025-04-20 03:32:19 +00:00
nextcloud-command
c6e075af92 chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2025-04-20 03:12:21 +00:00
dependabot[bot]
144f293231 Chore(deps-dev): Bump eslint-webpack-plugin from 4.2.0 to 5.0.1
Bumps [eslint-webpack-plugin](https://github.com/webpack-contrib/eslint-webpack-plugin) from 4.2.0 to 5.0.1.
- [Release notes](https://github.com/webpack-contrib/eslint-webpack-plugin/releases)
- [Changelog](https://github.com/webpack-contrib/eslint-webpack-plugin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/eslint-webpack-plugin/compare/v4.2.0...v5.0.1)

---
updated-dependencies:
- dependency-name: eslint-webpack-plugin
  dependency-version: 5.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-19 01:50:17 +00:00
dependabot[bot]
6d78bc70f3 Chore(deps): Bump @nextcloud/vue from 8.24.0 to 8.25.1
Bumps [@nextcloud/vue](https://github.com/nextcloud-libraries/nextcloud-vue) from 8.24.0 to 8.25.1.
- [Release notes](https://github.com/nextcloud-libraries/nextcloud-vue/releases)
- [Changelog](https://github.com/nextcloud-libraries/nextcloud-vue/blob/v8.25.1/CHANGELOG.md)
- [Commits](https://github.com/nextcloud-libraries/nextcloud-vue/compare/v8.24.0...v8.25.1)

---
updated-dependencies:
- dependency-name: "@nextcloud/vue"
  dependency-version: 8.25.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-19 01:49:37 +00:00
dependabot[bot]
bf15865957 Chore(deps): Bump actions/setup-node from 4.3.0 to 4.4.0
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.3.0 to 4.4.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4.3.0...v4.4.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: 4.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-19 01:35:47 +00:00
Nextcloud bot
d2e5c0c515 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-18 00:43:11 +00:00
Nextcloud bot
933f2515db fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-17 00:42:38 +00:00
dependabot[bot]
17bf361767 Merge pull request #6917 from nextcloud/dependabot/npm_and_yarn/http-proxy-middleware-2.0.9 2025-04-16 18:31:25 +00:00
dependabot[bot]
1df731396f Merge pull request #6874 from nextcloud/dependabot/npm_and_yarn/main/nextcloud/vue-8.24.0 2025-04-16 18:27:55 +00:00
dependabot[bot]
968ea30fd4 Chore(deps): Bump @nextcloud/vue from 8.22.0 to 8.24.0
Bumps [@nextcloud/vue](https://github.com/nextcloud-libraries/nextcloud-vue) from 8.22.0 to 8.24.0.
- [Release notes](https://github.com/nextcloud-libraries/nextcloud-vue/releases)
- [Changelog](https://github.com/nextcloud-libraries/nextcloud-vue/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nextcloud-libraries/nextcloud-vue/compare/v8.22.0...v8.24.0)

---
updated-dependencies:
- dependency-name: "@nextcloud/vue"
  dependency-version: 8.24.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-16 18:22:48 +00:00
dependabot[bot]
8f75c7f92d Chore(deps-dev): Bump http-proxy-middleware from 2.0.7 to 2.0.9
Bumps [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware) from 2.0.7 to 2.0.9.
- [Release notes](https://github.com/chimurai/http-proxy-middleware/releases)
- [Changelog](https://github.com/chimurai/http-proxy-middleware/blob/v2.0.9/CHANGELOG.md)
- [Commits](https://github.com/chimurai/http-proxy-middleware/compare/v2.0.7...v2.0.9)

---
updated-dependencies:
- dependency-name: http-proxy-middleware
  dependency-version: 2.0.9
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-16 18:22:26 +00:00
Luka Trovic
234be011cc Merge pull request #6879 from nextcloud/dependabot/npm_and_yarn/multi-b29f0fd473
Chore(deps): Bump tar-fs and dockerode
2025-04-16 20:21:06 +02:00
Richard Steinmetz
fa2f5bcab8 perf: don't enrich cards when finding calendar entries
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
2025-04-16 13:49:58 +02:00
Nextcloud bot
685014ec48 fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-16 00:43:52 +00:00
Luka Trovic
1cd6c55d30 Merge pull request #6902 from nextcloud/update-card-move-dialog
Clear selected stack when selected board changed
2025-04-15 18:33:07 +02:00
Luka Trovic
6dbcf5d17b fix: clear selected stack when selected board changed
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2025-04-14 20:28:52 +02:00
dependabot[bot]
f84d7c372b Merge pull request #6885 from nextcloud/dependabot/composer/justinrainbow/json-schema-6.4.1 2025-04-14 14:50:36 +00:00
dependabot[bot]
8be8647f6d Merge pull request #6910 from nextcloud/dependabot/github_actions/nextcloud-libraries/npm-audit-action-0.2.0 2025-04-12 02:12:00 +00:00
dependabot[bot]
eb878055ae Merge pull request #6908 from nextcloud/dependabot/npm_and_yarn/main/nextcloud/webpack-vue-config-6.3.0 2025-04-12 02:04:52 +00:00
dependabot[bot]
00b334d3d9 Chore(deps): Bump nextcloud-libraries/npm-audit-action
Bumps [nextcloud-libraries/npm-audit-action](https://github.com/nextcloud-libraries/npm-audit-action) from 0.1.0 to 0.2.0.
- [Release notes](https://github.com/nextcloud-libraries/npm-audit-action/releases)
- [Commits](2a60bd2e79...1b1728b2b4)

---
updated-dependencies:
- dependency-name: nextcloud-libraries/npm-audit-action
  dependency-version: 0.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-12 01:54:09 +00:00
dependabot[bot]
5905154fe0 Chore(deps-dev): Bump @nextcloud/webpack-vue-config from 6.2.0 to 6.3.0
Bumps [@nextcloud/webpack-vue-config](https://github.com/nextcloud-libraries/webpack-vue-config) from 6.2.0 to 6.3.0.
- [Release notes](https://github.com/nextcloud-libraries/webpack-vue-config/releases)
- [Changelog](https://github.com/nextcloud-libraries/webpack-vue-config/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nextcloud-libraries/webpack-vue-config/compare/v6.2.0...v6.3.0)

---
updated-dependencies:
- dependency-name: "@nextcloud/webpack-vue-config"
  dependency-version: 6.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-12 01:39:42 +00:00
Nextcloud bot
8280f0796f Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-12 00:44:01 +00:00
Nextcloud bot
18ea2f9a7e Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-11 00:43:38 +00:00
Nextcloud bot
3cbddae6bc Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-10 00:42:51 +00:00
Julius Knorr
aac11e96b5 Merge pull request #6893 from nextcloud/perf/deck-share-deleted-cards 2025-04-08 22:59:39 +02:00
Julius Knorr
2e62a9c82a perf: Skip doing a query just to check if a board is deleted
Signed-off-by: Julius Knorr <jus@bitgrid.net>
2025-04-08 22:13:11 +02:00
Nextcloud bot
ec18ec758b Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-06 00:44:05 +00:00
dependabot[bot]
8f3e2ae1d9 Chore(deps): Bump justinrainbow/json-schema from 6.0.0 to 6.4.1
Bumps [justinrainbow/json-schema](https://github.com/jsonrainbow/json-schema) from 6.0.0 to 6.4.1.
- [Release notes](https://github.com/jsonrainbow/json-schema/releases)
- [Changelog](https://github.com/jsonrainbow/json-schema/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsonrainbow/json-schema/compare/6.0.0...6.4.1)

---
updated-dependencies:
- dependency-name: justinrainbow/json-schema
  dependency-version: 6.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-05 01:46:07 +00:00
dependabot[bot]
7f00601007 Chore(deps): Bump tar-fs and dockerode
Bumps [tar-fs](https://github.com/mafintosh/tar-fs) and [dockerode](https://github.com/apocas/dockerode). These dependencies needed to be updated together.

Updates `tar-fs` from 2.0.1 to 2.1.2
- [Commits](https://github.com/mafintosh/tar-fs/compare/v2.0.1...v2.1.2)

Updates `dockerode` from 4.0.2 to 4.0.5
- [Release notes](https://github.com/apocas/dockerode/releases)
- [Commits](https://github.com/apocas/dockerode/compare/v4.0.2...v4.0.5)

---
updated-dependencies:
- dependency-name: tar-fs
  dependency-version: 2.1.2
  dependency-type: indirect
- dependency-name: dockerode
  dependency-version: 4.0.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-05 01:17:26 +00:00
dependabot[bot]
175c10c146 Merge pull request #6873 from nextcloud/dependabot/npm_and_yarn/main/dompurify-3.2.5 2025-04-05 01:16:25 +00:00
dependabot[bot]
8dc0933c47 Chore(deps): Bump dompurify from 3.2.4 to 3.2.5
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.2.4 to 3.2.5.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.2.4...3.2.5)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.2.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-05 01:11:29 +00:00
Nextcloud bot
8c52b9bad9 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-04 00:42:52 +00:00
Nextcloud bot
a1c9396946 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-04-02 00:43:19 +00:00
Luka Trovic
b0fbb386b8 Merge pull request #6800 from gidan80/main
CSV export fixes
2025-03-31 13:56:15 +02:00
Ronni Dal Lago
e77a2fcd79 Merge branch 'main' of https://github.com/gidan80/deck 2025-03-31 12:19:51 +02:00
Ronni Dal Lago
89152325be Increased query count
Signed-off-by: Ronni Dal Lago <blackjacksuper@hotmail.it>
2025-03-31 12:19:36 +02:00
Ronni Dal Lago
03cb9e2bc5 CSV export fixes
Signed-off-by: Ronni Dal Lago <blackjacksuper@hotmail.it>
2025-03-31 09:53:36 +02:00
Nextcloud bot
3c6f8ec419 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-30 00:44:10 +00:00
dependabot[bot]
3cfb1f6bfe Merge pull request #6860 from nextcloud/dependabot/github_actions/actions/setup-node-4.3.0 2025-03-29 02:15:46 +00:00
dependabot[bot]
96ad191ce2 Chore(deps): Bump actions/setup-node from 4.1.0 to 4.3.0
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.1.0 to 4.3.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4.1.0...v4.3.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-29 02:06:40 +00:00
Nextcloud bot
52d4039dc8 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-29 00:43:37 +00:00
Nextcloud bot
73b3517840 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-28 00:44:51 +00:00
Nextcloud bot
3d78802446 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-27 00:44:45 +00:00
Julius Knorr
8a99e6d539 Merge pull request #6853 from nextcloud/ci/update-workflows
chore: update workflows from templates
2025-03-25 15:17:08 +01:00
grnd-alt
0e08ad16e1 chore: set minimum phpVersion for psalm
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-03-25 14:05:17 +01:00
Nextcloud bot
d04ab25315 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-25 00:43:41 +00:00
grnd-alt
19d35c65a0 chore: update workflows from templates
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-03-24 15:41:10 +01:00
Nextcloud bot
1783914d3a Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-24 00:43:02 +00:00
Nextcloud bot
c837dd4db6 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-23 00:43:32 +00:00
dependabot[bot]
db22052729 Merge pull request #6850 from nextcloud/dependabot/github_actions/actions/setup-node-4.3.0 2025-03-22 02:22:09 +00:00
dependabot[bot]
116babcaaf Chore(deps): Bump actions/setup-node from 4.2.0 to 4.3.0
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4.2.0...v4.3.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-22 02:16:47 +00:00
Ronni Dal Lago
94da732bfb CSV export fixes
Signed-off-by: Ronni Dal Lago <blackjacksuper@hotmail.it>
2025-03-21 18:20:37 +01:00
Nextcloud bot
86d42b7060 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-20 00:45:34 +00:00
Nextcloud bot
122387a195 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-18 00:45:10 +00:00
Nextcloud bot
028f26a969 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-16 00:43:43 +00:00
dependabot[bot]
13c13b8dde Merge pull request #6831 from nextcloud/dependabot/npm_and_yarn/main/babel/runtime-7.26.10 2025-03-15 02:14:25 +00:00
dependabot[bot]
5df4a49ff5 Chore(deps): Bump @babel/runtime from 7.26.7 to 7.26.10
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.26.7 to 7.26.10.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.10/packages/babel-runtime)

---
updated-dependencies:
- dependency-name: "@babel/runtime"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-15 02:05:59 +00:00
Nextcloud bot
97902d2f6a Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-15 00:45:23 +00:00
Nextcloud bot
db6221d1c9 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-12 00:44:24 +00:00
github-actions[bot]
0223dd9a3a Merge pull request #6825 from nextcloud/automated/noid/main-update-nextcloud-ocp
[main] Update nextcloud/ocp dependency
2025-03-09 03:34:50 +00:00
nextcloud-command
974a4c979a chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2025-03-09 02:36:44 +00:00
dependabot[bot]
51ba51fe33 Merge pull request #6822 from nextcloud/dependabot/npm_and_yarn/axios-1.8.2 2025-03-08 04:06:48 +00:00
dependabot[bot]
4d5c69f250 Chore(deps): Bump axios from 1.7.7 to 1.8.2
Bumps [axios](https://github.com/axios/axios) from 1.7.7 to 1.8.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.7...v1.8.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-08 04:01:11 +00:00
dependabot[bot]
9bddab4928 Merge pull request #6821 from nextcloud/dependabot/github_actions/peter-evans/create-pull-request-7.0.8 2025-03-08 03:59:58 +00:00
dependabot[bot]
6dcb1d4b8b bump peter-evans/create-pull-request from 7.0.7 to 7.0.8
---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-08 03:54:25 +00:00
Nextcloud bot
9ed384fa20 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-03 00:42:20 +00:00
github-actions[bot]
7cdc79a9ef Merge pull request #6812 from nextcloud/automated/noid/main-update-nextcloud-ocp
[main] Update nextcloud/ocp dependency
2025-03-02 03:46:38 +00:00
nextcloud-command
852770c574 chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2025-03-02 03:01:01 +00:00
dependabot[bot]
74afeb85d0 Merge pull request #6811 from nextcloud/dependabot/github_actions/peter-evans/create-pull-request-7.0.7 2025-03-01 03:44:08 +00:00
dependabot[bot]
12a494720b chore(deps): bump peter-evans/create-pull-request from 7.0.6 to 7.0.7
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.6 to 7.0.7.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](67ccf781d6...dd2324fc52)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-01 03:02:53 +00:00
dependabot[bot]
b3261e0b56 Merge pull request #6805 from nextcloud/dependabot/npm_and_yarn/main/nextcloud/event-bus-3.3.2 2025-03-01 02:22:07 +00:00
dependabot[bot]
88dbb010d0 chore(deps): bump @nextcloud/event-bus from 3.3.1 to 3.3.2
Bumps [@nextcloud/event-bus](https://github.com/nextcloud/nextcloud-event-bus) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/nextcloud/nextcloud-event-bus/releases)
- [Changelog](https://github.com/nextcloud-libraries/nextcloud-event-bus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/nextcloud-event-bus/compare/v3.3.1...v3.3.2)

---
updated-dependencies:
- dependency-name: "@nextcloud/event-bus"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-01 02:05:52 +00:00
Nextcloud bot
d8adaf5fe6 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-03-01 01:05:09 +00:00
Nextcloud bot
2a36b45072 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-27 00:44:24 +00:00
Nextcloud bot
4e6474fa99 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-25 00:45:11 +00:00
github-actions[bot]
dbe7536339 Merge pull request #6770 from nextcloud/automated/noid/main-update-nextcloud-ocp
[main] Update nextcloud/ocp dependency
2025-02-24 14:51:38 +00:00
nextcloud-command
b5e08110ab chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2025-02-24 15:46:05 +01:00
dependabot[bot]
a7f2558aab Merge pull request #6787 from nextcloud/dependabot/npm_and_yarn/main/nextcloud/eslint-config-8.4.2 2025-02-24 14:37:30 +00:00
dependabot[bot]
3c3e6fa7d2 chore(deps-dev): bump @nextcloud/eslint-config from 8.4.1 to 8.4.2
Bumps [@nextcloud/eslint-config](https://github.com/nextcloud-libraries/eslint-config) from 8.4.1 to 8.4.2.
- [Release notes](https://github.com/nextcloud-libraries/eslint-config/releases)
- [Changelog](https://github.com/nextcloud-libraries/eslint-config/blob/v8.4.2/CHANGELOG.md)
- [Commits](https://github.com/nextcloud-libraries/eslint-config/compare/v8.4.1...v8.4.2)

---
updated-dependencies:
- dependency-name: "@nextcloud/eslint-config"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 15:26:51 +01:00
Nextcloud bot
6a2b092ad6 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-24 00:41:53 +00:00
Nextcloud bot
5f2c300b21 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-22 00:41:52 +00:00
Luka Trovic
439e44128a Merge pull request #6778 from nextcloud/fix-cypress-main
fix: cypress issue
2025-02-21 10:58:05 +01:00
Nextcloud bot
55056e27f1 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-21 00:41:20 +00:00
Luka Trovic
22c36a0d77 fix: cypress issue
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2025-02-20 16:24:45 +01:00
Nextcloud bot
1ebaa0c41f Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-20 00:43:26 +00:00
Luka Trovic
a2dbb94179 Merge pull request #6724 from nextcloud/feat/workflow-auto-update-pr-feedback.yml
chore(CI): Updating pr-feedback.yml workflow from template
2025-02-19 13:43:07 +01:00
Nextcloud bot
6f6f54965c Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-19 00:42:11 +00:00
Nextcloud bot
5a833ec367 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-18 00:42:04 +00:00
Nextcloud bot
f1161be49f Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-17 00:41:29 +00:00
Nextcloud bot
c0731ce142 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-16 01:06:39 +00:00
Nextcloud bot
4534ad5a92 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-15 00:41:52 +00:00
Luka Trovic
6788210c27 Merge pull request #6740 from nextcloud/update-default-content
feat: update default content
2025-02-14 13:32:26 +01:00
Luka Trovic
1051dea281 Merge pull request #6745 from nextcloud/dependabot/npm_and_yarn/elliptic-6.6.1
chore(deps-dev): bump elliptic from 6.6.0 to 6.6.1
2025-02-14 08:42:28 +01:00
Nextcloud bot
eb9fce2e5f Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-14 00:42:23 +00:00
dependabot[bot]
955a16f1c5 chore(deps-dev): bump elliptic from 6.6.0 to 6.6.1
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.6.0 to 6.6.1.
- [Commits](https://github.com/indutny/elliptic/compare/v6.6.0...v6.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-13 17:43:42 +00:00
Luka Trovic
f38773473b Merge pull request #6736 from nextcloud/automated/noid/main-update-nextcloud-ocp
[main] Update nextcloud/ocp dependency
2025-02-13 18:41:01 +01:00
Luka Trovic
b15254f1ed feat: update default content
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2025-02-13 14:18:47 +01:00
Nextcloud bot
6dd623f796 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-13 00:42:08 +00:00
Julius Knorr
41e97d7281 Merge pull request #6649 from nextcloud/fix/redirect-no-rewrite
fix: Adapt URLs generated in the backend to new routes
2025-02-12 22:32:04 +01:00
Julius Knorr
1b2a352df1 ci: Update query count
Signed-off-by: Julius Knorr <jus@bitgrid.net>
2025-02-12 21:56:34 +01:00
Julius Knorr
7fcad2425d fix: Use dynamic base URL for vue router to make routing work in all cases
Signed-off-by: Julius Knorr <jus@bitgrid.net>
2025-02-12 21:56:06 +01:00
Julius Knorr
5fb43086b6 tests: Fix url generation mocks and cleanup some phpunit code
Signed-off-by: Julius Knorr <jus@bitgrid.net>
2025-02-12 21:56:06 +01:00
Julius Knorr
7b4586a43a fix: Adapt URLs generated in the backend to new routes
Signed-off-by: Julius Knorr <jus@bitgrid.net>
2025-02-12 21:56:06 +01:00
Nextcloud bot
aaa76f7bd0 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-12 00:43:09 +00:00
Nextcloud bot
8260296d64 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-11 00:41:47 +00:00
nextcloud-command
b02bc530f1 chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2025-02-09 02:54:36 +00:00
Nextcloud bot
1b4e859431 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-09 00:41:43 +00:00
dependabot[bot]
acc61ad584 Merge pull request #6729 from nextcloud/dependabot/npm_and_yarn/main/nextcloud/cypress-1.0.0-beta.13 2025-02-08 02:26:34 +00:00
dependabot[bot]
cb1d5c49e0 chore(deps-dev): bump @nextcloud/cypress
Bumps [@nextcloud/cypress](https://github.com/nextcloud/nextcloud-cypress) from 1.0.0-beta.12 to 1.0.0-beta.13.
- [Release notes](https://github.com/nextcloud/nextcloud-cypress/releases)
- [Commits](https://github.com/nextcloud/nextcloud-cypress/compare/v1.0.0-beta.12...v1.0.0-beta.13)

---
updated-dependencies:
- dependency-name: "@nextcloud/cypress"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-08 02:10:29 +00:00
Luka Trovic
0c7b1c4731 Merge pull request #6707 from nextcloud/feat/workflow-auto-update-npm-audit-fix.yml
chore(CI): Updating npm-audit-fix.yml workflow from template
2025-02-07 16:36:10 +01:00
Nextcloud bot
629ef85d64 chore(CI): Updating npm-audit-fix.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-07 16:22:02 +01:00
Luka Trovic
914f1d76ac Merge pull request #6720 from nextcloud/automated/noid/main-fix-npm-audit
[main] Fix npm audit
2025-02-07 10:18:15 +01:00
Nextcloud bot
0923070c45 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-07 00:41:26 +00:00
Nextcloud bot
bbf51952e0 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-05 00:43:20 +00:00
Nextcloud bot
1d1c2df8f3 chore(CI): Updating pr-feedback.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-04 18:42:46 +00:00
Elizabeth Danzberger
0780b10170 Merge pull request #6692 from nextcloud/fix/6446
fix: skip exporting a deleted card
2025-02-04 13:27:54 -05:00
Luka Trovic
fd6ef9b6eb Merge pull request #6712 from nextcloud/dependabot/npm_and_yarn/main/dompurify-3.2.4
chore(deps): bump dompurify from 3.2.3 to 3.2.4
2025-02-04 13:09:57 +01:00
Luka Trovic
da4a54900c Merge pull request #6711 from nextcloud/dependabot/github_actions/actions/setup-node-4.2.0
chore(deps): bump actions/setup-node from 4.1.0 to 4.2.0
2025-02-04 13:09:35 +01:00
Luka Trovic
53bd32d6b6 Merge pull request #6695 from nextcloud/dependabot/npm_and_yarn/main/babel/runtime-7.26.7
chore(deps): bump @babel/runtime from 7.26.0 to 7.26.7
2025-02-04 13:05:56 +01:00
Elizabeth Danzberger
f7fa419105 fix: skip exporting a deleted card
Signed-off-by: Elizabeth Danzberger <lizzy7128@tutanota.de>
2025-02-04 09:49:39 +01:00
dependabot[bot]
023ab01e93 Merge pull request #6668 from nextcloud/dependabot/composer/tests/integration/behat/behat-approx-3.18.1 2025-02-04 07:24:15 +00:00
dependabot[bot]
615d5ef871 chore(deps-dev): update behat/behat requirement in /tests/integration
Updates the requirements on [behat/behat](https://github.com/Behat/Behat) to permit the latest version.
- [Release notes](https://github.com/Behat/Behat/releases)
- [Changelog](https://github.com/Behat/Behat/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Behat/Behat/compare/v3.15.0...v3.18.1)

---
updated-dependencies:
- dependency-name: behat/behat
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-04 08:18:49 +01:00
Luka Trovic
a52b7b9742 Merge pull request #6665 from nextcloud/dependabot/github_actions/shivammathur/setup-php-2.32.0
chore(deps): bump shivammathur/setup-php from 2.31.1 to 2.32.0
2025-02-04 08:18:00 +01:00
Luka Trovic
dcbc6bc604 Merge pull request #6666 from nextcloud/dependabot/github_actions/peter-evans/create-pull-request-7.0.6
chore(deps): bump peter-evans/create-pull-request from 7.0.5 to 7.0.6
2025-02-04 08:12:07 +01:00
Nextcloud bot
ce13d89e07 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-03 01:02:33 +00:00
nextcloud-command
7114b10871 fix(deps): Fix npm audit
Signed-off-by: GitHub <noreply@github.com>
2025-02-02 03:25:51 +00:00
Nextcloud bot
100404d25f Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-02-02 00:42:30 +00:00
dependabot[bot]
60bfc192d3 chore(deps): bump actions/setup-node from 4.1.0 to 4.2.0
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4.1.0...v4.2.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-01 19:38:35 +01:00
dependabot[bot]
fd090c7749 chore(deps): bump peter-evans/create-pull-request from 7.0.5 to 7.0.6
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.5 to 7.0.6.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](5e914681df...67ccf781d6)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-01 19:14:56 +01:00
dependabot[bot]
d735308bd3 chore(deps): bump shivammathur/setup-php from 2.31.1 to 2.32.0
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.31.1 to 2.32.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.31.1...2.32.0)

---
updated-dependencies:
- dependency-name: shivammathur/setup-php
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-01 19:13:02 +01:00
github-actions[bot]
4ec068ca62 Merge pull request #6670 from nextcloud/automated/noid/main-update-nextcloud-ocp
[main] Update nextcloud/ocp dependency
2025-02-01 16:53:40 +00:00
nextcloud-command
f5e3e5e0f8 chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2025-02-01 17:48:09 +01:00
dependabot[bot]
94aee3e07a chore(deps): bump dompurify from 3.2.3 to 3.2.4
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.2.3 to 3.2.4.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.2.3...3.2.4)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-01 02:33:07 +00:00
Nextcloud bot
b1f7c623a1 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-01-28 00:41:14 +00:00
Julius Knorr
afa95d3c50 Merge pull request #6671 from nextcloud/fix/attachment-extension
fix: Properly show attachment extension
2025-01-27 08:43:31 +01:00
Nextcloud bot
ba8e77abfe Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-01-27 00:40:20 +00:00
dependabot[bot]
8c09047203 chore(deps): bump @babel/runtime from 7.26.0 to 7.26.7
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.26.0 to 7.26.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.26.7/packages/babel-runtime)

---
updated-dependencies:
- dependency-name: "@babel/runtime"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-25 02:29:31 +00:00
Nextcloud bot
baa85e8947 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-01-25 01:01:22 +00:00
Nextcloud bot
f1e5acc52e Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2025-01-24 00:41:33 +00:00
Elizabeth Danzberger
d76b7a4667 Merge pull request #6682 from nextcloud/update-main-version
feat(deps): Add Nextcloud 32 support on main
2025-01-23 14:08:15 -05:00
Joas Schilling
df32a3ee34 feat(deps): Add Nextcloud 32 support on main
Signed-off-by: Joas Schilling <coding@schilljs.com>
2025-01-23 10:57:25 +01:00
Julius Knorr
2fa74662db ci: Test for separate extension
Signed-off-by: Julius Knorr <jus@bitgrid.net>
2025-01-23 09:28:09 +01:00
Julius Härtl
d5fd80d116 fix: Properly show attachment extension
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2025-01-23 09:28:09 +01:00
103 changed files with 8806 additions and 6822 deletions

View File

@@ -13,6 +13,23 @@ updates:
- juliushaertl
- luka-nextcloud
- package-ecosystem: npm
target-branch: stable31
versioning-strategy: lockfile-only
directory: "/"
schedule:
interval: weekly
day: saturday
time: "03:15"
timezone: Europe/Paris
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]
open-pull-requests-limit: 30
labels:
- 3. to review
- dependencies
- package-ecosystem: npm
target-branch: stable30
versioning-strategy: lockfile-only
@@ -20,41 +37,7 @@ updates:
schedule:
interval: weekly
day: saturday
time: "03:00"
timezone: Europe/Paris
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]
open-pull-requests-limit: 30
labels:
- 3. to review
- dependencies
- package-ecosystem: npm
target-branch: stable29
versioning-strategy: lockfile-only
directory: "/"
schedule:
interval: weekly
day: saturday
time: "03:00"
timezone: Europe/Paris
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]
open-pull-requests-limit: 30
labels:
- 3. to review
- dependencies
- package-ecosystem: npm
target-branch: stable28
versioning-strategy: lockfile-only
directory: "/"
schedule:
interval: weekly
day: saturday
time: "03:00"
time: "03:30"
timezone: Europe/Paris
ignore:
- dependency-name: "*"
@@ -69,7 +52,7 @@ updates:
schedule:
interval: weekly
day: saturday
time: "03:00"
time: "03:45"
timezone: Europe/Paris
open-pull-requests-limit: 10
reviewers:
@@ -81,7 +64,7 @@ updates:
schedule:
interval: weekly
day: saturday
time: "03:00"
time: "04:00"
timezone: Europe/Paris
open-pull-requests-limit: 10
reviewers:
@@ -93,7 +76,7 @@ updates:
schedule:
interval: weekly
day: saturday
time: "03:00"
time: "04:15"
timezone: Europe/Paris
open-pull-requests-limit: 10
reviewers:

View File

@@ -18,13 +18,13 @@ jobs:
steps:
- uses: actions/checkout@v4.2.2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.1.0
uses: actions/setup-node@v4.4.0
with:
node-version: ${{ matrix.node-version }}
- name: Set up npm7
run: npm i -g npm@7
- name: Setup PHP
uses: shivammathur/setup-php@2.31.1
uses: shivammathur/setup-php@2.34.1
with:
php-version: '7.4'
tools: composer

View File

@@ -71,7 +71,7 @@ jobs:
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
# Skip if no package.json
if: ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
@@ -87,7 +87,7 @@ jobs:
filename: ${{ env.APP_NAME }}/appinfo/info.xml
- name: Set up php ${{ steps.php-versions.outputs.php-min }}
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
with:
php-version: ${{ steps.php-versions.outputs.php-min }}
coverage: none

View File

@@ -22,7 +22,7 @@ jobs:
node-version: [20.x]
# containers: [1, 2, 3]
php-versions: [ '8.2' ]
server-versions: [ 'stable31' ]
server-versions: [ 'master' ]
env:
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, zip, gd, apcu
@@ -41,7 +41,7 @@ jobs:
steps:
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.1.0
uses: actions/setup-node@v4.4.0
with:
node-version: ${{ matrix.node-version }}
@@ -91,7 +91,7 @@ jobs:
restore-keys: ${{ steps.extcache.outputs.key }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2.31.1
uses: shivammathur/setup-php@2.34.1
with:
php-version: ${{ matrix.php-versions }}
extensions: ${{ env.extensions }}

View File

@@ -78,7 +78,7 @@ jobs:
path: apps/activity
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2.31.1
uses: shivammathur/setup-php@2.34.1
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, mysql, pdo_mysql, pgsql, pdo_pgsql, apcu, gd

View File

@@ -68,7 +68,7 @@ jobs:
fallbackNpm: '^10'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}

View File

@@ -33,8 +33,8 @@ jobs:
id: versions
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
- name: Set up php${{ steps.versions.outputs.php-available }}
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
- name: Set up php${{ steps.versions.outputs.php-min }}
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
with:
php-version: ${{ steps.versions.outputs.php-min }}
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite

View File

@@ -48,7 +48,7 @@ jobs:
persist-credentials: false
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
with:
php-version: ${{ matrix.php-versions }}
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite

View File

@@ -37,7 +37,7 @@ jobs:
fallbackNpm: '^10'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}

View File

@@ -14,7 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v4.2.2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.1.0
uses: actions/setup-node@v4.4.0
with:
node-version: ${{ matrix.node-version }}
- name: Set up npm7

View File

@@ -14,6 +14,9 @@ on:
# At 2:30 on Sundays
- cron: '30 2 * * 0'
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
@@ -21,15 +24,18 @@ jobs:
strategy:
fail-fast: false
matrix:
branches: ['main', 'master', 'stable30', 'stable29', 'stable28']
branches: ['main', 'master', 'stable31', 'stable30', 'stable29']
name: npm-audit-fix-${{ matrix.branches }}
steps:
- name: Checkout
id: checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
ref: ${{ matrix.branches }}
continue-on-error: true
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
@@ -39,7 +45,7 @@ jobs:
fallbackNpm: '^10'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
@@ -48,10 +54,10 @@ jobs:
- name: Fix npm audit
id: npm-audit
uses: nextcloud-libraries/npm-audit-action@2a60bd2e79cc77f2cc4d9a3fe40f1a69896f3a87 # v0.1.0
uses: nextcloud-libraries/npm-audit-action@1b1728b2b4a7a78d69de65608efcf4db0e3e42d0 # v0.2.0
- name: Run npm ci and npm run build
if: always()
if: steps.checkout.outcome == 'success'
env:
CYPRESS_INSTALL_BINARY: 0
run: |
@@ -59,8 +65,8 @@ jobs:
npm run build --if-present
- name: Create Pull Request
if: always()
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
if: steps.checkout.outcome == 'success'
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: 'fix(deps): Fix npm audit'

View File

@@ -103,7 +103,7 @@ jobs:
path: apps/${{ env.APP_NAME }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation

View File

@@ -106,7 +106,7 @@ jobs:
path: apps/${{ env.APP_NAME }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation

View File

@@ -95,7 +95,7 @@ jobs:
path: apps/${{ env.APP_NAME }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
with:
php-version: ${{ matrix.php-versions }}
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation

View File

@@ -15,8 +15,13 @@ on:
schedule:
- cron: '30 1 * * *'
permissions:
contents: read
pull-requests: write
jobs:
pr-feedback:
if: ${{ github.repository_owner == 'nextcloud' }}
runs-on: ubuntu-latest
steps:
- name: The get-github-handles-from-website action

View File

@@ -35,8 +35,8 @@ jobs:
- name: Check enforcement of minimum PHP version ${{ steps.versions.outputs.php-min }} in psalm.xml
run: grep 'phpVersion="${{ steps.versions.outputs.php-min }}' psalm.xml
- name: Set up php${{ steps.versions.outputs.php-available }}
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
- name: Set up php${{ steps.versions.outputs.php-min }}
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
with:
php-version: ${{ steps.versions.outputs.php-min }}
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite

View File

@@ -16,7 +16,7 @@ permissions:
jobs:
reuse-compliance-check:
runs-on: ubuntu-latest
runs-on: ubuntu-latest-low
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

View File

@@ -23,7 +23,7 @@ jobs:
strategy:
fail-fast: false
matrix:
branches: ['main', 'master', 'stable30', 'stable29', 'stable28']
branches: ['main', 'master', 'stable31', 'stable30', 'stable29']
name: update-nextcloud-ocp-${{ matrix.branches }}
@@ -38,7 +38,7 @@ jobs:
- name: Set up php8.2
if: steps.checkout.outcome == 'success'
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
with:
php-version: 8.2
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
@@ -107,7 +107,7 @@ jobs:
- name: Create Pull Request
if: steps.checkout.outcome == 'success'
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: 'chore(dev-deps): Bump nextcloud/ocp package'

View File

@@ -5,49 +5,6 @@
# Changelog
All notable changes to this project will be documented in this file.
# 1.15.2
### Fixed
* [stable31] fix: update DeleteCron to remove deleted lists by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7029
* [stable31] fix: not show Share with a Deck card for unauthorized users by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7061
* [stable31] fix: unstable cypress test by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7063
* [stable31] fix: add retry and show warning on description saving error by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7091
* [stable31] fix: styling for new stack input field by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7113
* [stable31] fix:allow foreign label deletion by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7130
* [stable31] fix: acl check when delete, update board acl by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7132
### Improvements
* [stable31] perf: don't enrich cards when finding calendar entries by @backportbot[bot] in https://github.com/nextcloud/deck/pull/6959
## 1.15.1
### Fixed
* [stable31] fix: Properly show attachment extension by @backportbot in https://github.com/nextcloud/deck/pull/6701
* [stable31] Clear selected stack when selected board changed by @backportbot in https://github.com/nextcloud/deck/pull/6915
* [stable31] fix: Use strings as rich object ids by @backportbot in https://github.com/nextcloud/deck/pull/6951
* [stable31] fix: Limit label actions to labels of the cards board by @backportbot in https://github.com/nextcloud/deck/pull/6954
* [stable31] fix: only delete assignments on unshared board by @grnd-alt in https://github.com/nextcloud/deck/pull/6934
### Improvements
* [stable31] perf: Skip doing a query just to check if a board is deleted by @backportbot in https://github.com/nextcloud/deck/pull/6894
## 1.15.0
### Fixed
- Fix: Adapt URLs generated in the backend to new routes #6743
- Fix npm audit #6719
- Fix: skip exporting a deleted card #6723
## 1.15.0-beta.2
### Added
- feat: Implement reference resolving for cards that have a link in the title @juliusknorr [#6286](https://github.com/nextcloud/deck/pull/6286)
### Other
- Remove old project from README @edent [#6658](https://github.com/nextcloud/deck/pull/6658)
- devcontainer(image): Fix package path @niclasheinz [#6653](https://github.com/nextcloud/deck/pull/6653)
- remove deprecated nextcloud-vue-collections @grnd-alt [#6664](https://github.com/nextcloud/deck/pull/6664)
- fix: set cypress ci server version to stable31 @grnd-alt [#6705](https://github.com/nextcloud/deck/pull/6705)
## 1.15.0-beta.1
### Fixed
- fix: Catch not found card @juliusknorr [#6646](https://github.com/nextcloud/deck/pull/6646)

View File

@@ -12,7 +12,7 @@ SPDX-FileCopyrightText = "none"
SPDX-License-Identifier = "CC0-1.0"
[[annotations]]
path = ["l10n/**.js", "l10n/**.json", "js/**.js.map", "js/**.js", "js/**.mjs", "js/**.mjs.map", "js/templates/**.handlebars", "lib/Service/Importer/fixtures/config-deckJson-schema.json", "lib/Service/Importer/fixtures/config-trelloApi-schema.json", "lib/Service/Importer/fixtures/config-trelloJson-schema.json", "screenshots/screenshot1.png", "src/assets/file-placeholder.svg", "img/favicon.ico", "img/favicon.png", "img/favicon.svg", "img/activity.svg", "img/activity-dark.svg", "img/deck.svg", "img/deck-current.svg", "img/deck-dark.svg", "img/details-white.svg", "img/card.svg"]
path = ["l10n/**.js", "l10n/**.json", "js/**.js.map", "js/**.js", "js/**.mjs", "js/**.mjs.map", "js/templates/**.handlebars", "lib/Service/Importer/fixtures/config-deckJson-schema.json", "lib/Service/Importer/fixtures/config-trelloApi-schema.json", "lib/Service/Importer/fixtures/config-trelloJson-schema.json", "lib/Service/fixtures/default-board.json", "screenshots/screenshot1.png", "src/assets/file-placeholder.svg", "img/favicon.ico", "img/favicon.png", "img/favicon.svg", "img/activity.svg", "img/activity-dark.svg", "img/deck.svg", "img/deck-current.svg", "img/deck-dark.svg", "img/details-white.svg", "img/card.svg", "img/sample-image.jpg"]
precedence = "aggregate"
SPDX-FileCopyrightText = "2019 Nextcloud GmbH and Nextcloud contributors"
SPDX-License-Identifier = "AGPL-3.0-or-later"

View File

@@ -20,7 +20,7 @@
- 🚀 Get your project organized
</description>
<version>1.15.2</version>
<version>2.0.0-dev.0</version>
<licence>agpl</licence>
<author>Julius Härtl</author>
<namespace>Deck</namespace>
@@ -42,7 +42,7 @@
<database min-version="9.4">pgsql</database>
<database>sqlite</database>
<database min-version="8.0">mysql</database>
<nextcloud min-version="31" max-version="31"/>
<nextcloud min-version="32" max-version="32"/>
</dependencies>
<background-jobs>
<job>OCA\Deck\Cron\DeleteCron</job>
@@ -54,6 +54,9 @@
<live-migration>
<step>OCA\Deck\Migration\DeletedCircleCleanup</step>
</live-migration>
<post-migration>
<step>OCA\Deck\Migration\LabelMismatchCleanup</step>
</post-migration>
</repair-steps>
<commands>
<command>OCA\Deck\Command\UserExport</command>

View File

@@ -29,6 +29,7 @@ return [
['name' => 'board#clone', 'url' => '/boards/{boardId}/clone', 'verb' => 'POST'],
['name' => 'board#transferOwner', 'url' => '/boards/{boardId}/transferOwner', 'verb' => 'PUT'],
['name' => 'board#export', 'url' => '/boards/{boardId}/export', 'verb' => 'GET'],
['name' => 'board#import', 'url' => '/boards/import', 'verb' => 'POST'],
// stacks
['name' => 'stack#index', 'url' => '/stacks/{boardId}', 'verb' => 'GET'],

View File

@@ -15,7 +15,7 @@
"roave/security-advisories": "dev-master",
"phpunit/phpunit": "^9",
"nextcloud/coding-standard": "^1.1",
"nextcloud/ocp": "dev-stable31",
"nextcloud/ocp": "dev-master",
"psalm/phar": "^5.13"
},
"config": {

157
composer.lock generated
View File

@@ -4,146 +4,34 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c89537a172cee5c19093b4ea0cb5365c",
"content-hash": "6950663d9d213151028e780637480220",
"packages": [
{
"name": "icecave/parity",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/icecave/parity.git",
"reference": "0109fef58b3230d23b20b2ac52ecdf477218d300"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/icecave/parity/zipball/0109fef58b3230d23b20b2ac52ecdf477218d300",
"reference": "0109fef58b3230d23b20b2ac52ecdf477218d300",
"shasum": ""
},
"require": {
"icecave/repr": "~1",
"php": ">=5.3"
},
"require-dev": {
"eloquent/liberator": "~1",
"icecave/archer": "~1"
},
"suggest": {
"eloquent/asplode": "Drop-in exception-based error handling."
},
"type": "library",
"autoload": {
"psr-0": {
"Icecave\\Parity": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "James Harris",
"email": "james.harris@icecave.com.au",
"homepage": "https://github.com/jmalloc"
}
],
"description": "A customizable deep comparison library.",
"homepage": "https://github.com/IcecaveStudios/parity",
"keywords": [
"compare",
"comparison",
"equal",
"equality",
"greater",
"less",
"sort",
"sorting"
],
"support": {
"issues": "https://github.com/icecave/parity/issues",
"source": "https://github.com/icecave/parity/tree/1.0.0"
},
"time": "2014-01-17T05:56:27+00:00"
},
{
"name": "icecave/repr",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/icecave/repr.git",
"reference": "8a3d2953adf5f464a06e3e2587aeacc97e2bed07"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/icecave/repr/zipball/8a3d2953adf5f464a06e3e2587aeacc97e2bed07",
"reference": "8a3d2953adf5f464a06e3e2587aeacc97e2bed07",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"icecave/archer": "~1"
},
"suggest": {
"eloquent/asplode": "Drop-in exception-based error handling."
},
"type": "library",
"autoload": {
"psr-4": {
"Icecave\\Repr\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "James Harris",
"email": "james.harris@icecave.com.au",
"homepage": "https://github.com/jmalloc"
}
],
"description": "A library for generating string representations of any value, inspired by Python's reprlib library.",
"homepage": "https://github.com/IcecaveStudios/repr",
"keywords": [
"human",
"readable",
"repr",
"representation",
"string"
],
"support": {
"issues": "https://github.com/icecave/repr/issues",
"source": "https://github.com/icecave/repr/tree/1.0.1"
},
"time": "2014-07-25T05:44:41+00:00"
},
{
"name": "justinrainbow/json-schema",
"version": "6.0.0",
"version": "6.4.1",
"source": {
"type": "git",
"url": "https://github.com/jsonrainbow/json-schema.git",
"reference": "a38c6198d53b09c0702f440585a4f4a5d9137bd9"
"reference": "35d262c94959571e8736db1e5c9bc36ab94ae900"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/a38c6198d53b09c0702f440585a4f4a5d9137bd9",
"reference": "a38c6198d53b09c0702f440585a4f4a5d9137bd9",
"url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/35d262c94959571e8736db1e5c9bc36ab94ae900",
"reference": "35d262c94959571e8736db1e5c9bc36ab94ae900",
"shasum": ""
},
"require": {
"icecave/parity": "1.0.0",
"marc-mabe/php-enum": "^2.0 || ^3.0 || ^4.0",
"php": ">=5.3.3"
"ext-json": "*",
"marc-mabe/php-enum": "^4.0",
"php": "^7.2 || ^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2.2.20 || ~2.19.0",
"friendsofphp/php-cs-fixer": "3.3.0",
"json-schema/json-schema-test-suite": "1.2.0",
"phpunit/phpunit": "^4.8.35"
"marc-mabe/php-enum-phpstan": "^2.0",
"phpspec/prophecy": "^1.19",
"phpstan/phpstan": "^1.12",
"phpunit/phpunit": "^8.5"
},
"bin": [
"bin/validate-json"
@@ -189,9 +77,9 @@
],
"support": {
"issues": "https://github.com/jsonrainbow/json-schema/issues",
"source": "https://github.com/jsonrainbow/json-schema/tree/6.0.0"
"source": "https://github.com/jsonrainbow/json-schema/tree/6.4.1"
},
"time": "2024-07-30T17:49:21+00:00"
"time": "2025-04-04T13:08:07+00:00"
},
{
"name": "marc-mabe/php-enum",
@@ -488,16 +376,16 @@
},
{
"name": "nextcloud/ocp",
"version": "dev-stable31",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/nextcloud-deps/ocp.git",
"reference": "77679c75abf21dfc48a75fd282dea09b09ac096c"
"reference": "97d7aa6e535670437a178084eea91a42998fef5c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/77679c75abf21dfc48a75fd282dea09b09ac096c",
"reference": "77679c75abf21dfc48a75fd282dea09b09ac096c",
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/97d7aa6e535670437a178084eea91a42998fef5c",
"reference": "97d7aa6e535670437a178084eea91a42998fef5c",
"shasum": ""
},
"require": {
@@ -507,10 +395,11 @@
"psr/event-dispatcher": "^1.0",
"psr/log": "^3.0.2"
},
"default-branch": true,
"type": "library",
"extra": {
"branch-alias": {
"dev-stable31": "31.0.0-dev"
"dev-master": "32.0.0-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -530,9 +419,9 @@
"description": "Composer package containing Nextcloud's public OCP API and the unstable NCU API",
"support": {
"issues": "https://github.com/nextcloud-deps/ocp/issues",
"source": "https://github.com/nextcloud-deps/ocp/tree/stable31"
"source": "https://github.com/nextcloud-deps/ocp/tree/master"
},
"time": "2025-07-04T00:53:40+00:00"
"time": "2025-06-13T00:53:13+00:00"
},
{
"name": "nikic/php-parser",

View File

@@ -129,3 +129,81 @@ describe('Board cloning', function() {
})
})
})
describe('Board export', function() {
before(function() {
cy.createUser(user)
})
it('Exports a board as JSON', function() {
const boardName = 'Export JSON board'
const board = sampleBoard(boardName)
cy.createExampleBoard({ user, board }).then((board) => {
const boardId = board.id
cy.visit(`/apps/deck/board/${boardId}`)
cy.get('.app-navigation__list .app-navigation-entry:contains("' + boardName + '")')
.parent()
.find('button[aria-label="Actions"]')
.click()
cy.get('button:contains("Export board")')
.click()
cy.get('.modal-container .checkbox-radio-switch__text:contains("Export as JSON")')
.click()
cy.get('.modal-container button:contains("Export")')
.click()
const downloadsFolder = Cypress.config('downloadsFolder')
cy.readFile(`${downloadsFolder}/${boardName}.json`)
})
})
it('Exports a board as CSV', function() {
const boardName = 'Export CSV board'
const board = sampleBoard(boardName)
cy.createExampleBoard({ user, board }).then((board) => {
const boardId = board.id
cy.visit(`/apps/deck/board/${boardId}`)
cy.get('.app-navigation__list .app-navigation-entry:contains("' + boardName + '")')
.parent()
.find('button[aria-label="Actions"]')
.click()
cy.get('button:contains("Export board")')
.click()
cy.get('.modal-container .checkbox-radio-switch__text:contains("Export as CSV")')
.click()
cy.get('.modal-container button:contains("Export")')
.click()
const downloadsFolder = Cypress.config('downloadsFolder')
cy.readFile(`${downloadsFolder}/${boardName}.csv`)
})
})
})
describe('Board import', function() {
before(function () {
cy.createUser(user)
})
beforeEach(function() {
cy.login(user)
cy.visit('/apps/deck')
})
it('Imports a board from JSON', function() {
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry:contains("Import board")')
.should('be.visible')
.click()
// Upload a JSON file
cy.get('input[type="file"]')
.selectFile([
{
contents: 'cypress/fixtures/import-board.json',
fileName: 'import-board.json',
},
], { force: true })
cy.get('.app-navigation__list .app-navigation-entry:contains("Imported board")')
.should('be.visible')
})
})

View File

@@ -84,7 +84,7 @@ describe('Card', function () {
cy.get('.modal-mask.card-selector .multiselect-list').should('be.visible').click()
cy.get('.vs__dropdown-menu span[title="TestList"]').should('be.visible').click()
cy.get('.modal-mask.card-selector button.button-vue--vue-primary').should('be.visible').click()
cy.get('.modal-mask.card-selector button.button-vue--primary').contains('Create card').should('be.visible').click()
cy.wait('@save', { timeout: 7000 })
cy.reload()
@@ -187,7 +187,7 @@ describe('Card', function () {
cy.get('.file-picker__main').should('be.visible')
cy.get('.file-picker__main [data-filename="welcome.txt"]', { timeout: 30000 }).should('be.visible')
.click()
cy.get('.dialog__actions button.button-vue--vue-primary').click()
cy.get('.dialog__actions button.button-vue--primary').click()
cy.get('.attachment-list .filename').contains('welcome')
cy.get('.attachment-list .filename .extension').contains('txt')
})
@@ -302,8 +302,10 @@ describe('Card', function () {
.first().click()
cy.get(`.card:contains("${newCardTitle}")`).should('be.visible').click()
cy.get('#app-sidebar-vue [data-test="tag-selector"] .vs__dropdown-toggle').should('be.visible').click()
cy.get('#app-sidebar-vue [data-test="tag-selector"] .vs__dropdown-toggle .vs__actions').should('be.visible').click()
cy.get('.vs__dropdown-menu .tag:contains("Action needed")').should('be.visible').click()
cy.get('.vs__dropdown-menu .tag:contains("Later")').should('not.exist')
cy.get('#app-sidebar-vue [data-test="tag-selector"] .vs__dropdown-toggle .vs__actions').should('be.visible').click()
cy.get('.vs__dropdown-menu .tag:contains("Later")').should('be.visible').click()
cy.get('.vs__selected .tag:contains("Action needed")').should('be.visible')

View File

@@ -22,12 +22,12 @@ describe('Deck dashboard', function() {
.should($el => expect($el.text().trim()).to.equal('Upcoming cards'))
})
it('Can see the default "Personal Board" created for user by default', function() {
it('Can see the default "Welcome Board" created for user by default', function() {
cy.visit('/apps/deck')
const defaultBoard = 'Personal'
const defaultBoard = 'Welcome to Nextcloud Deck!'
cy.get('.app-navigation-entry-wrapper[icon=icon-deck]')
cy.get('#deck-navigation-all')
.find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + defaultBoard + ')')
.first()
.contains(defaultBoard)

View File

@@ -0,0 +1,102 @@
{
"boards": [
{
"id": 70,
"title": "Imported board",
"owner": "unvjrmwuag",
"color": "00ff00",
"archived": false,
"labels": [
{
"id": 293,
"title": "Finished",
"color": "31CC7C",
"boardId": 70,
"cardId": null,
"lastModified": 0,
"ETag": "cfcd208495d565ef66e7dff9f98764da"
},
{
"id": 294,
"title": "To review",
"color": "317CCC",
"boardId": 70,
"cardId": null,
"lastModified": 0,
"ETag": "cfcd208495d565ef66e7dff9f98764da"
},
{
"id": 295,
"title": "Action needed",
"color": "FF7A66",
"boardId": 70,
"cardId": null,
"lastModified": 0,
"ETag": "cfcd208495d565ef66e7dff9f98764da"
},
{
"id": 296,
"title": "Later",
"color": "F1DB50",
"boardId": 70,
"cardId": null,
"lastModified": 0,
"ETag": "cfcd208495d565ef66e7dff9f98764da"
}
],
"acl": [],
"permissions": [],
"users": [],
"stacks": {
"114": {
"id": 114,
"title": "TestList",
"boardId": 70,
"deletedAt": 0,
"lastModified": 1743495533,
"cards": [
{
"id": 124,
"title": "Hello world",
"description": "# Hello world",
"descriptionPrev": null,
"stackId": 114,
"type": "plain",
"lastModified": 1743495533,
"lastEditor": null,
"createdAt": 1743495533,
"labels": [],
"assignedUsers": null,
"attachments": null,
"attachmentCount": null,
"owner": {
"primaryKey": "unvjrmwuag",
"uid": "unvjrmwuag",
"displayname": "unvjrmwuag",
"type": 0
},
"order": 999,
"archived": false,
"done": null,
"duedate": null,
"notified": false,
"deletedAt": 0,
"commentsUnread": 0,
"commentsCount": 0,
"relatedStack": null,
"relatedBoard": null,
"ETag": "aa85bb973089e7fbc0bbf122e926c23f"
}
],
"order": 0,
"ETag": "aa85bb973089e7fbc0bbf122e926c23f"
}
},
"activeSessions": [],
"deletedAt": 0,
"lastModified": 1743495533,
"settings": [],
"ETag": "aa85bb973089e7fbc0bbf122e926c23f"
}
]
}

View File

@@ -93,7 +93,7 @@ Cypress.Commands.add('createExampleBoard', ({ user, board }) => {
})
Cypress.Commands.add('getNavigationEntry', (boardTitle) => {
return cy.get('.app-navigation-entry-wrapper[icon=icon-deck]')
return cy.get('#deck-navigation-all')
.find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + boardTitle + ')')
.find('a.app-navigation-entry-link')
})

BIN
img/sample-image.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

View File

@@ -1,35 +0,0 @@
OC.L10N.register(
"deck",
{
"Missing a temporary folder" : "Адсутнічае часовая папка",
"Could not write file to disk" : "Не ўдалося запісаць файл на дыск",
"copy" : "копія",
"Done" : "Гатова",
"File" : "Файл",
"Cancel" : "Скасаваць",
"Active filters" : "Актыўныя фільтры",
"Apply filter" : "Ужыць фільтр",
"Open" : "Адкрыць",
"Clear filter" : "Ачысціць фільтр",
"Tags" : "Тэгі",
"Activity" : "Актыўнасць",
"Can edit" : "Можа рэдагаваць",
"Can share" : "Можа абагульваць",
"Owner" : "Уладальнік",
"Delete" : "Выдаліць",
"Download" : "Спампаваць",
"Modified" : "Зменены",
"Save" : "Захаваць",
"Created:" : "Створана:",
"Open link" : "Адкрыць спасылку",
"seconds ago" : "с таму",
"Keyboard shortcuts" : "Спалучэнні клавіш",
"Keyboard shortcut" : "Спалучэнне клавіш",
"Search" : "Пошук",
"Shared with you" : "Абагулена з вамі",
"An error occurred" : "Узнікла памылка",
"Today" : "Сёння",
"Close" : "Закрыць",
"Share" : "Абагуліць"
},
"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);");

View File

@@ -1,33 +0,0 @@
{ "translations": {
"Missing a temporary folder" : "Адсутнічае часовая папка",
"Could not write file to disk" : "Не ўдалося запісаць файл на дыск",
"copy" : "копія",
"Done" : "Гатова",
"File" : "Файл",
"Cancel" : "Скасаваць",
"Active filters" : "Актыўныя фільтры",
"Apply filter" : "Ужыць фільтр",
"Open" : "Адкрыць",
"Clear filter" : "Ачысціць фільтр",
"Tags" : "Тэгі",
"Activity" : "Актыўнасць",
"Can edit" : "Можа рэдагаваць",
"Can share" : "Можа абагульваць",
"Owner" : "Уладальнік",
"Delete" : "Выдаліць",
"Download" : "Спампаваць",
"Modified" : "Зменены",
"Save" : "Захаваць",
"Created:" : "Створана:",
"Open link" : "Адкрыць спасылку",
"seconds ago" : "с таму",
"Keyboard shortcuts" : "Спалучэнні клавіш",
"Keyboard shortcut" : "Спалучэнне клавіш",
"Search" : "Пошук",
"Shared with you" : "Абагулена з вамі",
"An error occurred" : "Узнікла памылка",
"Today" : "Сёння",
"Close" : "Закрыць",
"Share" : "Абагуліць"
},"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"
}

View File

@@ -33,7 +33,6 @@ OC.L10N.register(
"Tags" : "Etiquetas",
"Activity" : "Actividad",
"Undo" : "Deshacer",
"Transfer" : "Transferencia",
"Can edit" : "Puede editar",
"Can share" : "Puede compartir",
"Owner" : "Dueño",
@@ -59,7 +58,6 @@ OC.L10N.register(
"Search" : "Buscar",
"Archived boards" : "Tableros archivados",
"Shared with you" : "Compartido con usted",
"Cancel edit" : "Cancelar edición",
"Board details" : "Detalles del tablero",
"Edit board" : "Editar el tablero",
"Unarchive board" : "Desarchivar tablero",

View File

@@ -31,7 +31,6 @@
"Tags" : "Etiquetas",
"Activity" : "Actividad",
"Undo" : "Deshacer",
"Transfer" : "Transferencia",
"Can edit" : "Puede editar",
"Can share" : "Puede compartir",
"Owner" : "Dueño",
@@ -57,7 +56,6 @@
"Search" : "Buscar",
"Archived boards" : "Tableros archivados",
"Shared with you" : "Compartido con usted",
"Cancel edit" : "Cancelar edición",
"Board details" : "Detalles del tablero",
"Edit board" : "Editar el tablero",
"Unarchive board" : "Desarchivar tablero",

View File

@@ -266,7 +266,6 @@ OC.L10N.register(
"{count} comments, {unread} unread" : "Komentarze: {count}, nieprzeczytane: {unread}",
"Todo items" : "Do zrobienia",
"Edit card title" : "Edytuj nazwę karty",
"Open link" : "Otwórz link",
"Card deleted" : "Karta usunięta",
"Edit title" : "Edytuj tytuł",
"Assign to me" : "Przydziel do mnie",
@@ -313,7 +312,6 @@ OC.L10N.register(
"Clone cards" : "Klonuj karty",
"Advanced options" : "Opcje zaawansowane",
"Clone" : "Klonuj",
"Export {boardTitle}" : "Eksportuj {boardTitle}",
"Export" : "Eksportuj",
"Loading filtered view" : "Wczytywanie przefiltrowanego widoku",
"Today" : "Dzisiaj",

View File

@@ -264,7 +264,6 @@
"{count} comments, {unread} unread" : "Komentarze: {count}, nieprzeczytane: {unread}",
"Todo items" : "Do zrobienia",
"Edit card title" : "Edytuj nazwę karty",
"Open link" : "Otwórz link",
"Card deleted" : "Karta usunięta",
"Edit title" : "Edytuj tytuł",
"Assign to me" : "Przydziel do mnie",
@@ -311,7 +310,6 @@
"Clone cards" : "Klonuj karty",
"Advanced options" : "Opcje zaawansowane",
"Clone" : "Klonuj",
"Export {boardTitle}" : "Eksportuj {boardTitle}",
"Export" : "Eksportuj",
"Loading filtered view" : "Wczytywanie przefiltrowanego widoku",
"Today" : "Dzisiaj",

View File

@@ -124,7 +124,6 @@ OC.L10N.register(
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Овај коментар има више од %s карактера.\nДодат је као прилог картици под именом %s.\nДоступно је на URL адреси: %s.",
"Attachments" : "Прилози",
"File" : "Фајл",
"date" : "датум",
"Card not found" : "Картица није нађена",
"Path is already shared with this card" : "Путања се већ дели са овом картицом",
"Invalid date, date format must be YYYY-MM-DD" : "Неисправан датум, формат датума мора бити ГГГГ-ММ-ДД",
@@ -240,7 +239,6 @@ OC.L10N.register(
"Modified" : "Измењен",
"Created" : "Направљен",
"The title cannot be empty." : "Наслов не може бити празан.",
"Cannot close unsaved card!" : "Не може да се затвори несачувана картица!",
"Open in sidebar view" : "Отвори у бочном прегледу",
"Open in bigger view" : "Отвори на већем приказу",
"Comments" : "Коментари",
@@ -255,7 +253,6 @@ OC.L10N.register(
"Reply" : "Одговори",
"Update" : "Ажурирај",
"Write a description …" : "Напишите опис ...",
"Could not save description" : "Не може да се сачува опис",
"Description" : "Опис",
"(Unsaved)" : "(несачуван)",
"(Saving…)" : "(чувам…)",

View File

@@ -122,7 +122,6 @@
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Овај коментар има више од %s карактера.\nДодат је као прилог картици под именом %s.\nДоступно је на URL адреси: %s.",
"Attachments" : "Прилози",
"File" : "Фајл",
"date" : "датум",
"Card not found" : "Картица није нађена",
"Path is already shared with this card" : "Путања се већ дели са овом картицом",
"Invalid date, date format must be YYYY-MM-DD" : "Неисправан датум, формат датума мора бити ГГГГ-ММ-ДД",
@@ -238,7 +237,6 @@
"Modified" : "Измењен",
"Created" : "Направљен",
"The title cannot be empty." : "Наслов не може бити празан.",
"Cannot close unsaved card!" : "Не може да се затвори несачувана картица!",
"Open in sidebar view" : "Отвори у бочном прегледу",
"Open in bigger view" : "Отвори на већем приказу",
"Comments" : "Коментари",
@@ -253,7 +251,6 @@
"Reply" : "Одговори",
"Update" : "Ажурирај",
"Write a description …" : "Напишите опис ...",
"Could not save description" : "Не може да се сачува опис",
"Description" : "Опис",
"(Unsaved)" : "(несачуван)",
"(Saving…)" : "(чувам…)",

View File

@@ -240,7 +240,6 @@ OC.L10N.register(
"Modified" : "Değiştirilme",
"Created" : "Oluşturulma",
"The title cannot be empty." : "Başlık boş olamaz.",
"Cannot close unsaved card!" : "Kaydedilmemiş bir kart kapatılamaz!",
"Open in sidebar view" : "Kenar çubuğu görünümünde aç",
"Open in bigger view" : "Daha büyük görünümde aç",
"Comments" : "Yorumlar",
@@ -255,7 +254,6 @@ OC.L10N.register(
"Reply" : "Yanıtla",
"Update" : "Güncelle",
"Write a description …" : "Bir açıklama yazın …",
"Could not save description" : "Açıklama kaydedilemedi",
"Description" : "Açıklama",
"(Unsaved)" : "(Kaydedilmemiş)",
"(Saving…)" : "(Kaydediliyor…)",

View File

@@ -238,7 +238,6 @@
"Modified" : "Değiştirilme",
"Created" : "Oluşturulma",
"The title cannot be empty." : "Başlık boş olamaz.",
"Cannot close unsaved card!" : "Kaydedilmemiş bir kart kapatılamaz!",
"Open in sidebar view" : "Kenar çubuğu görünümünde aç",
"Open in bigger view" : "Daha büyük görünümde aç",
"Comments" : "Yorumlar",
@@ -253,7 +252,6 @@
"Reply" : "Yanıtla",
"Update" : "Güncelle",
"Write a description …" : "Bir açıklama yazın …",
"Could not save description" : "Açıklama kaydedilemedi",
"Description" : "Açıklama",
"(Unsaved)" : "(Kaydedilmemiş)",
"(Saving…)" : "(Kaydediliyor…)",

View File

@@ -48,30 +48,8 @@ OC.L10N.register(
"You have updated the due date of card {card} to {after}" : "Ви оновили дату завершення картки {card} на {after}",
"{user} has updated the due date of card {card} to {after}" : "{user} оновив(-ла) дату завершення картки {card} на {after}",
"You have added the tag {label} to card {card} in list {stack} on board {board}" : "Ви додали мітку {label} до картки {card} в списку {board}",
"{user} has added the tag {label} to card {card} in list {stack} on board {board}" : "{user} додав тег {label} до карти {card} у списку {stack} на борту {board}",
"You have removed the tag {label} from card {card} in list {stack} on board {board}" : "Ви видалили тег {label} з карти {card} у списку {stack} на борту {board}",
"{user} has removed the tag {label} from card {card} in list {stack} on board {board}" : "{user} видалив тег {label} з карти {card} у списку {stack} на борту {board}",
"You have assigned {assigneduser} to card {card} on board {board}" : "Ви призначили {assigneduser} на картку {card} на борту {board}",
"{user} has assigned {assigneduser} to card {card} on board {board}" : "{user} призначив {assigneduser} на картку {card} на дошці {board}",
"You have unassigned {assigneduser} from card {card} on board {board}" : "Ви скасували призначення {assigneduser} з карти {card} на борту {board}",
"{user} has unassigned {assigneduser} from card {card} on board {board}" : "{user} скасував призначення {assigneduser} з карти {card} на дошці {board}",
"You have moved the card {card} from list {stackBefore} to {stack}" : "Ви перемістили картку {card} зі списку {stackBefore} до {stack}",
"{user} has moved the card {card} from list {stackBefore} to {stack}" : "{user} перемістив картку {card} зі списку {stackBefore} до {stack}",
"You have added the attachment {attachment} to card {card}" : "Ви додали вкладення {attachment} до картки {card}",
"{user} has added the attachment {attachment} to card {card}" : "{user} додав вкладення {attachment} до картки {card}",
"You have updated the attachment {attachment} on card {card}" : "Ви оновили вкладення {attachment} на картці {card}",
"{user} has updated the attachment {attachment} on card {card}" : " {user}оновив вкладення {attachment} на картці {card}",
"You have deleted the attachment {attachment} from card {card}" : "Ви видалили вкладення {attachment} з картки {card}",
"{user} has deleted the attachment {attachment} from card {card}" : "{user} видалив вкладення {attachment} з картки {card}",
"You have restored the attachment {attachment} to card {card}" : "Ви відновили вкладення {attachment} до картки {card}",
"{user} has restored the attachment {attachment} to card {card}" : "{user} відновив вкладення {attachment} до картки {card}",
"You have commented on card {card}" : "Ви залишили коментар до картки {card}",
"{user} has commented on card {card}" : "{user} прокоментував картку {card}",
"Deck" : "Колода",
"Changes in the <strong>Deck app</strong>" : "Зміни у застосунку <strong>Колода</strong>",
"A <strong>board, list or card</strong> was changed" : "Змінено <strong>таблицю, список або картку</strong>",
"A <strong>comment</strong> was created on a card" : "Створено <strong>коментар</strong> на картці",
"A <strong>card description</strong> has been changed" : "Змінено <strong>опис картки</strong>",
"The file was uploaded" : "Файл завантажено",
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "Файл для завантаження перевищує параметр upload_max_filesize у php.ini",
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Розмір завантаженого файлу перевищує значення MAX_FILE_SIZE, яке було зазначено у HTML формі",
@@ -81,66 +59,30 @@ OC.L10N.register(
"Could not write file to disk" : "Неможливо записати файл на диск",
"A PHP extension stopped the file upload" : "Розширення PHP призупинило завантаження файлу",
"No file uploaded or file size exceeds maximum of %s" : "Немає завантажених файлів або розмір файлу перевищує максимум %s",
"Invalid file type. Only JSON files are allowed." : "Неправильний тип файлу. Допускаються тільки файли у форматі JSON.",
"Invalid JSON data" : "Неправильні дані JSON",
"Failed to import board" : "Не вдалося імпортувати дошку",
"Cards due today" : "Картки повинні бути оплачені сьогодні",
"Cards due tomorrow" : "Картки на завтра",
"Upcoming cards" : "Очікують на виконання",
"Load more" : "Більше",
"Welcome to Nextcloud Deck!" : "Ласкаво просимо до колоди Nextcloud!",
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "Картка \"%s\" на \"%s\" була призначена вам %s.",
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} призначив вам карту {deck-card} на {deck-board}.",
"The card \"%s\" on \"%s\" has reached its due date." : "Термін дії картки \"%s\" на \"%s\" закінчився.",
"The card {deck-card} on {deck-board} has reached its due date." : "Термін дії карти {deck-card} на {deck-board} закінчився.",
"%s has mentioned you in a comment on \"%s\"." : "%s згадав вас у коментарі до \"%s\".",
"{user} has mentioned you in a comment on {deck-card}." : "{user} згадав вас у коментарі до {deck-card}.",
"The board \"%s\" has been shared with you by %s." : "Дошку \"%s\" з вами поділився %s.",
"{user} has shared {deck-board} with you." : "{user} поділився з вами {deck-board}.",
"Deck board" : "Дошка Deck",
"Owned by %1$s" : "Належить %1$s",
"Deck boards, cards and comments" : "Дошки колод, карти та коментарі",
"From %1$s, in %2$s/%3$s, owned by %4$s" : "З %1$s, в %2$s/%3$s, у власності %4$s",
"Create a new deck card" : "Створіть нову карту колоди",
"Card comments" : "Коментарі до картки",
"%s on %s" : "%s на %s",
"Deck boards and cards" : "Колода та карти",
"No data was provided to create an attachment." : "Для створення вкладення не було надано жодних даних.",
"Finished" : "Завершено",
"To review" : "На перегляд",
"Action needed" : "Потребує дій",
"Later" : "Пізніше",
"copy" : "копіювати",
"Read more inside" : "Читайте більше всередині",
"Custom lists - click to rename!" : "Користувацькі списки - натисніть, щоб перейменувати!",
"To Do" : "Зробити",
"In Progress" : "В процесі",
"Done" : "Готово",
"1. Open to learn more about boards and cards" : "1. Відкриті, щоб дізнатися більше про дошки та картки",
"2. Drag cards left and right, up and down" : "2. Перетягування карток вліво і вправо, вгору і вниз",
"3. Apply rich formatting and link content" : "3. Застосовуйте багате форматування та посилання на вміст",
"4. Share, comment and collaborate!" : "4. Діліться, коментуйте та співпрацюйте!",
"Create your first card!" : "Створіть свою першу листівку!",
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Цей коментар містить більше %s символів.\nДодано як вкладення до картки з іменем %s.\nДоступний за URL: %s.",
"Attachments" : "Вкладення",
"File" : "Файл",
"date" : "дата",
"Card not found" : "Картку не знайдено",
"Path is already shared with this card" : "Шлях вже є спільним з цією карткою",
"Invalid date, date format must be YYYY-MM-DD" : "Недійсна дата, формат дати має бути РРРР-ММ-ДД",
"Personal planning and team project organization" : "Особисте планування та організація командних проектів",
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck - це інструмент організації в стилі канбан, призначений для особистого планування та організації проектів для команд, інтегрованих з Nextcloud.\n\n\n- 📥 Додавайте свої завдання на картки та впорядковуйте їх\n- 📄 Записуйте додаткові нотатки в Markdown\n- 🔖 Призначайте мітки для ще кращої організації\n- 👥 Діліться з командою, друзями чи родиною\n- Прикріплюйте файли та вбудовуйте їх в опис Markdown\n- 💬 Обговорюйте зі своєю командою за допомогою коментарів\n- ⚡ Відстежуйте зміни в потоці активностей\n- 🚀 Організуйте свій проект",
"Add board" : "Додати дошку",
"Card details" : "Деталі картки",
"Select the board to link to a project" : "Виберіть дошку для прив'зки до проєкту",
"Search by board title" : "Шукати за назвою дошки",
"Select board" : "Вибрати дошку",
"Move/copy card" : "Картка переміщення/копіювання",
"Select a board" : "Вибрати дошку",
"No lists available" : "Списки відсутні",
"Select a list" : "Виберіть список",
"Move card" : "Пересунути картку",
"Copy card" : "Копіювальна картка",
"Select the card to link to a project" : "Виберіть картку для прив'язки до проєкту",
"Link to card" : "Прив'язати до картки",
"Select a card" : "Вибрати картку",
@@ -161,27 +103,19 @@ OC.L10N.register(
"Filter by tag" : "Відібрати за мітками",
"Filter by assigned user" : "Відібрати за призначеним користувачем",
"Unassigned" : "Скасовано призначення",
"Filter by status" : "Фільтр за статусом",
"Open and completed" : "Відкрито та завершено",
"Open" : "Відкрити",
"Completed" : "Виконано",
"Filter by due date" : "Відібрати за датою завершення",
"Overdue" : "Протерміновано",
"Next 24 hours" : "Наступні 24 години",
"Next 7 days" : "Наступні 7 днів",
"Next 30 days" : "Наступні 30 днів",
"No due date" : "Без дати завершення",
"Clear filter" : "Очистити фільтр",
"View Modes" : "Режими перегляду",
"Toggle View Modes" : "Перемикання режимів перегляду",
"Hide archived cards" : "Приховати архівні картки",
"Show archived cards" : "Показати архівні картки",
"Toggle compact mode" : "Перемкнути компактний вигляд",
"Hide card cover images" : "Приховати зображення обкладинок карток",
"Show card cover images" : "Показати зображення обкладинки картки",
"Open details" : "Показати деталі",
"Details" : "Деталі",
"Currently present people" : "Наразі присутні люди",
"Loading board" : "Завантаження дошки",
"Board not found" : "Дошку не знайдено",
"Create a new list to add cards to this board" : "Створіть список щоб додати картки на цю дошку",
@@ -192,62 +126,35 @@ OC.L10N.register(
"Deleted lists" : "Вилучені списки",
"Undo" : "Скасувати",
"Deleted cards" : "Вилучені картки",
"Failed to create share with {displayName}" : "Не вдалося створити спільний доступ з {displayName}",
"Are you sure you want to transfer the board {title} to {user}?" : "Ви впевнені, що хочете перенести дошку {title} користувачеві {user}?",
"Transfer the board." : "Перенесіть дошку.",
"Transfer" : "Передати",
"The board has been transferred to {user}" : "Дошка була передана {user}",
"Failed to transfer the board to {user}" : "Не вдалося передати дошку користувачеві {user}",
"Share board with a user, group or team …" : "Спільний доступ до дошки з користувачем, групою або командою ...",
"Searching for users, groups and teams …" : "Пошук користувачів, груп і команд ...",
"No participants found" : "Учасників не знайдено",
"Board owner" : "Власник дошки",
"(Group)" : "(група)",
"(Team)" : "(Команда)",
"Can edit" : "Може редагувати",
"Can share" : "Can share",
"Can manage" : "Може керувати",
"Owner" : "Власник",
"Delete" : "Вилучити",
"List deleted" : "Список видалено",
"Edit list title" : "Редагувати заголовок списку",
"Archive all cards" : "Архівувати всі картки",
"Unarchive all cards" : "Розархівувати всі картки",
"Delete list" : "Вилучити список",
"Archive all cards in this list" : "Архівуйте всі картки в цьому списку",
"Unarchive all cards in this list" : "Розархівувати всі картки в цьому списку",
"Add a new card" : "Додати нову картку",
"Card name" : "Назва картки",
"title and color value must be provided" : "потрібно зазначити назву та колір",
"Edit" : "Редагувати",
"Add a new tag" : "Додати нову мітку",
"Board name" : "Назва дошки",
"Members" : "Учасники",
"Assign to users/groups/team" : "Призначити користувачам/групам/команді",
"Assign a user to this card…" : "Призначити користувачеві цю картку",
"Select a user to assign to this card…" : "Виберіть користувача, якого слід призначити на цю картку...",
"File to share" : "Виберіть файл для надання доступу",
"Invalid path selected" : "Вибрано неправильний шлях",
"Upload new files" : "Додати файл",
"Share from Files" : "Відкрити Файли",
"Pending share" : "Очікувана акція",
"Add this attachment" : "Долучити вкладення",
"Show in Files" : "Показати в Файлах",
"Download" : "Звантажити",
"Remove attachment" : "Зніміть вкладення",
"Delete Attachment" : "Забрати вкладення",
"Restore Attachment" : "Відновити вкладення",
"Modified" : "Змінено",
"Created" : "Створено",
"The title cannot be empty." : "Заголовок не може бути порожнім.",
"Cannot close unsaved card!" : "Неможливо закрити незбережену картку!",
"Open in sidebar view" : "Відкрити у вигляді бічної панелі",
"Open in bigger view" : "Відкрити в більшому розмірі",
"Comments" : "Коментарі",
"Failed to load comments" : "Не вдалося завантажити коментарі",
"No comments yet. Begin the discussion!" : "Коментарів немає, почніть обговорення!",
"The comment cannot be empty." : "Коментар не може бути порожнім.",
"The comment cannot be longer than 1000 characters." : "Коментар не може бути довшим за 1000 символів.",
"Save" : "Зберегти",
"Created:" : "Створено:",
"In reply to" : "У відповідь",
@@ -255,7 +162,6 @@ OC.L10N.register(
"Reply" : "Відповісти",
"Update" : "Оновлення",
"Write a description …" : "Додайте опис ...",
"Could not save description" : "Не вдалося зберегти опис",
"Description" : "Опис",
"(Unsaved)" : "(Не збережено)",
"(Saving…)" : "(Зберігання...)",
@@ -265,150 +171,73 @@ OC.L10N.register(
"Add Attachment" : "Долучити вкладення",
"Choose attachment" : "Вибрати вкладення",
"Select Date" : "Вкажіть дату",
"Later today {timeLocale}" : "Пізніше сьогодні - {timeLocale}",
"Set due date for later today" : "Встановіть термін сплати на сьогоднішній день",
"Tomorrow {timeLocale}" : "Завтра - {timeLocale}",
"Set due date for tomorrow" : "Встановіть дедлайн на завтра",
"This weekend {timeLocale}" : "На цих вихідних - {timeLocale}",
"Set due date for this weekend" : "Встановіть термін виконання на ці вихідні",
"Next week {timeLocale}" : "Наступного тижня - {timeLocale}",
"Set due date for next week" : "Встановіть термін виконання на наступний тиждень",
"Assign a due date to this card…" : "Призначте цій картці термін оплати...",
"Set a due date" : "Встановити дату завершення",
"Add due date" : "Додати термін сплати",
"Choose a date" : "Виберіть дату",
"Remove due date" : "Вилучити до",
"Mark as done" : "Позначити як виконане",
"Due at:" : "На часі:",
"Not done" : "Ще не все.",
"Unarchive card" : "Розархівувати картку",
"Archive card" : "Архівувати картку",
"Assign a tag to this card…" : "Додати мітку до цієї картки",
"Select or create a tag…" : "Виберіть або створіть тег...",
"Create a new tag:" : "Створіть новий тег:",
"(group)" : "(група)",
"{count} comments, {unread} unread" : "{count} коментарів, {unread} непрочитаних",
"Todo items" : "Пункти завдань",
"Edit card title" : "Редагувати заголовок картки",
"Open link" : "Відкрити посилання",
"Card deleted" : "Картку видалено",
"Edit title" : "Редагувати",
"Assign to me" : "Призначити мені",
"Unassign myself" : "Зняти з себе повноваження.",
"Mark as not done" : "Позначити як не виконано",
"Delete card" : "Вилучити картку",
"seconds ago" : "секунд тому",
"Keyboard shortcuts" : "Скорочення",
"Boost your productivity using Deck with keyboard shortcuts." : "Підвищуйте свою продуктивність, використовуючи Deck за допомогою комбінацій клавіш.",
"Board actions" : "Дії правління",
"Keyboard shortcut" : "Сполучення клавіш",
"Action" : "Дія ",
"Shift" : "Shift",
"Scroll" : "Прокрутка",
"Scroll sideways" : "Прокрутіть вбік",
"Navigate between cards" : "Перехід між картками",
"Esc" : "Esc",
"Close card details" : "Закрити дані картки",
"Ctrl" : "Ctrl",
"Search" : "Пошук",
"Show card filters" : "Показати фільтри карток",
"Clear card filters" : "Очистити фільтри карток",
"Show help dialog" : "Показати діалогове вікно довідки",
"Card actions" : "Дії з карткою",
"The following actions can be triggered on the currently highlighted card" : "На поточній виділеній картці можна виконати такі дії",
"Enter" : "Ввід",
"Space" : "Простір",
"Open card details" : "Відкрити реквізити картки",
"Edit the card title" : "Відредагуйте назву картки",
"Assign yourself to the current card" : "Приєднайте себе до поточної картки",
"Archive/unarchive the current card" : "Архівувати/розархівувати поточну картку",
"Mark card as completed/not completed" : "Позначте картку як завершену/не завершену",
"Open card menu" : "Відкрити меню картки",
"All boards" : "Усі дошки",
"Archived boards" : "Архівні дошки",
"Shared with you" : "Вам надано доступ",
"Deck settings" : "Налаштування колоди",
"Use bigger card view" : "Режим перегляду зі збільшеними картками",
"Show card ID badge" : "Покажіть бейдж з ідентифікаційною карткою",
"Show boards in calendar/tasks" : "Показувати дошки в календарі та завданнях",
"Limit board creation to some groups" : "Обмежити створення дошки для деяких груп",
"Users outside of those groups will not be able to create their own boards, but will still be able to work on boards that have been shared with them." : "Користувачі поза цими групами не зможуть створювати власні дошки, але зможуть працювати на дошках, до яких їм надано спільний доступ.",
"Cancel edit" : "Скасувати редагування",
"Save board" : "Зберегти дошку",
"Board {0} deleted" : "Дошку {0} вилучено",
"All cards" : "Всі карти",
"Only assigned cards" : "Тільки призначені картки",
"No reminder" : "Відсутні нагадування",
"An error occurred" : "Виникла помилка",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Ви впевнені, що хочете вилучити дошку {title}? Це призведе до видалення всіх даних цієї дошки, включно архівні картки.",
"Delete the board?" : "Вилучити дошку?",
"Exporting board..." : "Експортна дошка...",
"Board details" : "Деталі дошки",
"Edit board" : "Редагувати дошку",
"Clone board" : "Копіювати дошку",
"Unarchive board" : "Розархівувати дошку",
"Archive board" : "Архівувати дошку",
"Export board" : "Дошка експорту",
"Turn on due date reminders" : "Нагадування про термін виконання",
"Turn off due date reminders" : "Вимкнути нагадування про терміни виконання",
"Due date reminders" : "Нагадування про терміни виконання",
"Assigned cards" : "Призначені картки",
"No notifications" : "Немає сповіщень",
"Delete board" : "Вилучити дошку",
"Importing board..." : "Імпортна дошка...",
"Board imported successfully" : "Плату успішно імпортовано",
"Import board" : "Імпортна дошка",
"Clone {boardTitle}" : "Клон {boardTitle}",
"Clone cards" : "Копіювати картки",
"Clone assignments" : "Призначення клонів",
"Clone labels" : "Етикетки клонів",
"Clone due dates" : "Клонувати дві дати",
"Advanced options" : "Розширені налаштування",
"Move all cards to the first list" : "Перемістіть усі картки до першого списку",
"Restore archived cards" : "Відновлення заархівованих карток",
"Clone" : "Копіювати",
"Export {boardTitle}" : "Експорт {boardTitle}",
"Export as JSON" : "Експорт як JSON",
"Export as CSV" : "Експорт у CSV",
"Note: Only the JSON format is supported for importing back into the Deck app." : "Примітка: Для імпорту в додаток Deck підтримується лише формат JSON.",
"Export" : "Експортувати",
"Loading filtered view" : "Завантаження відфільтрованого перегляду",
"Today" : "Сьогодні",
"Tomorrow" : "Завтра",
"No due" : "Без призначеної дати",
"Search for {searchQuery} in all boards" : "Шукати {searchQuery} на всіх дошках оголошень",
"No results found" : "Не знайдено жодного результату",
"Deck board {name}\n* Last modified on {lastMod}" : "Колода {name}\n* Востаннє змінено на {lastMod}",
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Створено на {created}\n* Востаннє змінено на {lastMod}\n* {nbAttachments} вкладення\n* {nbComments} коментарі",
"{nbCards} cards" : "{nbCards} картки",
"Due on {date}" : "До {date}",
"{stack} in {board}" : "{stack} в {board}",
"Click to expand description" : "Натисніть, щоб розгорнути опис",
"Click to expand comment" : "Натисніть, щоб розгорнути коментар",
"Create card" : "Створити картку",
"Create a new card" : "Створити нову картку",
"Card title" : "Заголовок картки",
"Creating the new card …" : "Створення нової картки ...",
"Card \"{card}\" was added to \"{board}\"" : "Картку \"{card}\" додано до \"{board}\"",
"Open card" : "Відкрити картку",
"Close" : "Закрити",
"No upcoming cards" : "Немає майбутніх завдань",
"upcoming cards today" : "найближчі картки на сьогодні",
"upcoming cards tomorrow" : "найближчі картки завтра",
"upcoming cards" : "очікують на виконання",
"New card" : "Нова картка",
"Link to a board" : "Прив'язати до дошки",
"Link to a card" : "Прив'язати до картки",
"Create a card" : "Створити картку",
"Message from {author} in {conversationName}" : "Повідомлення від {author} у {conversationName}",
"Something went wrong" : "От халепа!",
"Failed to upload {name}" : "Не вдалося завантажити {name}",
"Maximum file size of {size} exceeded" : "Досягнуто максимальний розмір файлу {size}",
"Assigned users" : "Призначені користувачі",
"Due date" : "Дата виконання",
"Error creating the share" : "Помилка створення спільного доступу",
"Share with a Deck card" : "Поділіться з картою з колоди",
"Share {file} with a Deck card" : "Поділіться {file} з картою колоди",
"Share" : "Спільний доступ",
"Personal" : "Особисте",
"To do" : "Заплановано",

View File

@@ -46,30 +46,8 @@
"You have updated the due date of card {card} to {after}" : "Ви оновили дату завершення картки {card} на {after}",
"{user} has updated the due date of card {card} to {after}" : "{user} оновив(-ла) дату завершення картки {card} на {after}",
"You have added the tag {label} to card {card} in list {stack} on board {board}" : "Ви додали мітку {label} до картки {card} в списку {board}",
"{user} has added the tag {label} to card {card} in list {stack} on board {board}" : "{user} додав тег {label} до карти {card} у списку {stack} на борту {board}",
"You have removed the tag {label} from card {card} in list {stack} on board {board}" : "Ви видалили тег {label} з карти {card} у списку {stack} на борту {board}",
"{user} has removed the tag {label} from card {card} in list {stack} on board {board}" : "{user} видалив тег {label} з карти {card} у списку {stack} на борту {board}",
"You have assigned {assigneduser} to card {card} on board {board}" : "Ви призначили {assigneduser} на картку {card} на борту {board}",
"{user} has assigned {assigneduser} to card {card} on board {board}" : "{user} призначив {assigneduser} на картку {card} на дошці {board}",
"You have unassigned {assigneduser} from card {card} on board {board}" : "Ви скасували призначення {assigneduser} з карти {card} на борту {board}",
"{user} has unassigned {assigneduser} from card {card} on board {board}" : "{user} скасував призначення {assigneduser} з карти {card} на дошці {board}",
"You have moved the card {card} from list {stackBefore} to {stack}" : "Ви перемістили картку {card} зі списку {stackBefore} до {stack}",
"{user} has moved the card {card} from list {stackBefore} to {stack}" : "{user} перемістив картку {card} зі списку {stackBefore} до {stack}",
"You have added the attachment {attachment} to card {card}" : "Ви додали вкладення {attachment} до картки {card}",
"{user} has added the attachment {attachment} to card {card}" : "{user} додав вкладення {attachment} до картки {card}",
"You have updated the attachment {attachment} on card {card}" : "Ви оновили вкладення {attachment} на картці {card}",
"{user} has updated the attachment {attachment} on card {card}" : " {user}оновив вкладення {attachment} на картці {card}",
"You have deleted the attachment {attachment} from card {card}" : "Ви видалили вкладення {attachment} з картки {card}",
"{user} has deleted the attachment {attachment} from card {card}" : "{user} видалив вкладення {attachment} з картки {card}",
"You have restored the attachment {attachment} to card {card}" : "Ви відновили вкладення {attachment} до картки {card}",
"{user} has restored the attachment {attachment} to card {card}" : "{user} відновив вкладення {attachment} до картки {card}",
"You have commented on card {card}" : "Ви залишили коментар до картки {card}",
"{user} has commented on card {card}" : "{user} прокоментував картку {card}",
"Deck" : "Колода",
"Changes in the <strong>Deck app</strong>" : "Зміни у застосунку <strong>Колода</strong>",
"A <strong>board, list or card</strong> was changed" : "Змінено <strong>таблицю, список або картку</strong>",
"A <strong>comment</strong> was created on a card" : "Створено <strong>коментар</strong> на картці",
"A <strong>card description</strong> has been changed" : "Змінено <strong>опис картки</strong>",
"The file was uploaded" : "Файл завантажено",
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "Файл для завантаження перевищує параметр upload_max_filesize у php.ini",
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Розмір завантаженого файлу перевищує значення MAX_FILE_SIZE, яке було зазначено у HTML формі",
@@ -79,66 +57,30 @@
"Could not write file to disk" : "Неможливо записати файл на диск",
"A PHP extension stopped the file upload" : "Розширення PHP призупинило завантаження файлу",
"No file uploaded or file size exceeds maximum of %s" : "Немає завантажених файлів або розмір файлу перевищує максимум %s",
"Invalid file type. Only JSON files are allowed." : "Неправильний тип файлу. Допускаються тільки файли у форматі JSON.",
"Invalid JSON data" : "Неправильні дані JSON",
"Failed to import board" : "Не вдалося імпортувати дошку",
"Cards due today" : "Картки повинні бути оплачені сьогодні",
"Cards due tomorrow" : "Картки на завтра",
"Upcoming cards" : "Очікують на виконання",
"Load more" : "Більше",
"Welcome to Nextcloud Deck!" : "Ласкаво просимо до колоди Nextcloud!",
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "Картка \"%s\" на \"%s\" була призначена вам %s.",
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} призначив вам карту {deck-card} на {deck-board}.",
"The card \"%s\" on \"%s\" has reached its due date." : "Термін дії картки \"%s\" на \"%s\" закінчився.",
"The card {deck-card} on {deck-board} has reached its due date." : "Термін дії карти {deck-card} на {deck-board} закінчився.",
"%s has mentioned you in a comment on \"%s\"." : "%s згадав вас у коментарі до \"%s\".",
"{user} has mentioned you in a comment on {deck-card}." : "{user} згадав вас у коментарі до {deck-card}.",
"The board \"%s\" has been shared with you by %s." : "Дошку \"%s\" з вами поділився %s.",
"{user} has shared {deck-board} with you." : "{user} поділився з вами {deck-board}.",
"Deck board" : "Дошка Deck",
"Owned by %1$s" : "Належить %1$s",
"Deck boards, cards and comments" : "Дошки колод, карти та коментарі",
"From %1$s, in %2$s/%3$s, owned by %4$s" : "З %1$s, в %2$s/%3$s, у власності %4$s",
"Create a new deck card" : "Створіть нову карту колоди",
"Card comments" : "Коментарі до картки",
"%s on %s" : "%s на %s",
"Deck boards and cards" : "Колода та карти",
"No data was provided to create an attachment." : "Для створення вкладення не було надано жодних даних.",
"Finished" : "Завершено",
"To review" : "На перегляд",
"Action needed" : "Потребує дій",
"Later" : "Пізніше",
"copy" : "копіювати",
"Read more inside" : "Читайте більше всередині",
"Custom lists - click to rename!" : "Користувацькі списки - натисніть, щоб перейменувати!",
"To Do" : "Зробити",
"In Progress" : "В процесі",
"Done" : "Готово",
"1. Open to learn more about boards and cards" : "1. Відкриті, щоб дізнатися більше про дошки та картки",
"2. Drag cards left and right, up and down" : "2. Перетягування карток вліво і вправо, вгору і вниз",
"3. Apply rich formatting and link content" : "3. Застосовуйте багате форматування та посилання на вміст",
"4. Share, comment and collaborate!" : "4. Діліться, коментуйте та співпрацюйте!",
"Create your first card!" : "Створіть свою першу листівку!",
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Цей коментар містить більше %s символів.\nДодано як вкладення до картки з іменем %s.\nДоступний за URL: %s.",
"Attachments" : "Вкладення",
"File" : "Файл",
"date" : "дата",
"Card not found" : "Картку не знайдено",
"Path is already shared with this card" : "Шлях вже є спільним з цією карткою",
"Invalid date, date format must be YYYY-MM-DD" : "Недійсна дата, формат дати має бути РРРР-ММ-ДД",
"Personal planning and team project organization" : "Особисте планування та організація командних проектів",
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck - це інструмент організації в стилі канбан, призначений для особистого планування та організації проектів для команд, інтегрованих з Nextcloud.\n\n\n- 📥 Додавайте свої завдання на картки та впорядковуйте їх\n- 📄 Записуйте додаткові нотатки в Markdown\n- 🔖 Призначайте мітки для ще кращої організації\n- 👥 Діліться з командою, друзями чи родиною\n- Прикріплюйте файли та вбудовуйте їх в опис Markdown\n- 💬 Обговорюйте зі своєю командою за допомогою коментарів\n- ⚡ Відстежуйте зміни в потоці активностей\n- 🚀 Організуйте свій проект",
"Add board" : "Додати дошку",
"Card details" : "Деталі картки",
"Select the board to link to a project" : "Виберіть дошку для прив'зки до проєкту",
"Search by board title" : "Шукати за назвою дошки",
"Select board" : "Вибрати дошку",
"Move/copy card" : "Картка переміщення/копіювання",
"Select a board" : "Вибрати дошку",
"No lists available" : "Списки відсутні",
"Select a list" : "Виберіть список",
"Move card" : "Пересунути картку",
"Copy card" : "Копіювальна картка",
"Select the card to link to a project" : "Виберіть картку для прив'язки до проєкту",
"Link to card" : "Прив'язати до картки",
"Select a card" : "Вибрати картку",
@@ -159,27 +101,19 @@
"Filter by tag" : "Відібрати за мітками",
"Filter by assigned user" : "Відібрати за призначеним користувачем",
"Unassigned" : "Скасовано призначення",
"Filter by status" : "Фільтр за статусом",
"Open and completed" : "Відкрито та завершено",
"Open" : "Відкрити",
"Completed" : "Виконано",
"Filter by due date" : "Відібрати за датою завершення",
"Overdue" : "Протерміновано",
"Next 24 hours" : "Наступні 24 години",
"Next 7 days" : "Наступні 7 днів",
"Next 30 days" : "Наступні 30 днів",
"No due date" : "Без дати завершення",
"Clear filter" : "Очистити фільтр",
"View Modes" : "Режими перегляду",
"Toggle View Modes" : "Перемикання режимів перегляду",
"Hide archived cards" : "Приховати архівні картки",
"Show archived cards" : "Показати архівні картки",
"Toggle compact mode" : "Перемкнути компактний вигляд",
"Hide card cover images" : "Приховати зображення обкладинок карток",
"Show card cover images" : "Показати зображення обкладинки картки",
"Open details" : "Показати деталі",
"Details" : "Деталі",
"Currently present people" : "Наразі присутні люди",
"Loading board" : "Завантаження дошки",
"Board not found" : "Дошку не знайдено",
"Create a new list to add cards to this board" : "Створіть список щоб додати картки на цю дошку",
@@ -190,62 +124,35 @@
"Deleted lists" : "Вилучені списки",
"Undo" : "Скасувати",
"Deleted cards" : "Вилучені картки",
"Failed to create share with {displayName}" : "Не вдалося створити спільний доступ з {displayName}",
"Are you sure you want to transfer the board {title} to {user}?" : "Ви впевнені, що хочете перенести дошку {title} користувачеві {user}?",
"Transfer the board." : "Перенесіть дошку.",
"Transfer" : "Передати",
"The board has been transferred to {user}" : "Дошка була передана {user}",
"Failed to transfer the board to {user}" : "Не вдалося передати дошку користувачеві {user}",
"Share board with a user, group or team …" : "Спільний доступ до дошки з користувачем, групою або командою ...",
"Searching for users, groups and teams …" : "Пошук користувачів, груп і команд ...",
"No participants found" : "Учасників не знайдено",
"Board owner" : "Власник дошки",
"(Group)" : "(група)",
"(Team)" : "(Команда)",
"Can edit" : "Може редагувати",
"Can share" : "Can share",
"Can manage" : "Може керувати",
"Owner" : "Власник",
"Delete" : "Вилучити",
"List deleted" : "Список видалено",
"Edit list title" : "Редагувати заголовок списку",
"Archive all cards" : "Архівувати всі картки",
"Unarchive all cards" : "Розархівувати всі картки",
"Delete list" : "Вилучити список",
"Archive all cards in this list" : "Архівуйте всі картки в цьому списку",
"Unarchive all cards in this list" : "Розархівувати всі картки в цьому списку",
"Add a new card" : "Додати нову картку",
"Card name" : "Назва картки",
"title and color value must be provided" : "потрібно зазначити назву та колір",
"Edit" : "Редагувати",
"Add a new tag" : "Додати нову мітку",
"Board name" : "Назва дошки",
"Members" : "Учасники",
"Assign to users/groups/team" : "Призначити користувачам/групам/команді",
"Assign a user to this card…" : "Призначити користувачеві цю картку",
"Select a user to assign to this card…" : "Виберіть користувача, якого слід призначити на цю картку...",
"File to share" : "Виберіть файл для надання доступу",
"Invalid path selected" : "Вибрано неправильний шлях",
"Upload new files" : "Додати файл",
"Share from Files" : "Відкрити Файли",
"Pending share" : "Очікувана акція",
"Add this attachment" : "Долучити вкладення",
"Show in Files" : "Показати в Файлах",
"Download" : "Звантажити",
"Remove attachment" : "Зніміть вкладення",
"Delete Attachment" : "Забрати вкладення",
"Restore Attachment" : "Відновити вкладення",
"Modified" : "Змінено",
"Created" : "Створено",
"The title cannot be empty." : "Заголовок не може бути порожнім.",
"Cannot close unsaved card!" : "Неможливо закрити незбережену картку!",
"Open in sidebar view" : "Відкрити у вигляді бічної панелі",
"Open in bigger view" : "Відкрити в більшому розмірі",
"Comments" : "Коментарі",
"Failed to load comments" : "Не вдалося завантажити коментарі",
"No comments yet. Begin the discussion!" : "Коментарів немає, почніть обговорення!",
"The comment cannot be empty." : "Коментар не може бути порожнім.",
"The comment cannot be longer than 1000 characters." : "Коментар не може бути довшим за 1000 символів.",
"Save" : "Зберегти",
"Created:" : "Створено:",
"In reply to" : "У відповідь",
@@ -253,7 +160,6 @@
"Reply" : "Відповісти",
"Update" : "Оновлення",
"Write a description …" : "Додайте опис ...",
"Could not save description" : "Не вдалося зберегти опис",
"Description" : "Опис",
"(Unsaved)" : "(Не збережено)",
"(Saving…)" : "(Зберігання...)",
@@ -263,150 +169,73 @@
"Add Attachment" : "Долучити вкладення",
"Choose attachment" : "Вибрати вкладення",
"Select Date" : "Вкажіть дату",
"Later today {timeLocale}" : "Пізніше сьогодні - {timeLocale}",
"Set due date for later today" : "Встановіть термін сплати на сьогоднішній день",
"Tomorrow {timeLocale}" : "Завтра - {timeLocale}",
"Set due date for tomorrow" : "Встановіть дедлайн на завтра",
"This weekend {timeLocale}" : "На цих вихідних - {timeLocale}",
"Set due date for this weekend" : "Встановіть термін виконання на ці вихідні",
"Next week {timeLocale}" : "Наступного тижня - {timeLocale}",
"Set due date for next week" : "Встановіть термін виконання на наступний тиждень",
"Assign a due date to this card…" : "Призначте цій картці термін оплати...",
"Set a due date" : "Встановити дату завершення",
"Add due date" : "Додати термін сплати",
"Choose a date" : "Виберіть дату",
"Remove due date" : "Вилучити до",
"Mark as done" : "Позначити як виконане",
"Due at:" : "На часі:",
"Not done" : "Ще не все.",
"Unarchive card" : "Розархівувати картку",
"Archive card" : "Архівувати картку",
"Assign a tag to this card…" : "Додати мітку до цієї картки",
"Select or create a tag…" : "Виберіть або створіть тег...",
"Create a new tag:" : "Створіть новий тег:",
"(group)" : "(група)",
"{count} comments, {unread} unread" : "{count} коментарів, {unread} непрочитаних",
"Todo items" : "Пункти завдань",
"Edit card title" : "Редагувати заголовок картки",
"Open link" : "Відкрити посилання",
"Card deleted" : "Картку видалено",
"Edit title" : "Редагувати",
"Assign to me" : "Призначити мені",
"Unassign myself" : "Зняти з себе повноваження.",
"Mark as not done" : "Позначити як не виконано",
"Delete card" : "Вилучити картку",
"seconds ago" : "секунд тому",
"Keyboard shortcuts" : "Скорочення",
"Boost your productivity using Deck with keyboard shortcuts." : "Підвищуйте свою продуктивність, використовуючи Deck за допомогою комбінацій клавіш.",
"Board actions" : "Дії правління",
"Keyboard shortcut" : "Сполучення клавіш",
"Action" : "Дія ",
"Shift" : "Shift",
"Scroll" : "Прокрутка",
"Scroll sideways" : "Прокрутіть вбік",
"Navigate between cards" : "Перехід між картками",
"Esc" : "Esc",
"Close card details" : "Закрити дані картки",
"Ctrl" : "Ctrl",
"Search" : "Пошук",
"Show card filters" : "Показати фільтри карток",
"Clear card filters" : "Очистити фільтри карток",
"Show help dialog" : "Показати діалогове вікно довідки",
"Card actions" : "Дії з карткою",
"The following actions can be triggered on the currently highlighted card" : "На поточній виділеній картці можна виконати такі дії",
"Enter" : "Ввід",
"Space" : "Простір",
"Open card details" : "Відкрити реквізити картки",
"Edit the card title" : "Відредагуйте назву картки",
"Assign yourself to the current card" : "Приєднайте себе до поточної картки",
"Archive/unarchive the current card" : "Архівувати/розархівувати поточну картку",
"Mark card as completed/not completed" : "Позначте картку як завершену/не завершену",
"Open card menu" : "Відкрити меню картки",
"All boards" : "Усі дошки",
"Archived boards" : "Архівні дошки",
"Shared with you" : "Вам надано доступ",
"Deck settings" : "Налаштування колоди",
"Use bigger card view" : "Режим перегляду зі збільшеними картками",
"Show card ID badge" : "Покажіть бейдж з ідентифікаційною карткою",
"Show boards in calendar/tasks" : "Показувати дошки в календарі та завданнях",
"Limit board creation to some groups" : "Обмежити створення дошки для деяких груп",
"Users outside of those groups will not be able to create their own boards, but will still be able to work on boards that have been shared with them." : "Користувачі поза цими групами не зможуть створювати власні дошки, але зможуть працювати на дошках, до яких їм надано спільний доступ.",
"Cancel edit" : "Скасувати редагування",
"Save board" : "Зберегти дошку",
"Board {0} deleted" : "Дошку {0} вилучено",
"All cards" : "Всі карти",
"Only assigned cards" : "Тільки призначені картки",
"No reminder" : "Відсутні нагадування",
"An error occurred" : "Виникла помилка",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Ви впевнені, що хочете вилучити дошку {title}? Це призведе до видалення всіх даних цієї дошки, включно архівні картки.",
"Delete the board?" : "Вилучити дошку?",
"Exporting board..." : "Експортна дошка...",
"Board details" : "Деталі дошки",
"Edit board" : "Редагувати дошку",
"Clone board" : "Копіювати дошку",
"Unarchive board" : "Розархівувати дошку",
"Archive board" : "Архівувати дошку",
"Export board" : "Дошка експорту",
"Turn on due date reminders" : "Нагадування про термін виконання",
"Turn off due date reminders" : "Вимкнути нагадування про терміни виконання",
"Due date reminders" : "Нагадування про терміни виконання",
"Assigned cards" : "Призначені картки",
"No notifications" : "Немає сповіщень",
"Delete board" : "Вилучити дошку",
"Importing board..." : "Імпортна дошка...",
"Board imported successfully" : "Плату успішно імпортовано",
"Import board" : "Імпортна дошка",
"Clone {boardTitle}" : "Клон {boardTitle}",
"Clone cards" : "Копіювати картки",
"Clone assignments" : "Призначення клонів",
"Clone labels" : "Етикетки клонів",
"Clone due dates" : "Клонувати дві дати",
"Advanced options" : "Розширені налаштування",
"Move all cards to the first list" : "Перемістіть усі картки до першого списку",
"Restore archived cards" : "Відновлення заархівованих карток",
"Clone" : "Копіювати",
"Export {boardTitle}" : "Експорт {boardTitle}",
"Export as JSON" : "Експорт як JSON",
"Export as CSV" : "Експорт у CSV",
"Note: Only the JSON format is supported for importing back into the Deck app." : "Примітка: Для імпорту в додаток Deck підтримується лише формат JSON.",
"Export" : "Експортувати",
"Loading filtered view" : "Завантаження відфільтрованого перегляду",
"Today" : "Сьогодні",
"Tomorrow" : "Завтра",
"No due" : "Без призначеної дати",
"Search for {searchQuery} in all boards" : "Шукати {searchQuery} на всіх дошках оголошень",
"No results found" : "Не знайдено жодного результату",
"Deck board {name}\n* Last modified on {lastMod}" : "Колода {name}\n* Востаннє змінено на {lastMod}",
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Створено на {created}\n* Востаннє змінено на {lastMod}\n* {nbAttachments} вкладення\n* {nbComments} коментарі",
"{nbCards} cards" : "{nbCards} картки",
"Due on {date}" : "До {date}",
"{stack} in {board}" : "{stack} в {board}",
"Click to expand description" : "Натисніть, щоб розгорнути опис",
"Click to expand comment" : "Натисніть, щоб розгорнути коментар",
"Create card" : "Створити картку",
"Create a new card" : "Створити нову картку",
"Card title" : "Заголовок картки",
"Creating the new card …" : "Створення нової картки ...",
"Card \"{card}\" was added to \"{board}\"" : "Картку \"{card}\" додано до \"{board}\"",
"Open card" : "Відкрити картку",
"Close" : "Закрити",
"No upcoming cards" : "Немає майбутніх завдань",
"upcoming cards today" : "найближчі картки на сьогодні",
"upcoming cards tomorrow" : "найближчі картки завтра",
"upcoming cards" : "очікують на виконання",
"New card" : "Нова картка",
"Link to a board" : "Прив'язати до дошки",
"Link to a card" : "Прив'язати до картки",
"Create a card" : "Створити картку",
"Message from {author} in {conversationName}" : "Повідомлення від {author} у {conversationName}",
"Something went wrong" : "От халепа!",
"Failed to upload {name}" : "Не вдалося завантажити {name}",
"Maximum file size of {size} exceeded" : "Досягнуто максимальний розмір файлу {size}",
"Assigned users" : "Призначені користувачі",
"Due date" : "Дата виконання",
"Error creating the share" : "Помилка створення спільного доступу",
"Share with a Deck card" : "Поділіться з картою з колоди",
"Share {file} with a Deck card" : "Поділіться {file} з картою колоди",
"Share" : "Спільний доступ",
"Personal" : "Особисте",
"To do" : "Заплановано",

View File

@@ -20,12 +20,12 @@ OC.L10N.register(
"Card not found" : "Karta topilmadi",
"Add board" : "Doska qo'shing",
"Move card" : "Kartani ko'chirish",
"Cancel" : "Bekor qilish",
"Cancel" : "Cancel",
"Add card" : "Karta qo'shing",
"Archived cards" : "Arxivlangan kartalar",
"Add list" : "Roʻyxat qoʻshish",
"Unassigned" : "Tayinlanmagan",
"Open" : "Ochish",
"Open" : "Open",
"Overdue" : "Muddati o'tgan",
"Next 7 days" : "Keyingi 7 kun",
"Next 30 days" : "Keyingi 30 kun",
@@ -37,13 +37,13 @@ OC.L10N.register(
"Undo" : "Bekor qilish",
"Can edit" : "Can edit",
"Owner" : "Owner",
"Delete" : "O'chirish",
"Delete" : "Delete",
"Delete list" : "Roʻyxatni oʻchirish",
"Edit" : "Tahrirlash",
"Download" : "Yuklab olish",
"Download" : "Download",
"Modified" : "Modified",
"Comments" : "Comments",
"Save" : "Saqlash",
"Save" : "Save",
"In reply to" : "ga javoban",
"Reply" : "Javob bering",
"Update" : "Update",
@@ -55,7 +55,7 @@ OC.L10N.register(
"Edit title" : "Sarlavhani tahrirlash",
"Delete card" : "Kartani o'chirish",
"seconds ago" : "seconds ago",
"Search" : "Qidirish",
"Search" : "Search",
"Archived boards" : "Arxivlangan taxtalar",
"Shared with you" : "Shared with you",
"No reminder" : "Eslatma yo'q",

View File

@@ -18,12 +18,12 @@
"Card not found" : "Karta topilmadi",
"Add board" : "Doska qo'shing",
"Move card" : "Kartani ko'chirish",
"Cancel" : "Bekor qilish",
"Cancel" : "Cancel",
"Add card" : "Karta qo'shing",
"Archived cards" : "Arxivlangan kartalar",
"Add list" : "Roʻyxat qoʻshish",
"Unassigned" : "Tayinlanmagan",
"Open" : "Ochish",
"Open" : "Open",
"Overdue" : "Muddati o'tgan",
"Next 7 days" : "Keyingi 7 kun",
"Next 30 days" : "Keyingi 30 kun",
@@ -35,13 +35,13 @@
"Undo" : "Bekor qilish",
"Can edit" : "Can edit",
"Owner" : "Owner",
"Delete" : "O'chirish",
"Delete" : "Delete",
"Delete list" : "Roʻyxatni oʻchirish",
"Edit" : "Tahrirlash",
"Download" : "Yuklab olish",
"Download" : "Download",
"Modified" : "Modified",
"Comments" : "Comments",
"Save" : "Saqlash",
"Save" : "Save",
"In reply to" : "ga javoban",
"Reply" : "Javob bering",
"Update" : "Update",
@@ -53,7 +53,7 @@
"Edit title" : "Sarlavhani tahrirlash",
"Delete card" : "Kartani o'chirish",
"seconds ago" : "seconds ago",
"Search" : "Qidirish",
"Search" : "Search",
"Archived boards" : "Arxivlangan taxtalar",
"Shared with you" : "Shared with you",
"No reminder" : "Eslatma yo'q",

View File

@@ -10,10 +10,12 @@ namespace OCA\Deck\Controller;
use OCA\Deck\Db\Acl;
use OCA\Deck\Db\Board;
use OCA\Deck\Service\BoardService;
use OCA\Deck\Service\Importer\BoardImportService;
use OCA\Deck\Service\PermissionService;
use OCP\AppFramework\ApiController;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\IL10N;
use OCP\IRequest;
class BoardController extends ApiController {
@@ -22,6 +24,8 @@ class BoardController extends ApiController {
IRequest $request,
private BoardService $boardService,
private PermissionService $permissionService,
private BoardImportService $boardImportService,
private IL10N $l10n,
private $userId,
) {
parent::__construct($appName, $request);
@@ -163,4 +167,62 @@ class BoardController extends ApiController {
public function export($boardId) {
return $this->boardService->export($boardId);
}
/**
* @NoAdminRequired
*/
public function import(): DataResponse {
$file = $this->request->getUploadedFile('file');
$error = null;
$phpFileUploadErrors = [
UPLOAD_ERR_OK => $this->l10n->t('The file was uploaded'),
UPLOAD_ERR_INI_SIZE => $this->l10n->t('The uploaded file exceeds the upload_max_filesize directive in php.ini'),
UPLOAD_ERR_FORM_SIZE => $this->l10n->t('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'),
UPLOAD_ERR_PARTIAL => $this->l10n->t('The file was only partially uploaded'),
UPLOAD_ERR_NO_FILE => $this->l10n->t('No file was uploaded'),
UPLOAD_ERR_NO_TMP_DIR => $this->l10n->t('Missing a temporary folder'),
UPLOAD_ERR_CANT_WRITE => $this->l10n->t('Could not write file to disk'),
UPLOAD_ERR_EXTENSION => $this->l10n->t('A PHP extension stopped the file upload'),
];
if (empty($file)) {
$error = $this->l10n->t('No file uploaded or file size exceeds maximum of %s', [\OCP\Util::humanFileSize(\OCP\Util::uploadLimit())]);
}
if (!empty($file) && array_key_exists('error', $file) && $file['error'] !== UPLOAD_ERR_OK) {
$error = $phpFileUploadErrors[$file['error']];
}
if (!empty($file) && $file['error'] === UPLOAD_ERR_OK && !in_array($file['type'], ['application/json', 'text/plain'])) {
$error = $this->l10n->t('Invalid file type. Only JSON files are allowed.');
}
if ($error !== null) {
return new DataResponse([
'status' => 'error',
'message' => $error,
], Http::STATUS_BAD_REQUEST);
}
try {
$fileContent = file_get_contents($file['tmp_name']);
$this->boardImportService->setSystem('DeckJson');
$config = new \stdClass();
$config->owner = $this->userId;
$this->boardImportService->setConfigInstance($config);
$this->boardImportService->setData(json_decode($fileContent));
$this->boardImportService->import();
$importedBoard = $this->boardImportService->getBoard();
$board = $this->boardService->find($importedBoard->getId());
return new DataResponse($board, Http::STATUS_OK);
} catch (\TypeError $e) {
return new DataResponse([
'status' => 'error',
'message' => $this->l10n->t('Invalid JSON data'),
], Http::STATUS_BAD_REQUEST);
} catch (\Exception $e) {
return new DataResponse([
'status' => 'error',
'message' => $this->l10n->t('Failed to import board'),
], Http::STATUS_BAD_REQUEST);
}
}
}

View File

@@ -27,7 +27,7 @@ class DefaultBoardMiddleware extends Middleware {
public function beforeController($controller, $methodName) {
try {
if ($this->userId !== null && $this->defaultBoardService->checkFirstRun($this->userId) && $this->permissionService->canCreate()) {
$this->defaultBoardService->createDefaultBoard($this->l10n->t('Personal'), $this->userId, '0087C5');
$this->defaultBoardService->createDefaultBoard($this->l10n->t('Welcome to Nextcloud Deck!'), $this->userId, 'bf678b');
}
} catch (\Throwable $e) {
$this->logger->error('Could not create default board', ['exception' => $e]);

View File

@@ -0,0 +1,78 @@
<?php
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Deck\Migration;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
class LabelMismatchCleanup implements IRepairStep {
public function __construct(
private IDBConnection $db,
) {
}
public function getName() {
return 'Migrate labels with wrong board mapping';
}
public function run(IOutput $output) {
// Find assingments where a label of another (wrong) board is used
$qb = $this->db->getQueryBuilder();
$qb->select('al.id', 'al.label_id', 'al.card_id', 's.board_id as actual_board_id', 'l.board_id as wrong_id', 'l.color', 'l.title')
->from('deck_assigned_labels', 'al')
->innerJoin('al', 'deck_cards', 'c', 'c.id = al.card_id')
->innerJoin('c', 'deck_stacks', 's', 'c.stack_id = s.id')
->innerJoin('al', 'deck_labels', 'l', 'l.id = al.label_id')
->where($qb->expr()->neq('l.board_id', 's.board_id'));
$labels = $qb->executeQUery()->fetchAll();
if (count($labels) === 0) {
return;
}
$output->info('Found ' . count($labels) . ' labels with wrong board mapping');
foreach ($labels as $label) {
// Select existing label on the correct board
$qb = $this->db->getQueryBuilder();
$qb->select('id')
->from('deck_labels')
->where($qb->expr()->eq('title', $qb->createNamedParameter($label['title'])))
->andWhere($qb->expr()->eq('color', $qb->createNamedParameter($label['color'])))
->andWhere($qb->expr()->eq('board_id', $qb->createNamedParameter($label['actual_board_id'])));
$result = $qb->executeQuery();
$newLabel = $result->fetchOne();
$result->closeCursor();
if (!$newLabel) {
// Create a new label with the same title and color on the correct board
$qb = $this->db->getQueryBuilder();
$qb->insert('deck_labels')
->values([
'title' => $qb->createNamedParameter($label['title']),
'color' => $qb->createNamedParameter($label['color']),
'board_id' => $qb->createNamedParameter($label['actual_board_id']),
]);
$qb->executeStatement();
$newLabel = $qb->getLastInsertId();
$output->debug('Created new label ' . $label['title'] . ' on board ' . $label['actual_board_id']);
} else {
$output->debug('Found existing label ' . $label['title'] . ' on board ' . $label['actual_board_id']);
}
// Update the assignment to use the new label
$qb = $this->db->getQueryBuilder();
$qb->update('deck_assigned_labels')
->set('label_id', $qb->createNamedParameter($newLabel))
->where($qb->expr()->eq('id', $qb->createNamedParameter($label['id'])));
$qb->executeStatement();
$output->debug('Updated label assignment ' . $label['id'] . ' to use label ' . $newLabel);
}
}
}

View File

@@ -320,14 +320,14 @@ class BoardService {
return $board;
}
private function applyPermissions($boardId, $edit, $share, $manage, $oldAcl = null) {
private function applyPermissions($boardId, $edit, $share, $manage) {
try {
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_MANAGE);
} catch (NoPermissionException $e) {
$acls = $this->aclMapper->findAll($boardId);
$edit = $this->permissionService->userCan($acls, Acl::PERMISSION_EDIT, $this->userId) ? $edit : $oldAcl?->getPermissionEdit() ?? false;
$share = $this->permissionService->userCan($acls, Acl::PERMISSION_SHARE, $this->userId) ? $share : $oldAcl?->getPermissionShare() ?? false;
$manage = $this->permissionService->userCan($acls, Acl::PERMISSION_MANAGE, $this->userId) ? $manage : $oldAcl?->getPermissionManage() ?? false;
$edit = $this->permissionService->userCan($acls, Acl::PERMISSION_EDIT, $this->userId) && $edit;
$share = $this->permissionService->userCan($acls, Acl::PERMISSION_SHARE, $this->userId) && $share;
$manage = $this->permissionService->userCan($acls, Acl::PERMISSION_MANAGE, $this->userId) && $manage;
}
return [$edit, $share, $manage];
}
@@ -417,7 +417,7 @@ class BoardService {
/** @var Acl $acl */
$acl = $this->aclMapper->find($id);
[$edit, $share, $manage] = $this->applyPermissions($acl->getBoardId(), $edit, $share, $manage, $acl);
[$edit, $share, $manage] = $this->applyPermissions($acl->getBoardId(), $edit, $share, $manage);
$acl->setPermissionEdit($edit);
$acl->setPermissionShare($share);
$acl->setPermissionManage($manage);
@@ -439,7 +439,7 @@ class BoardService {
* @throws NotFoundExceptionInterface
*/
public function deleteAcl(int $id): ?Acl {
$this->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_MANAGE);
$this->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_SHARE);
/** @var Acl $acl */
$acl = $this->aclMapper->find($id);
$this->boardMapper->mapAcl($acl);
@@ -762,6 +762,8 @@ class BoardService {
$fullCards = [];
foreach ($cards as $card) {
$fullCard = $this->cardMapper->find($card->getId());
$assignedUsers = $this->assignedUsersMapper->findAll($card->getId());
$fullCard->setAssignedUsers($assignedUsers);
array_push($fullCards, $fullCard);
}
$stack->setCards($fullCards);

View File

@@ -652,6 +652,9 @@ class CardService {
throw new StatusException('Operation not allowed. This card is archived.');
}
$label = $this->labelMapper->find($labelId);
if ($label->getBoardId() !== $this->cardMapper->findBoardId($card->getId())) {
throw new StatusException('Operation not allowed. Label does not exist.');
}
$this->cardMapper->removeLabel($cardId, $labelId);
$this->changeHelper->cardChanged($cardId);
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_LABEL_UNASSING, ['label' => $label]);

View File

@@ -9,6 +9,7 @@ namespace OCA\Deck\Service;
use OCA\Deck\AppInfo\Application;
use OCA\Deck\BadRequestException;
use OCA\Deck\Db\Board;
use OCA\Deck\Db\BoardMapper;
use OCP\IConfig;
use OCP\IL10N;
@@ -21,6 +22,8 @@ class DefaultBoardService {
private $cardService;
private $config;
private $l10n;
private LabelService $labelService;
private AttachmentService $attachmentService;
public function __construct(
IL10N $l10n,
@@ -29,6 +32,8 @@ class DefaultBoardService {
StackService $stackService,
CardService $cardService,
IConfig $config,
LabelService $labelService,
AttachmentService $attachmentService,
) {
$this->boardService = $boardService;
$this->stackService = $stackService;
@@ -36,6 +41,8 @@ class DefaultBoardService {
$this->config = $config;
$this->boardMapper = $boardMapper;
$this->l10n = $l10n;
$this->labelService = $labelService;
$this->attachmentService = $attachmentService;
}
/**
@@ -59,10 +66,13 @@ class DefaultBoardService {
return false;
}
private function getDefaultBoardData(): array {
$defaultBoardDataJson = file_get_contents(__DIR__ . '/fixtures/default-board.json');
return json_decode($defaultBoardDataJson, true);
}
/**
* @param $title
* @param $userId
* @param $color
* @return \OCP\AppFramework\Db\Entity
* @throws \OCA\Deck\NoPermissionException
* @throws \OCA\Deck\StatusException
@@ -71,19 +81,71 @@ class DefaultBoardService {
* @throws BadRequestException
*/
public function createDefaultBoard(string $title, string $userId, string $color) {
$defaultBoard = $this->boardService->create($title, $userId, $color);
$defaultStacks = [];
$defaultCards = [];
$boardData = $this->getDefaultBoardData();
/** @var Board $defaultBoard */
$defaultBoard = $this->boardService->create(
$boardData['title'] ?? $title,
$userId,
$boardData['color'] ?? $color,
);
$boardId = $defaultBoard->getId();
$additionLabels = [];
$translatedLabelTitles = [
'Read more inside' => $this->l10n->t('Read more inside'),
];
$translatedStackTitles = [
'Custom lists - click to rename!' => $this->l10n->t('Custom lists - click to rename!'),
'To Do' => $this->l10n->t('To Do'),
'In Progress' => $this->l10n->t('In Progress'),
'Done' => $this->l10n->t('Done'),
];
$translatedCardTitles = [
'1. Open to learn more about boards and cards' => $this->l10n->t('1. Open to learn more about boards and cards'),
'2. Drag cards left and right, up and down' => $this->l10n->t('2. Drag cards left and right, up and down'),
'3. Apply rich formatting and link content' => $this->l10n->t('3. Apply rich formatting and link content'),
'4. Share, comment and collaborate!' => $this->l10n->t('4. Share, comment and collaborate!'),
'Create your first card!' => $this->l10n->t('Create your first card!'),
];
$defaultStacks[] = $this->stackService->create($this->l10n->t('To do'), $boardId, 1);
$defaultStacks[] = $this->stackService->create($this->l10n->t('Doing'), $boardId, 1);
$defaultStacks[] = $this->stackService->create($this->l10n->t('Done'), $boardId, 1);
foreach ($boardData['addition_labels'] as $labelData) {
$additionLabels[] = $this->labelService->create(
$translatedLabelTitles[$labelData['title']] ?? $labelData['title'],
$labelData['color'],
$boardId
);
}
$defaultCards[] = $this->cardService->create($this->l10n->t('Example Task 3'), $defaultStacks[0]->getId(), 'text', 0, $userId);
$defaultCards[] = $this->cardService->create($this->l10n->t('Example Task 2'), $defaultStacks[1]->getId(), 'text', 0, $userId);
$defaultCards[] = $this->cardService->create($this->l10n->t('Example Task 1'), $defaultStacks[2]->getId(), 'text', 0, $userId);
$defaultLabels = array_merge($defaultBoard->getLabels() ?? [], $additionLabels);
foreach ($boardData['stacks'] as $stackData) {
$stack = $this->stackService->create(
$translatedStackTitles[$stackData['title']] ?? $stackData['title'],
$boardId,
$stackData['order']
);
foreach ($stackData['cards'] as $cardData) {
$card = $this->cardService->create(
$translatedCardTitles[$cardData['title']] ?? $cardData['title'],
$stack->getId(),
$cardData['type'],
$cardData['order'],
$userId,
$cardData['description'],
);
foreach ($defaultLabels as $defaultLabel) {
if ($defaultLabel && in_array($defaultLabel->getTitle(), $cardData['labels'])) {
$this->cardService->assignLabel($card->getId(), $defaultLabel->getId());
}
}
if (!empty($cardData['has_example_attachment'])) {
$this->attachmentService->create($card->getId(), 'file', 'DEFAULT_SAMPLE_FILE');
}
}
}
return $defaultBoard;
}

View File

@@ -162,7 +162,15 @@ class FilesAppService implements IAttachmentService, ICustomAttachmentService {
}
public function create(Attachment $attachment) {
$file = $this->getUploadedFile();
if ($attachment->getData() === 'DEFAULT_SAMPLE_FILE' && !$this->request->getUploadedFile('file')) {
$file = [
'name' => 'Nextcloud sample image - add your image here!.jpg',
'tmp_name' => __DIR__ . '/../../img/sample-image.jpg',
];
} else {
$file = $this->getUploadedFile();
}
$fileName = $file['name'];
// get shares for current card

View File

@@ -0,0 +1,81 @@
{
"color": "bf678b",
"addition_labels": [
{
"title": "Read more inside",
"color": "CC317C"
}
],
"stacks": [
{
"title": "Custom lists - click to rename!",
"order": 0,
"cards": [
{
"title": "1. Open to learn more about boards and cards",
"description": "## Welcome to Nextcloud Deck!\n\nNextcloud Deck is a kanban style project management app that integrates seamlessly with the Nextcloud ecosystem. Here, you can create and manage boards to streamline your projects and organize project tasks visually using cards. A versatile tool, Nextcloud Deck will help you stay efficient in both personal and collaborative settings!\n\n### \ud83d\udccc How to set up a new board?\n\nAdd a new board via the \u201c+\u201d button or \u201cAdd board\u201d. Name your board and add a description to clarify its purpose if you wish.\n\nAdd task lists to your board via \u201cAdd List\u201d (e.g., \"To Do\"). Add cards to these lists to represent individual tasks or items. Organize your cards visually by assigning labels or colors.\n\nManage your board list: In the board menu next to the board name, you can edit, clone, archive and export your boards.\n\n### \ud83d\uddc2\ufe0f How to create and edit task cards?\n\nAdd cards via the \u201c+\u201d button on top of the list of your choice. Name your card and add a description using the available rich text formatting instruments.\n\nSet a due date to track deadlines and add responsible team members. Label your cards with tags for better navigation. You can create and manage tags in the sidebar, which is accessible via the toolbar button.\n\n### \ud83d\udca1Useful tips for Nextcloud Deck\n\n- Integrate Nextcloud Deck with Nextcloud Calendar and track the upcoming card deadlines.\n- Use comments to keep discussions around a task within its dedicated card.\n- Enable Nextcloud Deck notifications to always stay updated on changes to your boards.",
"labels": [
"Read more inside"
],
"type": "text",
"order": 0
}
]
},
{
"title": "To Do",
"order": 1,
"cards": [
{
"title": "2. Drag cards left and right, up and down",
"description": "## \ud83d\udea6 Manage your boards and cards\n\nDrag your cards around the board to change position in the list or move them to other lists.\n\nArchive cards to remove them from the board without losing your content. You can always access archived cards and put them back by going to \"Show archived cards\" in the board menu.\n\nUse tags to assign types, statuses and other special attributes to your cards to aid visual navigation. Open the \"Tags\" tab in the sidebar of Nextcloud Deck to manage tags you can add to your cards.\n\n## \ud83d\udc53 Change how you view your boards\n\nTo navigate large boards easily, you can filter your cards by tags, team members, statuses and due dates. Open filter menu via Nextcloud Deck toolbar.\n\nEnable compact display mode in the Deck Board menu via the three dots menu in the toolbar. In the same menu, you can disable and enable cover images.",
"labels": [
"Read more inside"
],
"type": "text",
"order": 0
},
{
"title": "Create your first card!",
"description": "",
"labels": [
"Action needed"
],
"type": "text",
"order": 1
}
]
},
{
"title": "In Progress",
"order": 2,
"cards": [
{
"title": "3. Apply rich formatting and link content",
"description": "## \ud83c\udfa8 Make use of rich formatting in card descriptions\n\nYou can use various instruments to make your content more structured and informative. Try all the instruments yourself - use this checklist!\n\n- [ ] Apply headings of different hierarchy (H1-H6).\n- [ ] Use **bold** *italic* __underline__ and ~~strikethrough~~ text formatting.\n- [ ] Create unordered, ordered and to-do lists.\n- [ ] Highlight code and blockquotes, add various illustrated callouts.\n- [ ] Create and format tables\n- [ ] Add details\n- [ ] Add links, for example to [the Nextcloud website](https:\/\/nextcloud.com\/)\n- [ ] Insert attachments\n- [ ] Add emojis \ud83d\udd76\ufe0f \n\n## \ud83d\udd17 Attach files to cards\n\nYou can upload any files from your machine or pick from your Nextcloud Files, such as documents, presentations, images, video clips and anything else. Add files via \"Attachments\" tab.\n\n## \ud83c\udf04 Illustrate cards with images\n\nAttach images to your cards - they will automatically work as card covers.",
"labels": [
"Read more inside"
],
"type": "text",
"order": 0,
"has_example_attachment": true
}
]
},
{
"title": "Done",
"order": 3,
"cards": [
{
"title": "4. Share, comment and collaborate!",
"description": "## \ud83e\udd1d How to collaborate in your board?\n\nShare your cards and boards with others. In many Nextcloud apps, linked Nextcloud Deck items will appear as rich, interactive widgets. Once you assign someone to a card, they will receive a notification.\n\nEdit cards together, leave notes for your teammates, share task-related files by adding attachments and discuss your tasks using card comments.\n\n### ",
"labels": [
"Read more inside"
],
"type": "text",
"order": 0
}
]
}
]
}

12728
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "deck",
"description": "",
"version": "1.15.2",
"version": "2.0.0-dev.0",
"authors": [
{
"name": "Julius Härtl",
@@ -31,22 +31,25 @@
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.26.0",
"@babel/runtime": "^7.27.0",
"@nextcloud/auth": "^2.4.0",
"@nextcloud/axios": "^2.5.1",
"@nextcloud/capabilities": "^1.2.0",
"@nextcloud/dialogs": "^6.0.1",
"@nextcloud/event-bus": "^3.3.1",
"@nextcloud/dialogs": "^7.0.0-rc.1",
"@nextcloud/event-bus": "^3.3.2",
"@nextcloud/files": "^3.10.1",
"@nextcloud/initial-state": "^2.2.0",
"@nextcloud/l10n": "^3.1.0",
"@nextcloud/moment": "^1.3.2",
"@nextcloud/notify_push": "^1.3.0",
"@nextcloud/router": "^3.0.1",
"@nextcloud/vue": "^8.22.0",
"@nextcloud/vue": "^9.0.0-rc.3",
"@vue/compiler-sfc": "^3.5.13",
"@vue/vue3-jest": "^29.2.6",
"@vueuse/core": "^13.1.0",
"blueimp-md5": "^2.19.0",
"chroma-js": "^3.1.2",
"dompurify": "^3.2.3",
"dompurify": "^3.2.5",
"lodash": "^4.17.21",
"markdown-it": "^14.1.0",
"markdown-it-link-attributes": "^4.0.1",
@@ -54,16 +57,14 @@
"moment": "^2.30.1",
"p-queue": "^8.0.1",
"url-search-params-polyfill": "^8.2.5",
"vue": "^2.7.15",
"vue-at": "^2.5.1",
"v3-infinite-loading": "^1.3.2",
"vue": "^3.5.13",
"vue-click-outside": "^1.1.0",
"vue-easymde": "^2.0.0",
"vue-infinite-loading": "^2.4.5",
"vue-material-design-icons": "^5.3.1",
"vue-router": "^3.6.5",
"vue-smooth-dnd": "^0.8.1",
"vuex": "^3.6.2",
"vuex-router-sync": "^5.0.0"
"vue-router": "^4.5.0",
"vue3-smooth-dnd": "^0.0.6",
"vuex": "^4.1.0"
},
"browserslist": [
"extends @nextcloud/browserslist-config"
@@ -75,20 +76,18 @@
"devDependencies": {
"@nextcloud/babel-config": "^1.2.0",
"@nextcloud/browserslist-config": "^3.0.1",
"@nextcloud/cypress": "^1.0.0-beta.12",
"@nextcloud/eslint-config": "^8.4.1",
"@nextcloud/cypress": "^1.0.0-beta.13",
"@nextcloud/eslint-config": "^8.4.2",
"@nextcloud/stylelint-config": "^3.0.1",
"@nextcloud/webpack-vue-config": "^6.2.0",
"@nextcloud/webpack-vue-config": "github:nextcloud-libraries/webpack-vue-config#vue3",
"@relative-ci/agent": "^4.2.14",
"@vue/test-utils": "^2.4.6",
"@vue/vue2-jest": "^29.2.6",
"cypress": "^13.17.0",
"eslint-plugin-cypress": "^3.6.0",
"eslint-webpack-plugin": "^4.2.0",
"eslint-webpack-plugin": "^5.0.1",
"jest": "^29.7.0",
"jest-serializer-vue": "^3.1.0",
"stylelint-webpack-plugin": "^5.0.1",
"vue-template-compiler": "^2.7.16"
"stylelint-webpack-plugin": "^5.0.1"
},
"jest": {
"moduleFileExtensions": [
@@ -106,4 +105,4 @@
"<rootDir>/node_modules/jest-serializer-vue"
]
}
}
}

View File

@@ -1,15 +1,51 @@
<!--
- SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
- SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<script>
import { NcAppContent, NcContent, NcModal } from '@nextcloud/vue'
import CardMoveDialog from './CardMoveDialog.vue'
import AppNavigation from './components/navigation/AppNavigation.vue'
import KeyboardShortcuts from './components/KeyboardShortcuts.vue'
import { BoardApi } from './services/BoardApi.js'
const boardApi = new BoardApi()
export default {
name: 'App',
components: {
NcContent,
AppNavigation,
NcAppContent,
KeyboardShortcuts,
CardMoveDialog,
NcModal,
},
provide() {
return {
boardApi,
}
},
computed: {
cardDetailsInModal() {
return this.$store.getters.config('cardDetailsInModal')
},
},
methods: {
hideModal() {
this.$router.push({ name: 'board' })
},
},
}
</script>
<template>
<NcContent app-name="deck" :class="{ 'nav-hidden': !navShown, 'sidebar-hidden': !sidebarRouterView }">
<NcContent app-name="deck">
<AppNavigation />
<NcAppContent :allow-swipe-navigation="false">
<router-view />
</NcAppContent>
<div v-if="$route.params.id || $route.params.cardId">
<NcModal v-if="cardDetailsInModal && $route.params.cardId"
:name="t('deck', 'Card details')"
@@ -21,179 +57,10 @@
<router-view name="sidebar" />
</div>
</NcModal>
<router-view name="sidebar" :visible="!cardDetailsInModal || !$route.params.cardId" />
</div>
<KeyboardShortcuts />
<CardMoveDialog />
</NcContent>
</template>
<script>
import { mapState } from 'vuex'
import AppNavigation from './components/navigation/AppNavigation.vue'
import KeyboardShortcuts from './components/KeyboardShortcuts.vue'
import { NcModal, NcContent, NcAppContent, isMobile } from '@nextcloud/vue'
import { BoardApi } from './services/BoardApi.js'
import { emit, subscribe } from '@nextcloud/event-bus'
import { loadState } from '@nextcloud/initial-state'
import CardMoveDialog from './CardMoveDialog.vue'
const boardApi = new BoardApi()
export default {
name: 'App',
components: {
CardMoveDialog,
AppNavigation,
NcModal,
NcContent,
NcAppContent,
KeyboardShortcuts,
},
mixins: [isMobile],
provide() {
return {
boardApi,
}
},
data() {
return {
addButton: {
icon: 'icon-add',
classes: [],
text: t('deck', 'Add board'),
edit: {
text: t('deck', 'Add board'),
action: () => {
},
reset: () => {
},
},
action: () => {
this.addButton.classes.push('editing')
},
},
}
},
computed: {
...mapState({
navShown: state => state.navShown,
sidebarShownState: state => state.sidebarShown,
currentBoard: state => state.currentBoard,
}),
// TODO: properly handle sidebar showing for route subview and board sidebar
sidebarRouterView() {
// console.log(this.$route)
return this.$route.name === 'card' || this.$route.name === 'board.details'
},
sidebarShown() {
return this.sidebarRouterView || this.sidebarShownState
},
cardDetailsInModal: {
get() {
return this.$store.getters.config('cardDetailsInModal')
},
set(newValue) {
this.$store.dispatch('setConfig', { cardDetailsInModal: newValue })
},
},
},
created() {
const initialState = loadState('deck', 'initialBoards', null)
if (initialState !== null) {
this.$store.dispatch('loadBoards')
}
this.$store.dispatch('loadSharees')
},
mounted() {
// Set navigation to initial state and update in case it gets toggled
emit('toggle-navigation', { open: !this.isMobile && this.navShown, _initial: true })
this.$nextTick(() => {
subscribe('navigation-toggled', (navState) => {
this.$store.dispatch('toggleNav', navState.open)
})
})
},
methods: {
hideModal() {
this.$router.push({ name: 'board' })
},
},
}
</script>
<style lang="scss" scoped>
#content-vue {
#app-content {
transition: margin-left 100ms ease;
position: relative;
overflow-x: hidden;
align-items: stretch;
}
#app-sidebar {
transition: max-width 100ms ease;
}
&.nav-hidden {
#app-content {
margin-left: 0;
}
}
&.sidebar-hidden {
#app-sidebar {
max-width: 0;
min-width: 0;
}
}
}
</style>
<style lang="scss">
@import '../css/print';
.icon-activity {
background-image: url(../img/activity-dark.svg);
body[data-theme-dark] & {
background-image: url(../img/activity.svg);
}
}
.avatardiv.circles {
background: var(--color-primary-element);
}
.icon-circles {
background-image: url(../img/circles-dark.svg);
opacity: 1;
background-size: 20px;
background-position: center center;
}
.icon-circles-white, .icon-circles.icon-white {
background-image: url(../img/circles.svg);
opacity: 1;
background-size: 20px;
background-position: center center;
}
.icon-colorpicker {
background-image: url('../img/color_picker.svg');
}
.v-select {
width: 100%;
}
.modal__card {
width: 100%;
min-width: 100%;
height: calc(100% - 20px);
overflow: hidden;
}
</style>

View File

@@ -22,10 +22,10 @@
label="title" />
</div>
<template #actions>
<NcButton :disabled="!isBoardAndStackChoosen" type="secondary" @click="moveCard">
<NcButton :disabled="!isBoardAndStackChoosen" variant="secondary" @click="moveCard">
{{ t('deck', 'Move card') }}
</NcButton>
<NcButton :disabled="!isBoardAndStackChoosen" type="primary" @click="cloneCard">
<NcButton :disabled="!isBoardAndStackChoosen" variant="primary" @click="cloneCard">
{{ t('deck', 'Copy card') }}
</NcButton>
</template>
@@ -72,7 +72,7 @@ export default {
mounted() {
subscribe('deck:card:show-move-dialog', this.openModal)
},
destroyed() {
unmounted() {
unsubscribe('deck:card:show-move-dialog', this.openModal)
},
methods: {

View File

@@ -10,9 +10,15 @@
:key="activity.activity_id"
:activity="activity" />
<InfiniteLoading :identifier="objectId" @infinite="infiniteHandler" @change="changeObject">
<div slot="spinner" class="icon-loading" />
<div slot="no-more" />
<div slot="no-results" />
<template #spinner>
<div class="icon-loading" />
</template>
<template #no-more>
<div />
</template>
<template #no-results>
<div />
</template>
</InfiniteLoading>
</div>
</template>
@@ -21,7 +27,7 @@
import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router'
import ActivityEntry from './ActivityEntry.vue'
import InfiniteLoading from 'vue-infinite-loading'
// import InfiniteLoading from 'v3-infinite-loading'
const ACTIVITY_FETCH_LIMIT = 50
@@ -29,7 +35,6 @@ export default {
name: 'ActivityList',
components: {
ActivityEntry,
InfiniteLoading,
},
props: {
filter: {
@@ -87,7 +92,7 @@ export default {
// to tell the backend to fetch all activites related to cards of a given board
activities = activities.filter((activity) => {
return (activity.object_type === 'deck_board' && activity.object_id === this.objectId)
|| (activity.object_type === 'deck_card' && activity.subject_rich[1].board.id === this.objectId)
|| (activity.object_type === 'deck_card' && activity.subject_rich[1].board.id === this.objectId.toString())
})
}
this.activities.push(...activities)

View File

@@ -84,7 +84,7 @@
:title="t('deck', 'Apply filter')"
:aria-label="t('deck', 'Apply filter')"
class="filter-button"
:type="isFilterActive ? 'primary' : 'tertiary'">
:variant="isFilterActive ? 'primary' : 'tertiary'">
<template #icon>
<FilterIcon v-if="isFilterActive" :size="20" decorative />
<FilterOffIcon v-else :size="20" decorative />
@@ -231,12 +231,16 @@
</NcActionButton>
<NcActionButton v-if="compactMode"
@click="toggleCompactMode">
<ArrowExpandVerticalIcon slot="icon" :size="20" decorative />
<template #icon>
<ArrowExpandVerticalIcon :size="20" decorative />
</template>
{{ t('deck', 'Toggle compact mode') }}
</NcActionButton>
<NcActionButton v-else
@click="toggleCompactMode">
<ArrowCollapseVerticalIcon slot="icon" :size="20" decorative />
<template #icon>
<ArrowCollapseVerticalIcon :size="20" decorative />
</template>
{{ t('deck', 'Toggle compact mode') }}
</NcActionButton>
<NcActionButton @click="toggleShowCardCover">
@@ -274,6 +278,7 @@ import SessionList from './SessionList.vue'
import { isNotifyPushEnabled } from '../sessions.js'
import CreateNewCardCustomPicker from '../views/CreateNewCardCustomPicker.vue'
import { getCurrentUser } from '@nextcloud/auth'
import { onClickOutside } from '@vueuse/core'
export default {
name: 'Controls',
@@ -359,6 +364,11 @@ export default {
}
},
},
created() {
onClickOutside(() => {
this.hideAddStack()
})
},
beforeMount() {
subscribe('deck:board:show-new-card', this.clickShowAddCardModel)
subscribe('deck:board:toggle-filter-popover', this.triggerOpenFilters)
@@ -366,7 +376,7 @@ export default {
subscribe('deck:board:toggle-filter-by-me', this.triggerFilterByMe)
},
beforeDestroy() {
beforeUnmount() {
unsubscribe('deck:board:show-new-card', this.clickShowAddCardModel)
unsubscribe('deck:board:toggle-filter-popover', this.triggerOpenFilters)
unsubscribe('deck:board:clear-filter', this.triggerClearFilter)
@@ -508,20 +518,6 @@ export default {
#stack-add form {
display: flex;
#new-stack-input-main {
margin-right: 8px;
}
.icon-confirm {
border: 2px solid var(--color-border-maxcontrast) !important;
border-left: none !important;
}
&:focus-within, &:focus, &:focus-visible,
&:hover {
.icon-confirm {
border-color: var(--color-main-text) !important;
}
}
}
}

View File

@@ -6,7 +6,6 @@
<!-- :style="{top:cardTop, left:cardLeft}" -->
<div v-if="card && selector"
ref="shortcutModal"
v-click-outside="close"
class="keyboard-shortcuts__modal"
tabindex="0"
@keydown.esc="close">
@@ -18,6 +17,7 @@
</template>
<script>
import DueDateSelector from './card/DueDateSelector.vue'
import { onClickOutside } from '@vueuse/core'
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
import { mapState } from 'vuex'
import TagSelector from './card/TagSelector.vue'
@@ -50,8 +50,9 @@ export default {
subscribe('deck:card:show-assignment-selector', this.handleShowAssignemnt)
subscribe('deck:card:show-due-date-selector', this.handleShowDueDate)
subscribe('deck:card:show-label-selector', this.handleShowLabel)
onClickOutside(this.close)
},
destroyed() {
unmounted() {
document.removeEventListener('keydown', this.onKeydown)
unsubscribe('deck:card:show-assignment-selector', this.handleShowAssignemnt)
unsubscribe('deck:card:show-due-date-selector', this.handleShowDueDate)

View File

@@ -29,12 +29,12 @@
{{ t('deck', 'Create a new list to add cards to this board') }}
<form @submit.prevent="addNewStack()">
<NcTextField ref="newStackInput"
v-model="newStackTitle"
:disable="loading"
:value.sync="newStackTitle"
:placeholder="t('deck', 'List name')"
type="text" />
<NcButton type="secondary"
native-type="submit"
<NcButton variant="secondary"
type="submit"
:disabled="loading"
:title="t('deck', 'Add list')">
<template #icon>
@@ -63,7 +63,10 @@
data-click-closes-sidebar="true"
data-dragscroll-enabled
class="stack-draggable-wrapper">
<Stack :stack="stack" :dragging="draggingStack" data-click-closes-sidebar="true" />
<Stack :stack="stack"
:dragging="draggingStack"
data-click-closes-sidebar="true"
@open-card="openCard" />
</Draggable>
</Container>
</div>
@@ -82,7 +85,7 @@
</template>
<script>
import { Container, Draggable } from 'vue-smooth-dnd'
import { Container, Draggable } from 'vue3-smooth-dnd'
import { mapState, mapGetters } from 'vuex'
import Controls from '../Controls.vue'
import DeckIcon from '../icons/DeckIcon.vue'
@@ -165,14 +168,14 @@ export default {
created() {
this.session = createSession(this.id)
this.fetchData()
this.$root.$on('open-card', (cardId) => {
this.localModal = cardId
})
},
beforeDestroy() {
beforeUnmount() {
this.session.close()
},
methods: {
openCard(cardId) {
},
async fetchData() {
this.loading = true
try {
@@ -253,8 +256,8 @@ export default {
</script>
<style lang="scss" scoped>
@import '../../css/animations';
@import '../../css/variables';
@use '../../css/animations';
@use '../../css/variables';
form {
text-align: center;
@@ -282,7 +285,7 @@ export default {
}
.board {
padding-left: $board-spacing;
padding-left: variables.$board-spacing;
position: relative;
max-height: calc(100% - var(--default-clickable-area));
overflow: hidden;
@@ -313,8 +316,8 @@ export default {
display: flex;
flex-direction: column;
// Margin left instead of padidng to avoid jumps on dropping a card
margin-left: $stack-spacing;
padding-right: $stack-spacing;
margin-left: variables.$stack-spacing;
padding-right: variables.$stack-spacing;
overflow-x: hidden;
overflow-y: auto;
padding-top: 15px;

View File

@@ -94,7 +94,7 @@
non-drag-area-selector=".dragDisabled"
:drag-handle-selector="dragHandleSelector"
data-dragscroll-enabled
@should-accept-drop="canEdit"
:should-accept-drop="() => canEdit"
@drag-start="draggingCard = true"
@drag-end="draggingCard = false"
@drop="($event) => onDropCard(stack.id, $event)">
@@ -102,7 +102,10 @@
<transition :appear="animate && !card.animated && (card.animated=true)"
:appear-class="'zoom-appear-class'"
:appear-active-class="'zoom-appear-active-class'">
<CardItem :id="card.id" ref="card" :dragging="draggingCard" />
<CardItem :id="card.id"
ref="card"
:dragging="draggingCard"
@open-card="openCard" />
</transition>
</Draggable>
</Container>
@@ -136,7 +139,7 @@
<script>
import ClickOutside from 'vue-click-outside'
import { mapGetters, mapState } from 'vuex'
import { Container, Draggable } from 'vue-smooth-dnd'
import { Container, Draggable } from 'vue3-smooth-dnd'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import CardPlusOutline from 'vue-material-design-icons/CardPlusOutline.vue'
import { NcActions, NcActionButton, NcModal } from '@nextcloud/vue'
@@ -171,6 +174,9 @@ export default {
default: undefined,
},
},
emits: [
'open-card',
],
data() {
return {
editing: false,
@@ -233,6 +239,9 @@ export default {
},
methods: {
openCard(cardId) {
this.$emit('open-card', cardId)
},
stopCardCreation(e) {
// For some reason the submit event triggers a MouseEvent that is bubbling to the outside
// so we have to ignore it
@@ -362,10 +371,10 @@ export default {
@use 'sass:math';
@import './../../css/variables';
@use './../../css/variables';
.stack {
width: $stack-width + $stack-spacing * 3;
width: variables.$stack-width + variables.$stack-spacing * 3;
}
.stack__header {
@@ -373,8 +382,8 @@ export default {
position: sticky;
top: 0;
z-index: 100;
padding-left: $card-spacing;
padding-right: $card-spacing;
padding-left: variables.$card-spacing;
padding-right: variables.$card-spacing;
margin: 6px;
margin-top: 0;
cursor: grab;
@@ -418,7 +427,7 @@ export default {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: calc($stack-width - 60px);
max-width: calc(variables.$stack-width - 60px);
border-radius: 3px;
padding: 4px 4px;
font-size: var(--default-font-size);
@@ -459,8 +468,8 @@ export default {
form {
display: flex;
margin-left: $stack-spacing;
margin-right: $stack-spacing;
margin-left: variables.$stack-spacing;
margin-right: variables.$stack-spacing;
width: 100%;
border: 2px solid var(--color-border-maxcontrast);
border-radius: var(--border-radius-large);

View File

@@ -3,15 +3,16 @@
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<!-- eslint-disable vue/no-v-model-argument -->
<template>
<NcAppSidebar v-if="currentBoard && currentCard"
ref="cardSidebar"
v-model:name-editable="isEditingTitle"
:active="tabId"
:name="displayTitle"
:subname="subtitle"
:subtitle="subtitleTooltip"
:name-editable.sync="isEditingTitle"
@update:name="(value) => titleEditing = value"
@update:name="value => titleEditing = value"
@dismiss-editing="titleEditing = currentCard.title"
@submit-name="handleSubmitTitle"
@opened="focusHeader"
@@ -24,35 +25,69 @@
{{ t('deck', 'Open in bigger view') }}
</NcActionButton>
<CardMenuEntries :card="currentCard" :hide-details-entry="true" />
<NcActionButton v-if="canEdit && !isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="assignCardToMe()">
{{ t('deck', 'Assign to me') }}
</NcActionButton>
<NcActionButton v-if="canEdit && isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="unassignCardFromMe()">
{{ t('deck', 'Unassign myself') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-checkmark"
:close-after-click="true"
@click="changeCardDoneStatus()">
{{ currentCard.done ? t('deck', 'Mark as not done') : t('deck', 'Mark as done') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-external"
:close-after-click="true"
@click="openCardMoveDialog">
{{ t('deck', 'Move/copy card') }}
</NcActionButton>
<NcActionButton v-for="action in cardActions"
:key="action.label"
:close-after-click="true"
:icon="action.icon"
@click="action.callback(cardRichObject)">
{{ action.label }}
</NcActionButton>
<NcActionButton v-if="canEditBoard" :close-after-click="true" @click="archiveUnarchiveCard()">
<template #icon>
<ArchiveIcon :size="20" decorative />
</template>
{{ currentCard.archived ? t('deck', 'Unarchive card') : t('deck', 'Archive card') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-delete"
:close-after-click="true"
@click="deleteCard()">
{{ t('deck', 'Delete card') }}
</NcActionButton>
</template>
<template #description>
<NcReferenceList v-if="currentCard.referenceData"
:text="currentCard.title"
:interactive="false" />
<NcReferenceList v-if="currentCard.referenceData" :text="currentCard.title" :interactive="false" />
</template>
<NcAppSidebarTab id="details"
:order="0"
:name="t('deck', 'Details')">
<NcAppSidebarTab id="details" :order="0" :name="t('deck', 'Details')">
<CardSidebarTabDetails :card="currentCard" />
<template #icon>
<HomeIcon :size="20" />
</template>
</NcAppSidebarTab>
<NcAppSidebarTab id="attachments"
:order="1"
:name="t('deck', 'Attachments')">
<NcAppSidebarTab id="attachments" :order="1" :name="t('deck', 'Attachments')">
<template #icon>
<AttachmentIcon :size="20" />
</template>
<CardSidebarTabAttachments :card="currentCard" />
</NcAppSidebarTab>
<NcAppSidebarTab id="comments"
:order="2"
:name="t('deck', 'Comments')">
<NcAppSidebarTab id="comments" :order="2" :name="t('deck', 'Comments')">
<template #icon>
<CommentIcon :size="20" />
</template>
@@ -73,7 +108,7 @@
<script>
import { NcActionButton, NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue'
import { NcReferenceList } from '@nextcloud/vue/dist/Components/NcRichText.js'
import { NcReferenceList } from '@nextcloud/vue/components/NcRichText'
import { getCapabilities } from '@nextcloud/capabilities'
import { mapState, mapGetters } from 'vuex'
import CardSidebarTabDetails from './CardSidebarTabDetails.vue'
@@ -87,9 +122,15 @@ import HomeIcon from 'vue-material-design-icons/Home.vue'
import CommentIcon from 'vue-material-design-icons/Comment.vue'
import ActivityIcon from 'vue-material-design-icons/LightningBolt.vue'
import { showError, showWarning } from '@nextcloud/dialogs'
import { showError, showWarning, showUndo } from '@nextcloud/dialogs'
import { getLocale } from '@nextcloud/l10n'
import CardMenuEntries from '../cards/CardMenuEntries.vue'
import { emit } from '@nextcloud/event-bus'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import { getCurrentUser } from '@nextcloud/auth'
import { generateUrl } from '@nextcloud/router'
import '@nextcloud/dialogs/style.css'
const capabilities = getCapabilities()
@@ -108,7 +149,7 @@ export default {
AttachmentIcon,
CommentIcon,
HomeIcon,
CardMenuEntries,
ArchiveIcon,
},
mixins: [relativeDate],
props: {
@@ -140,8 +181,17 @@ export default {
isFullApp: (state) => state.isFullApp,
currentBoard: (state) => state.currentBoard,
hasCardSaveError: (state) => state.hasCardSaveError,
showArchived: (state) => state.showArchived,
}),
...mapGetters(['canEdit', 'assignables', 'cardActions', 'stackById']),
...mapGetters([
'canEdit',
'assignables',
'cardActions',
'stackById',
'isArchived',
'boards',
'boardById',
]),
currentCard() {
return this.$store.getters.cardById(this.id)
},
@@ -168,6 +218,31 @@ export default {
return reference ? reference.openGraphObject.name : this.currentCard.title
},
},
canEdit() {
return !this.currentCard.archived
},
canEditBoard() {
if (this.currentBoard) {
return this.$store.getters.canEdit
}
const board = this.$store.getters.boards.find((item) => item.id === this.currentCard.boardId)
return !!board?.permissions?.PERMISSION_EDIT
},
isCurrentUserAssigned() {
return this.currentCard.assignedUsers.find((item) => item.type === 0 && item.participant.uid === getCurrentUser()?.uid)
},
boardId() {
return this.card?.boardId ? this.currentCard.boardId : Number(this.$route.params.id)
},
cardRichObject() {
return {
id: '' + this.currentCard.id,
name: this.currentCard.title,
boardname: this.boardById(this.boardId)?.title,
stackname: this.stackById(this.currentCard.stackId)?.title,
link: window.location.protocol + '//' + window.location.host + generateUrl('/apps/deck/') + `card/${this.currentCard.id}`,
}
},
},
watch: {
currentCard() {
@@ -216,12 +291,46 @@ export default {
formatDate(timestamp) {
return moment.unix(timestamp).locale(this.locale).format('LLLL')
},
deleteCard() {
this.$store.dispatch('deleteCard', this.currentCard)
const undoCard = { ...this.currentCard, deletedAt: 0 }
showUndo(t('deck', 'Card deleted'), () => this.$store.dispatch('cardUndoDelete', undoCard))
if (this.$router.currentRoute.name === 'card') {
this.$router.push({ name: 'board' })
}
},
changeCardDoneStatus() {
this.$store.dispatch('changeCardDoneStatus', { ...this.currentCard, done: !this.currentCard.done })
},
archiveUnarchiveCard() {
this.$store.dispatch('archiveUnarchiveCard', { ...this.currentCard, archived: !this.currentCard.archived })
},
assignCardToMe() {
this.$store.dispatch('assignCardToUser', {
card: this.currentCard,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
unassignCardFromMe() {
this.$store.dispatch('removeUserFromCard', {
card: this.currentCard,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
openCardMoveDialog() {
emit('deck:card:show-move-dialog', this.currentCard)
},
},
}
</script>
<style lang="scss">
section.app-sidebar__tab--active {
min-height: auto;
display: flex;
@@ -273,6 +382,7 @@ section.app-sidebar__tab--active {
z-index: 100;
background-color: var(--color-main-background);
}
.app-sidebar-tabs__nav {
position: sticky;
top: 87px;
@@ -285,10 +395,10 @@ section.app-sidebar__tab--active {
overflow: initial;
}
#emptycontent, .emptycontent {
#emptycontent,
.emptycontent {
margin-top: 88px;
}
}
}
</style>

View File

@@ -23,11 +23,11 @@
:key="comment.id"
:comment="comment"
@doReload="loadComments" />
<InfiniteLoading :identifier="card.id" @infinite="infiniteHandler">
<!-- <InfiniteLoading :identifier="card.id" @infinite="infiniteHandler">
<div slot="spinner" class="icon-loading" />
<div slot="no-more" />
<div slot="no-results" />
</InfiniteLoading>
</InfiniteLoading> -->
</ul>
<div v-else-if="isLoading" class="icon icon-loading" />
<div v-else class="emptycontent">
@@ -42,7 +42,7 @@ import { mapState, mapGetters } from 'vuex'
import { NcAvatar } from '@nextcloud/vue'
import CommentItem from './CommentItem.vue'
import CommentForm from './CommentForm.vue'
import InfiniteLoading from 'vue-infinite-loading'
// import InfiniteLoading from 'v3-infinite-loading'
import { getCurrentUser } from '@nextcloud/auth'
export default {
@@ -51,7 +51,7 @@ export default {
NcAvatar,
CommentItem,
CommentForm,
InfiniteLoading,
// InfiniteLoading,
},
props: {
card: {

View File

@@ -2,8 +2,13 @@
- SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<div>
THIS HAS AT
</div>
</template>
<!-- <template>
<div class="comment-form">
<form @submit.prevent="submit">
<At ref="at"
@@ -191,4 +196,4 @@ export default {
.atwho-li--avatar {
margin-right: 10px;
}
</style>
</style> -->

View File

@@ -175,7 +175,7 @@ export default {
mounted() {
this.setupEditor()
},
async beforeDestroy() {
async beforeUnmount() {
await this.destroyEditor()
},
methods: {

View File

@@ -4,8 +4,12 @@
-->
<template>
<CardDetailEntry :label="t('deck', 'Assign a due date to this card…')" data-test="due-date-selector">
<Calendar v-if="!card.done" slot="icon" :size="20" />
<CalendarCheck v-else slot="icon" :size="20" />
<template v-if="!card.done" #icon>
<Calendar :size="20" />
</template>
<template v-else #icon>
<CalendarCheck :size="20" />
</template>
<template v-if="!card.done && !card.archived">
<NcDateTimePickerNative v-if="duedate"
id="card-duedate-picker"
@@ -15,7 +19,7 @@
type="datetime-local" />
<NcActions v-if="canEdit"
:menu-title="!duedate ? t('deck', 'Add due date') : null"
type="tertiary"
variant="tertiary"
data-cy-due-date-actions>
<template v-if="!duedate" #icon>
<Plus :size="20" />
@@ -48,7 +52,7 @@
</NcActions>
<NcButton v-if="!card.done"
type="secondary"
variant="secondary"
class="completed-button"
@click="changeCardDoneStatus()">
<template #icon>
@@ -69,14 +73,14 @@
</div>
<div class="due-actions">
<NcButton v-if="!card.archived"
type="tertiary"
variant="tertiary"
:name="t('deck', 'Not done')"
@click="changeCardDoneStatus()">
<template #icon>
<ClearIcon :size="20" />
</template>
</NcButton>
<NcButton type="secondary" @click="archiveUnarchiveCard()">
<NcButton variant="secondary" @click="archiveUnarchiveCard()">
<template #icon>
<ArchiveIcon :size="20" />
</template>

View File

@@ -7,7 +7,7 @@
<div class="selector-wrapper--icon">
<TagMultiple :size="20" />
</div>
<NcSelect :value="assignedLabels"
<NcSelect v-model="assignedLabels"
class="selector-wrapper--selector"
:multiple="true"
:disabled="disabled"

View File

@@ -72,7 +72,7 @@ export default {
</script>
<style lang="scss" scoped>
@import '../../css/variables';
@use '../../css/variables';
.card-cover {
height: 90px;

View File

@@ -88,6 +88,7 @@ import CardMenu from './CardMenu.vue'
import CardCover from './CardCover.vue'
import DueDate from './badges/DueDate.vue'
import { getCurrentUser } from '@nextcloud/auth'
import { emit } from '@nextcloud/event-bus'
const TITLE_EDITING_STATE = {
OFF: 0,
@@ -120,6 +121,7 @@ export default {
default: false,
},
},
emits: ['open-card'],
data() {
return {
highlight: false,
@@ -226,8 +228,9 @@ export default {
this.$router.push({ name: 'card', params: { id: boardId, cardId: this.card.id } }).catch(() => {})
return
}
this.$root.$emit('open-card', this.card.id)
emit('open-card', {
cardId: this.card.id,
})
},
triggerEditTitle() {
this.editingTitle = TITLE_EDITING_STATE.PENDING
@@ -318,8 +321,8 @@ export default {
</script>
<style lang="scss" scoped>
@import './../../css/animations';
@import './../../css/variables';
@use './../../css/animations';
@use './../../css/variables';
@mixin dark-card {
border: 2px solid var(--color-border-dark);
@@ -331,8 +334,8 @@ export default {
border-radius: var(--border-radius-large);
font-size: 100%;
background-color: var(--color-main-background);
margin-bottom: $card-spacing;
padding: var(--default-grid-baseline) $card-padding;
margin-bottom: variables.$card-spacing;
padding: var(--default-grid-baseline) variables.$card-padding;
border: 2px solid var(--color-border-dark);
width: 100%;
display: flex;
@@ -470,7 +473,7 @@ export default {
width: 32px;
}
&.has-labels {
padding-bottom: $card-padding;
padding-bottom: variables.$card-padding;
}
.labels {
height: 6px;

View File

@@ -6,40 +6,190 @@
<template>
<div v-if="card" class="card-menu" @click.stop.prevent>
<NcButton v-if="card.referenceData"
type="tertiary"
:title="t('deck','Open link')"
variant="tertiary"
:title="t('deck', 'Open link')"
@click="openLink">
<template #icon>
<LinkIcon :size="20" />
</template>
</NcButton>
<NcActions>
<CardMenuEntries :card="card" @edit-title="editTitle" />
<NcActionButton v-if="!hideDetailsEntry" :close-after-click="true" @click="openCard">
<template #icon>
<CardBulletedIcon icon :size="20" decorative />
</template>
{{ t('deck', 'Card details') }}
</NcActionButton>
<NcActionButton v-if="canEdit" :close-after-click="true" @click="editTitle">
<template #icon>
<PencilIcon :size="20" decorative />
</template>
{{ t('deck', 'Edit title') }}
</NcActionButton>
<NcActionButton v-if="canEdit && !isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="assignCardToMe()">
{{ t('deck', 'Assign to me') }}
</NcActionButton>
<NcActionButton v-if="canEdit && isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="unassignCardFromMe()">
{{ t('deck', 'Unassign myself') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-checkmark"
:close-after-click="true"
@click="changeCardDoneStatus()">
{{ card.done ? t('deck', 'Mark as not done') : t('deck', 'Mark as done') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-external"
:close-after-click="true"
@click="openCardMoveDialog">
{{ t('deck', 'Move/copy card') }}
</NcActionButton>
<NcActionButton v-for="action in cardActions"
:key="action.label"
:close-after-click="true"
:icon="action.icon"
@click="action.callback(cardRichObject)">
{{ action.label }}
</NcActionButton>
<NcActionButton v-if="canEditBoard" :close-after-click="true" @click="archiveUnarchiveCard()">
<template #icon>
<ArchiveIcon :size="20" decorative />
</template>
{{ card.archived ? t('deck', 'Unarchive card') : t('deck', 'Archive card') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-delete"
:close-after-click="true"
@click="deleteCard()">
{{ t('deck', 'Delete card') }}
</NcActionButton>
</NcActions>
</div>
</template>
<script>
import { NcActions, NcButton } from '@nextcloud/vue'
import { NcActions, NcButton, NcActionButton } from '@nextcloud/vue'
import LinkIcon from 'vue-material-design-icons/Link.vue'
import CardMenuEntries from './CardMenuEntries.vue'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import { getCurrentUser } from '@nextcloud/auth'
import CardBulletedIcon from 'vue-material-design-icons/CardBulleted.vue'
import PencilIcon from 'vue-material-design-icons/Pencil.vue'
import { mapGetters, mapState } from 'vuex'
import { showUndo } from '@nextcloud/dialogs'
import { generateUrl } from '@nextcloud/router'
import '@nextcloud/dialogs/style.css'
import { emit } from '@nextcloud/event-bus'
export default {
name: 'CardMenu',
components: { NcActions, NcButton, LinkIcon, CardMenuEntries },
components: { NcActions, NcButton, LinkIcon, NcActionButton, PencilIcon, CardBulletedIcon, ArchiveIcon },
props: {
card: {
type: Object,
default: null,
},
hideDetailsEntry: {
type: Boolean,
default: false,
},
},
emits: ['edit-title'],
computed: {
...mapGetters([
'isArchived',
'boards',
'cardActions',
'stackById',
'boardById',
]),
...mapState({
showArchived: state => state.showArchived,
currentBoard: state => state.currentBoard,
}),
canEdit() {
return !this.card.archived
},
canEditBoard() {
if (this.currentBoard) {
return this.$store.getters.canEdit
}
const board = this.$store.getters.boards.find((item) => item.id === this.card.boardId)
return !!board?.permissions?.PERMISSION_EDIT
},
isCurrentUserAssigned() {
return this.card.assignedUsers.find((item) => item.type === 0 && item.participant.uid === getCurrentUser()?.uid)
},
boardId() {
return this.card?.boardId ? this.card.boardId : Number(this.$route.params.id)
},
cardRichObject() {
return {
id: '' + this.card.id,
name: this.card.title,
boardname: this.boardById(this.boardId)?.title,
stackname: this.stackById(this.card.stackId)?.title,
link: window.location.protocol + '//' + window.location.host + generateUrl('/apps/deck/') + `card/${this.card.id}`,
}
},
},
methods: {
openLink() {
window.open(this.card?.referenceData?.openGraphObject?.link)
return false
},
editTitle(id) {
this.$emit('edit-title', id)
openCard() {
const boardId = this.card?.boardId ? this.card.boardId : this.$route?.params.id ?? this.currentBoard.id
if (this.$router) {
this.$router?.push({ name: 'card', params: { id: boardId, cardId: this.card.id } }).catch(() => { })
return
}
this.$root.$emit('open-card', this.card.id)
},
editTitle() {
this.$emit('edit-title', this.card.id)
},
deleteCard() {
this.$store.dispatch('deleteCard', this.card)
const undoCard = { ...this.card, deletedAt: 0 }
showUndo(t('deck', 'Card deleted'), () => this.$store.dispatch('cardUndoDelete', undoCard))
if (this.$router.currentRoute.name === 'card') {
this.$router.push({ name: 'board' })
}
},
changeCardDoneStatus() {
this.$store.dispatch('changeCardDoneStatus', { ...this.card, done: !this.card.done })
},
archiveUnarchiveCard() {
this.$store.dispatch('archiveUnarchiveCard', { ...this.card, archived: !this.card.archived })
},
assignCardToMe() {
this.$store.dispatch('assignCardToUser', {
card: this.card,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
unassignCardFromMe() {
this.$store.dispatch('removeUserFromCard', {
card: this.card,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
openCardMoveDialog() {
emit('deck:card:show-move-dialog', this.card)
},
},
}

View File

@@ -1,187 +0,0 @@
<!--
- SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<div>
<NcActionButton v-if="!hideDetailsEntry" :close-after-click="true" @click="openCard">
<CardBulletedIcon slot="icon" :size="20" decorative />
{{ t('deck', 'Card details') }}
</NcActionButton>
<NcActionButton v-if="canEdit" :close-after-click="true" @click="editTitle">
<template #icon>
<PencilIcon :size="20" decorative />
</template>
{{ t('deck', 'Edit title') }}
</NcActionButton>
<NcActionButton v-if="canEdit && !isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="assignCardToMe()">
{{ t('deck', 'Assign to me') }}
</NcActionButton>
<NcActionButton v-if="canEdit && isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="unassignCardFromMe()">
{{ t('deck', 'Unassign myself') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-checkmark"
:close-after-click="true"
@click="changeCardDoneStatus()">
{{ card.done ? t('deck', 'Mark as not done') : t('deck', 'Mark as done') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-external"
:close-after-click="true"
@click="openCardMoveDialog">
{{ t('deck', 'Move/copy card') }}
</NcActionButton>
<NcActionButton v-for="action in cardActions"
:key="action.label"
:close-after-click="true"
:icon="action.icon"
@click="action.callback(cardRichObject)">
{{ action.label }}
</NcActionButton>
<NcActionButton v-if="canEditBoard" :close-after-click="true" @click="archiveUnarchiveCard()">
<template #icon>
<ArchiveIcon :size="20" decorative />
</template>
{{ card.archived ? t('deck', 'Unarchive card') : t('deck', 'Archive card') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-delete"
:close-after-click="true"
@click="deleteCard()">
{{ t('deck', 'Delete card') }}
</NcActionButton>
</div>
</template>
<script>
import { NcActionButton } from '@nextcloud/vue'
import { mapGetters, mapState } from 'vuex'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import CardBulletedIcon from 'vue-material-design-icons/CardBulleted.vue'
import PencilIcon from 'vue-material-design-icons/Pencil.vue'
import { generateUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { showUndo } from '@nextcloud/dialogs'
import '@nextcloud/dialogs/style.css'
import { emit } from '@nextcloud/event-bus'
export default {
name: 'CardMenuEntries',
components: { NcActionButton, ArchiveIcon, CardBulletedIcon, PencilIcon },
props: {
card: {
type: Object,
default: null,
},
hideDetailsEntry: {
type: Boolean,
default: false,
},
},
emits: ['edit-title'],
data() {
return {
modalShow: false,
selectedBoard: '',
selectedStack: '',
stacksFromBoard: [],
}
},
computed: {
...mapGetters([
'isArchived',
'boards',
'cardActions',
'stackById',
'boardById',
]),
...mapState({
showArchived: state => state.showArchived,
currentBoard: state => state.currentBoard,
}),
canEdit() {
return !this.card.archived
},
canEditBoard() {
if (this.currentBoard) {
return this.$store.getters.canEdit
}
const board = this.$store.getters.boards.find((item) => item.id === this.card.boardId)
return !!board?.permissions?.PERMISSION_EDIT
},
isCurrentUserAssigned() {
return this.card.assignedUsers.find((item) => item.type === 0 && item.participant.uid === getCurrentUser()?.uid)
},
boardId() {
return this.card?.boardId ? this.card.boardId : Number(this.$route.params.id)
},
cardRichObject() {
return {
id: '' + this.card.id,
name: this.card.title,
boardname: this.boardById(this.boardId)?.title,
stackname: this.stackById(this.card.stackId)?.title,
link: window.location.protocol + '//' + window.location.host + generateUrl('/apps/deck/') + `card/${this.card.id}`,
}
},
},
methods: {
openCard() {
const boardId = this.card?.boardId ? this.card.boardId : this.$route?.params.id ?? this.currentBoard.id
if (this.$router) {
this.$router?.push({ name: 'card', params: { id: boardId, cardId: this.card.id } }).catch(() => {})
return
}
this.$root.$emit('open-card', this.card.id)
},
editTitle() {
this.$emit('edit-title', this.card.id)
},
deleteCard() {
this.$store.dispatch('deleteCard', this.card)
const undoCard = { ...this.card, deletedAt: 0 }
showUndo(t('deck', 'Card deleted'), () => this.$store.dispatch('cardUndoDelete', undoCard))
if (this.$router.currentRoute.name === 'card') {
this.$router.push({ name: 'board' })
}
},
changeCardDoneStatus() {
this.$store.dispatch('changeCardDoneStatus', { ...this.card, done: !this.card.done })
},
archiveUnarchiveCard() {
this.$store.dispatch('archiveUnarchiveCard', { ...this.card, archived: !this.card.archived })
},
assignCardToMe() {
this.$store.dispatch('assignCardToUser', {
card: this.card,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
unassignCardFromMe() {
this.$store.dispatch('removeUserFromCard', {
card: this.card,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
openCardMoveDialog() {
emit('deck:card:show-move-dialog', this.card)
},
},
}
</script>

View File

@@ -151,16 +151,13 @@
</template>
<script>
import { NcModal, Tooltip } from '@nextcloud/vue'
import { NcModal } from '@nextcloud/vue'
export default {
name: 'HelpModal',
components: {
NcModal,
},
directives: {
Tooltip,
},
}
</script>

View File

@@ -42,6 +42,7 @@
</template>
</AppNavigationBoardCategory>
<AppNavigationAddBoard v-if="canCreate" />
<AppNavigationImportBoard v-if="canCreate" />
</template>
<template #footer>
<NcAppNavigationSettings :name="t('deck', 'Deck settings')">
@@ -116,6 +117,7 @@ import DeckIcon from './../icons/DeckIcon.vue'
import ShareVariantIcon from 'vue-material-design-icons/Share.vue'
import HelpModal from './../modals/HelpModal.vue'
import { subscribe } from '@nextcloud/event-bus'
import AppNavigationImportBoard from './AppNavigationImportBoard.vue'
const canCreateState = loadState('deck', 'canCreate')
@@ -127,6 +129,7 @@ export default {
NcButton,
AppNavigationAddBoard,
AppNavigationBoardCategory,
AppNavigationImportBoard,
NcSelect,
NcAppNavigationItem,
ArchiveIcon,

View File

@@ -13,12 +13,12 @@
</NcColorPicker>
<form @submit.prevent.stop="createBoard">
<NcTextField ref="inputField"
v-model="value"
:disable="loading"
:value.sync="value"
:placeholder="t('deck', 'Board name')"
type="text"
required />
<NcButton type="tertiary"
<NcButton variant="tertiary"
:disabled="loading"
:title="t('deck', 'Cancel edit')"
@click.stop.prevent="cancelEdit">
@@ -26,8 +26,8 @@
<CloseIcon :size="20" />
</template>
</NcButton>
<NcButton type="tertiary"
native-type="submit"
<NcButton variant="tertiary"
type="submit"
:disabled="loading"
:title="t('deck', 'Save board')">
<template #icon>
@@ -77,6 +77,7 @@ export default {
})
},
async createBoard(e) {
alert('createBoard called')
this.loading = true
const title = this.value.trim()
await this.$store.dispatch('createBoard', {
@@ -88,6 +89,7 @@ export default {
this.color = randomColor()
},
cancelEdit(e) {
alert('cancelEdit called')
this.editing = false
this.color = randomColor()
},

View File

@@ -15,13 +15,17 @@
<template #icon>
<NcAppNavigationIconBullet :color="board.color" />
<BoardCloneModal v-if="cloneModalOpen" :board-title="board.title" @close="onCloseCloneModal" />
<BoardExportModal v-if="exportModalOpen"
:board-title="board.title"
@export="onExportBoard"
@close="onCloseExportBoard" />
</template>
<template #counter>
<AccountIcon v-if="board.acl.length > 0" />
</template>
<template v-if="!deleted" slot="actions">
<template v-if="!deleted" #actions>
<template v-if="!isDueSubmenuActive">
<NcActionButton icon="icon-info"
:close-after-click="true"
@@ -125,17 +129,17 @@
:placeholder="t('deck', 'Board name')"
type="text"
required />
<NcButton type="tertiary"
<NcButton variant="tertiary"
:disabled="loading"
native-type="submit"
type="submit"
:title="t('deck', 'Cancel edit')"
@click.stop.prevent="cancelEdit">
<template #icon>
<CloseIcon :size="20" />
</template>
</NcButton>
<NcButton type="tertiary"
native-type="submit"
<NcButton variant="tertiary"
type="submit"
:disabled="loading"
:title="t('deck', 'Save board')">
<template #icon>
@@ -148,7 +152,7 @@
</template>
<script>
import { NcAppNavigationIconBullet, NcAppNavigationItem, NcColorPicker, NcButton, NcTextField, NcActionButton } from '@nextcloud/vue'
import { NcAppNavigationIconBullet, NcAppNavigationItem, NcColorPicker, NcButton, NcTextField, NcActionButton, NcLoadingIcon } from '@nextcloud/vue'
import ClickOutside from 'vue-click-outside'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import CloneIcon from 'vue-material-design-icons/ContentDuplicate.vue'
@@ -161,6 +165,8 @@ import { emit } from '@nextcloud/event-bus'
import isTouchDevice from '../../mixins/isTouchDevice.js'
import BoardCloneModal from './BoardCloneModal.vue'
import BoardExportModal from './BoardExportModal.vue'
import { showLoading } from '@nextcloud/dialogs'
const canCreateState = loadState('deck', 'canCreate')
@@ -179,6 +185,8 @@ export default {
CloseIcon,
CheckIcon,
BoardCloneModal,
BoardExportModal,
NcLoadingIcon,
},
directives: {
ClickOutside,
@@ -207,6 +215,7 @@ export default {
updateDueSetting: null,
canCreate: canCreateState,
cloneModalOpen: false,
exportModalOpen: false,
}
},
computed: {
@@ -346,7 +355,16 @@ export default {
this.updateDueSetting = null
},
actionExport() {
this.boardApi.exportBoard(this.board)
this.exportModalOpen = true
},
async onExportBoard(format) {
this.exportModalOpen = false
const loadingToast = showLoading(t('deck', 'Exporting board...'))
await this.boardApi.exportBoard(this.board, format)
loadingToast.hideToast()
},
onCloseExportBoard() {
this.exportModalOpen = false
},
onNavigate() {
if (this.isTouchDevice) {

View File

@@ -31,10 +31,6 @@ export default {
type: String,
default: '',
},
id: {
type: String,
required: true,
},
text: {
type: String,
required: true,

View File

@@ -0,0 +1,55 @@
<!--
- SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<div>
<NcAppNavigationItem :name="t('deck', 'Import board')" icon="icon-upload" @click.prevent.stop="startImportBoard" />
<input ref="fileInput"
type="file"
accept="application/json"
style="display: none;"
@change="doImportBoard">
</div>
</template>
<script>
import { NcAppNavigationItem } from '@nextcloud/vue'
import { showError } from '../../helpers/errors.js'
import { showSuccess, showLoading } from '@nextcloud/dialogs'
export default {
name: 'AppNavigationImportBoard',
components: { NcAppNavigationItem },
props: {
loading: {
type: Boolean,
default: false,
},
},
data() {
return {
value: '',
}
},
methods: {
startImportBoard() {
this.$refs.fileInput.value = ''
this.$refs.fileInput.click()
},
async doImportBoard(event) {
const file = event.target.files[0]
if (file) {
const loadingToast = showLoading(t('deck', 'Importing board...'))
const result = await this.$store.dispatch('importBoard', file)
loadingToast.hideToast()
if (result?.message) {
showError(result)
} else {
showSuccess(t('deck', 'Board imported successfully'))
}
}
},
},
}
</script>

View File

@@ -5,16 +5,16 @@
<template>
<NcDialog :name="t('deck', 'Clone {boardTitle}', {boardTitle: boardTitle})" :show="true" @close="close(false)">
<div class="modal__content">
<NcCheckboxRadioSwitch :checked.sync="withCards">
<NcCheckboxRadioSwitch v-model="withCards">
{{ t('deck', 'Clone cards') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="withCards" :checked.sync="withAssignments">
<NcCheckboxRadioSwitch v-if="withCards" v-model="withAssignments">
{{ t('deck', 'Clone assignments') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="withCards" :checked.sync="withLabels">
<NcCheckboxRadioSwitch v-if="withCards" v-model="withLabels">
{{ t('deck', 'Clone labels') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="withCards" :checked.sync="withDueDate">
<NcCheckboxRadioSwitch v-if="withCards" v-model="withDueDate">
{{ t('deck', 'Clone due dates') }}
</NcCheckboxRadioSwitch>
<div v-if="withCards" class="accordion" :class="{ 'is-open': accordionOpen }">
@@ -25,10 +25,10 @@
{{ t('deck', 'Advanced options') }}
</div>
<div v-if="accordionOpen" class="accordion__content">
<NcCheckboxRadioSwitch v-if="withCards" :checked.sync="moveCardsToLeftStack">
<NcCheckboxRadioSwitch v-if="withCards" v-model="moveCardsToLeftStack">
{{ t('deck', 'Move all cards to the first list') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="withCards" :checked.sync="restoreArchivedCards">
<NcCheckboxRadioSwitch v-if="withCards" v-model="restoreArchivedCards">
{{ t('deck', 'Restore archived cards') }}
</NcCheckboxRadioSwitch>
</div>
@@ -39,7 +39,7 @@
<NcButton @click="cancel">
{{ t('deck', 'Cancel') }}
</NcButton>
<NcButton type="primary" @click="save">
<NcButton variant="primary" @click="save">
{{ t('deck', 'Clone') }}
</NcButton>
</template>

View File

@@ -0,0 +1,78 @@
<!--
- SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<NcDialog :name="t('deck', 'Export {boardTitle}', {boardTitle: boardTitle})" @update:open="close">
<div class="modal__content">
<NcCheckboxRadioSwitch v-model="exportFormat"
value="json"
type="radio"
name="board_export_format">
{{ t('deck', 'Export as JSON') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-model="exportFormat"
value="csv"
type="radio"
name="board_export_format">
{{ t('deck', 'Export as CSV') }}
</NcCheckboxRadioSwitch>
<p class="note">
{{ t('deck', 'Note: Only the JSON format is supported for importing back into the Deck app.') }}
</p>
</div>
<template #actions>
<NcButton @click="close">
{{ t('deck', 'Cancel') }}
</NcButton>
<NcButton variant="primary" @click="exportBoard">
{{ t('deck', 'Export') }}
</NcButton>
</template>
</NcDialog>
</template>
<script>
import { NcButton, NcCheckboxRadioSwitch, NcDialog } from '@nextcloud/vue'
export default {
name: 'BoardExportModal',
components: {
NcDialog,
NcCheckboxRadioSwitch,
NcButton,
},
props: {
boardTitle: {
type: String,
default: 'Board',
},
},
data() {
return {
exportFormat: 'json',
}
},
methods: {
exportBoard() {
this.$emit('export', this.exportFormat)
this.close()
},
close() {
this.$emit('close')
},
},
}
</script>
<style scoped>
.modal__content {
margin: 20px;
}
p.note {
margin-top: 10px;
}
</style>

View File

@@ -145,7 +145,7 @@ export default {
</script>
<style lang="scss" scoped>
@import './../../css/variables';
@use './../../css/variables';
.overview-wrapper {
position: relative;
@@ -162,16 +162,16 @@ export default {
overflow-x: scroll;
display: flex;
align-items: stretch;
padding-left: $board-spacing;
padding-right: $board-spacing;
padding-left: variables.$board-spacing;
padding-right: variables.$board-spacing;
.dashboard-column {
display: flex;
flex-direction: column;
min-width: $stack-width;
width: $stack-width;
margin-left: $stack-spacing;
margin-right: $stack-spacing;
min-width: variables.$stack-width;
width: variables.$stack-width;
margin-left: variables.$stack-spacing;
margin-right: variables.$stack-spacing;
h3 {
font-size: var(--default-font-size);

View File

@@ -4,7 +4,7 @@
-->
<template>
<div v-if="searchQuery!==''" class="global-search">
<div v-if="searchQuery !== ''" class="global-search">
<h2>
<NcRichText :text="t('deck', 'Search for {searchQuery} in all boards')" :arguments="queryStringArgs" />
<div v-if="loading" class="icon-loading-small" />
@@ -19,13 +19,13 @@
:key="card.id"
:standalone="true" />
<Placeholder v-if="loading" />
<InfiniteLoading :identifier="searchQuery" @infinite="infiniteHandler">
<!-- <InfiniteLoading :identifier="searchQuery" @infinite="infiniteHandler">
<div slot="spinner" />
<div slot="no-more" />
<div slot="no-results">
{{ t('deck', 'No results found') }}
</div>
</InfiniteLoading>
</InfiniteLoading> -->
</div>
<div v-else>
<p>{{ t('deck', 'No results found') }}</p>
@@ -39,7 +39,7 @@ import CardItem from '../cards/CardItem.vue'
import { mapState } from 'vuex'
import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router'
import InfiniteLoading from 'vue-infinite-loading'
// import InfiniteLoading from 'v3-infinite-loading'
import Placeholder from './Placeholder.vue'
import { NcActions, NcActionButton, NcRichText } from '@nextcloud/vue'
@@ -70,7 +70,14 @@ function search({ query, cursor }) {
export default {
name: 'GlobalSearchResults',
components: { CardItem, InfiniteLoading, NcRichText, Placeholder, NcActions, NcActionButton },
components: {
CardItem,
// InfiniteLoading,
NcRichText,
Placeholder,
NcActions,
NcActionButton,
},
data() {
return {
results: [],
@@ -155,11 +162,11 @@ export default {
</script>
<style lang="scss" scoped>
@import '../../css/variables';
@use '../../css/variables';
.global-search {
width: 100%;
padding: $board-spacing + $stack-spacing;
padding: variables.$board-spacing + variables.$stack-spacing;
padding-bottom: 0;
overflow: hidden;
min-height: 35vh;
@@ -175,6 +182,7 @@ export default {
top: 10px;
right: 10px;
}
.search-wrapper {
overflow: scroll;
height: 100%;
@@ -182,13 +190,14 @@ export default {
padding: 10px;
}
h2 > div {
h2>div {
display: inline-block;
&.icon-loading-small {
margin-right: 20px;
}
}
h2:deep(span) {
background-color: var(--color-background-dark);
padding: 3px;
@@ -199,13 +208,14 @@ export default {
display: flex;
flex-wrap: wrap;
& > div {
&>div {
flex-grow: 0;
}
}
&:deep(.card) {
width: $stack-width;
margin-right: $stack-spacing;
width: variables.$stack-width;
margin-right: variables.$stack-spacing;
}
}
</style>

View File

@@ -58,18 +58,18 @@ export default {
</script>
<style lang="scss" scoped>
@import '../../css/variables';
@use '../../css/variables';
$clickable-area: var(--default-clickable-area);
.card--placeholder {
width: $stack-width;
margin-right: $stack-spacing;
padding: $card-padding;
width: variables.$stack-width;
margin-right: variables.$stack-spacing;
padding: variables.$card-padding;
transition: box-shadow 0.1s ease-in-out;
box-shadow: 0 0 2px 0 var(--color-box-shadow);
border-radius: var(--border-radius-large);
font-size: 100%;
margin-bottom: $card-spacing;
margin-bottom: variables.$card-spacing;
height: 100px;
}

View File

@@ -3,38 +3,34 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import Vue from 'vue'
import './../css/collections.css'
import FileSharingPicker from './views/FileSharingPicker.js'
import { buildSelector } from './helpers/selector.js'
import './shared-init.js'
Vue.prototype.t = t
Vue.prototype.n = n
Vue.prototype.OC = OC
export function initCollections() {
window.addEventListener('DOMContentLoaded', () => {
if (OCA.Sharing && OCA.Sharing.ShareSearch) {
OCA.Sharing.ShareSearch.addNewResult(FileSharingPicker)
}
window.addEventListener('DOMContentLoaded', () => {
if (OCA.Sharing && OCA.Sharing.ShareSearch) {
OCA.Sharing.ShareSearch.addNewResult(FileSharingPicker)
}
window.OCP.Collaboration.registerType('deck', {
action: () => {
const BoardSelector = () => import('./BoardSelector.vue')
return buildSelector(BoardSelector)
},
typeString: t('deck', 'Link to a board'),
typeIconClass: 'icon-deck',
})
window.OCP.Collaboration.registerType('deck', {
action: () => {
const BoardSelector = () => import('./BoardSelector.vue')
return buildSelector(BoardSelector)
},
typeString: t('deck', 'Link to a board'),
typeIconClass: 'icon-deck',
window.OCP.Collaboration.registerType('deck-card', {
action: () => {
const CardSelector = () => import('./CardSelector.vue')
return buildSelector(CardSelector)
},
typeString: t('deck', 'Link to a card'),
typeIconClass: 'icon-deck',
})
})
window.OCP.Collaboration.registerType('deck-card', {
action: () => {
const CardSelector = () => import('./CardSelector.vue')
return buildSelector(CardSelector)
},
typeString: t('deck', 'Link to a card'),
typeIconClass: 'icon-deck',
})
})
}

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { registerWidget, registerCustomPickerElement, NcCustomPickerRenderResult } from '@nextcloud/vue/dist/Functions/registerReference.js'
import { registerWidget, registerCustomPickerElement, NcCustomPickerRenderResult } from '@nextcloud/vue'
import { translate, translatePlural } from '@nextcloud/l10n'
import './shared-init.js'

View File

@@ -2,11 +2,10 @@
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import Vue from 'vue'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router.js'
import store from './store/main.js'
import { sync } from 'vuex-router-sync'
import { translate, translatePlural } from '@nextcloud/l10n'
import { showError } from '@nextcloud/dialogs'
import { subscribe } from '@nextcloud/event-bus'
@@ -14,27 +13,33 @@ import ClickOutside from 'vue-click-outside'
import './shared-init.js'
import './models/index.js'
import './sessions.js'
import { initCollections } from './init-collections.js'
// the server snap.js conflicts with vertical scrolling so we disable it
document.body.setAttribute('data-snap-ignore', 'true')
sync(store, router)
const app = createApp(App)
Vue.prototype.t = translate
Vue.prototype.n = translatePlural
app.config.globalProperties.t = translate
app.config.globalProperties.n = translatePlural
app.config.globalProperties.OC = OC
Vue.directive('click-outside', ClickOutside)
initCollections({ t, n, OC })
Vue.directive('focus', {
inserted(el) {
app.directive('click-outside', ClickOutside)
app.directive('focus', {
mounted(el) {
el.focus()
},
})
Vue.config.errorHandler = (err, vm, info) => {
app.config.errorHandler = (err, vm, info) => {
if (err.response && err.response.data.message) {
const errorMessage = t('deck', 'Something went wrong')
showError(`${errorMessage}: ${err.response.data.status} ${err.response.data.message}`)
const errorMessage = translate('deck', 'Something went wrong')
showError(
`${errorMessage}: ${err.response.data.status} ${err.response.data.message}`,
)
}
console.error(err)
}
@@ -47,16 +52,14 @@ window.addEventListener('DOMContentLoaded', () => {
window.OCA.Files = {}
}
// register unused client for the sidebar to have access to its parser methods
Object.assign(window.OCA.Files, { App: { fileList: { filesClient: OC.Files.getClient() } } }, window.OCA.Files)
Object.assign(
window.OCA.Files,
{ App: { fileList: { filesClient: OC.Files.getClient() } } },
window.OCA.Files,
)
})
/* eslint-disable-next-line no-new */
new Vue({
el: '#content',
// eslint-disable-next-line vue/match-component-file-name
name: 'Deck',
router,
store,
app.mixin({
data() {
return {
time: Date.now(),
@@ -75,7 +78,7 @@ new Vue({
this.time = Date.now()
}, 1000)
},
beforeDestroy() {
beforeUnmount() {
clearInterval(this.interval)
},
methods: {
@@ -86,9 +89,12 @@ new Vue({
this.$store.commit('setSearchQuery', '')
},
},
render: h => h(App),
})
app.use(router)
app.use(store)
app.mount('#content')
if (!window.OCA.Deck) {
window.OCA.Deck = {}
}

View File

@@ -26,7 +26,8 @@ export default {
return
}
this.$set(this.uploadQueue, file.name, { name: file.name, progress: 0 })
this.uploadQueue[file.name] = { name: file.name, progress: 0 }
const bodyFormData = new FormData()
bodyFormData.append('cardId', this.cardId)
bodyFormData.append('type', type)
@@ -39,7 +40,7 @@ export default {
onUploadProgress: (e) => {
const percentCompleted = Math.round((e.loaded * 100) / e.total)
console.debug(percentCompleted)
this.$set(this.uploadQueue[file.name], 'progress', percentCompleted)
this.uploadQueue[file.name].progress = percentCompleted
},
})
} catch (err) {
@@ -50,7 +51,7 @@ export default {
showError(err.response.data ? err.response.data.message : 'Failed to upload file')
}
}
this.$delete(this.uploadQueue, file.name)
delete this.uploadQueue[file.name]
})
},

View File

@@ -3,8 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import Vue from 'vue'
import Router from 'vue-router'
import { createRouter, createWebHistory } from 'vue-router'
import { generateUrl, getRootUrl } from '@nextcloud/router'
import { BOARD_FILTERS } from './store/main.js'
import Boards from './components/boards/Boards.vue'
@@ -14,17 +13,14 @@ import BoardSidebar from './components/board/BoardSidebar.vue'
import CardSidebar from './components/card/CardSidebar.vue'
import Overview from './components/overview/Overview.vue'
Vue.use(Router)
// We apply a dynamic base URL depending on the URL used in the browser
const baseUrl = generateUrl('/apps/deck/')
const webRootWithIndexPHP = getRootUrl() + '/index.php'
const doesURLContainIndexPHP = window.location.pathname.startsWith(webRootWithIndexPHP)
const currentBaseUrl = doesURLContainIndexPHP ? baseUrl : baseUrl.replace('/index.php/', '/')
const router = new Router({
mode: 'history',
base: currentBaseUrl,
const router = createRouter({
history: createWebHistory(currentBaseUrl),
linkActiveClass: 'active',
routes: [
{

View File

@@ -139,11 +139,30 @@ export class BoardApi {
}
}
exportBoard(board) {
exportBoard(board, format) {
return axios.get(this.url(`/boards/${board.id}/export`))
.then(
(response) => {
const fields = { title: t('deck', 'Card title'), description: t('deck', 'Description'), stackId: t('deck', 'List name'), labels: t('deck', 'Tags'), duedate: t('deck', 'Due date'), createdAt: t('deck', 'Created'), lastModified: t('deck', 'Modified') }
if (format === 'json') {
const exportData = {
boards: [response.data],
}
const stacks = {}
for (const stack of response.data.stacks) {
stacks[stack.id] = stack
}
exportData.boards[0].stacks = stacks
const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' })
const blobUrl = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = blobUrl
a.download = response.data.title + '.json'
a.click()
a.remove()
return Promise.resolve()
}
const fields = { title: t('deck', 'Card title'), description: t('deck', 'Description'), stackId: t('deck', 'List name'), labels: t('deck', 'Tags'), assignedUsers: t('deck', 'Assigned users'), duedate: t('deck', 'Due date'), createdAt: t('deck', 'Created'), lastModified: t('deck', 'Modified') }
let row = ''
Object.keys(fields).forEach(field => {
row += '"' + fields[field] + '"' + '\t'
@@ -160,16 +179,27 @@ export class BoardApi {
const date = new Date(Number(card[field]) * 1000)
row += '"' + date.toLocaleDateString() + '"' + '\t'
} else if (field === 'stackId') {
row += '"' + stack.title + '"' + '\t'
row += '"' + stack.title.replaceAll('"', '""') + '"' + '\t'
} else if (field === 'labels') {
row += '"'
card[field].forEach(label => {
row += label.title + ', '
row += label.title.replaceAll('"', '""') + ', '
})
if (card[field].length > 0) {
row = row.slice(0, -1)
}
row += '"' + '\t'
} else if (field === 'assignedUsers') {
row += '"'
card[field].forEach(assignedUsers => {
row += assignedUsers.participant.displayname.replaceAll('"', '""') + ', '
})
if (card[field].length > 0) {
row = row.slice(0, -1)
}
row += '"' + '\t'
} else if (field === 'description' || field === 'title') {
row += '"' + card[field].replaceAll('"', '""') + '"' + '\t'
} else {
row += '"' + card[field] + '"' + '\t'
}
@@ -204,6 +234,27 @@ export class BoardApi {
})
}
importBoard(file) {
const formData = new FormData()
formData.append('file', file)
return axios.post(this.url('/boards/import'), formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
.then(
(response) => {
return Promise.resolve(response.data)
},
(err) => {
return Promise.reject(err)
},
)
.catch((err) => {
return Promise.reject(err)
})
}
// Label API Calls
deleteLabel(id) {
return axios.delete(this.url(`/labels/${id}`))

View File

@@ -4,7 +4,6 @@
*/
import { AttachmentApi } from './../services/AttachmentApi.js'
import Vue from 'vue'
const apiClient = new AttachmentApi()
@@ -24,20 +23,20 @@ export default {
mutations: {
createAttachment(state, { cardId, attachment }) {
if (typeof state.attachments[cardId] === 'undefined') {
Vue.set(state.attachments, cardId, [attachment])
state.attachments[cardId] = [attachment]
} else {
state.attachments[cardId].push(attachment)
}
},
createAttachments(state, { cardId, attachments }) {
Vue.set(state.attachments, cardId, attachments)
state.attachments[cardId] = attachments
},
updateAttachment(state, { cardId, attachment }) {
const existingIndex = state.attachments[attachment.cardId].findIndex(a => a.id === attachment.id && a.type === attachment.type)
if (existingIndex !== -1) {
Vue.set(state.attachments[cardId], existingIndex, attachment)
state.attachments[cardId][existingIndex] = attachment
}
},

View File

@@ -5,7 +5,6 @@
import { CardApi } from './../services/CardApi.js'
import moment from 'moment'
import Vue from 'vue'
const apiClient = new CardApi()
@@ -190,7 +189,7 @@ export default {
const existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) {
const existingCard = state.cards.find(_card => _card.id === card.id)
Vue.set(state.cards, existingIndex, Object.assign({}, existingCard, card))
state.cards[existingIndex] = { ...existingCard, ...card }
} else {
state.cards.push(card)
}
@@ -204,15 +203,15 @@ export default {
updateCard(state, card) {
const existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) {
Vue.set(state.cards, existingIndex, Object.assign({}, state.cards[existingIndex], card))
state.cards[existingIndex] = { ...state.cards[existingIndex], ...card }
}
},
updateCardsReorder(state, cards) {
for (const newCard of cards) {
const existingIndex = state.cards.findIndex(_card => _card.id === newCard.id)
if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], 'order', newCard.order)
Vue.set(state.cards[existingIndex], 'stackId', newCard.stackId)
state.cards[existingIndex].order = newCard.order
state.cards[existingIndex].stackId = newCard.stackId
}
}
},
@@ -234,26 +233,26 @@ export default {
updateCardProperty(state, { card, property }) {
const existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], property, card[property])
Vue.set(state.cards[existingIndex], 'lastModified', Date.now() / 1000)
state.cards[existingIndex][property] = card[property]
state.cards[existingIndex].lastModifiedBy = Date.now() / 1000
}
},
cardSetAttachmentCount(state, { cardId, count }) {
const existingIndex = state.cards.findIndex(_card => _card.id === cardId)
if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], 'attachmentCount', count)
state.cards[existingIndex].attachmentCount = count
}
},
cardIncreaseAttachmentCount(state, cardId) {
const existingIndex = state.cards.findIndex(_card => _card.id === cardId)
if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], 'attachmentCount', state.cards[existingIndex].attachmentCount + 1)
state.cards[existingIndex].attachmentCount = state.cards[existingIndex].attachmentCount + 1
}
},
cardDecreaseAttachmentCount(state, cardId) {
const existingIndex = state.cards.findIndex(_card => _card.id === cardId)
if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], 'attachmentCount', state.cards[existingIndex].attachmentCount - 1)
state.cards[existingIndex].attachmentCount = state.cards[existingIndex].attachmentCount - 1
}
},
addNewCard(state, card) {

View File

@@ -4,7 +4,6 @@
*/
import { CommentApi } from '../services/CommentApi.js'
import Vue from 'vue'
const apiClient = new CommentApi()
@@ -34,10 +33,10 @@ export default {
},
addComments(state, { comments, cardId }) {
if (state.comments[cardId] === undefined) {
Vue.set(state.comments, cardId, {
hasMore: comments.length > 0,
state.comments[cardId] = {
hasMore: comments.length >= 0,
comments: [...comments],
})
}
} else {
const newComments = comments.filter((comment) => {
return state.comments[cardId].comments.findIndex((item) => item.id === comment.id) === -1
@@ -59,11 +58,11 @@ export default {
},
markCommentsAsRead(state, cardId) {
state.comments[cardId].comments.forEach(_comment => {
Vue.set(_comment, 'isUnread', false)
_comment.isUnread = false
})
},
setReplyTo(state, comment) {
Vue.set(state, 'replyTo', comment)
state.replyTo = comment
},
},
actions: {

View File

@@ -6,8 +6,7 @@
import 'url-search-params-polyfill'
import { loadState } from '@nextcloud/initial-state'
import Vue from 'vue'
import Vuex from 'vuex'
import { createStore } from 'vuex'
import axios from '@nextcloud/axios'
import { generateOcsUrl, generateUrl } from '@nextcloud/router'
import { BoardApi } from '../services/BoardApi.js'
@@ -18,7 +17,6 @@ import comment from './comment.js'
import trashbin from './trashbin.js'
import attachment from './attachment.js'
import overview from './overview.js'
Vue.use(Vuex)
const apiClient = new BoardApi()
const debug = process.env.NODE_ENV !== 'production'
@@ -29,7 +27,7 @@ export const BOARD_FILTERS = {
SHARED: 'shared',
}
export default new Vuex.Store({
const store = createStore({
modules: {
actions,
stack,
@@ -130,10 +128,10 @@ export default new Vuex.Store({
},
mutations: {
setFullApp(state, isFullApp) {
Vue.set(state, 'isFullApp', isFullApp)
state.isFullApp = isFullApp
},
setHasCardSaveError(state, hasCardSaveError) {
Vue.set(state, 'hasCardSaveError', hasCardSaveError)
state.hasCardSaveError = hasCardSaveError
},
SET_CONFIG(state, { key, value }) {
const [scope, id, configKey] = key.split(':', 3)
@@ -145,11 +143,11 @@ export default new Vuex.Store({
})
if (indexExisting > -1) {
Vue.set(state.boards[indexExisting].settings, configKey, value)
state.boards[indexExisting].settings[configKey] = value
}
break
default:
Vue.set(state.config, key, value)
state.config[key] = value
}
},
setSearchQuery(state, searchQuery) {
@@ -162,7 +160,7 @@ export default new Vuex.Store({
Object.keys(filter).forEach((key) => {
switch (key) {
case 'due':
Vue.set(state.filter, key, filter.due)
state.filter[key] = filter.due
break
default:
filter[key].forEach((item) => {
@@ -189,7 +187,7 @@ export default new Vuex.Store({
})
if (indexExisting > -1) {
Vue.set(state.boards, indexExisting, board)
state.boards[indexExisting] = board
} else {
state.boards.push(board)
}
@@ -201,7 +199,7 @@ export default new Vuex.Store({
})
if (indexExisting > -1) {
Vue.set(state.boards, indexExisting, board)
state.boards[indexExisting] = board
} else {
state.boards.push(board)
}
@@ -234,7 +232,7 @@ export default new Vuex.Store({
state.boards = boards
},
setSharees(state, shareesUsersAndGroups) {
Vue.set(state, 'sharees', shareesUsersAndGroups.exact.users)
state.sharees = shareesUsersAndGroups.exact.users
state.sharees.push(...shareesUsersAndGroups.exact.groups)
state.sharees.push(...shareesUsersAndGroups.exact.circles)
@@ -284,7 +282,7 @@ export default new Vuex.Store({
updateAclFromCurrentBoard(state, acl) {
for (const acl_ in state.currentBoard.acl) {
if (state.currentBoard.acl[acl_].participant.uid === acl.participant.uid) {
Vue.set(state.currentBoard.acl, acl_, acl)
state.currentBoard.acl[acl_] = acl
break
}
}
@@ -300,7 +298,7 @@ export default new Vuex.Store({
}
if (removeIndex > -1) {
Vue.delete(state.currentBoard.acl, removeIndex)
state.currentBoard.acl.splice(removeIndex, 1)
}
},
TOGGLE_SHORTCUT_LOCK(state, lock) {
@@ -402,6 +400,14 @@ export default new Vuex.Store({
return err
}
},
async importBoard({ commit }, file) {
try {
const board = await apiClient.importBoard(file)
commit('addBoard', board)
} catch (err) {
return err
}
},
async cloneBoard({ commit }, { boardData, settings }) {
const { withCards, withAssignments, withLabels, withDueDate, moveCardsToLeftStack, restoreArchivedCards } = settings
@@ -523,3 +529,5 @@ export default new Vuex.Store({
},
},
})
export default store

View File

@@ -3,10 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import Vue from 'vue'
import Vuex from 'vuex'
import { OverviewApi } from '../services/OverviewApi.js'
Vue.use(Vuex)
const apiClient = new OverviewApi()
export default {

View File

@@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import Vue from 'vue'
import { StackApi } from './../services/StackApi.js'
import applyOrderToArray from './../helpers/applyOrderToArray.js'
@@ -26,7 +25,7 @@ export default {
const existingIndex = state.stacks.findIndex(_stack => _stack.id === stack.id)
if (existingIndex !== -1) {
const existingStack = state.stacks.find(_stack => _stack.id === stack.id)
Vue.set(state.stacks, existingIndex, Object.assign({}, existingStack, stack))
state.stacks[existingIndex] = { ...existingStack, ...stack }
} else {
state.stacks.push(stack)
}

View File

@@ -33,7 +33,7 @@ import DeckIcon from '../components/icons/DeckIcon.vue'
import { BoardApi } from './../services/BoardApi.js'
import store from './../store/main.js'
import NcUserBubble from '@nextcloud/vue/dist/Components/NcUserBubble.js'
import { NcUserBubble } from '@nextcloud/vue'
import moment from '@nextcloud/moment'
import { generateUrl } from '@nextcloud/router'

View File

@@ -82,7 +82,7 @@
{{ t('deck', 'Cancel') }}
</NcButton>
<NcButton :disabled="loading || !isBoardAndStackChoosen"
type="primary"
variant="primary"
@click="createCard">
{{ t('deck', 'Create card') }}
</NcButton>
@@ -212,8 +212,8 @@ export default {
},
},
beforeMount() {
this.$set(this.card, 'title', this.title)
this.$set(this.card, 'description', this.description)
this.card.title = this.title
this.card.description = this.description
this.fetchBoards()
},
mounted() {

View File

@@ -1 +1 @@
72460
81091

View File

@@ -1,8 +1,7 @@
{
"require-dev": {
"phpunit/phpunit": "~9",
"behat/behat": "~3.15.0",
"behat/gherkin": "4.11.0",
"behat/behat": "~3.21.1",
"guzzlehttp/guzzle": "7.9.2",
"jarnaiz/behat-junit-formatter": "^1.3",
"sabre/dav": "4.7.0",

View File

@@ -29,6 +29,7 @@ use OCA\Deck\Controller\PageController;
use OCA\Deck\NoPermissionException;
use OCA\Deck\NotFoundException;
use OCA\Deck\Service\BoardService;
use OCA\Deck\Service\Importer\BoardImportService;
use OCA\Deck\Service\PermissionService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse;
@@ -86,7 +87,15 @@ class ExceptionMiddlewareTest extends \Test\TestCase {
public function testAfterExceptionFail() {
$this->request->expects($this->any())->method('getId')->willReturn('abc123');
// BoardService $boardService, PermissionService $permissionService, $userId
$boardController = new BoardController('deck', $this->createMock(IRequest::class), $this->createMock(BoardService::class), $this->createMock(PermissionService::class), 'admin');
$boardController = new BoardController(
'deck',
$this->createMock(IRequest::class),
$this->createMock(BoardService::class),
$this->createMock(PermissionService::class),
$this->createMock(BoardImportService::class),
$this->createMock(\OCP\IL10N::class),
'admin'
);
$result = $this->exceptionMiddleware->afterException($boardController, 'bar', new \Exception('other exception message'));
$this->assertEquals('Internal server error: Please contact the server administrator if this error reappears multiple times, please include the request ID "abc123" below in your report.', $result->getData()['message']);
$this->assertEquals(500, $result->getData()['status']);

View File

@@ -475,6 +475,9 @@ class CardServiceTest extends TestCase {
$label->setBoardId(1);
$this->cardMapper->expects($this->once())->method('find')->willReturn($card);
$this->cardMapper->expects($this->once())->method('removeLabel');
$this->cardMapper->expects($this->once())
->method('findBoardId')
->willReturn(1);
$this->labelMapper->expects($this->once())
->method('find')
->willReturn($label);

Some files were not shown because too many files have changed in this diff Show More