Compare commits

..

340 Commits

Author SHA1 Message Date
Julius Härtl
9932a7b972 fix: Revert append to body as it fails on 24
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2023-06-23 11:34:17 +02:00
Julius Härtl
e10ab29f28 fix: Properly overwrite z-index of datepicker above modal
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2023-06-23 11:25:46 +02:00
Julius Härtl
0ac494df9d Merge pull request #4795 from nextcloud/dependabot/npm_and_yarn/stable24/vue/test-utils-1.3.6 2023-06-10 12:47:17 +02:00
Julius Härtl
a8ce89d487 Merge pull request #4793 from nextcloud/dependabot/npm_and_yarn/stable24/babel/runtime-7.22.5 2023-06-10 12:47:08 +02:00
dependabot[bot]
2fcbbbbc23 Chore(deps-dev): Bump @vue/test-utils from 1.3.5 to 1.3.6
Bumps [@vue/test-utils](https://github.com/vuejs/test-utils) from 1.3.5 to 1.3.6.
- [Release notes](https://github.com/vuejs/test-utils/releases)
- [Commits](https://github.com/vuejs/test-utils/commits)

---
updated-dependencies:
- dependency-name: "@vue/test-utils"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-10 03:40:27 +00:00
dependabot[bot]
4f673fe598 Chore(deps): Bump @babel/runtime from 7.22.3 to 7.22.5
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.22.3 to 7.22.5.
- [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.22.5/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>
2023-06-10 03:30:15 +00:00
Julius Härtl
02ba8f85ce Merge pull request #4759 from nextcloud/dependabot/npm_and_yarn/stable24/babel/runtime-7.22.3 2023-06-05 07:45:41 +02:00
Julius Härtl
f88d53d7f1 Merge pull request #4762 from nextcloud/dependabot/npm_and_yarn/stable24/url-search-params-polyfill-8.2.2 2023-06-05 07:45:09 +02:00
dependabot[bot]
6a5eecea76 Chore(deps): Bump url-search-params-polyfill from 8.1.1 to 8.2.2
Bumps [url-search-params-polyfill](https://github.com/jerrybendy/url-search-params-polyfill) from 8.1.1 to 8.2.2.
- [Release notes](https://github.com/jerrybendy/url-search-params-polyfill/releases)
- [Commits](https://github.com/jerrybendy/url-search-params-polyfill/commits)

---
updated-dependencies:
- dependency-name: url-search-params-polyfill
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-03 03:39:30 +00:00
dependabot[bot]
b61667c90b Chore(deps): Bump @babel/runtime from 7.22.0 to 7.22.3
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.22.0 to 7.22.3.
- [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.22.3/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>
2023-06-03 03:07:49 +00:00
Julius Härtl
6864846d84 Merge pull request #4745 from nextcloud/dependabot/npm_and_yarn/stable24/babel/runtime-7.22.0 2023-05-30 10:55:23 +02:00
dependabot[bot]
962256acb0 Chore(deps): Bump @babel/runtime from 7.21.5 to 7.22.0
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.21.5 to 7.22.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.22.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>
2023-05-27 03:33:27 +00:00
Nextcloud bot
9db8c9af80 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-05-21 00:29:12 +00:00
Nextcloud bot
88bd868e76 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-05-18 00:29:48 +00:00
Julius Härtl
3c88551ad5 Merge pull request #4681 from nextcloud/automated/noid/stable24-fix-npm-audit 2023-05-15 08:25:09 +02:00
nextcloud-command
0872b1b606 chore(deps): fix npm audit
Signed-off-by: GitHub <noreply@github.com>
2023-05-14 03:09:57 +00:00
Nextcloud bot
65242c2b6c Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-05-12 02:43:23 +00:00
Julius Härtl
a3527542f9 Bump version to 1.7.4
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2023-05-10 15:41:56 +02:00
Nextcloud bot
28e4b12428 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-05-08 02:40:24 +00:00
Julius Härtl
628cd333f1 Merge pull request #4646 from nextcloud/backport/4643/stable24
[stable24] fix: Append datetime picker to body to avoid cut off
2023-05-03 13:32:01 +02:00
Julius Härtl
ccfaa4886a fix: z-index of datepicker in modal
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2023-05-03 13:10:40 +02:00
Julius Härtl
0ef238da0e Merge pull request #4639 from nextcloud/automated/noid/stable24-fix-npm-audit
[stable24] Fix npm audit
2023-05-03 12:45:05 +02:00
Julius Härtl
333b904335 fix: Append datetime picker to body to avoid cut off
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2023-05-03 10:41:52 +00:00
nextcloud-command
32a956af02 chore(deps): fix npm audit
Signed-off-by: GitHub <noreply@github.com>
2023-05-03 08:12:52 +00:00
Julius Härtl
b7dad3134d Merge pull request #4629 from nextcloud/dependabot/npm_and_yarn/stable24/nextcloud/webpack-vue-config-5.5.1 2023-05-02 10:31:28 +02:00
Julius Härtl
42f76117f2 Merge pull request #4631 from nextcloud/dependabot/npm_and_yarn/stable24/babel/runtime-7.21.5 2023-05-02 10:31:15 +02:00
dependabot[bot]
be1c646bd7 Chore(deps): Bump @babel/runtime from 7.21.0 to 7.21.5
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.21.0 to 7.21.5.
- [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.21.5/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>
2023-04-29 01:58:38 +00:00
dependabot[bot]
137fece0b8 Chore(deps-dev): Bump @nextcloud/webpack-vue-config from 5.5.0 to 5.5.1
Bumps [@nextcloud/webpack-vue-config](https://github.com/nextcloud/webpack-vue-config) from 5.5.0 to 5.5.1.
- [Release notes](https://github.com/nextcloud/webpack-vue-config/releases)
- [Changelog](https://github.com/nextcloud/webpack-vue-config/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/webpack-vue-config/compare/v5.5.0...v5.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-29 01:58:09 +00:00
Nextcloud bot
81e5922dfd Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-04-28 02:40:36 +00:00
Nextcloud bot
ccc216d388 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-04-27 02:40:52 +00:00
Julius Härtl
3f7ab93df9 Update appbuild.yml
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2023-04-25 08:28:20 +02:00
Julius Härtl
a621aacac0 Update phpunit.yml
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2023-04-24 12:52:14 +02:00
Julius Härtl
bb7ed1bc31 Merge pull request #4595 from nextcloud/dependabot/npm_and_yarn/stable24/vue/test-utils-1.3.5 2023-04-24 12:26:08 +02:00
Nextcloud bot
4d0f7ddef3 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-04-23 02:40:59 +00:00
Nextcloud bot
bd13cc09d8 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-04-19 02:40:51 +00:00
Nextcloud bot
cb3925faeb Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-04-16 02:39:55 +00:00
dependabot[bot]
ac11571a7d Chore(deps-dev): Bump @vue/test-utils from 1.3.4 to 1.3.5
Bumps [@vue/test-utils](https://github.com/vuejs/test-utils) from 1.3.4 to 1.3.5.
- [Release notes](https://github.com/vuejs/test-utils/releases)
- [Commits](https://github.com/vuejs/test-utils/commits)

---
updated-dependencies:
- dependency-name: "@vue/test-utils"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-15 01:57:50 +00:00
Nextcloud bot
fd4564450b Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-04-09 02:42:15 +00:00
Nextcloud bot
acbd42d6a4 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-04-06 02:41:16 +00:00
Nextcloud bot
458831dfc7 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-04-05 02:42:40 +00:00
Jonas
8a5098951c Merge pull request #4569 from nextcloud/backport/4566/stable24
[stable24] Gracefully handle not found card for a share
2023-03-29 11:17:55 +02:00
Jonas
99260ae966 Gracefully handle not found card for a share
Fixes: #3464
Fixes: #4565

Signed-off-by: Jonas <jonas@freesources.org>
2023-03-29 09:01:10 +00:00
Nextcloud bot
ea592251f9 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-03-28 02:31:42 +00:00
Julius Härtl
6c80674ce0 Merge pull request #4541 from nextcloud/backport/4487/stable24 2023-03-20 07:16:14 +01:00
Julius Härtl
060e8cd7db Merge pull request #4551 from nextcloud/automated/noid/stable24-update-nextcloud-ocp
[stable24] Update nextcloud/ocp dependency
2023-03-20 07:15:33 +01:00
nextcloud-command
f05bd86be9 chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2023-03-19 03:09:00 +00:00
dependabot[bot]
1ce7856cae Merge pull request #4549 from nextcloud/dependabot/npm_and_yarn/stable24/nextcloud/webpack-vue-config-5.5.0 2023-03-18 05:23:13 +00:00
dependabot[bot]
678e4c9569 Chore(deps-dev): Bump @nextcloud/webpack-vue-config from 5.4.0 to 5.5.0
Bumps [@nextcloud/webpack-vue-config](https://github.com/nextcloud/webpack-vue-config) from 5.4.0 to 5.5.0.
- [Release notes](https://github.com/nextcloud/webpack-vue-config/releases)
- [Changelog](https://github.com/nextcloud/webpack-vue-config/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/webpack-vue-config/compare/v5.4.0...v5.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-18 04:11:24 +00:00
Nextcloud bot
4fe4216cb5 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-03-18 02:39:40 +00:00
Julius Härtl
85e7305d8d fix: Use passed userid when getting attachment folder
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2023-03-17 14:05:15 +00:00
Nextcloud bot
090378580c Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-03-17 02:39:10 +00:00
Nextcloud bot
3f8efb5368 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-03-16 02:40:49 +00:00
Julius Härtl
c1f2fd452b Merge pull request #4538 from nextcloud/backport/4535/stable24 2023-03-15 15:32:42 +01:00
Jérôme Herbinet
576c47bdef Fix : Overlapping expiry dates on tags
Signed-off-by: Jérôme Herbinet <33763786+Jerome-Herbinet@users.noreply.github.com>

Signed-off-by: Jérôme Herbinet <33763786+Jerome-Herbinet@users.noreply.github.com>
2023-03-15 12:50:37 +00:00
Nextcloud bot
e907aeb8c0 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-03-15 02:38:47 +00:00
Nextcloud bot
c51119d051 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-03-10 02:40:09 +00:00
Nextcloud bot
ee72cb4660 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-03-06 02:39:16 +00:00
dependabot[bot]
d4f2ed263f Merge pull request #4501 from nextcloud/dependabot/npm_and_yarn/stable24/dompurify-2.4.5 2023-03-04 04:06:06 +00:00
dependabot[bot]
e6f8796b63 Chore(deps): Bump dompurify from 2.4.4 to 2.4.5
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 2.4.4 to 2.4.5.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/2.4.4...2.4.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-04 02:57:56 +00:00
Nextcloud bot
846443d003 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-03-04 02:40:29 +00:00
dependabot[bot]
144c27d403 Merge pull request #4475 from nextcloud/dependabot/npm_and_yarn/stable24/babel/runtime-7.21.0 2023-02-25 04:26:43 +00:00
dependabot[bot]
f374084989 chore(deps): bump @babel/runtime from 7.20.13 to 7.21.0
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.20.13 to 7.21.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.21.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>
2023-02-25 02:57:54 +00:00
Nextcloud bot
0656e53508 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-24 02:42:13 +00:00
Nextcloud bot
7506126ef7 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-22 02:34:22 +00:00
Nextcloud bot
5214721875 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-21 02:33:48 +00:00
Julius Härtl
34f7b726cd Merge pull request #4465 from nextcloud/automated/noid/stable24-update-nextcloud-ocp 2023-02-20 14:57:17 +01:00
nextcloud-command
ea5baa5339 chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2023-02-19 03:33:35 +00:00
Nextcloud bot
7c3aa301ac Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-19 02:34:29 +00:00
dependabot[bot]
313bc90ce9 Merge pull request #4462 from nextcloud/dependabot/npm_and_yarn/stable24/dompurify-2.4.4 2023-02-18 05:31:36 +00:00
dependabot[bot]
be06c7ab70 Chore(deps): Bump dompurify from 2.4.3 to 2.4.4
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 2.4.3 to 2.4.4.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/2.4.3...2.4.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-18 04:46:30 +00:00
Nextcloud bot
5964da382e Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-18 02:34:50 +00:00
Nextcloud bot
eaa2facc29 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-17 02:33:47 +00:00
Nextcloud bot
13e836760a Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-16 02:33:30 +00:00
Nextcloud bot
73815827e1 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-15 02:33:45 +00:00
Nextcloud bot
34107ad06f Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-14 02:33:25 +00:00
Nextcloud bot
90535b3c30 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-13 02:32:44 +00:00
Nextcloud bot
312376e596 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-12 02:33:25 +00:00
Nextcloud bot
04dbe45f29 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-11 02:33:40 +00:00
Nextcloud bot
bc38340daf Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-10 02:34:53 +00:00
Nextcloud bot
9b89897d74 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-07 02:33:12 +00:00
Nextcloud bot
f411181dcf Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-05 02:32:16 +00:00
Nextcloud bot
080465d48a Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-04 02:32:52 +00:00
Nextcloud bot
2358645037 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-02-01 02:32:45 +00:00
Nextcloud bot
c6545c7c00 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-31 02:33:59 +00:00
Nextcloud bot
3baa2fc1a0 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-30 02:34:13 +00:00
Julius Härtl
fd297dc92e Merge pull request #4416 from nextcloud/automated/noid/stable24-update-nextcloud-ocp 2023-01-29 08:41:17 +01:00
nextcloud-command
4608e4b77b chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2023-01-29 02:56:09 +00:00
dependabot[bot]
524b8ba90e Merge pull request #4413 from nextcloud/dependabot/npm_and_yarn/stable24/vue/test-utils-1.3.4 2023-01-28 06:50:48 +00:00
dependabot[bot]
569e568136 Merge pull request #4403 from nextcloud/dependabot/npm_and_yarn/stable24/babel/runtime-7.20.13 2023-01-28 05:17:01 +00:00
dependabot[bot]
d9c563d5bf Chore(deps-dev): Bump @vue/test-utils from 1.3.3 to 1.3.4
Bumps [@vue/test-utils](https://github.com/vuejs/test-utils) from 1.3.3 to 1.3.4.
- [Release notes](https://github.com/vuejs/test-utils/releases)
- [Commits](https://github.com/vuejs/test-utils/commits)

---
updated-dependencies:
- dependency-name: "@vue/test-utils"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-28 03:28:46 +00:00
Nextcloud bot
f51956891e Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-28 02:33:42 +00:00
dependabot[bot]
053ecdacee Chore(deps): Bump @babel/runtime from 7.20.7 to 7.20.13
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.20.7 to 7.20.13.
- [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.20.13/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>
2023-01-28 02:01:56 +00:00
Nextcloud bot
8f755ee3eb Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-25 02:51:31 +00:00
Nextcloud bot
fa6d819409 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-24 02:32:51 +00:00
Nextcloud bot
fa17dfac3a Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-23 02:33:00 +00:00
Nextcloud bot
92b20efa89 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-22 02:32:42 +00:00
Nextcloud bot
2849177998 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-21 02:32:35 +00:00
Nextcloud bot
0bbeedb7e3 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-17 02:34:22 +00:00
Nextcloud bot
918f22f7a6 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-16 02:32:13 +00:00
Nextcloud bot
ecac9b772b Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-14 02:33:55 +00:00
Nextcloud bot
f0a4469be5 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-13 02:33:55 +00:00
Nextcloud bot
f47f4983d9 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-11 02:32:12 +00:00
Nextcloud bot
c9b8735804 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-10 02:33:45 +00:00
Julius Härtl
c9d7647200 Merge pull request #4370 from nextcloud/automated/noid/stable24-update-nextcloud-ocp 2023-01-09 16:38:03 +01:00
Nextcloud bot
4a8410f0fc Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-09 02:32:10 +00:00
nextcloud-command
4fbb383c0f Update psalm baseline
Signed-off-by: GitHub <noreply@github.com>
2023-01-08 02:51:52 +00:00
dependabot[bot]
98361ff096 Merge pull request #4364 from nextcloud/dependabot/npm_and_yarn/stable24/dompurify-2.4.3 2023-01-07 03:45:56 +00:00
Nextcloud bot
31f2ca49d5 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-07 02:32:16 +00:00
dependabot[bot]
e0e6f86801 Bump dompurify from 2.4.1 to 2.4.3
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 2.4.1 to 2.4.3.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/2.4.1...2.4.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-07 02:02:47 +00:00
Nextcloud bot
0bc4e1fa7b Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-05 02:32:03 +00:00
Nextcloud bot
0d137a372c Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-04 02:25:31 +00:00
Nextcloud bot
2d1ad75f35 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-03 02:47:16 +00:00
Nextcloud bot
e381e021d6 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-02 03:17:23 +00:00
Nextcloud bot
59f0813aa5 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2023-01-01 03:01:30 +00:00
Nextcloud bot
90d14c544f Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-12-31 03:20:24 +00:00
dependabot[bot]
02ca7acf4f Merge pull request #4346 from nextcloud/dependabot/npm_and_yarn/stable24/nextcloud/router-2.0.1 2022-12-30 13:32:22 +00:00
dependabot[bot]
0725b55773 Bump @nextcloud/router from 2.0.0 to 2.0.1
Bumps [@nextcloud/router](https://github.com/nextcloud/nextcloud-router) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/nextcloud/nextcloud-router/releases)
- [Changelog](https://github.com/nextcloud/nextcloud-router/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/nextcloud-router/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-30 13:17:49 +00:00
Nextcloud bot
1219c0aed0 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-12-27 03:13:49 +00:00
dependabot[bot]
da57b9c7e1 Merge pull request #4336 from nextcloud/dependabot/npm_and_yarn/stable24/babel/runtime-7.20.7 2022-12-24 04:46:16 +00:00
Nextcloud bot
e67822167b Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-12-24 03:40:01 +00:00
dependabot[bot]
20e3729b86 Bump @babel/runtime from 7.20.6 to 7.20.7
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.20.6 to 7.20.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.20.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>
2022-12-24 02:01:47 +00:00
Nextcloud bot
5c3d88dae0 Fix(l10n): 🔠 Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-12-21 02:38:12 +00:00
Nextcloud bot
2fb86b11ec [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-12-18 02:27:11 +00:00
Nextcloud bot
5d9c504842 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-12-16 02:27:05 +00:00
Nextcloud bot
1610968ed7 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-12-14 02:29:30 +00:00
Nextcloud bot
aad4aafc03 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-12-13 02:40:06 +00:00
Marcel Klehr
40e3987ae6 Merge pull request #4302 from nextcloud/backport/4194/stable24 2022-12-09 16:04:50 +01:00
Michal Polacik
d3a77e4a11 Permanently delete deck cards marked as deleted after 5 min in a cron job
Limit deleted cards in one cron job run to 500

Converted spaces to tabs

Added missing import for CardMapper class

Added another missing import for CardMapper class

Fixed response object in findToDelete method + fixed 2 misspellings in API.md

Fixed invalid parameter type

Fix DeleteCronTest

Signed-off-by: Marcel Klehr <mklehr@gmx.net>

Fix lint errors

Signed-off-by: Marcel Klehr <mklehr@gmx.net>
2022-12-09 14:38:59 +00:00
Nextcloud bot
c93189ff9a [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-12-04 02:22:13 +00:00
dependabot[bot]
bca7b3386c Merge pull request #4283 from nextcloud/dependabot/npm_and_yarn/stable24/babel/runtime-7.20.6 2022-12-03 03:47:27 +00:00
dependabot[bot]
3c7cc0b09c Bump @babel/runtime from 7.20.1 to 7.20.6
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.20.1 to 7.20.6.
- [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.20.6/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>
2022-12-03 02:02:26 +00:00
Nextcloud bot
8e35b67a0d [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-12-01 02:23:05 +00:00
Nextcloud bot
bfb292c54d [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-30 02:23:28 +00:00
Nextcloud bot
ab6c775f5c [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-23 02:26:02 +00:00
Nextcloud bot
e3e9e4596a [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-22 02:26:48 +00:00
Nextcloud bot
fefe77c245 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-21 02:22:57 +00:00
Nextcloud bot
42108cb223 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-20 02:24:07 +00:00
dependabot[bot]
72d7a245d2 Merge pull request #4271 from nextcloud/dependabot/npm_and_yarn/stable24/nextcloud/webpack-vue-config-5.4.0 2022-11-19 08:38:43 +00:00
Nextcloud bot
e187a665d5 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-19 02:25:09 +00:00
dependabot[bot]
01ab23dc82 Bump @nextcloud/webpack-vue-config from 5.0.0 to 5.4.0
Bumps [@nextcloud/webpack-vue-config](https://github.com/nextcloud/webpack-vue-config) from 5.0.0 to 5.4.0.
- [Release notes](https://github.com/nextcloud/webpack-vue-config/releases)
- [Changelog](https://github.com/nextcloud/webpack-vue-config/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/webpack-vue-config/compare/v5.0.0...v5.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-19 01:53:18 +00:00
dependabot[bot]
004814ace7 Merge pull request #4267 from nextcloud/dependabot/npm_and_yarn/stable24/vue-2.7.14 2022-11-19 01:52:04 +00:00
dependabot[bot]
326a38557b Merge pull request #4264 from nextcloud/dependabot/npm_and_yarn/stable24/relative-ci/agent-3.1.3 2022-11-19 01:50:28 +00:00
dependabot[bot]
6e43ed5fce Merge pull request #4245 from nextcloud/dependabot/npm_and_yarn/stable24/moment-2.29.4 2022-11-18 23:41:59 +00:00
dependabot[bot]
8b92610f67 Merge pull request #4243 from nextcloud/dependabot/npm_and_yarn/stable24/nextcloud/moment-1.2.1 2022-11-18 23:36:56 +00:00
dependabot[bot]
6cc919b62d Bump vue from 2.6.14 to 2.7.14
Bumps [vue](https://github.com/vuejs/core) from 2.6.14 to 2.7.14.
- [Release notes](https://github.com/vuejs/core/releases)
- [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vuejs/core/commits)

---
updated-dependencies:
- dependency-name: vue
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 22:30:17 +00:00
dependabot[bot]
3ff47580ad Bump @relative-ci/agent from 3.1.2 to 3.1.3
Bumps [@relative-ci/agent](https://github.com/relative-ci/agent) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/relative-ci/agent/releases)
- [Commits](https://github.com/relative-ci/agent/compare/v3.1.2...v3.1.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 22:29:42 +00:00
dependabot[bot]
a1a2120d43 Merge pull request #4270 from nextcloud/dependabot/npm_and_yarn/stable24/nextcloud/vue-5.4.0 2022-11-18 22:29:17 +00:00
dependabot[bot]
273222bb21 Merge pull request #4269 from nextcloud/dependabot/npm_and_yarn/stable24/vue-router-3.6.5 2022-11-18 22:29:12 +00:00
dependabot[bot]
1255e5a6c9 Merge pull request #4268 from nextcloud/dependabot/npm_and_yarn/stable24/vue/test-utils-1.3.3 2022-11-18 22:27:26 +00:00
dependabot[bot]
dace366b6c Merge pull request #4260 from nextcloud/dependabot/npm_and_yarn/stable24/nextcloud/browserslist-config-2.3.0 2022-11-18 21:49:06 +00:00
dependabot[bot]
a2f5414c48 Merge pull request #4257 from nextcloud/dependabot/npm_and_yarn/stable24/nextcloud/dialogs-3.2.0 2022-11-18 21:47:15 +00:00
dependabot[bot]
1887527197 Merge pull request #4254 from nextcloud/dependabot/npm_and_yarn/stable24/babel/runtime-7.20.1 2022-11-18 21:25:07 +00:00
dependabot[bot]
6d35c2f1c1 Merge pull request #4252 from nextcloud/dependabot/npm_and_yarn/stable24/dompurify-2.4.1 2022-11-18 21:18:01 +00:00
dependabot[bot]
51626698c4 Merge pull request #4266 from nextcloud/dependabot/npm_and_yarn/stable24/vue-at-2.5.1 2022-11-18 21:06:31 +00:00
dependabot[bot]
5ed2b23f76 Merge pull request #4265 from nextcloud/dependabot/npm_and_yarn/stable24/nextcloud/axios-1.11.0 2022-11-18 21:03:26 +00:00
dependabot[bot]
502b5acb69 Merge pull request #4261 from nextcloud/dependabot/npm_and_yarn/stable24/markdown-it-link-attributes-4.0.1 2022-11-18 20:46:28 +00:00
dependabot[bot]
03b5257fea Bump moment from 2.29.2 to 2.29.4
Bumps [moment](https://github.com/moment/moment) from 2.29.2 to 2.29.4.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.2...2.29.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 20:20:50 +00:00
dependabot[bot]
39b158f92d Bump @nextcloud/moment from 1.2.0 to 1.2.1
Bumps [@nextcloud/moment](https://github.com/nextcloud/nextcloud-moment) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/nextcloud/nextcloud-moment/releases)
- [Changelog](https://github.com/nextcloud/nextcloud-moment/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/nextcloud-moment/compare/v1.2.0...v1.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 20:20:49 +00:00
dependabot[bot]
3163136b73 Merge pull request #4248 from nextcloud/dependabot/npm_and_yarn/stable24/nextcloud/l10n-1.6.0 2022-11-18 20:19:42 +00:00
dependabot[bot]
9791444167 Bump @nextcloud/vue from 5.3.1 to 5.4.0
Bumps [@nextcloud/vue](https://github.com/nextcloud/nextcloud-vue) from 5.3.1 to 5.4.0.
- [Release notes](https://github.com/nextcloud/nextcloud-vue/releases)
- [Changelog](https://github.com/nextcloud/nextcloud-vue/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/nextcloud-vue/compare/v5.3.1...v5.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 17:35:27 +00:00
dependabot[bot]
77acf95106 Bump vue-router from 3.5.3 to 3.6.5
Bumps [vue-router](https://github.com/vuejs/router) from 3.5.3 to 3.6.5.
- [Release notes](https://github.com/vuejs/router/releases)
- [Commits](https://github.com/vuejs/router/commits)

---
updated-dependencies:
- dependency-name: vue-router
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 17:35:11 +00:00
dependabot[bot]
6505cc99ce Bump @vue/test-utils from 1.3.0 to 1.3.3
Bumps [@vue/test-utils](https://github.com/vuejs/test-utils) from 1.3.0 to 1.3.3.
- [Release notes](https://github.com/vuejs/test-utils/releases)
- [Commits](https://github.com/vuejs/test-utils/commits)

---
updated-dependencies:
- dependency-name: "@vue/test-utils"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 17:35:01 +00:00
dependabot[bot]
54d1a40eeb Bump vue-at from 2.5.0-beta.2 to 2.5.1
Bumps [vue-at](https://github.com/fritx/vue-at) from 2.5.0-beta.2 to 2.5.1.
- [Release notes](https://github.com/fritx/vue-at/releases)
- [Commits](https://github.com/fritx/vue-at/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 17:32:26 +00:00
dependabot[bot]
ab577a95eb Bump @nextcloud/axios from 1.9.0 to 1.11.0
Bumps [@nextcloud/axios](https://github.com/nextcloud/nextcloud-axios) from 1.9.0 to 1.11.0.
- [Release notes](https://github.com/nextcloud/nextcloud-axios/releases)
- [Changelog](https://github.com/nextcloud/nextcloud-axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/nextcloud-axios/compare/v1.9.0...v1.11.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 17:32:14 +00:00
dependabot[bot]
8537d4acef Bump markdown-it-link-attributes from 4.0.0 to 4.0.1
Bumps [markdown-it-link-attributes](https://github.com/crookedneighbor/markdown-it-link-attributes) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/crookedneighbor/markdown-it-link-attributes/releases)
- [Changelog](https://github.com/crookedneighbor/markdown-it-link-attributes/blob/main/CHANGELOG.md)
- [Commits](https://github.com/crookedneighbor/markdown-it-link-attributes/compare/v4.0.0...v4.0.1)

---
updated-dependencies:
- dependency-name: markdown-it-link-attributes
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 17:31:22 +00:00
dependabot[bot]
d0fda8a546 Bump @nextcloud/browserslist-config from 2.2.0 to 2.3.0
Bumps [@nextcloud/browserslist-config](https://github.com/nextcloud/browserslist-config) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/nextcloud/browserslist-config/releases)
- [Commits](https://github.com/nextcloud/browserslist-config/compare/v2.2.0...v2.3.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 17:31:12 +00:00
dependabot[bot]
031f69523d Bump @nextcloud/dialogs from 3.1.2 to 3.2.0
Bumps [@nextcloud/dialogs](https://github.com/nextcloud/nextcloud-dialogs) from 3.1.2 to 3.2.0.
- [Release notes](https://github.com/nextcloud/nextcloud-dialogs/releases)
- [Changelog](https://github.com/nextcloud/nextcloud-dialogs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/nextcloud-dialogs/compare/v3.1.2...v3.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 17:31:00 +00:00
dependabot[bot]
3864f29bbd Bump @babel/runtime from 7.17.9 to 7.20.1
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.17.9 to 7.20.1.
- [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.20.1/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>
2022-11-18 17:30:49 +00:00
dependabot[bot]
ee1b32fcd7 Bump dompurify from 2.3.6 to 2.4.1
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 2.3.6 to 2.4.1.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/2.3.6...2.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 17:30:38 +00:00
dependabot[bot]
6ad6b1680f Bump @nextcloud/l10n from 1.4.1 to 1.6.0
Bumps [@nextcloud/l10n](https://github.com/nextcloud/nextcloud-l10n) from 1.4.1 to 1.6.0.
- [Release notes](https://github.com/nextcloud/nextcloud-l10n/releases)
- [Changelog](https://github.com/nextcloud/nextcloud-l10n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/nextcloud-l10n/compare/v1.4.1...v1.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-18 17:30:24 +00:00
Julius Härtl
b158d79403 Bump version to 1.7.3
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-11-18 16:29:52 +01:00
Nextcloud bot
2d823e3321 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-17 02:21:30 +00:00
Julius Härtl
9a153356c2 Merge pull request #4207 from nextcloud/automated/noid/stable24-update-nextcloud-ocp 2022-11-13 16:55:55 +01:00
nextcloud-command
eaf5e6ff29 Update psalm baseline
Signed-off-by: GitHub <noreply@github.com>
2022-11-13 03:36:07 +00:00
Nextcloud bot
585a02a3d2 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-12 02:22:17 +00:00
Julius Härtl
30acd27c94 Merge pull request #4202 from nextcloud/backport/4180/stable24 2022-11-11 14:59:23 +01:00
Nextcloud bot
71db398e9a [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-11 02:21:22 +00:00
Johannes Szeibert
d8f44e2c94 minor style fixes
Signed-off-by: Johannes Szeibert <johannes@szeibert.de>
2022-11-10 08:31:48 +00:00
Nextcloud bot
20c8cb12e3 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-10 02:23:00 +00:00
Nextcloud bot
60eadb7035 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-09 02:21:47 +00:00
Julius Härtl
17e71c5c9a Merge pull request #4188 from nextcloud/automated/noid/stable24-update-nextcloud-ocp 2022-11-07 08:26:43 +01:00
nextcloud-command
289c0f72dd Update psalm baseline
Signed-off-by: GitHub <noreply@github.com>
2022-11-06 03:33:40 +00:00
Nextcloud bot
c2a326d538 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-05 02:22:34 +00:00
Nextcloud bot
438bb8cb0d [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-04 02:21:19 +00:00
Julius Härtl
b98f8e3b07 Merge pull request #4178 from nextcloud/backport/4173/stable24 2022-11-03 21:47:23 +01:00
Julius Härtl
333206c549 Fix validation of attachment data
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-11-03 20:43:47 +01:00
Julius Härtl
5359ec34ef Unify getting the share for attachments
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-11-03 20:43:45 +01:00
Julius Härtl
ab7da85964 Add integration test for attachment handling on cards
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-11-03 20:43:45 +01:00
Marcel Klehr
7ecb215957 Merge pull request #4182 from nextcloud/backport/4101/stable24 2022-11-03 18:54:37 +01:00
mokkin
df89839b51 disables autocomplete on card creation
solves https://github.com/nextcloud/deck/issues/4083

Signed-off-by: mokkin <markus@haybach.com>
2022-11-03 18:25:22 +01:00
Nextcloud bot
03ed40df67 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-03 02:21:17 +00:00
Nextcloud bot
ad1429b4a2 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-02 02:21:35 +00:00
Nextcloud bot
eb03cd6814 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-11-01 02:21:41 +00:00
Julius Härtl
566846fe4d Merge pull request #4176 from nextcloud/backport/4059/stable24 2022-10-31 21:17:49 +01:00
Julius Härtl
f4c09fefd9 Add some tests for parameter validation
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-10-31 14:22:23 +01:00
Luka Trovic
bd6e632055 feat: add validators to check values in services
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2022-10-31 14:22:20 +01:00
Nextcloud bot
75ddc058b8 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-31 02:21:06 +00:00
Julius Härtl
8558ce432a Merge pull request #4171 from nextcloud/automated/noid/stable24-update-nextcloud-ocp
[stable24] Update nextcloud/ocp dependency
2022-10-30 08:40:38 +01:00
nextcloud-command
7586084980 Update psalm baseline
Signed-off-by: GitHub <noreply@github.com>
2022-10-30 03:57:06 +00:00
Nextcloud bot
863de715a4 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-30 02:24:11 +00:00
Nextcloud bot
04abf47653 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-29 02:23:25 +00:00
Marcel Klehr
45c9a8ba27 Merge pull request #4158 from nextcloud/release/1.7.2 2022-10-27 11:47:09 +02:00
Nextcloud bot
3d10521524 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-27 02:21:17 +00:00
Marcel Klehr
ef616f37bd v1.7.2
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
2022-10-26 16:15:54 +02:00
Nextcloud bot
e64c36ffce [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-25 02:26:18 +00:00
Nextcloud bot
837d925536 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-24 02:21:56 +00:00
Julius Härtl
feaeb90f76 Merge pull request #4132 from nextcloud/backport/4065/stable24 2022-10-18 19:22:08 +02:00
Julius Härtl
2ea94a12ad Cache user membership for circles
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-10-18 11:35:19 +02:00
Julius Härtl
c8cf8238b8 Pin postgres to 14
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-10-18 11:29:51 +02:00
Julius Härtl
16f41f74b3 Merge pull request #4118 from nextcloud/backport/3439/stable24 2022-10-18 11:26:27 +02:00
Nextcloud bot
3a78eea105 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-18 02:21:41 +00:00
Julius Härtl
8e158972f4 Activity: Set event link also for notifications that get emitted from activity
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-10-14 10:51:06 +00:00
Nextcloud bot
b12a1306eb [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-13 02:22:23 +00:00
Julius Härtl
1175c8b605 Merge pull request #4103 from nextcloud/fix/24-no-card-menu-without-description 2022-10-11 14:53:35 +02:00
Nextcloud bot
4b06ef3ac0 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-08 02:21:52 +00:00
Marcel Klehr
5f59f485f2 Merge pull request #4019 from nextcloud/backport/4014/stable24 2022-10-07 12:07:41 +02:00
Marcel Klehr
2f28015b91 Fix Card menu not displaying when description is not set
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
2022-10-07 11:40:31 +02:00
Nextcloud bot
675aff612d [tx-robot] Update transifex configuration
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-07 02:21:55 +00:00
Nextcloud bot
9ad65af60e [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-06 02:26:16 +00:00
Nextcloud bot
2210c05e28 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-05 02:21:23 +00:00
Côme Chilliet
a189139a04 Merge pull request #4093 from nextcloud/migrate-stable24-christophwurst-package
Migrate to nextcloud/OCP package in stable24
2022-10-02 10:39:09 +02:00
Joas Schilling
c6a209c63a Migrate to nextcloud/OCP package in stable24
Signed-off-by: Joas Schilling <coding@schilljs.com>
2022-10-02 09:18:23 +02:00
Nextcloud bot
1968d8493b [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-01 02:24:38 +00:00
Nextcloud bot
a94eb0cd31 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-30 03:23:40 +00:00
Nextcloud bot
b2bbf31f46 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-28 02:46:17 +00:00
Nextcloud bot
2b959c10dd [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-26 02:47:18 +00:00
Nextcloud bot
81669635c5 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-24 02:47:23 +00:00
Nextcloud bot
7350a2a811 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-23 02:42:09 +00:00
Nextcloud bot
e677cbcdac [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-22 02:45:48 +00:00
Nextcloud bot
6d7461d0d1 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-20 02:45:57 +00:00
Nextcloud bot
86d94166f0 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-17 02:45:14 +00:00
Nextcloud bot
a664545ebf [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-16 02:39:38 +00:00
Nextcloud bot
360bd4192b [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-15 02:45:09 +00:00
Nextcloud bot
da3f2b8ee4 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-14 02:39:54 +00:00
Nextcloud bot
78aa411e09 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-13 02:40:41 +00:00
Nextcloud bot
2d318c0ac1 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-12 02:39:42 +00:00
Nextcloud bot
b58f598044 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-09 02:40:41 +00:00
Julien Veyssier
bad2a19be6 Merge pull request #4037 from nextcloud/backport/4036/stable24
[stable24] Fix attachment creator name: show display name
2022-09-08 12:23:00 +02:00
Julien Veyssier
a89bdab5e3 fix tests
Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
2022-09-08 12:09:23 +02:00
Julien Veyssier
5b2c03f733 refs #4035 fix attachment creator name: show display name instead of user id
Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
2022-09-08 12:09:23 +02:00
Nextcloud bot
552e10d79d [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-08 02:40:32 +00:00
Nextcloud bot
40f39fa21a [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-07 02:40:01 +00:00
Nextcloud bot
d5c1833638 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-06 02:39:38 +00:00
Nextcloud bot
36dd98c93e [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-05 02:38:59 +00:00
Nextcloud bot
ccbec7f5ac [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-04 02:38:02 +00:00
Nextcloud bot
0359e89b22 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-03 02:44:35 +00:00
Robin Appelman
e9f8634334 disable Create card button while no stack is chosen
make the `isBoardAndStackChoosen` method do what it says

Signed-off-by: Robin Appelman <robin@icewind.nl>
2022-09-02 11:12:41 +00:00
Nextcloud bot
1889c0c4f9 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-09-01 02:50:07 +00:00
Nextcloud bot
1ac501db79 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-28 02:36:32 +00:00
Nextcloud bot
c9ddd4f997 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-27 02:36:44 +00:00
Julius Härtl
e8a0d7c47c Merge pull request #3997 from nextcloud/backport/3980/stable24 2022-08-26 10:50:27 +02:00
Julius Härtl
8ace53bfe2 Make CappedMemoryCache usage compatible with older releases
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-08-26 10:07:59 +02:00
Raul Ferreira Fuentes
89c3490015 Merge pull request #3995 from nextcloud/backport/3982/stable24
[stable24] Improve CalDAV integration performance
2022-08-25 12:13:48 +00:00
Julius Härtl
72bc2f438a Use capped memory cache for board permissions
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-08-25 10:47:40 +00:00
Julius Härtl
1183459608 Avoid fetching archived cards for calendars
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-08-25 10:47:32 +00:00
Julius Härtl
a4e6c7b746 Avoid querying each card when getting the calendars only
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-08-25 10:47:32 +00:00
Nextcloud bot
b99fb6e8f6 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-24 02:39:41 +00:00
Nextcloud bot
f613a60f7c [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-22 02:37:15 +00:00
Nextcloud bot
7c77cde669 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-21 02:36:35 +00:00
Nextcloud bot
9a7bde4cbd [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-20 02:36:58 +00:00
Nextcloud bot
b807a71f1f [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-13 02:37:50 +00:00
Nextcloud bot
33942236f0 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-12 02:36:56 +00:00
Nextcloud bot
3dd3301ffc [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-09 02:36:37 +00:00
Julius Härtl
0d310d317e Merge pull request #3959 from nextcloud/backport/3952/stable24 2022-08-08 09:32:39 +02:00
Julius Härtl
82515e5731 Fetch attachment folder for the correct user during cron job
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-08-08 07:00:52 +00:00
Nextcloud bot
4cd4707559 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-07 02:40:59 +00:00
Nextcloud bot
90c14861c4 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-06 02:37:35 +00:00
Nextcloud bot
17a51501ec [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-05 02:13:42 +00:00
Nextcloud bot
86707f18dd [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-03 02:13:43 +00:00
Julius Härtl
a28cd746f1 Merge pull request #3925 from nextcloud/backport/3898/stable24
[stable24] Switch to 'markdown-it-task-checkbox' for rendering of task lists
2022-08-01 22:06:14 +02:00
Nextcloud bot
10ad995cd0 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-29 02:13:34 +00:00
Nextcloud bot
856c5f50c4 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-28 02:13:40 +00:00
Nextcloud bot
0a9d96d964 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-27 02:13:38 +00:00
Nextcloud bot
1d15921a57 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-25 02:39:10 +00:00
Nextcloud bot
b9826cb29f [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-24 02:40:48 +00:00
Nextcloud bot
94c13bbbdb [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-23 02:38:35 +00:00
Nextcloud bot
549f9c9045 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-21 02:38:53 +00:00
q-wertz
ac16521404 Switch to 'markdown-it-task-checkbox' for rendering of task lists
Signed-off-by: q-wertz <clemens.sonnleitner@web.de>
2022-07-19 09:33:39 +02:00
Nextcloud bot
4be298f537 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-19 02:38:00 +00:00
Nextcloud bot
10dead9d9f [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-18 02:37:16 +00:00
Nextcloud bot
f9cb601a99 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-14 02:37:44 +00:00
Julius Härtl
efdd3b0056 Merge pull request #3917 from nextcloud/backport/3916/stable24
[stable24] Prevent opening card and applyLabelFilter on card drag end
2022-07-12 16:37:01 +02:00
Julien Veyssier
a18f550dc1 refs #2594 prevent opening card and applyLabelFilter on card drag end
Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
2022-07-12 11:57:22 +00:00
Nextcloud bot
d808b9fef7 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-08 02:37:16 +00:00
Nextcloud bot
f4742259f2 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-06 02:35:55 +00:00
Julius Härtl
3fe5da0ee1 Merge pull request #3901 from nextcloud/backport/3833/stable24
[stable24] Fix for issue #3637
2022-07-05 14:30:09 +02:00
Thomas Flummer
17ae3a9a39 Fix for issue #3637
Added padding on nested ul, to compensate for the negative margin on the containing li

Signed-off-by: Thomas Flummer <tf@flummer.net>
2022-07-05 10:41:38 +00:00
Nextcloud bot
1ff588a15a [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-04 02:35:49 +00:00
Nextcloud bot
2bb04ef298 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-07-02 02:37:23 +00:00
Raul Ferreira Fuentes
055dda909e Merge pull request #3885 from nextcloud/backport/3884/stable24
[stable24] Fix z-index for deck sidebar
2022-06-28 15:26:18 +02:00
Raul
f364709318 Fix z-index for deck sidebar
The sidebar would previously render above the user menu (logout, settings, etc)

Signed-off-by: Raul <r.ferreira.fuentes@gmail.com>
2022-06-28 12:40:36 +00:00
Nextcloud bot
84de1c0198 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-06-22 02:40:26 +00:00
Nextcloud bot
413017d333 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-06-14 02:41:52 +00:00
Nextcloud bot
5c069e5413 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-06-12 02:41:04 +00:00
Nextcloud bot
9d9cdb0f95 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-06-09 02:45:32 +00:00
Nextcloud bot
74f45e2e54 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-06-07 02:44:07 +00:00
Nextcloud bot
f82c48ad29 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-06-03 02:47:52 +00:00
Nextcloud bot
ece052a20d [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-06-02 02:47:09 +00:00
Luka Trovic
8a9a36ed10 Merge pull request #3847 from nextcloud/release/1.7.1
release/1.7.1
2022-06-01 13:36:59 +02:00
Luka Trovic
82f2a2c363 changes for 1.7.1
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2022-05-30 08:21:03 +02:00
Nextcloud bot
3016659c81 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-29 02:46:53 +00:00
Nextcloud bot
b9ab0f14ab [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-28 02:43:24 +00:00
Nextcloud bot
2d90ed7414 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-26 02:44:17 +00:00
Nextcloud bot
5d87f05994 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-24 02:47:12 +00:00
Nextcloud bot
9ef183bcaa [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-23 02:43:45 +00:00
Nextcloud bot
34f18fbd7d [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-22 02:43:40 +00:00
Nextcloud bot
27fa2bbc54 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-21 02:47:13 +00:00
Nextcloud bot
03a88327a5 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-20 02:46:27 +00:00
Julius Härtl
67ac21e688 Merge pull request #3815 from nextcloud/backport/3811/stable24
[stable24] Align Duedate-delete icon properly - fixes nextcloud/deck#3791
2022-05-13 09:34:37 +02:00
Nextcloud bot
e90f32ca32 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-13 02:41:48 +00:00
ben
b21e65027c Align Duedate-delete icon properly - fixes nextcloud/deck#3791
Signed-off-by: ben <ben@ro.tt>
2022-05-12 14:54:17 +00:00
Julius Härtl
b628532def Merge pull request #3804 from nextcloud/backport/3682/stable24
[stable24] Increase file count after sharing
2022-05-12 09:18:37 +02:00
Julius Härtl
e0b2755b7c Fix php-cs-fixer failure
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-05-12 09:09:20 +02:00
Julius Härtl
9e1fbb9852 Move all caching to helper
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-05-11 14:43:32 +00:00
Luka Trovic
047ca3e203 fix: move shares count cache logic to the DeckShareProvider
Signed-off-by: Luka Trovic <luka@nextcloud.com>

fix: conflicts

Signed-off-by: Luka Trovic <luka@nextcloud.com>

fix: conflicts and test issues

Signed-off-by: Luka Trovic <luka@nextcloud.com>
2022-05-11 14:43:31 +00:00
Luka Trovic
bfcd5357e3 fix: update attachments count when sharing
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2022-05-11 14:43:30 +00:00
Luka Trovic
461ed6b81f fix: increase file count after sharing
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2022-05-11 14:43:29 +00:00
Nextcloud bot
ee2969fc5b [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-06 02:41:15 +00:00
Nextcloud bot
ca32ebd9cb [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-05 02:41:05 +00:00
Julius Härtl
4a29617fed Merge pull request #3779 from nextcloud/backport/3777/stable24
[stable24] Fetch full board data after cloning
2022-05-04 17:17:07 +02:00
Julius Härtl
8eab97a92a Fetch full board data after cloning
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-05-04 10:29:18 +00:00
Nextcloud bot
f453f69cce [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-04 02:42:57 +00:00
Nextcloud bot
8ca84147e8 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-03 02:41:23 +00:00
Julius Härtl
5e3ddd83fc Bump version to 1.7.0
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-05-02 16:43:48 +02:00
Julius Härtl
6b985463d8 Merge pull request #3769 from nextcloud/bugfix/noid/stable24-psalm
Handle qb mapper exception messages properly
2022-04-29 17:28:20 +02:00
Julius Härtl
25e0ae2670 Bump version to 1.7.0-rc.1
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-04-29 16:17:24 +02:00
Julius Härtl
614c6fbdba Handle qb mapper exception messages properly
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-04-29 15:45:07 +02:00
Julius Härtl
8efe415558 Merge pull request #3765 from nextcloud/backport/3761/stable24
[stable24] Fix text selection in dark mode and modal view
2022-04-29 15:41:06 +02:00
Julius Härtl
f3ad2a3709 Fix text selection in dark mode and modal view
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-04-29 09:33:06 +00:00
Julius Härtl
25dd71ba04 Merge pull request #3764 from nextcloud/backport/3762/stable24
[stable24] Adapt the card modal to upstream changes
2022-04-29 11:09:08 +02:00
Julius Härtl
a514e6e168 Adapt modal size to viewer upstream changes
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-04-29 08:47:21 +00:00
Julius Härtl
cb5553ea94 Merge pull request #3754 from nextcloud/backport/3745/stable24
[stable24] Add missing indices
2022-04-28 10:10:31 +02:00
Julius Härtl
335ee31c7c Add missing indices
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2022-04-26 16:26:17 +00:00
Julius Härtl
9b4379727d Merge pull request #3736 from nextcloud/backport/3681/stable24
[stable24] Show cards after moving into another list
2022-04-20 18:14:34 +02:00
Julius Härtl
a5fe2f59be Merge pull request #3733 from nextcloud/backport/3692/stable24
[stable24] Fix hidden attachment icon on archived cards
2022-04-20 18:14:13 +02:00
Luka Trovic
1b58f7854e fix: feedback
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2022-04-20 14:24:24 +00:00
Luka Trovic
b6effa468f fix: show card after moving into another list
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2022-04-20 14:24:24 +00:00
Luka Trovic
2b512b88c4 fix: hidden attachment icon on archived cards
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2022-04-20 14:22:23 +00:00
Julius Härtl
5cb61cba90 Merge pull request #3723 from nextcloud/update-stable24-target-versions
Update stable24 target versions
2022-04-19 15:38:37 +02:00
Joas Schilling
0657efe239 Update stable24 target versions
Signed-off-by: Joas Schilling <coding@schilljs.com>
2022-04-14 22:09:00 +02:00
260 changed files with 11083 additions and 18989 deletions

View File

@@ -1,29 +0,0 @@
{
"image": "ghcr.io/juliushaertl/nextcloud-dev-php80:latest",
"forwardPorts": [80],
"containerEnv": {
"NEXTCLOUD_AUTOINSTALL_APPS": "deck",
"XDEBUG_MODE": "debug"
},
"customizations": {
"vscode": {
"extensions": [
"felixfbecker.php-intellisense",
"octref.vetur"
],
"settings": {
"php.suggest.basic": false,
"git.alwaysSignOff": true
}
}
},
"workspaceMount": "source=${localWorkspaceFolder},target=/var/www/html/apps-extra/deck,type=bind",
"workspaceFolder": "/var/www/html/apps-extra/deck",
"overrideCommand": true,
"postAttachCommand": "bash ./.devcontainer/setup.sh",
"portsAttributes": {
"80": {
"label": "Webserver"
}
}
}

View File

@@ -1,9 +0,0 @@
#!/bin/bash
(
cd /tmp && /usr/local/bin/bootstrap.sh apache2ctl start
)
composer install --no-dev
npm ci
npm run dev

View File

@@ -3,10 +3,7 @@ root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = tab
indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
[*.{js,vue}]
indent_style = tab

View File

@@ -1,5 +1,4 @@
module.exports = {
root: true,
extends: [
'@nextcloud',
],
@@ -8,7 +7,6 @@ module.exports = {
'jsdoc/require-param-type': ['off'],
'jsdoc/check-param-names': ['off'],
'jsdoc/no-undefined-types': ['off'],
'jsdoc/require-property-description': ['off'],
'import/no-named-as-default-member': ['off'],
'jsdoc/require-property-description' : ['off']
},
}

View File

@@ -2,7 +2,7 @@ version: 2
updates:
- package-ecosystem: npm
directory: "/"
target-branch: "main"
target-branch: "master"
schedule:
interval: weekly
day: saturday
@@ -11,41 +11,6 @@ updates:
open-pull-requests-limit: 10
reviewers:
- juliushaertl
- package-ecosystem: npm
target-branch: stable25
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: stable24
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: composer
directory: "/"
schedule:

View File

@@ -1,6 +1,6 @@
* Resolves: # <!-- related github issue -->
* Target version: main
* Target version: master
### Summary

View File

@@ -1,11 +1,7 @@
name: Package build
on:
push:
branches:
- main
- master
- stable*
pull_request:
jobs:
build:
@@ -13,7 +9,7 @@ jobs:
strategy:
matrix:
node-version: [16.x]
node-version: [14.x]
steps:
- uses: actions/checkout@v3
@@ -24,14 +20,14 @@ jobs:
- name: Set up npm7
run: npm i -g npm@7
- name: Setup PHP
uses: shivammathur/setup-php@2.25.1
uses: shivammathur/setup-php@2.18.0
with:
php-version: '7.4'
tools: composer
- name: install dependencies
run: |
wget https://github.com/ChristophWurst/krankerl/releases/download/v0.14.0/krankerl_0.14.0_amd64.deb
sudo dpkg -i krankerl_0.14.0_amd64.deb
wget https://github.com/ChristophWurst/krankerl/releases/download/v0.12.2/krankerl_0.12.2_amd64.deb
sudo dpkg -i krankerl_0.12.2_amd64.deb
- name: package
run: |
uname -a

View File

@@ -10,7 +10,7 @@ on:
types: [published]
env:
PHP_VERSION: 8.1
PHP_VERSION: 7.4
jobs:
build_and_publish:
@@ -21,42 +21,42 @@ jobs:
steps:
- name: Check actor permission
uses: skjnldsv/check-actor-permission@e591dbfe838300c007028e1219ca82cc26e8d7c5 # v2.1
uses: skjnldsv/check-actor-permission@v2
with:
require: write
- name: Set app env
run: |
# Split and keep last
# Split and keep last
echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
echo "APP_VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
uses: actions/checkout@v3
with:
path: ${{ env.APP_NAME }}
- name: Get appinfo data
id: appinfo
uses: skjnldsv/xpath-action@7e6a7c379d0e9abc8acaef43df403ab4fc4f770c # master
uses: skjnldsv/xpath-action@master
with:
filename: ${{ env.APP_NAME }}/appinfo/info.xml
expression: "//info//dependencies//nextcloud/@min-version"
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@0ce2ed60f6df073a62a77c0a4958dd0fc68e32e7 # v2.1
uses: skjnldsv/read-package-engines-version-actions@v1.2
id: versions
# Continue if no package.json
continue-on-error: true
with:
path: ${{ env.APP_NAME }}
fallbackNode: "^16"
fallbackNpm: "^7"
fallbackNode: "^12"
fallbackNpm: "^6"
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
# Skip if no package.json
if: ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # v3
uses: actions/setup-node@v3
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
@@ -66,16 +66,14 @@ jobs:
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
- name: Set up php ${{ env.PHP_VERSION }}
uses: shivammathur/setup-php@2.25.1 # v2
uses: shivammathur/setup-php@2.18.0
with:
php-version: ${{ env.PHP_VERSION }}
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check composer.json
id: check_composer
uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2
uses: andstor/file-existence-action@v1
with:
files: "${{ env.APP_NAME }}/composer.json"
@@ -93,29 +91,16 @@ jobs:
npm ci
npm run build
- name: Check Krankerl config
id: krankerl
uses: andstor/file-existence-action@20b4d2e596410855db8f9ca21e96fbe18e12930b # v2
with:
files: ${{ env.APP_NAME }}/krankerl.toml
- name: Install Krankerl
if: steps.krankerl.outputs.files_exists == 'true'
run: |
wget https://github.com/ChristophWurst/krankerl/releases/download/v0.14.0/krankerl_0.14.0_amd64.deb
sudo dpkg -i krankerl_0.14.0_amd64.deb
wget https://github.com/ChristophWurst/krankerl/releases/download/v0.13.0/krankerl_0.13.0_amd64.deb
sudo dpkg -i krankerl_0.13.0_amd64.deb
- name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with krankerl
if: steps.krankerl.outputs.files_exists == 'true'
- name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }}
# Try krankerl, fallback to makefile
run: |
cd ${{ env.APP_NAME }}
krankerl package
- name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with makefile
if: steps.krankerl.outputs.files_exists != 'true'
run: |
cd ${{ env.APP_NAME }}
make appstore
krankerl package || make appstore
- name: Checkout server ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}
continue-on-error: true
@@ -126,7 +111,7 @@ jobs:
unzip latest-$NCVERSION.zip
- name: Checkout server master fallback
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
uses: actions/checkout@v3
if: ${{ steps.server-checkout.outcome != 'success' }}
with:
repository: nextcloud/server
@@ -148,7 +133,7 @@ jobs:
tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }}
- name: Attach tarball to github release
uses: svenstaro/upload-release-action@7319e4733ec7a184d739a6f412c40ffc339b69c7 # v2
uses: svenstaro/upload-release-action@v2
id: attach_to_release
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
@@ -158,7 +143,7 @@ jobs:
overwrite: true
- name: Upload app to Nextcloud appstore
uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 # v1
uses: nextcloud-releases/nextcloud-appstore-push-action@v1
with:
app_name: ${{ env.APP_NAME }}
appstore_token: ${{ secrets.APPSTORE_TOKEN }}

View File

@@ -9,21 +9,16 @@ on:
issue_comment:
types: created
permissions:
contents: read
jobs:
rebase:
runs-on: ubuntu-latest
permissions:
contents: none
# On pull requests and if the comment starts with `/rebase`
if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/rebase')
steps:
- name: Add reaction on start
uses: peter-evans/create-or-update-comment@ca08ebd5dc95aa0cd97021e9708fcd6b87138c9b # v3.0.1
uses: peter-evans/create-or-update-comment@v2
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
repository: ${{ github.event.repository.full_name }}
@@ -31,18 +26,18 @@ jobs:
reaction-type: "+1"
- name: Checkout the latest code
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
uses: actions/checkout@v3
with:
fetch-depth: 0
token: ${{ secrets.COMMAND_BOT_PAT }}
- name: Automatic Rebase
uses: cirrus-actions/rebase@6e572f08c244e2f04f9beb85a943eb618218714d # 1.7
uses: cirrus-actions/rebase@1.5
env:
GITHUB_TOKEN: ${{ secrets.COMMAND_BOT_PAT }}
- name: Add reaction on failure
uses: peter-evans/create-or-update-comment@ca08ebd5dc95aa0cd97021e9708fcd6b87138c9b # v3.0.1
uses: peter-evans/create-or-update-comment@v2
if: failure()
with:
token: ${{ secrets.COMMAND_BOT_PAT }}

View File

@@ -1,124 +0,0 @@
name: Cypress
on:
pull_request:
push:
branches:
- main
- stable*
env:
APP_NAME: deck
CYPRESS_baseUrl: http://localhost:8081/index.php
jobs:
cypress:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [14.x]
# containers: [1, 2, 3]
php-versions: [ '8.0' ]
databases: [ 'sqlite' ]
server-versions: [ 'stable27' ]
steps:
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Set up npm7
run: npm i -g npm@7
- name: Register text Git reference
run: |
text_app_ref="$(if [ "${{ matrix.server-versions }}" = "master" ]; then echo -n "main"; else echo -n "${{ matrix.server-versions }}"; fi)"
echo "text_app_ref=$text_app_ref" >> $GITHUB_ENV
- name: Checkout server
uses: actions/checkout@v3
with:
repository: nextcloud/server
ref: ${{ matrix.server-versions }}
- name: Checkout submodules
shell: bash
run: |
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
git submodule sync --recursive
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
- name: Checkout ${{ env.APP_NAME }}
uses: actions/checkout@v3
with:
path: apps/${{ env.APP_NAME }}
- name: Checkout text
uses: actions/checkout@v3
with:
repository: nextcloud/text
ref: ${{ env.text_app_ref }}
path: apps/text
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2.25.1
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, zip, gd, apcu
ini-values:
apc.enable_cli=on
coverage: none
- name: Set up Nextcloud
env:
DB_PORT: 4444
PHP_CLI_SERVER_WORKERS: 10
run: |
mkdir data
php occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
php occ config:system:set memcache.local --value="\\OC\\Memcache\\APCu"
php occ config:system:set debug --value=true --type=boolean
php -f index.php
php -S 0.0.0.0:8081 &
export OC_PASS=1234561
php occ user:add --password-from-env user1
php occ user:add --password-from-env user2
php occ app:enable deck
php occ app:list
cd apps/deck
composer install --no-dev
npm ci
npm run build
cd ../../
curl -v http://localhost:8081/index.php/login
- name: Cypress run
uses: cypress-io/github-action@v5
with:
record: true
parallel: false
wait-on: '${{ env.CYPRESS_baseUrl }}'
working-directory: 'apps/${{ env.APP_NAME }}'
config: defaultCommandTimeout=10000,video=false
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
npm_package_name: ${{ env.APP_NAME }}
- name: Upload test failure screenshots
uses: actions/upload-artifact@v3
if: failure()
with:
name: Upload screenshots
path: apps/${{ env.APP_NAME }}/cypress/screenshots/
retention-days: 5
- name: Upload nextcloud logs
uses: actions/upload-artifact@v3
if: failure()
with:
name: Upload nextcloud log
path: data/nextcloud.log
retention-days: 5

View File

@@ -8,33 +8,22 @@ name: Dependabot
on:
pull_request_target:
branches:
- main
- master
- stable*
permissions:
contents: read
concurrency:
group: dependabot-approve-merge-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
auto-approve-merge:
if: github.actor == 'dependabot[bot]'
runs-on: ubuntu-latest
permissions:
# for hmarr/auto-approve-action to approve PRs
pull-requests: write
steps:
# Github actions bot approve
- uses: hmarr/auto-approve-action@b40d6c9ed2fa10c9a2749eca7eb004418a705501 # v2
- uses: hmarr/auto-approve-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# Nextcloud bot approve and merge request
- uses: ahmadnassri/action-dependabot-auto-merge@45fc124d949b19b6b8bf6645b6c9d55f4f9ac61a # v2
- uses: ahmadnassri/action-dependabot-auto-merge@v2
with:
target: minor
github-token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN }}

View File

@@ -5,29 +5,16 @@
name: Pull request checks
on:
pull_request:
types: [opened, ready_for_review, reopened, synchronize]
permissions:
contents: read
concurrency:
group: fixup-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on: pull_request
jobs:
commit-message-check:
if: github.event.pull_request.draft == false
commit-message-check:
name: Block fixup and squash commits
permissions:
pull-requests: write
name: Block fixup and squash commits
runs-on: ubuntu-latest
runs-on: ubuntu-latest
steps:
- name: Run check
uses: xt0rted/block-autosquash-commits-action@79880c36b4811fe549cfffe20233df88876024e7 # v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Run check
uses: xt0rted/block-autosquash-commits-action@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -2,17 +2,8 @@ name: Integration tests
on:
pull_request:
paths:
- '.github/workflows/integration.yml'
- 'appinfo/**'
- 'lib/**'
- 'templates/**'
- 'tests/**'
- 'composer.json'
- 'composer.lock'
push:
branches:
- main
- master
- stable*
@@ -26,9 +17,9 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['8.1']
php-versions: ['7.4']
databases: ['sqlite', 'mysql', 'pgsql']
server-versions: ['stable27']
server-versions: ['stable24']
name: php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }}
@@ -63,7 +54,7 @@ jobs:
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
git submodule sync --recursive
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
cd build/integration && composer require --dev phpunit/phpunit:~9
cd build/integration && composer require --dev phpunit/phpunit:~8
- name: Checkout app
uses: actions/checkout@v3
@@ -71,17 +62,16 @@ jobs:
path: apps/${{ env.APP_NAME }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2.25.1
uses: shivammathur/setup-php@2.18.0
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, mysql, pdo_mysql, pgsql, pdo_pgsql, apcu
ini-values:
apc.enable_cli=on
tools: phpunit
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, mysql, pdo_mysql, pgsql, pdo_pgsql,
coverage: none
- name: Set up dependencies
- name: Set up PHPUnit
working-directory: apps/${{ env.APP_NAME }}
run: composer i --no-dev
run: composer i
- name: Set up Nextcloud
run: |
@@ -92,63 +82,11 @@ jobs:
fi
mkdir data
./occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
./occ config:system:set hashing_default_password --value=true --type=boolean
./occ config:system:set memcache.local --value="\\OC\\Memcache\\APCu"
./occ config:system:set memcache.distributed --value="\\OC\\Memcache\\APCu"
cat config/config.php
./occ user:list
./occ app:enable --force ${{ env.APP_NAME }}
./occ config:system:set query_log_file --value '/home/runner/work/${{ env.APP_NAME }}/${{ env.APP_NAME }}/query.log'
php -S localhost:8080 &
- name: Run behat
working-directory: apps/${{ env.APP_NAME }}/tests/integration
run: ./run.sh
- name: Query count
if: ${{ matrix.databases == 'mysql' }}
uses: actions/github-script@v6
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
let myOutput = ''
let myError = ''
const options = {}
options.listeners = {
stdout: (data) => {
myOutput += data.toString()
},
stderr: (data) => {
myError += data.toString()
}
}
await exec.exec(`/bin/bash -c "cat /home/runner/work/${{ env.APP_NAME }}/${{ env.APP_NAME }}/query.log | wc -l"`, [], options)
msg = myOutput
const queryCount = parseInt(myOutput, 10)
myOutput = ''
await exec.exec('cat', ['/home/runner/work/${{ env.APP_NAME }}/${{ env.APP_NAME }}/apps/${{ env.APP_NAME }}/tests/integration/base-query-count.txt'], options)
const baseCount = parseInt(myOutput, 10)
const absoluteIncrease = queryCount - baseCount
const relativeIncrease = baseCount <= 0 ? 100 : (parseInt((absoluteIncrease / baseCount * 10000), 10) / 100)
if (absoluteIncrease >= 100 || relativeIncrease > 5) {
const comment = `🐢 Performance warning.\nIt looks like the query count of the integration tests increased with this PR.\nDatabase query count is now ` + queryCount + ' was ' + baseCount + ' (+' + relativeIncrease + '%)\nPlease check your code again. If you added a new test this can be expected and the base value in tests/integration/base-query-count.txt can be increased.'
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
})
}
if (queryCount < 100) {
const comment = `🐈 Performance messuring seems broken. Failed to get query count.`
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
})
}

View File

@@ -1,62 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# Use lint-eslint together with lint-eslint-when-unrelated to make eslint a required check for GitHub actions
# https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks
name: Lint
on:
pull_request:
paths:
- '.github/workflows/**'
- 'src/**'
- 'appinfo/info.xml'
- 'package.json'
- 'package-lock.json'
- 'tsconfig.json'
- '.eslintrc.*'
- '.eslintignore'
- '**.js'
- '**.ts'
- '**.vue'
permissions:
contents: read
concurrency:
group: lint-eslint-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
name: eslint
steps:
- name: Checkout
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@0ce2ed60f6df073a62a77c0a4958dd0fc68e32e7 # v2.1
id: versions
with:
fallbackNode: '^16'
fallbackNpm: '^7'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # v3
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run lint

View File

@@ -1,39 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
name: Lint
on: pull_request
permissions:
contents: read
concurrency:
group: lint-php-cs-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
name: php-cs
steps:
- name: Checkout
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Set up php
uses: shivammathur/setup-php@2.25.1 # v2
with:
php-version: 8.1
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
run: composer i
- name: Lint
run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 )

View File

@@ -1,59 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
name: Lint
on:
pull_request:
push:
branches:
- main
- master
- stable*
permissions:
contents: read
concurrency:
group: lint-php-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
php-lint:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: [ "8.0", "8.1", "8.2" ]
name: php-lint
steps:
- name: Checkout
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2.25.1 # v2
with:
php-version: ${{ matrix.php-versions }}
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Lint
run: composer run lint
summary:
permissions:
contents: none
runs-on: ubuntu-latest
needs: php-lint
if: always()
name: php-lint-summary
steps:
- name: Summary status
run: if ${{ needs.php-lint.result != 'success' && needs.php-lint.result != 'skipped' }}; then exit 1; fi

View File

@@ -1,46 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
name: Lint
on: pull_request
permissions:
contents: read
concurrency:
group: lint-stylelint-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
name: stylelint
steps:
- name: Checkout
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@0ce2ed60f6df073a62a77c0a4958dd0fc68e32e7 # v2.1
id: versions
with:
fallbackNode: '^16'
fallbackNpm: '^7'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # v3
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run stylelint

88
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,88 @@
name: Lint
on:
pull_request:
push:
branches:
- master
- stable*
jobs:
php:
runs-on: ubuntu-latest
strategy:
matrix:
php-versions: ['7.4', '8.0', '8.1']
name: php${{ matrix.php-versions }} lint
steps:
- uses: actions/checkout@v3
- name: Set up php${{ matrix.php-versions }}
uses: shivammathur/setup-php@2.18.0
with:
php-version: ${{ matrix.php-versions }}
coverage: none
- name: Lint
run: composer run lint
php-cs-fixer:
name: php-cs check
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up php
uses: shivammathur/setup-php@2.18.0
with:
php-version: 7.4
coverage: none
- name: Install dependencies
run: composer i
- name: Run coding standards check
run: composer run cs:check
node:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v3
- name: Use node ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Set up npm7
run: npm i -g npm@7
- name: Install dependencies
run: npm ci
- name: ESLint
run: npm run lint
stylelint:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
name: stylelint node${{ matrix.node-version }}
steps:
- uses: actions/checkout@v3
- name: Set up node ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: Set up npm7
run: npm i -g npm@7
- name: Install dependencies
run: npm ci
- name: Lint
run: npm run stylelint

View File

@@ -25,7 +25,7 @@ jobs:
- name: Set up npm7
run: npm i -g npm@7
- name: Setup PHP
uses: shivammathur/setup-php@2.25.1
uses: shivammathur/setup-php@2.18.0
with:
php-version: '7.4'
tools: composer
@@ -44,14 +44,14 @@ jobs:
git config --local user.name "GitHub Action"
git tag -f nightly
- name: Push tag
uses: juliushaertl/github-push-action@main
uses: juliushaertl/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
tags: true
force: true
- name: Create Release
id: create_release
uses: juliushaertl/action-release@main
uses: juliushaertl/action-release@master
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag: nightly

View File

@@ -1,71 +0,0 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
name: npm audit fix and compile
on:
workflow_dispatch:
schedule:
# At 2:30 on Sundays
- cron: '30 2 * * 0'
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
branches: ["main", "master", "stable26", "stable25", "stable24"]
name: npm-audit-fix-${{ matrix.branches }}
steps:
- name: Checkout
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
with:
ref: ${{ matrix.branches }}
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@0ce2ed60f6df073a62a77c0a4958dd0fc68e32e7 # v2.1
id: versions
with:
fallbackNode: '^16'
fallbackNpm: '^7'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@8c91899e586c5b171469028077307d293428b516 # v3
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
- name: Fix npm audit
run: |
npm audit fix
- name: Run npm ci and npm run build
if: always()
run: |
npm ci
npm run build --if-present
- name: Create Pull Request
if: always()
uses: peter-evans/create-pull-request@284f54f989303d2699d373481a0cfa13ad5a6666 # v3
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: "chore(deps): fix npm audit"
committer: GitHub <noreply@github.com>
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
signoff: true
branch: automated/noid/${{ matrix.branches }}-fix-npm-audit
title: "[${{ matrix.branches }}] Fix npm audit"
body: |
Auto-generated fix of npm audit
labels: |
dependencies
3. to review

View File

@@ -2,14 +2,6 @@ name: PHPUnit
on:
pull_request:
paths:
- '.github/workflows/phpunit.yml'
- 'appinfo/**'
- 'lib/**'
- 'templates/**'
- 'tests/**'
- 'composer.json'
- 'composer.lock'
push:
branches:
- master
@@ -26,9 +18,9 @@ jobs:
strategy:
fail-fast: false
matrix:
php-versions: ['8.0', '8.1']
php-versions: ['7.4', '8.0', '8.1']
databases: ['sqlite', 'mysql', 'pgsql']
server-versions: ['stable27']
server-versions: ['stable24']
name: php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }}
@@ -70,7 +62,7 @@ jobs:
path: apps/${{ env.APP_NAME }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2.25.1
uses: shivammathur/setup-php@2.18.0
with:
php-version: ${{ matrix.php-versions }}
tools: phpunit

View File

@@ -13,10 +13,6 @@ on:
- main
- stable*
concurrency:
group: psalm-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
static-analysis:
runs-on: ubuntu-latest
@@ -24,15 +20,13 @@ jobs:
name: Nextcloud
steps:
- name: Checkout
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
uses: actions/checkout@v3
- name: Set up php
uses: shivammathur/setup-php@2.25.1 # v2
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
php-version: 7.4
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
run: composer i

View File

@@ -17,24 +17,22 @@ jobs:
strategy:
fail-fast: false
matrix:
branches: ["master", "stable26", "stable25", "stable24"]
branches: ["master", "stable25", "stable24", "stable23"]
name: update-nextcloud-ocp-${{ matrix.branches }}
steps:
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- uses: actions/checkout@v3
with:
ref: ${{ matrix.branches }}
submodules: true
- name: Set up php8.1
uses: shivammathur/setup-php@2.25.1 # v2
- name: Set up php7.4
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
php-version: 7.4
extensions: ctype,curl,dom,fileinfo,gd,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Composer install
run: composer install
@@ -47,15 +45,14 @@ jobs:
run: |
git clean -f 3rdparty
git clean -f vendor
git clean -f vendor-bin
git checkout 3rdparty vendor vendor-bin
git checkout 3rdparty vendor
continue-on-error: true
- name: Create Pull Request
uses: peter-evans/create-pull-request@284f54f989303d2699d373481a0cfa13ad5a6666 # v3
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: "chore(dev-deps): Bump nextcloud/ocp package"
commit-message: Update psalm baseline
committer: GitHub <noreply@github.com>
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
signoff: true

2
.gitignore vendored
View File

@@ -3,11 +3,9 @@ js/
build/
css/style.css
css/vendor.css
cypress/videos/
tests/integration/vendor/
tests/integration/composer.lock
tests/.phpunit.result.cache
vendor/
.php_cs.cache
\.idea/
settings.json

View File

@@ -1,6 +1,6 @@
[main]
host = https://www.transifex.com
lang_map = hu_HU: hu, nb_NO: nb, sk_SK: sk, th_TH: th, ja_JP: ja, bg_BG: bg, cs_CZ: cs, fi_FI: fi
lang_map = bg_BG: bg, cs_CZ: cs, fi_FI: fi, hu_HU: hu, nb_NO: nb, sk_SK: sk, th_TH: th, ja_JP: ja
[o:nextcloud:p:nextcloud:r:deck]
file_filter = translationfiles/<lang>/deck.po

View File

@@ -1,115 +1,51 @@
# Changelog
All notable changes to this project will be documented in this file.
## 1.10.0-beta.2
## 1.7.4
### Fixed
- fix: Properly overwrite z-index of datepicker above modal @juliushaertl [#4664](https://github.com/nextcloud/deck/pull/4664)
- Use the color-primary-element* variables @szaimen [#4673](https://github.com/nextcloud/deck/pull/4673)
- Dependency updates
- Gracefully handle not found card for a share [#4569](https://github.com/nextcloud/deck/pull/4569)
- fix: Use passed userid when getting attachment folder [#4541](https://github.com/nextcloud/deck/pull/4541)
- fix: Append datetime picker to body to avoid cut off [#4646](https://github.com/nextcloud/deck/pull/4646)
- Permanently delete deck cards marked as deleted after 5 min in a cron job [#4302](https://github.com/nextcloud/deck/pull/4302)
- Fix : Overlapping expiry dates on tags [#4538](https://github.com/nextcloud/deck/pull/4538)
- Update dependencies
### Other
- feat: Add devcontainer and update dev docs @juliushaertl [#4683](https://github.com/nextcloud/deck/pull/4683)
- chore(CI): Adjust testing matrix for Nextcloud 27 on stable27 @nickvergessen [#4691](https://github.com/nextcloud/deck/pull/4691)
## 1.10.0-beta.1
### Added
- Compatibility with Nextcloud 27
## 1.7.3
### Fixed
- fix(references): Mute NoPermissionException as it is expected to happen for references @juliushaertl [#4514](https://github.com/nextcloud/deck/pull/4514)
- fix(cards): Fix card sizing by limiting too wide style rules @juliushaertl [#4512](https://github.com/nextcloud/deck/pull/4512)
- fix: Adapt NcEmptyContent usages to new slots @juliushaertl [#4561](https://github.com/nextcloud/deck/pull/4561)
- Gracefully handle not found card for a share @mejo- [#4566](https://github.com/nextcloud/deck/pull/4566)
- Prevent tag itself being edit button if user lacks permissions @joshtrichards [#4574](https://github.com/nextcloud/deck/pull/4574)
- chore: Remove unused @nextcloud/vue-dashboard @juliushaertl [#4586](https://github.com/nextcloud/deck/pull/4586)
- Update Description.vue: Fixes the issue of hidden text by menu bar @pschopen [#4617](https://github.com/nextcloud/deck/pull/4617)
- allow user to toggle visibility of the calendar for a deck board @schiessle [#4622](https://github.com/nextcloud/deck/pull/4622)
- fix: Append datetime picker to body to avoid cut off @juliushaertl [#4643](https://github.com/nextcloud/deck/pull/4643)
- fix: Bring back overdue column by removing faulty condition @juliushaertl [#4660](https://github.com/nextcloud/deck/pull/4660)
- fix(sessions): Do not send close request without token @juliushaertl [#4510](https://github.com/nextcloud/deck/pull/4510)
- tests(integration): Add test for multiple board shares to the same user @juliushaertl [#4494](https://github.com/nextcloud/deck/pull/4494)
- fix(API): Fix board API details parameter to work as expected @nickvergessen [#4518](https://github.com/nextcloud/deck/pull/4518)
- Fix : Overlapping expiry dates on tags @Jerome-Herbinet [#4535](https://github.com/nextcloud/deck/pull/4535)
- Fix consistency of a "Create card" wording with its equivalent for Notes ("New card") @Jerome-Herbinet [#4534](https://github.com/nextcloud/deck/pull/4534)
- tests(integration): Add integration tests for due dates @juliushaertl [#4489](https://github.com/nextcloud/deck/pull/4489)
- Better display of card dates (creation and change dates) @Jerome-Herbinet [#4604](https://github.com/nextcloud/deck/pull/4604)
- Refactors lib\Activity\DeckProvider.php to improve code readability. @fsamapoor [#4648](https://github.com/nextcloud/deck/pull/4648)
- Converts 'strpos()' calls to improve code readability. @fsamapoor [#4657](https://github.com/nextcloud/deck/pull/4657)
- feat: add validators to check values in services @juliushaertl [#4176](https://github.com/nextcloud/deck/pull/4176)
- Add integration test for attachment handling on cards [#4178](https://github.com/nextcloud/deck/pull/4178)
- disables autocomplete on card creation @juliushaertl [#4182](https://github.com/nextcloud/deck/pull/4182)
- minor style fixes [#4202](https://github.com/nextcloud/deck/pull/4202)
## 1.9.0-beta.1
### Added
- Export Board @david-loe [#3065](https://github.com/nextcloud/deck/pull/3065)
- basic notify_push usage with session handling @alangecker [#3876](https://github.com/nextcloud/deck/pull/3876)
- feat(Description): Use text as editor if available @juliushaertl [#4399](https://github.com/nextcloud/deck/pull/4399)
- Improve reference provider and add reference widgets @julien-nc [#4422](https://github.com/nextcloud/deck/pull/4422)
- live updates 🎉 @alangecker [#4273](https://github.com/nextcloud/deck/pull/4273)
- Tag creation from card view @juliushaertl [#4344](https://github.com/nextcloud/deck/pull/4344)
## 1.7.2
### Fixed
- Fix component renaming so that acl works on shares again @small1 [#4315](https://github.com/nextcloud/deck/pull/4315)
- fix(Sidebar): Only close sidebar on v-click-outside for specific targets @juliushaertl [#4350](https://github.com/nextcloud/deck/pull/4350)
- add basic e2e tests for stack title @shoetten [#4206](https://github.com/nextcloud/deck/pull/4206)
- App metadata: add links to user and developer documentation @p-bo [#4356](https://github.com/nextcloud/deck/pull/4356)
- Update signature of Entity::markFieldUpdated @nickvergessen [#4398](https://github.com/nextcloud/deck/pull/4398)
- Remove updated nightly information @xf- [#4419](https://github.com/nextcloud/deck/pull/4419)
- perf: Register notifier and resource listener lazy @juliushaertl [#4439](https://github.com/nextcloud/deck/pull/4439)
- perf: Lazy load dashboard components @juliushaertl [#4440](https://github.com/nextcloud/deck/pull/4440)
- Optimise upcomming overview creation @Raudius [#3793](https://github.com/nextcloud/deck/pull/3793)
- Performance boost @juliushaertl [#4452](https://github.com/nextcloud/deck/pull/4452)
- Cache user membership for circles [#4132](https://github.com/nextcloud/deck/pull/4132)
- Set event link also for notifications that get emitted from activities [#4118](https://github.com/nextcloud/deck/pull/4118)
- Fix Card menu not displaying when description is not set [#4103](https://github.com/nextcloud/deck/pull/4103)
- disable Create card button while no stack is chosen [#4019](https://github.com/nextcloud/deck/pull/4019)
- to nextcloud/OCP package in stable24 [#4093](https://github.com/nextcloud/deck/pull/4093)
- Fix attachment creator name: show display name [#4037](https://github.com/nextcloud/deck/pull/4037)
- Use capped memory cache for board permissions [#3997](https://github.com/nextcloud/deck/pull/3997)
- Improve CalDAV integration performance [#3995](https://github.com/nextcloud/deck/pull/3995)
- Fetch attachment folder for the correct user during cron job [#3959](https://github.com/nextcloud/deck/pull/3959)
- Switch to 'markdown-it-task-checkbox' for rendering of task lists [#3925](https://github.com/nextcloud/deck/pull/3925)
- Prevent opening card and applyLabelFilter on card drag end [#3917](https://github.com/nextcloud/deck/pull/3917)
- Fix for issue #3637 [#3901](https://github.com/nextcloud/deck/pull/3901)
- Fix z-index for deck sidebar [#3885](https://github.com/nextcloud/deck/pull/3885)
### Other
- Dependency updates
## 1.8.0-beta.1
### Enhancements
- Nextcloud 25 compatibility
- Performance improvements
- Use capped memory cache for board permissions @juliushaertl [#3980](https://github.com/nextcloud/deck/pull/3980)
- Improve CalDAV integration performance @juliushaertl [#3982](https://github.com/nextcloud/deck/pull/3982)
- Simpify query for getting shared files @juliushaertl [#3983](https://github.com/nextcloud/deck/pull/3983)
- Accessibility improvements
- Add a11y label for sidebar button @marcelklehr [#3986](https://github.com/nextcloud/deck/pull/3986)
- Improve filter popover accessibility @juliushaertl [#3820](https://github.com/nextcloud/deck/pull/3820)
- Set ids to skip to content/navigation @juliushaertl [#3924](https://github.com/nextcloud/deck/pull/3924)
- Invert icons properly in dark mode @juliushaertl [#3939](https://github.com/nextcloud/deck/pull/3939)
- Bump dependencies
## 1.7.1
### Fixed
- set last modified when the card was found. Fixes #3763 @ylebre [#3796](https://github.com/nextcloud/deck/pull/3796)
- Increase file count after sharing @luka-nextcloud [#3682](https://github.com/nextcloud/deck/pull/3682)
- Align Duedate-delete icon properly - fixes nextcloud/deck#3791 @Ben-Ro [#3811](https://github.com/nextcloud/deck/pull/3811)
- Fix for issue #3637 @flummer [#3833](https://github.com/nextcloud/deck/pull/3833)
- Switch to 'markdown-it-task-checkbox' for rendering of task lists @q-wertz [#3898](https://github.com/nextcloud/deck/pull/3898)
- Make rename functions accessibly by keyboard navigation @juliushaertl [#3813](https://github.com/nextcloud/deck/pull/3813)
- Prevent opening card and applyLabelFilter on card drag end @eneiluj [#3916](https://github.com/nextcloud/deck/pull/3916)
- Inserted required property in the rename list field, to prevent the l… @mstolf [#3862](https://github.com/nextcloud/deck/pull/3862)
- Fix share provider for master changes @nickvergessen [#3942](https://github.com/nextcloud/deck/pull/3942)
- Fetch attachment folder for the correct user during cron job @juliushaertl [#3952](https://github.com/nextcloud/deck/pull/3952)
- Fix z-index for deck sidebar @Raudius [#3884](https://github.com/nextcloud/deck/pull/3884)
### Other
- Switch from OC::$server->get to OCP\Server::get @CarlSchwan [#3801](https://github.com/nextcloud/deck/pull/3801)
- Add performance section in README @eneiluj [#3830](https://github.com/nextcloud/deck/pull/3830)
- Fix static analysis by stubbing more circle methods @juliushaertl [#3900](https://github.com/nextcloud/deck/pull/3900)
- fix(docs): fix links to JSON schemas for Trello @wiktor2200 [#3872](https://github.com/nextcloud/deck/pull/3872)
- Move to OCP\Collaboration\Resources\LoadAdditionalScriptsEvent @juliushaertl [#3818](https://github.com/nextcloud/deck/pull/3818)
- Rename settings to deck settings @PVince81 [#3928](https://github.com/nextcloud/deck/pull/3928)
- SCSS cleanup @juliushaertl [#3803](https://github.com/nextcloud/deck/pull/3803)
- Hide deprecated projects in sidebar and card details by default @Pytal [#3984](https://github.com/nextcloud/deck/pull/3984)
- Align Duedate-delete icon properly - fixes nextcloud/deck#3791 [#3817](https://github.com/nextcloud/deck/pull/3817)
- Increase file count after sharing [#3806](https://github.com/nextcloud/deck/pull/3806)
- Fetch full board data after cloning [#3781](https://github.com/nextcloud/deck/pull/3781)
## 1.7.0
@@ -161,7 +97,7 @@ All notable changes to this project will be documented in this file.
- Adapt the card modal to upstream changes [#3764](https://github.com/nextcloud/deck/pull/3764)
- Fix text selection in dark mode and modal view [#3765](https://github.com/nextcloud/deck/pull/3765)
- Add missing indices [#3754](https://github.com/nextcloud/deck/pull/3754)
- Handle qb mapper exception messages properly @juliushaertl [#3769](https://github.com/nextcloud/deck/pull/3769)
## 1.6.0-beta1

View File

@@ -30,16 +30,6 @@ build: clean-dist install-deps build-js
release: clean-dist install-deps-nodev build-js
lint: lint-js lint-php
lint-js:
npm run lint
npm run stylelint
lint-php:
composer run lint 1>/dev/null
composer run cs:check
build-js: install-deps-js
npm run build

View File

@@ -1,6 +1,6 @@
# Deck
[![Build Status](https://travis-ci.org/nextcloud/deck.svg?branch=main)](https://travis-ci.org/nextcloud/deck) [![CodeCov](https://codecov.io/github/nextcloud/deck/coverage.svg?branch=main)](https://codecov.io/github/nextcloud/deck) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/e403f723f42a4abd93b2cfe36cbd7eee)](https://www.codacy.com/app/juliushaertl/deck?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=nextcloud/deck&amp;utm_campaign=Badge_Grade) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/nextcloud/deck/badges/quality-score.png?b=main)](https://scrutinizer-ci.com/g/nextcloud/deck/?branch=main) [![#nextcloud-deck](https://img.shields.io/badge/IRC-%23nextcloud--deck%20on%20freenode-blue.svg)](https://webchat.freenode.net/?channels=nextcloud-deck)
[![Build Status](https://travis-ci.org/nextcloud/deck.svg?branch=master)](https://travis-ci.org/nextcloud/deck) [![CodeCov](https://codecov.io/github/nextcloud/deck/coverage.svg?branch=master)](https://codecov.io/github/nextcloud/deck) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/e403f723f42a4abd93b2cfe36cbd7eee)](https://www.codacy.com/app/juliushaertl/deck?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=nextcloud/deck&amp;utm_campaign=Badge_Grade) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/nextcloud/deck/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/nextcloud/deck/?branch=master) [![#nextcloud-deck](https://img.shields.io/badge/IRC-%23nextcloud--deck%20on%20freenode-blue.svg)](https://webchat.freenode.net/?channels=nextcloud-deck)
Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.
@@ -20,71 +20,68 @@ Deck is a kanban style organization tool aimed at personal planning and project
### Mobile apps
- [Nextcloud Deck app for Android](https://github.com/stefan-niedermann/nextcloud-deck) - It is available in [F-Droid](https://f-droid.org/de/packages/it.niedermann.nextcloud.deck/) and the [Google Play Store](https://play.google.com/store/apps/details?id=it.niedermann.nextcloud.deck.play)
- [deck NG for Android and iOS](https://github.com/meltzow/deck-ng) - It is available in [Google Play Store](https://play.google.com/store/apps/details?id=net.meltzow.deckng) and [Apple App Store](https://apps.apple.com/us/app/deck-ng/id6443334702)
### 3rd-Party Integrations
- [trello-to-deck](https://github.com/maxammann/trello-to-deck) - Migrates cards from Trello
- [mail2deck](https://github.com/newroco/mail2deck) - Provides an "email in" solution
- [mail2deck](https://github.com/newroco/mail2deck) - Provides an "email in" solution
- [A-deck](https://github.com/leoossa/A-deck) - Chrome Extension that allows to create new card in selected stack based on current tab
## Installation/Update
The app can be installed through the app store within Nextcloud. You can also download the latest release from the [release page](https://github.com/nextcloud-releases/deck/releases).
This app is supposed to work on the two latest Nextcloud versions.
## Performance limitations
### Install latest release
Deck is not yet ready for intensive usage.
A lot of database queries are generated when the number of boards, cards and attachments is high.
For example, a user having access to 13 boards, with each board having on average 100 cards,
and each card having on average 5 attachments,
would generate 6500 database queries when doing the file related queries
which would increase the page loading time significantly.
You can download and install the latest release from the [Nextcloud app store](https://apps.nextcloud.com/apps/deck)
Improvements on Nextcloud server and Deck itself will improve the situation.
### Install from git
If you want to run the latest development version from git source, you need to clone the repo to your apps folder:
```
git clone https://github.com/nextcloud/deck.git
cd deck
make install-deps
make build
```
Please make sure you have installed the following dependencies: `make, which, tar, npm, curl, composer`
### Install the nightly builds
Instead of setting everything up manually, you can just [download the nightly build](https://github.com/nextcloud/deck/releases/tag/nightly) instead. These builds are updated every 24 hours, and are pre-configured with all the needed dependencies.
## Developing
There are multiple ways to develop on Deck. As you will need a Nextcloud server running, the individual options are described below.
### PHP
### General build instructions
Nothing to prepare, just dig into the code.
General build instructions for the app itself are the same for all options.
### JavaScript
To build you will need to have [Node.js](https://nodejs.org/en/) and [Composer](https://getcomposer.org/) installed.
Deck requires running a `make build-js` to install npm dependencies and build the JavaScript code using webpack. While developing you can also use `make watch` to rebuild everytime the code changes.
- Install PHP dependencies: `composer install --no-dev`
- Install JS dependencies: `npm ci`
- Build JavaScript for the frontend
- Development build `npm run dev`
- Watch for changes `npm run watch`
- Production build `npm run build`
#### Hot reloading
### GitHub Codespaces / VS Code devcontainer
- Open code spaces or the repository in VS Code to start the dev container
- The container will automatically install all dependencies and build the app
- Nextcloud will be installed from the master development branch and be available on a port exposed by the container
### Docker: Simple app development container
- Fork the app
- Clone the repository: `git clone https://github.com/nextcloud/deck.git`
- Go into deck directory: `cd deck`
- Build the app as described in the general build instructions
- Run Nextcloud development container and mount the apps source code into it
Enable debug mode in your config.php `'debug' => true,`
Without SSL:
```
docker run --rm \
-p 8080:80 \
-v ~/path/to/app:/var/www/html/apps-extra/app \
ghcr.io/juliushaertl/nextcloud-dev-php80:latest
npx webpack-dev-server --config webpack.hot.js \
--public localhost:3000 \
--output-public-path 'http://localhost:3000/js/'
```
### Full Nextcloud development environment
With SSL:
```
npx webpack-dev-server --config webpack.dev.js --https \
--cert ~/repos/nextcloud/nc-dev/data/ssl/nextcloud.local.crt \
--key ~/repos/nextcloud/nc-dev/data/ssl/nextcloud.local.key \
--public nextcloud.local:3000 \
--output-public-path 'https://nextcloud.local:3000/js/'
```
You need to setup a [development environment](https://docs.nextcloud.com/server/latest/developer_manual//getting_started/devenv.html) of the current Nextcloud version. You can also alternatively install & run the [nextcloud docker container](https://github.com/juliushaertl/nextcloud-docker-dev).
After the finished installation, you can clone the deck project directly in the `/[nextcloud-docker-dev-dir]/workspace/server/apps/` folder.
### Running tests
You can use the provided Makefile to run all tests by using:

View File

@@ -20,7 +20,7 @@ Your report should include:
- Reproduction steps
A member of the security team will confirm the vulnerability, determine its impact, and develop a fix.
The fix will be applied to the main branch, tested, and packaged in the next security release.
The fix will be applied to the master branch, tested, and packaged in the next security release.
The vulnerability will be publicly announced after the release. Finally, your name will be added
to the [hall of fame](https://hackerone.com/nextcloud/thanks) as a thank you from the entire Nextcloud community. Note our
[threat model](https://nextcloud.com/security/threat-model) to know what is expected behavior.

View File

@@ -16,13 +16,9 @@
- 🚀 Get your project organized
</description>
<version>1.10.0-beta.2</version>
<version>1.7.4</version>
<licence>agpl</licence>
<author>Julius Härtl</author>
<documentation>
<user>https://deck.readthedocs.io/en/latest/User_documentation_en/</user>
<developer>https://deck.readthedocs.io/en/latest/API/</developer>
</documentation>
<namespace>Deck</namespace>
<types>
<dav/>
@@ -38,19 +34,13 @@
<database min-version="9.4">pgsql</database>
<database>sqlite</database>
<database min-version="8.0">mysql</database>
<nextcloud min-version="27" max-version="27"/>
<nextcloud min-version="24" max-version="24"/>
</dependencies>
<background-jobs>
<job>OCA\Deck\Cron\DeleteCron</job>
<job>OCA\Deck\Cron\ScheduledNotifications</job>
<job>OCA\Deck\Cron\CardDescriptionActivity</job>
<job>OCA\Deck\Cron\SessionsCleanup</job>
</background-jobs>
<repair-steps>
<live-migration>
<step>OCA\Deck\Migration\DeletedCircleCleanup</step>
</live-migration>
</repair-steps>
<commands>
<command>OCA\Deck\Command\UserExport</command>
<command>OCA\Deck\Command\BoardImport</command>

View File

@@ -40,7 +40,6 @@ return [
['name' => 'board#deleteAcl', 'url' => '/boards/{boardId}/acl/{aclId}', 'verb' => 'DELETE'],
['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'],
// stacks
['name' => 'stack#index', 'url' => '/stacks/{boardId}', 'verb' => 'GET'],
@@ -150,10 +149,5 @@ return [
['name' => 'overview_api#upcomingCards', 'url' => '/api/v{apiVersion}/overview/upcoming', 'verb' => 'GET'],
['name' => 'search#search', 'url' => '/api/v{apiVersion}/search', 'verb' => 'GET'],
// sessions
['name' => 'Session#create', 'url' => '/api/v{apiVersion}/session/create', 'verb' => 'PUT'],
['name' => 'Session#sync', 'url' => '/api/v{apiVersion}/session/sync', 'verb' => 'POST'],
['name' => 'Session#close', 'url' => '/api/v{apiVersion}/session/close', 'verb' => 'POST'],
]
];

View File

@@ -17,9 +17,9 @@
"phpunit/phpunit": "^9",
"nextcloud/coding-standard": "^1.0.0",
"symfony/event-dispatcher": "^4.0",
"vimeo/psalm": "^5.4",
"vimeo/psalm": "^4.3",
"php-parallel-lint/php-parallel-lint": "^1.2",
"nextcloud/ocp": "dev-stable27"
"nextcloud/ocp": "dev-stable24"
},
"config": {
"optimize-autoloader": true,
@@ -28,7 +28,7 @@
"composer/package-versions-deprecated": true
},
"platform": {
"php": "8.0"
"php": "7.4"
}
},
"scripts": {
@@ -36,14 +36,13 @@
"cs:check": "php-cs-fixer fix --dry-run --diff",
"cs:fix": "php-cs-fixer fix",
"psalm": "psalm",
"psalm:update-baseline": "psalm --update-baseline",
"psalm:fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType",
"test": [
"@test:unit",
"@test:integration"
],
"test:unit": "vendor/bin/phpunit -c tests/phpunit.xml",
"test:integration": "vendor/bin/phpunit -c tests/phpunit.integration.xml && cd tests/integration && ./run.sh"
"test:unit": "phpunit -c tests/phpunit.xml",
"test:integration": "phpunit -c tests/phpunit.integration.xml && cd tests/integration && ./run.sh"
},
"autoload-dev": {
"psr-4": {

977
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
.icon-deck {
background-image: url(../img/deck-dark.svg);
filter: var(--background-invert-if-dark);
}
.icon-deck-white, .icon-deck.icon-white {
background-image: url(../img/deck.svg);
filter: var(--background-invert-if-dark);
}

1
css/deck.scss Normal file
View File

@@ -0,0 +1 @@
@include icon-black-white('deck', 'deck', 1);

View File

@@ -1,8 +1,11 @@
<?php
/**
* @copyright Copyright (c) 2022 Raul Ferreira Fuentes <raul@nextcloud.com>
/*
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
*
* @author Raul Ferreira Fuentes <raul@nextcloud.com>
* @author Julius Härtl <jus@bitgrid.net>
* @author Artem Anufrij <artem.anufrij@live.de>
* @author Marin Treselj <marin@pixelipo.com>
* @author Oskar Kurz <oskar.kurz@gmail.com>
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
*
* @license GNU AGPL version 3 or any later version
*
@@ -20,30 +23,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Model;
use OCA\Deck\Db\Board;
class BoardSummary extends Board {
private Board $board;
public function __construct(Board $board) {
parent::__construct();
$this->board = $board;
}
public function jsonSerialize(): array {
return [
'id' => $this->getId(),
'title' => $this->getTitle()
];
}
protected function getter(string $name): mixed {
return $this->board->getter($name);
}
public function __call($name, $arguments) {
return $this->board->__call($name, $arguments);
}
}
@import 'icons';
@import 'print';

41
css/icons.scss Normal file
View File

@@ -0,0 +1,41 @@
/**
* Custom icons
*/
@include icon-black-white('deck', 'deck', 1);
@include icon-black-white('archive', 'deck', 1);
@include icon-black-white('circles', 'deck', 1);
@include icon-black-white('clone', 'deck', 1);
@include icon-black-white('filter', 'deck', 1);
@include icon-black-white('filter_set', 'deck', 1);
@include icon-black-white('attach', 'deck', 1);
@include icon-black-white('reply', 'deck', 1);
@include icon-black-white('notifications-dark', 'deck', 1);
@include icon-black-white('description', 'deck', 1);
.icon-toggle-compact-collapsed {
@include icon-color('toggle-view-expand', 'deck', $color-black);
}
.icon-toggle-compact-expanded {
@include icon-color('toggle-view-collapse', 'deck', $color-black);
}
.icon-activity {
@include icon-color('activity-dark', 'activity', $color-black);
}
.icon-comment--unread {
@include icon-color('comment', 'actions', $color-primary, 1, true);
}
.avatardiv.circles {
background: var(--color-primary);
}
.icon-circles {
opacity: 1;
background-size: 20px;
background-position: center center;
}
.icon-colorpicker {
background-image: url('../img/color_picker.svg');
}

View File

@@ -1,16 +0,0 @@
const { defineConfig } = require('cypress')
module.exports = defineConfig({
projectId: '1s7wkc',
viewportWidth: 1280,
viewportHeight: 720,
e2e: {
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents(on, config) {
return require('./cypress/plugins/index.js')(on, config)
},
baseUrl: 'http://nextcloud.local/index.php',
specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
},
})

View File

@@ -1,5 +0,0 @@
module.exports = {
extends: [
'plugin:cypress/recommended',
],
}

View File

@@ -1,56 +0,0 @@
import { randUser } from '../utils/index.js'
const user = randUser()
const recipient = randUser()
describe('Board', function() {
before(function() {
cy.createUser(user)
cy.createUser(recipient)
})
beforeEach(function() {
cy.login(user)
cy.visit('/apps/deck')
})
it('Can create a board', function() {
const board = 'TestBoard'
cy.intercept({
method: 'POST',
url: '/index.php/apps/deck/boards',
}).as('createBoardRequest')
// Click "Add board"
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry')
.eq(3).find('a').first().click({ force: true })
// Type the board title
cy.get('.board-create form input[type=text]')
.type(board, { force: true })
// Submit
cy.get('.board-create form input[type=submit]')
.first().click({ force: true })
cy.wait('@createBoardRequest').its('response.statusCode').should('equal', 200)
cy.get('.app-navigation__list .app-navigation-entry__children .app-navigation-entry')
.contains(board).should('be.visible')
})
it('Shows and hides the navigation', () => {
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry')
.contains('Upcoming cards')
.should('be.visible')
cy.openLeftSidebar()
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry')
.contains('Upcoming cards')
.should('not.be.visible')
cy.openLeftSidebar()
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry')
.contains('Upcoming cards')
.should('be.visible')
})
})

View File

@@ -1,129 +0,0 @@
import { randUser } from '../utils/index.js'
import { sampleBoard } from '../utils/sampleBoard'
const user = randUser()
const boardData = sampleBoard()
const auth = {
user: user.userId,
password: user.password,
}
const useModal = (useModal) => {
return cy.request({
method: 'POST',
url: `${Cypress.env('baseUrl')}/ocs/v2.php/apps/deck/api/v1.0/config/cardDetailsInModal?format=json`,
auth,
body: { value: useModal },
}).then((response) => {
expect(response.status).to.eq(200)
})
}
describe('Card', function() {
let boardId
before(function() {
cy.createUser(user)
cy.login(user)
cy.createExampleBoard({
user,
board: boardData,
}).then((board) => {
boardId = board.id
})
})
beforeEach(function() {
cy.login(user)
})
it('Can add a card', function() {
cy.visit(`/apps/deck/#/board/${boardId}`)
const newCardTitle = 'Write some cypress tests'
cy.getNavigationEntry(boardData.title)
.first().click({ force: true })
cy.get('.board .stack').eq(0).within(() => {
cy.get('.card:contains("Hello world")').should('be.visible')
cy.get('.button-vue[aria-label*="Add card"]')
.first().click()
cy.get('.stack__card-add form input#new-stack-input-main')
.type(newCardTitle)
cy.get('.stack__card-add form input[type=submit]')
.first().click()
cy.get(`.card:contains("${newCardTitle}")`).should('be.visible')
})
})
describe('Modal', () => {
beforeEach(function() {
cy.login(user)
useModal(true).then(() => {
cy.visit(`/apps/deck/#/board/${boardId}`)
})
})
it('Can show card details modal', function() {
cy.getNavigationEntry(boardData.title)
.first().click({ force: true })
cy.get('.board .stack').eq(0).within(() => {
cy.get('.card:contains("Hello world")').should('be.visible').click()
})
cy.get('.modal__card').should('be.visible')
cy.get('.app-sidebar-header__maintitle').contains('Hello world')
})
it('Attachment from files app', () => {
cy.get('.card:contains("Hello world")').should('be.visible').click()
cy.get('.modal__card').should('be.visible')
cy.get('.app-sidebar-tabs__tab [data-id="attachments"]').click()
cy.get('button.icon-upload').should('be.visible')
cy.get('button.icon-folder').should('be.visible')
.click()
cy.get('.oc-dialog #picker-filestable tr[data-entryname="welcome.txt"] td.filename').should('be.visible')
.click()
cy.get('.oc-dialog button.primary').click()
cy.get('.attachment-list .basename').contains('welcome.txt')
})
it('Shows the modal with the editor', () => {
cy.get('.card:contains("Hello world")').should('be.visible').click()
cy.intercept({ method: 'PUT', url: '**/apps/deck/cards/*' }).as('save')
cy.get('.modal__card').should('be.visible')
cy.get('.app-sidebar-header__maintitle').contains('Hello world')
cy.get('.modal__card .ProseMirror h1').contains('Hello world').should('be.visible')
cy.get('.modal__card .ProseMirror h1')
.click()
.type(' writing more text{enter}- List item{enter}with entries{enter}{enter}Paragraph')
cy.wait('@save', { timeout: 7000 })
cy.reload()
cy.get('.modal__card').should('be.visible')
cy.get('.modal__card .ProseMirror h1').contains('Hello world writing more text').should('be.visible')
cy.get('.modal__card .ProseMirror li').eq(0).contains('List item').should('be.visible')
cy.get('.modal__card .ProseMirror li').eq(1).contains('with entries').should('be.visible')
cy.get('.modal__card .ProseMirror p').contains('Paragraph').should('be.visible')
})
})
describe('Sidebar', () => {
beforeEach(function() {
cy.login(user)
useModal(false).then(() => {
cy.visit(`/apps/deck/#/board/${boardId}`)
})
})
it('Show the sidebar', () => {
cy.get('.card:contains("Hello world")').should('be.visible').click()
cy.get('#app-sidebar-vue')
.find('.ProseMirror h1').contains('Hello world writing more text').should('be.visible')
})
})
})

View File

@@ -1,29 +0,0 @@
import { randUser } from '../utils/index.js'
const user = randUser()
describe('Deck dashboard', function() {
before(function() {
cy.createUser(user)
})
beforeEach(function() {
cy.login(user)
cy.visit('/apps/deck')
})
it('Can show the right title on the dashboard', function() {
cy.get('.board-title h2')
.should('have.length', 1).first()
.should('have.text', 'Upcoming cards')
})
it('Can see the default "Personal Board" created for user by default', function() {
const defaultBoard = 'Personal'
cy.get('.app-navigation-entry-wrapper[icon=icon-deck]')
.find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + defaultBoard + ')')
.first()
.contains(defaultBoard)
.should('be.visible')
})
})

View File

@@ -1,50 +0,0 @@
import { randUser } from '../utils/index.js'
import { sampleBoard } from '../utils/sampleBoard'
const user = randUser()
const recipient = randUser()
describe('Board', function() {
before(function() {
cy.createUser(user)
cy.createUser(recipient)
})
beforeEach(function() {
cy.login(user)
})
it('Share a board to a user', function() {
const board = sampleBoard('Read only board')
cy.createExampleBoard({ user, board }).then((board) => {
const boardId = board.id
cy.visit(`/apps/deck/#/board/${boardId}`)
cy.get('.board-title').contains(board.title)
cy.shareBoardWithUi(recipient.userId)
cy.login(recipient)
cy.visit(`/apps/deck/#/board/${boardId}`)
cy.get('.board-title').contains(board.title)
cy.get('.button-vue[aria-label*="Add card"]')
.should('not.exist')
})
})
it('Share a board to a user as writable', function() {
const board = sampleBoard('Editable board')
cy.createExampleBoard({ user, board }).then((board) => {
const boardId = board.id
cy.visit(`/apps/deck/#/board/${boardId}`)
cy.get('.board-title').contains(board.title)
cy.shareBoardWithUi(recipient.userId)
cy.get(`[data-cy="acl-participant:${recipient.userId}"]`).find('[data-cy="action:permission-edit"]').click()
cy.login(recipient)
cy.visit(`/apps/deck/#/board/${boardId}`)
cy.get('.board-title').contains(board.title)
cy.get('.button-vue[aria-label*="Add card"]')
.first().click()
})
})
})

View File

@@ -1,68 +0,0 @@
import { randUser } from '../utils/index.js'
const user = randUser()
const boardTitle = 'TestBoard'
const testBoardData = {
title: boardTitle,
stacks: [
{ title: 'Existing Stack1' },
{ title: 'Existing Stack2' },
],
}
describe('Stack', function() {
before(function() {
cy.createUser(user)
cy.login(user)
cy.createExampleBoard({
user,
board: testBoardData,
})
})
beforeEach(function() {
cy.login(user)
cy.visit('/apps/deck')
cy.openLeftSidebar()
cy.getNavigationEntry(boardTitle)
.click({ force: true })
})
it('Can create a stack', function() {
cy.get('#stack-add button').first().click()
cy.focused().type('List 1')
cy.get('#stack-add form input[type=submit]').first().click()
cy.contains('List 1').should('be.visible')
})
it('Can edit a stack title', function() {
cy.contains('Existing Stack1')
cy.get('[data-cy-stack="Existing Stack1"]').within(() => {
cy.contains('Existing Stack1').click()
cy.focused().type(' renamed')
cy.get('[data-cy="editStackTitleForm"] input[type="submit"]').click()
})
cy.contains('Existing Stack1 renamed').should('be.visible')
})
it('Can abort a stack title edit via esc', function() {
cy.contains('Existing Stack2').click()
cy.focused().type(' with a new title, maybe?')
cy.focused().type('{esc}')
cy.contains('Existing Stack2').should('be.visible')
cy.contains('Existing Stack2 with a new title, maybe?').should('not.exist')
})
it('Can abort a stack title edit via click outside', function() {
cy.contains('Existing Stack2').click()
cy.focused().type(' with a new title, maybe?')
cy.get('[data-cy-stack="Existing Stack2"]').click('bottom')
cy.contains('Existing Stack2').should('be.visible')
cy.contains('Existing Stack2 with a new title, maybe?').should('not.exist')
})
})

View File

@@ -1,5 +0,0 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@@ -1,22 +0,0 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
}

View File

@@ -1,117 +0,0 @@
/**
* @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
import { addCommands } from '@nextcloud/cypress'
addCommands()
const url = Cypress.config('baseUrl').replace(/\/index.php\/?$/g, '')
Cypress.env('baseUrl', url)
Cypress.Commands.add('openLeftSidebar', () => {
cy.get('.app-navigation button.app-navigation-toggle').click()
})
Cypress.Commands.add('deckCreateBoard', ({ user, password }, title) => {
cy.login(user, password)
cy.get('.app-navigation button.app-navigation-toggle').click()
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry')
.eq(3)
.find('a')
.first()
.click({ force: true })
cy.get('.board-create form input[type=text]').type(title, { force: true })
cy.get('.board-create form input[type=submit]')
.first()
.click({ force: true })
})
Cypress.Commands.add('deckCreateList', ({ user, password }, title) => {
cy.login(user, password)
cy.get('.app-navigation button.app-navigation-toggle').click()
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry')
.eq(3)
.find('a.app-navigation-entry-link')
.first()
.click({ force: true })
cy.get('#stack-add button').first().click()
cy.get('#stack-add form input#new-stack-input-main').type(title)
cy.get('#stack-add form input[type=submit]').first().click()
})
Cypress.Commands.add('createExampleBoard', ({ user, board }) => {
const auth = {
user: user.userId,
password: user.password,
}
cy.request({
method: 'POST',
url: `${Cypress.env('baseUrl')}/index.php/apps/deck/api/v1.0/boards`,
auth,
body: { title: board.title, color: board.color ?? 'ff0000' },
}).then((boardResponse) => {
expect(boardResponse.status).to.eq(200)
const boardData = boardResponse.body
for (const stackIndex in board.stacks) {
const stack = board.stacks[stackIndex]
cy.request({
method: 'POST',
url: `${Cypress.env('baseUrl')}/index.php/apps/deck/api/v1.0/boards/${boardData.id}/stacks`,
auth,
body: { title: stack.title, order: 0 },
}).then((stackResponse) => {
const stackData = stackResponse.body
for (const cardIndex in stack.cards) {
const card = stack.cards[cardIndex]
cy.request({
method: 'POST',
url: `${Cypress.env('baseUrl')}/index.php/apps/deck/api/v1.0/boards/${boardData.id}/stacks/${stackData.id}/cards`,
auth,
body: { title: card.title, description: card.description ?? '' },
})
}
})
}
cy.wrap(boardData)
})
})
Cypress.Commands.add('getNavigationEntry', (boardTitle) => {
return cy.get('.app-navigation-entry-wrapper[icon=icon-deck]')
.find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + boardTitle + ')')
.find('a.app-navigation-entry-link')
})
Cypress.Commands.add('shareBoardWithUi', (userId) => {
cy.get('[aria-label="Open details"]').click()
cy.get('.app-sidebar').should('be.visible')
cy.get('.multiselect__input').type(`${userId}`)
cy.get('.multiselect__content .multiselect__element').first().contains(userId)
cy.get('.multiselect__input').type('{enter}')
cy.get('.shareWithList').contains(userId)
})

View File

@@ -1,12 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Components App</title>
</head>
<body>
<div data-cy-root></div>
</body>
</html>

View File

@@ -1,27 +0,0 @@
// ***********************************************************
// This example support/component.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
import { mount } from 'cypress/vue2'
Cypress.Commands.add('mount', mount)
// Example use:
// cy.mount(MyComponent)

View File

@@ -1,20 +0,0 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands.js'
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@@ -1,4 +0,0 @@
import { User } from '@nextcloud/cypress'
export const randHash = () => Math.random().toString(36).replace(/[^a-z]+/g, '').slice(0, 10)
export const randUser = () => new User(randHash(), randHash())

View File

@@ -1,38 +0,0 @@
/*
* @copyright Copyright (c) 2022 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
export const sampleBoard = (title = 'MyTestBoard') => {
return {
title: title,
color: '00ff00',
stacks: [
{
title: 'TestList',
cards: [
{
title: 'Hello world',
description: '# Hello world',
},
],
},
],
}
}

View File

@@ -1066,7 +1066,6 @@ Deck stores user and app configuration values globally and per board. The GET en
| --- | --- |
| calendar | Determines if the calendar/tasks integration through the CalDAV backend is enabled for the user (boolean) |
| cardDetailsInModal | Determines if the bigger view is used (boolean) |
| cardIdBadge | Determines if the ID badges are displayed on cards (boolean) |
| groupLimit | Determines if creating new boards is limited to certain groups of the instance. The resulting output is an array of group objects with the id and the displayname (Admin only)|
```
@@ -1080,7 +1079,6 @@ Deck stores user and app configuration values globally and per board. The GET en
"data": {
"calendar": true,
"cardDetailsInModal": true,
"cardIdBadge": true,
"groupLimit": [
{
"id": "admin",
@@ -1111,7 +1109,6 @@ Deck stores user and app configuration values globally and per board. The GET en
| notify-due | `off`, `assigned` or `all` |
| calendar | Boolean |
| cardDetailsInModal | Boolean |
| cardIdBadge | Boolean |
#### Example request
@@ -1394,110 +1391,3 @@ A bad request response is returned if invalid input values are provided. The res
A not found response might be returned if:
- The card for the given cardId could not be found
- The comment could not be found
## Sessions
### PUT /session/create - creates a new session
#### Request parameters
| Parameter | Type | Description |
| --------- | ------- | ---------------------------------------------------- |
| boardId | Integer | The id of the opened board |
```
curl -X PUT 'https://admin:admin@nextcloud/ocs/v2.php/apps/deck/api/v1.0/session/create' \
-H 'Accept: application/json' -H 'OCS-APIRequest: true' \
-H 'Content-Type: application/json;charset=utf-8' \
--data '{"boardId":1}'
```
#### Response
##### 200 Success
```json
{
"ocs": {
"meta": {
"status": "ok",
"statuscode": 200,
"message": "OK"
},
"data": {
"token": "+zcJHf4rC6dobVSbuNa3delkCSfTW8OvYWTyLFvSpIv80FjtgLIj0ARlxspsazNQ"
}
}
}
```
### POST /session/sync - notifies the server, that the session is still open
#### Request body
| Parameter | Type | Description |
| --------- | ------- | ---------------------------------------------------- |
| boardId | Integer | The id of the opened board |
| token | String | The session token from the /sessions/create response |
```
curl -X POST 'https://admin:admin@nextcloud/ocs/v2.php/apps/deck/api/v1.0/session/create' \
-H 'Accept: application/json' -H 'OCS-APIRequest: true' \
-H 'Content-Type: application/json;charset=utf-8' \
--data '{"boardId":1, "token":"X3DyyoFslArF0t0NBZXzZXzcy8feoX/OEytSNXZtPg9TpUgO5wrkJ38IW3T/FfpV"}'
```
#### Response
##### 200 Success
```json
{
"ocs": {
"meta": {
"status": "ok",
"statuscode": 200,
"message": "OK"
},
"data": []
}
}
```
##### 404 Not Found
the provided token is invalid or expired
### POST /session/close - closes the session
#### Request body
| Parameter | Type | Description |
| --------- | ------- | ---------------------------------------------------- |
| boardId | Integer | The id of the opened board |
| token | String | The session token from the /sessions/create response |
```
curl -X POST 'https://admin:admin@nextcloud/ocs/v2.php/apps/deck/api/v1.0/session/close' \
-H 'Accept: application/json' -H 'OCS-APIRequest: true' \
-H 'Content-Type: application/json;charset=utf-8' \
--data '{"boardId":1, "token":"X3DyyoFslArF0t0NBZXzZXzcy8feoX/OEytSNXZtPg9TpUgO5wrkJ38IW3T/FfpV"}'
```
#### Response
##### 200 Success
```json
{
"ocs": {
"meta": {
"status": "ok",
"statuscode": 200,
"message": "OK"
},
"data": []
}
}
```

View File

@@ -90,7 +90,7 @@ Steps:
* Create the configuration file
* Execute the import informing the import file path, data file and source as `Trello JSON`
Create the configuration file respecting the [JSON Schema](https://github.com/nextcloud/deck/blob/main/lib/Service/Importer/fixtures/config-trelloJson-schema.json) for import `Trello JSON`
Create the configuration file respecting the [JSON Schema](https://github.com/nextcloud/deck/blob/master/lib/Service/fixtures/config-trelloJson-schema.json) for import `Trello JSON`
Example configuration file:
```json
@@ -120,7 +120,7 @@ https://api.trello.com/1/members/me/boards?key={yourKey}&token={yourToken}&field
This ID you will use in the configuration file in the `board` property
* Create the configuration file
Create the configuration file respecting the [JSON Schema](https://github.com/nextcloud/deck/blob/main/lib/Service/Importer/fixtures/config-trelloApi-schema.json) for import `Trello JSON`
Create the configuration file respecting the [JSON Schema](https://github.com/nextcloud/deck/blob/master/lib/Service/fixtures/config-trelloApi-schema.json) for import `Trello JSON`
Example configuration file:
```json

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" version="1.0" viewbox="0 0 32 32">
<path d="m16 1-10 18h11l-1 12 10-18h-11z"/>
</svg>

Before

Width:  |  Height:  |  Size: 205 B

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" version="1.0" viewBox="0 0 32 32">
<path d="m16 1-10 18h11l-1 12 10-18h-11z" fill="#FFF"/>
</svg>

Before

Width:  |  Height:  |  Size: 217 B

1
img/archive-white.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><g transform="translate(0 -1036.362)" fill="#fff"><path d="M1.93 1041.296c-.185 0-.336.138-.336.31v9.842c0 .172.15.313.336.313h12.517c.185 0 .333-.14.333-.313v-9.842c0-.172-.148-.31-.333-.31H1.93zm4.124 1.507h4.223c.39 0 .705.314.705.704v.43c0 .39-.315.705-.705.705H6.054a.703.703 0 0 1-.705-.705v-.43c0-.39.314-.704.705-.704z"/><rect width="15.742" height="2.296" x=".136" y="1037.543" ry="0"/></g></svg>

After

Width:  |  Height:  |  Size: 488 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" style="height: 240px; width: 240px;" viewBox="0 0 24 24">
<path fill="currentColor" d="M12,15H10V13H12V15M18,15H14V13H18V15M8,11H6V9H8V11M18,11H10V9H18V11M20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20M4,6V18H20V6H4Z" />
</svg>

Before

Width:  |  Height:  |  Size: 298 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 58 58" width="512" height="512"><g fill="#000"><path d="M54.319 37.839C54.762 35.918 55 33.96 55 32c0-9.095-4.631-17.377-12.389-22.153a1 1 0 1 0-1.049 1.703C48.724 15.96 53 23.604 53 32c0 1.726-.2 3.451-.573 5.147A6.992 6.992 0 0 0 51 37c-3.86 0-7 3.141-7 7s3.14 7 7 7 7-3.141 7-7a7.006 7.006 0 0 0-3.681-6.161zM38.171 54.182A23.867 23.867 0 0 1 29 56a24.047 24.047 0 0 1-17.017-7.092A6.974 6.974 0 0 0 14 44c0-3.859-3.14-7-7-7s-7 3.141-7 7 3.14 7 7 7a6.952 6.952 0 0 0 3.381-.875C15.26 55.136 21.994 58 29 58c3.435 0 6.778-.663 9.936-1.971.51-.211.753-.796.542-1.307a1.001 1.001 0 0 0-1.307-.54zM4 31.213a1 1 0 0 0 1.068-.927c.712-10.089 7.586-18.52 17.22-21.314C23.142 11.874 25.825 14 29 14c3.86 0 7-3.141 7-7s-3.14-7-7-7c-3.851 0-6.985 3.127-6.999 6.975C11.42 9.922 3.851 19.12 3.073 30.146A.999.999 0 0 0 4 31.213z"/></g></svg>

Before

Width:  |  Height:  |  Size: 885 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 58 58" width="512" height="512"><g fill="#fff"><path d="M54.319 37.839C54.762 35.918 55 33.96 55 32c0-9.095-4.631-17.377-12.389-22.153a1 1 0 1 0-1.049 1.703C48.724 15.96 53 23.604 53 32c0 1.726-.2 3.451-.573 5.147A6.992 6.992 0 0 0 51 37c-3.86 0-7 3.141-7 7s3.14 7 7 7 7-3.141 7-7a7.006 7.006 0 0 0-3.681-6.161zM38.171 54.182A23.867 23.867 0 0 1 29 56a24.047 24.047 0 0 1-17.017-7.092A6.974 6.974 0 0 0 14 44c0-3.859-3.14-7-7-7s-7 3.141-7 7 3.14 7 7 7a6.952 6.952 0 0 0 3.381-.875C15.26 55.136 21.994 58 29 58c3.435 0 6.778-.663 9.936-1.971.51-.211.753-.796.542-1.307a1.001 1.001 0 0 0-1.307-.54zM4 31.213a1 1 0 0 0 1.068-.927c.712-10.089 7.586-18.52 17.22-21.314C23.142 11.874 25.825 14 29 14c3.86 0 7-3.141 7-7s-3.14-7-7-7c-3.851 0-6.985 3.127-6.999 6.975C11.42 9.922 3.851 19.12 3.073 30.146A.999.999 0 0 0 4 31.213z"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 58 58" width="512" height="512"><g fill="#000"><path d="M54.319 37.839C54.762 35.918 55 33.96 55 32c0-9.095-4.631-17.377-12.389-22.153a1 1 0 1 0-1.049 1.703C48.724 15.96 53 23.604 53 32c0 1.726-.2 3.451-.573 5.147A6.992 6.992 0 0 0 51 37c-3.86 0-7 3.141-7 7s3.14 7 7 7 7-3.141 7-7a7.006 7.006 0 0 0-3.681-6.161zM38.171 54.182A23.867 23.867 0 0 1 29 56a24.047 24.047 0 0 1-17.017-7.092A6.974 6.974 0 0 0 14 44c0-3.859-3.14-7-7-7s-7 3.141-7 7 3.14 7 7 7a6.952 6.952 0 0 0 3.381-.875C15.26 55.136 21.994 58 29 58c3.435 0 6.778-.663 9.936-1.971.51-.211.753-.796.542-1.307a1.001 1.001 0 0 0-1.307-.54zM4 31.213a1 1 0 0 0 1.068-.927c.712-10.089 7.586-18.52 17.22-21.314C23.142 11.874 25.825 14 29 14c3.86 0 7-3.141 7-7s-3.14-7-7-7c-3.851 0-6.985 3.127-6.999 6.975C11.42 9.922 3.851 19.12 3.073 30.146A.999.999 0 0 0 4 31.213z"/></g></svg>

Before

Width:  |  Height:  |  Size: 885 B

After

Width:  |  Height:  |  Size: 885 B

1
img/clone.svg Normal file
View File

@@ -0,0 +1 @@
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M11.8 13.8H2.2V4.2h9.6m1.2 0c0-.67-.53-1.2-1.2-1.2H2.2C1.53 3 1 3.53 1 4.2v9.6c0 .67.53 1.2 1.2 1.2h9.6c.67 0 1.2-.53 1.2-1.2"/><path d="m4.2 1c-0.67 0-1.2 0.54-1.2 1.2h10.8v10.8c0.67 0 1.2-0.53 1.2-1.2v-9.6c0-0.67-0.53-1.2-1.2-1.2z"/></svg>

After

Width:  |  Height:  |  Size: 327 B

1
img/reply.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"><path d="M15 15s-.4-7.8-7-10V1L1 8l7 7v-4c5.1 0 7 4 7 4z"/></svg>

After

Width:  |  Height:  |  Size: 128 B

View File

@@ -78,7 +78,7 @@ OC.L10N.register(
"{user} has mentioned you in a comment on {deck-card}." : "{user} har nämnt dig i en kommentar i {deck-card}.",
"The board \"%s\" has been shared with you by %s." : "Tavlan \"%s\" har delats med dig av %s.",
"{user} has shared {deck-board} with you." : "{user} har delat {deck-board} med dig.",
"Deck board" : "Deck-plank",
"Deck board" : "Deck-tavla",
"Owned by %1$s" : "Ägd av %1$s",
"Deck boards, cards and comments" : "Deck tavlor, kort och kommentarer",
"From %1$s, in %2$s/%3$s, owned by %4$s" : "Från %1$s, i %2$s/%3$s, ägd av %4$s",
@@ -92,7 +92,7 @@ OC.L10N.register(
"Later" : "Senare",
"copy" : "kopiera",
"To do" : "Att göra",
"Doing" : "Gör",
"Doing" : "Pågående",
"Done" : "Klart",
"Example Task 3" : "Exempeluppgift 3",
"Example Task 2" : "Exempeluppgift 2",
@@ -249,7 +249,7 @@ OC.L10N.register(
"Write a description …" : "Ange en beskrivning ...",
"Choose attachment" : "Välj bilaga",
"(group)" : " (grupp)",
"Todo items" : "Todo saker",
"Todo items" : "Att göra saker",
"{count} comments, {unread} unread" : "{count} kommentarer, {unread} olästa",
"Edit card title" : "Ändra korttitel",
"Assign to me" : "Tilldela till mig",
@@ -289,7 +289,7 @@ OC.L10N.register(
"Only assigned cards" : "Bara tilldelade kort",
"No reminder" : "Ingen påminnelse",
"An error occurred" : "Ett fel uppstod",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Är du säker på att du vill radera brädet {title}? Detta kommer radera all data som tillhör brädet inklusive arkiverade kort.",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Är du säker på att du vill radera tavla {title}? Detta kommer radera all data som tillhör tavlan inklusive arkiverade kort.",
"Delete the board?" : "Ta bort tavlan?",
"Loading filtered view" : "Laddar filtrerad vy",
"No due" : "Inget slut",
@@ -316,9 +316,9 @@ OC.L10N.register(
"Share with a Deck card" : "Dela med ett Deck-kort",
"Share {file} with a Deck card" : "Dela {file} med ett Deck-kort",
"Share" : "Dela",
"Are you sure you want to transfer the board {title} for {user}?" : "Är du säker på att du vill överföra brädet {title} för {user}?",
"Transfer the board for {user} successfully" : "Överförde brädet för {user}",
"Failed to transfer the board for {user}" : "Misslyckades med att överföra brädet för {user}",
"Are you sure you want to transfer the board {title} for {user}?" : "Är du säker på att du vill överföra tavla {title} för {user}?",
"Transfer the board for {user} successfully" : "Överförde tavlan för {user}",
"Failed to transfer the board for {user}" : "Misslyckades med att överföra tavlan för {user}",
"Add a new list" : "Lägg till en ny lista",
"Are you sure you want to delete the board {title}? This will delete all the data of this board." : "Är du säker på att du vill radera tavla {title}? Detta kommer att radera all information från denna tavla."
},

View File

@@ -76,7 +76,7 @@
"{user} has mentioned you in a comment on {deck-card}." : "{user} har nämnt dig i en kommentar i {deck-card}.",
"The board \"%s\" has been shared with you by %s." : "Tavlan \"%s\" har delats med dig av %s.",
"{user} has shared {deck-board} with you." : "{user} har delat {deck-board} med dig.",
"Deck board" : "Deck-plank",
"Deck board" : "Deck-tavla",
"Owned by %1$s" : "Ägd av %1$s",
"Deck boards, cards and comments" : "Deck tavlor, kort och kommentarer",
"From %1$s, in %2$s/%3$s, owned by %4$s" : "Från %1$s, i %2$s/%3$s, ägd av %4$s",
@@ -90,7 +90,7 @@
"Later" : "Senare",
"copy" : "kopiera",
"To do" : "Att göra",
"Doing" : "Gör",
"Doing" : "Pågående",
"Done" : "Klart",
"Example Task 3" : "Exempeluppgift 3",
"Example Task 2" : "Exempeluppgift 2",
@@ -247,7 +247,7 @@
"Write a description …" : "Ange en beskrivning ...",
"Choose attachment" : "Välj bilaga",
"(group)" : " (grupp)",
"Todo items" : "Todo saker",
"Todo items" : "Att göra saker",
"{count} comments, {unread} unread" : "{count} kommentarer, {unread} olästa",
"Edit card title" : "Ändra korttitel",
"Assign to me" : "Tilldela till mig",
@@ -287,7 +287,7 @@
"Only assigned cards" : "Bara tilldelade kort",
"No reminder" : "Ingen påminnelse",
"An error occurred" : "Ett fel uppstod",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Är du säker på att du vill radera brädet {title}? Detta kommer radera all data som tillhör brädet inklusive arkiverade kort.",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Är du säker på att du vill radera tavla {title}? Detta kommer radera all data som tillhör tavlan inklusive arkiverade kort.",
"Delete the board?" : "Ta bort tavlan?",
"Loading filtered view" : "Laddar filtrerad vy",
"No due" : "Inget slut",
@@ -314,9 +314,9 @@
"Share with a Deck card" : "Dela med ett Deck-kort",
"Share {file} with a Deck card" : "Dela {file} med ett Deck-kort",
"Share" : "Dela",
"Are you sure you want to transfer the board {title} for {user}?" : "Är du säker på att du vill överföra brädet {title} för {user}?",
"Transfer the board for {user} successfully" : "Överförde brädet för {user}",
"Failed to transfer the board for {user}" : "Misslyckades med att överföra brädet för {user}",
"Are you sure you want to transfer the board {title} for {user}?" : "Är du säker på att du vill överföra tavla {title} för {user}?",
"Transfer the board for {user} successfully" : "Överförde tavlan för {user}",
"Failed to transfer the board for {user}" : "Misslyckades med att överföra tavlan för {user}",
"Add a new list" : "Lägg till en ny lista",
"Are you sure you want to delete the board {title}? This will delete all the data of this board." : "Är du säker på att du vill radera tavla {title}? Detta kommer att radera all information från denna tavla."
},"pluralForm" :"nplurals=2; plural=(n != 1);"

View File

@@ -173,7 +173,7 @@ OC.L10N.register(
"Can manage" : "可以管理",
"Owner" : "所有者",
"Delete" : "删除",
"Failed to create share with {displayName}" : "用 {displayName} 创建分享失败",
"Failed to create share with {displayName}" : "用{displayName}创建分享失败",
"Transfer" : "传输",
"Archive all cards" : "归档所有卡片",
"Delete list" : "删除列表",
@@ -285,7 +285,7 @@ OC.L10N.register(
"Create a card" : "创建一张卡片",
"Message from {author} in {conversationName}" : "{conversationName} 会话中来自 {author} 的消息",
"Something went wrong" : "发生了错误",
"Failed to upload {name}" : "未能上传 {name}",
"Failed to upload {name}" : "未能上传{name}",
"Maximum file size of {size} exceeded" : "文件容量已超过 {size} 的上限",
"Error creating the share" : "创建分享出错",
"Share with a Deck card" : "分享给一张看板卡片",

View File

@@ -171,7 +171,7 @@
"Can manage" : "可以管理",
"Owner" : "所有者",
"Delete" : "删除",
"Failed to create share with {displayName}" : "用 {displayName} 创建分享失败",
"Failed to create share with {displayName}" : "用{displayName}创建分享失败",
"Transfer" : "传输",
"Archive all cards" : "归档所有卡片",
"Delete list" : "删除列表",
@@ -283,7 +283,7 @@
"Create a card" : "创建一张卡片",
"Message from {author} in {conversationName}" : "{conversationName} 会话中来自 {author} 的消息",
"Something went wrong" : "发生了错误",
"Failed to upload {name}" : "未能上传 {name}",
"Failed to upload {name}" : "未能上传{name}",
"Maximum file size of {size} exceeded" : "文件容量已超过 {size} 的上限",
"Error creating the share" : "创建分享出错",
"Share with a Deck card" : "分享给一张看板卡片",

View File

@@ -45,9 +45,7 @@ use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\Comments\IComment;
use OCP\IUser;
use OCP\Server;
use OCP\L10N\IFactory;
use Psr\Log\LoggerInterface;
class ActivityManager {
public const DECK_NOAUTHOR_COMMENT_SYSTEM_ENFORCED = 'DECK_NOAUTHOR_COMMENT_SYSTEM_ENFORCED';
@@ -55,14 +53,14 @@ class ActivityManager {
public const SUBJECT_PARAMS_MAX_LENGTH = 4000;
public const SHORTENED_DESCRIPTION_MAX_LENGTH = 2000;
private IManager $manager;
private ?string $userId;
private PermissionService $permissionService;
private BoardMapper $boardMapper;
private CardMapper $cardMapper;
private AclMapper $aclMapper;
private StackMapper $stackMapper;
private IFactory $l10nFactory;
private $manager;
private $userId;
private $permissionService;
private $boardMapper;
private $cardMapper;
private $aclMapper;
private $stackMapper;
private $l10nFactory;
public const DECK_OBJECT_BOARD = 'deck_board';
public const DECK_OBJECT_CARD = 'deck_card';
@@ -116,7 +114,7 @@ class ActivityManager {
StackMapper $stackMapper,
AclMapper $aclMapper,
IFactory $l10nFactory,
?string $userId
$userId
) {
$this->manager = $manager;
$this->permissionService = $permissionsService;
@@ -312,10 +310,10 @@ class ActivityManager {
try {
$object = $this->findObjectForEntity($objectType, $entity);
} catch (DoesNotExistException $e) {
Server::get(LoggerInterface::class)->error('Could not create activity entry for ' . $subject . '. Entity not found.', (array)$entity);
\OC::$server->getLogger()->error('Could not create activity entry for ' . $subject . '. Entity not found.', (array)$entity);
return null;
} catch (MultipleObjectsReturnedException $e) {
Server::get(LoggerInterface::class)->error('Could not create activity entry for ' . $subject . '. Entity not found.', (array)$entity);
\OC::$server->getLogger()->error('Could not create activity entry for ' . $subject . '. Entity not found.', (array)$entity);
return null;
}
@@ -325,6 +323,7 @@ class ActivityManager {
*/
$eventType = 'deck';
$subjectParams = [];
$message = null;
switch ($subject) {
// No need to enhance parameters since entity already contains the required data
case self::SUBJECT_BOARD_CREATE:
@@ -366,15 +365,7 @@ class ActivityManager {
case self::SUBJECT_CARD_USER_ASSIGN:
case self::SUBJECT_CARD_USER_UNASSIGN:
$subjectParams = $this->findDetailsForCard($entity->getId(), $subject);
if (isset($additionalParams['after']) && $additionalParams['after'] instanceof \DateTimeInterface) {
$additionalParams['after'] = $additionalParams['after']->format('c');
}
if (isset($additionalParams['before']) && $additionalParams['before'] instanceof \DateTimeInterface) {
$additionalParams['before'] = $additionalParams['before']->format('c');
}
break;
break;
case self::SUBJECT_ATTACHMENT_CREATE:
case self::SUBJECT_ATTACHMENT_UPDATE:
case self::SUBJECT_ATTACHMENT_DELETE:
@@ -433,6 +424,10 @@ class ActivityManager {
->setSubject($subject, $subjectParams)
->setTimestamp(time());
if ($message !== null) {
$event->setMessage($message);
}
// FIXME: We currently require activities for comments even if they are disabled though settings
// Get rid of this once the frontend fetches comments/activity individually
if ($eventType === 'deck_comment') {

View File

@@ -77,7 +77,7 @@ class DeckProvider implements IProvider {
* @throws \InvalidArgumentException Should be thrown if your provider does not know this event
* @since 11.0.0
*/
public function parse($language, IEvent $event, IEvent $previousEvent = null): IEvent {
public function parse($language, IEvent $event, IEvent $previousEvent = null) {
if ($event->getApp() !== 'deck') {
throw new \InvalidArgumentException();
}
@@ -186,28 +186,28 @@ class DeckProvider implements IProvider {
private function getIcon(IEvent $event) {
$event->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('deck', 'deck-dark.svg')));
if (str_contains($event->getSubject(), '_update')) {
if (strpos($event->getSubject(), '_update') !== false) {
$event->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('files', 'change.svg')));
}
if (str_contains($event->getSubject(), '_create')) {
if (strpos($event->getSubject(), '_create') !== false) {
$event->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('files', 'add-color.svg')));
}
if (str_contains($event->getSubject(), '_delete')) {
if (strpos($event->getSubject(), '_delete') !== false) {
$event->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('files', 'delete-color.svg')));
}
if (str_contains($event->getSubject(), 'archive')) {
if (strpos($event->getSubject(), 'archive') !== false) {
$event->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('deck', 'archive.svg')));
}
if (str_contains($event->getSubject(), '_restore')) {
if (strpos($event->getSubject(), '_restore') !== false) {
$event->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/history.svg')));
}
if (str_contains($event->getSubject(), 'attachment_')) {
if (strpos($event->getSubject(), 'attachment_') !== false) {
$event->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'places/files.svg')));
}
if (str_contains($event->getSubject(), 'comment_')) {
if (strpos($event->getSubject(), 'comment_') !== false) {
$event->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/comment.svg')));
}
if (str_contains($event->getSubject(), 'label_')) {
if (strpos($event->getSubject(), 'label_') !== false) {
$event->setIcon($this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/tag.svg')));
}
return $event;
@@ -294,7 +294,7 @@ class DeckProvider implements IProvider {
if (array_key_exists('comment', $subjectParams)) {
/** @var IComment $comment */
try {
$comment = $this->commentsManager->get($subjectParams['comment']);
$comment = $this->commentsManager->get((int)$subjectParams['comment']);
$event->setParsedMessage($comment->getMessage());
$params['comment'] = [
'type' => 'highlight',
@@ -312,19 +312,12 @@ class DeckProvider implements IProvider {
$userLanguage = $this->config->getUserValue($event->getAuthor(), 'core', 'lang', $this->l10nFactory->findLanguage());
$userLocale = $this->config->getUserValue($event->getAuthor(), 'core', 'locale', $this->l10nFactory->findLocale());
$l10n = $this->l10nFactory->get('deck', $userLanguage, $userLocale);
if (is_array($subjectParams['after'])) {
// Unluckily there was a time when we stored jsonSerialized date objects in the database
// Broken in 1.8.0 and fixed again in 1.8.1
$date = new \DateTime($subjectParams['after']['date']);
$date->setTimezone(new \DateTimeZone(\date_default_timezone_get()));
} else {
$date = new \DateTime($subjectParams['after']);
$date->setTimezone(new \DateTimeZone(\date_default_timezone_get()));
}
$date = new \DateTime($subjectParams['after']);
$date->setTimezone(new \DateTimeZone(\date_default_timezone_get()));
$params['after'] = [
'type' => 'highlight',
'id' => 'dt:' . $subjectParams['after'],
'name' => $l10n->l('datetime', $date),
'name' => $l10n->l('datetime', $date)
];
}
return $params;

View File

@@ -29,7 +29,7 @@ class DescriptionSetting extends Setting {
* @return string Lowercase a-z and underscore only identifier
* @since 11.0.0
*/
public function getIdentifier(): string {
public function getIdentifier() {
return 'deck_card_description';
}
@@ -37,7 +37,7 @@ class DescriptionSetting extends Setting {
* @return string A translated string
* @since 11.0.0
*/
public function getName(): string {
public function getName() {
return $this->l->t('A <strong>card description</strong> inside the Deck app has been changed');
}
}

View File

@@ -42,7 +42,7 @@ class Filter implements \OCP\Activity\IFilter {
* @return string Lowercase a-z and underscore only identifier
* @since 11.0.0
*/
public function getIdentifier(): string {
public function getIdentifier() {
return 'deck';
}
@@ -50,7 +50,7 @@ class Filter implements \OCP\Activity\IFilter {
* @return string A translated string
* @since 11.0.0
*/
public function getName(): string {
public function getName() {
return $this->l10n->t('Deck');
}
@@ -60,7 +60,7 @@ class Filter implements \OCP\Activity\IFilter {
* priority values. It is required to return a value between 0 and 100.
* @since 11.0.0
*/
public function getPriority(): int {
public function getPriority() {
return 90;
}
@@ -68,7 +68,7 @@ class Filter implements \OCP\Activity\IFilter {
* @return string Full URL to an icon, empty string when none is given
* @since 11.0.0
*/
public function getIcon(): string {
public function getIcon() {
return $this->urlGenerator->imagePath('deck', 'deck-dark.svg');
}
@@ -77,7 +77,7 @@ class Filter implements \OCP\Activity\IFilter {
* @return string[] An array of allowed apps from which activities should be displayed
* @since 11.0.0
*/
public function filterTypes(array $types): array {
public function filterTypes(array $types) {
return array_merge($types, ['deck_comment']);
}
@@ -85,7 +85,7 @@ class Filter implements \OCP\Activity\IFilter {
* @return string[] An array of allowed apps from which activities should be displayed
* @since 11.0.0
*/
public function allowedApps(): array {
public function allowedApps() {
return ['deck'];
}
}

View File

@@ -41,7 +41,7 @@ class Setting implements \OCP\Activity\ISetting {
* @return string Lowercase a-z and underscore only identifier
* @since 11.0.0
*/
public function getIdentifier(): string {
public function getIdentifier() {
return 'deck';
}
@@ -49,7 +49,7 @@ class Setting implements \OCP\Activity\ISetting {
* @return string A translated string
* @since 11.0.0
*/
public function getName(): string {
public function getName() {
return $this->l->t('Changes in the <strong>Deck app</strong>');
}
@@ -59,7 +59,7 @@ class Setting implements \OCP\Activity\ISetting {
* priority values. It is required to return a value between 0 and 100.
* @since 11.0.0
*/
public function getPriority(): int {
public function getPriority() {
return 90;
}
@@ -67,7 +67,7 @@ class Setting implements \OCP\Activity\ISetting {
* @return bool True when the option can be changed for the stream
* @since 11.0.0
*/
public function canChangeStream(): bool {
public function canChangeStream() {
return true;
}
@@ -75,7 +75,7 @@ class Setting implements \OCP\Activity\ISetting {
* @return bool True when the option can be changed for the stream
* @since 11.0.0
*/
public function isDefaultEnabledStream(): bool {
public function isDefaultEnabledStream() {
return true;
}
@@ -83,7 +83,7 @@ class Setting implements \OCP\Activity\ISetting {
* @return bool True when the option can be changed for the mail
* @since 11.0.0
*/
public function canChangeMail(): bool {
public function canChangeMail() {
return true;
}
@@ -91,7 +91,7 @@ class Setting implements \OCP\Activity\ISetting {
* @return bool True when the option can be changed for the stream
* @since 11.0.0
*/
public function isDefaultEnabledMail(): bool {
public function isDefaultEnabledMail() {
return false;
}
}

View File

@@ -29,7 +29,7 @@ class SettingComment extends Setting {
* @return string Lowercase a-z and underscore only identifier
* @since 11.0.0
*/
public function getIdentifier(): string {
public function getIdentifier() {
return 'deck_comment';
}
@@ -37,7 +37,7 @@ class SettingComment extends Setting {
* @return string A translated string
* @since 11.0.0
*/
public function getName(): string {
public function getName() {
return $this->l->t('A <strong>comment</strong> was created on a card');
}
@@ -45,7 +45,7 @@ class SettingComment extends Setting {
* @return bool True when the option can be changed for the stream
* @since 11.0.0
*/
public function canChangeStream(): bool {
public function canChangeStream() {
return false;
}
}

View File

@@ -25,35 +25,28 @@ namespace OCA\Deck\AppInfo;
use Closure;
use Exception;
use OCA\Circles\Events\CircleDestroyedEvent;
use OC\EventDispatcher\SymfonyAdapter;
use OCA\Deck\Activity\CommentEventHandler;
use OCA\Deck\Capabilities;
use OCA\Deck\Collaboration\Resources\ResourceProvider;
use OCA\Deck\Collaboration\Resources\ResourceProviderCard;
use OCA\Deck\Dashboard\DeckWidget;
use OCA\Deck\Db\Acl;
use OCA\Deck\Db\AclMapper;
use OCA\Deck\Db\AssignmentMapper;
use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\CardMapper;
use OCA\Deck\Event\AclCreatedEvent;
use OCA\Deck\Event\AclDeletedEvent;
use OCA\Deck\Event\AclUpdatedEvent;
use OCA\Deck\Event\BoardUpdatedEvent;
use OCA\Deck\Event\CardCreatedEvent;
use OCA\Deck\Event\CardDeletedEvent;
use OCA\Deck\Event\CardUpdatedEvent;
use OCA\Deck\Event\SessionClosedEvent;
use OCA\Deck\Event\SessionCreatedEvent;
use OCA\Deck\Listeners\BeforeTemplateRenderedListener;
use OCA\Deck\Listeners\ParticipantCleanupListener;
use OCA\Deck\Listeners\FullTextSearchEventListener;
use OCA\Deck\Listeners\ResourceAdditionalScriptsListener;
use OCA\Deck\Listeners\ResourceListener;
use OCA\Deck\Listeners\LiveUpdateListener;
use OCA\Deck\Middleware\DefaultBoardMiddleware;
use OCA\Deck\Middleware\ExceptionMiddleware;
use OCA\Deck\Notification\Notifier;
use OCA\Deck\Reference\BoardReferenceProvider;
use OCA\Deck\Reference\CardReferenceProvider;
use OCA\Deck\Reference\CommentReferenceProvider;
use OCA\Deck\Search\CardCommentProvider;
use OCA\Deck\Search\DeckProvider;
use OCA\Deck\Service\PermissionService;
@@ -64,17 +57,20 @@ use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
use OCP\Collaboration\Reference\RenderReferenceEvent;
use OCP\Collaboration\Resources\IProviderManager;
use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent;
use OCP\Comments\CommentsEntityEvent;
use OCP\Comments\ICommentsManager;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Group\Events\GroupDeletedEvent;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IServerContainer;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Notification\IManager as NotificationManager;
use OCP\Share\IManager;
use OCP\User\Events\UserDeletedEvent;
use OCP\Util;
use Psr\Container\ContainerInterface;
@@ -83,21 +79,20 @@ class Application extends App implements IBootstrap {
public const COMMENT_ENTITY_TYPE = 'deckCard';
/** @var IServerContainer */
private $server;
public function __construct(array $urlParams = []) {
parent::__construct(self::APP_ID, $urlParams);
// TODO move this back to ::register after fixing the autoload issue
// (and use a listener class)
$container = $this->getContainer();
$eventDispatcher = $container->get(IEventDispatcher::class);
$eventDispatcher->addListener(RenderReferenceEvent::class, function () {
Util::addScript(self::APP_ID, self::APP_ID . '-reference');
});
$this->server = \OC::$server;
}
public function boot(IBootContext $context): void {
$context->injectFn(Closure::fromCallable([$this, 'registerUserGroupHooks']));
$context->injectFn(Closure::fromCallable([$this, 'registerCommentsEntity']));
$context->injectFn(Closure::fromCallable([$this, 'registerCommentsEventHandler']));
$context->injectFn(Closure::fromCallable([$this, 'registerNotifications']));
$context->injectFn(Closure::fromCallable([$this, 'registerCollaborationResources']));
$context->injectFn(function (IManager $shareManager) {
@@ -129,13 +124,8 @@ class Application extends App implements IBootstrap {
$context->registerSearchProvider(CardCommentProvider::class);
$context->registerDashboardWidget(DeckWidget::class);
// reference widget
$context->registerReferenceProvider(CardReferenceProvider::class);
$context->registerReferenceProvider(BoardReferenceProvider::class);
$context->registerReferenceProvider(CommentReferenceProvider::class);
$context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class);
// Event listening for full text search indexing
$context->registerEventListener(CardCreatedEvent::class, FullTextSearchEventListener::class);
$context->registerEventListener(CardUpdatedEvent::class, FullTextSearchEventListener::class);
@@ -143,28 +133,47 @@ class Application extends App implements IBootstrap {
$context->registerEventListener(AclCreatedEvent::class, FullTextSearchEventListener::class);
$context->registerEventListener(AclUpdatedEvent::class, FullTextSearchEventListener::class);
$context->registerEventListener(AclDeletedEvent::class, FullTextSearchEventListener::class);
}
// Handling cache invalidation for collections
$context->registerEventListener(AclCreatedEvent::class, ResourceListener::class);
$context->registerEventListener(AclDeletedEvent::class, ResourceListener::class);
public function registerNotifications(NotificationManager $notificationManager): void {
$notificationManager->registerNotifierService(Notifier::class);
}
$context->registerEventListener(UserDeletedEvent::class, ParticipantCleanupListener::class);
$context->registerEventListener(GroupDeletedEvent::class, ParticipantCleanupListener::class);
$context->registerEventListener(CircleDestroyedEvent::class, ParticipantCleanupListener::class);
private function registerUserGroupHooks(IUserManager $userManager, IGroupManager $groupManager): void {
$container = $this->getContainer();
// Delete user/group acl entries when they get deleted
$userManager->listen('\OC\User', 'postDelete', static function (IUser $user) use ($container) {
// delete existing acl entries for deleted user
/** @var AclMapper $aclMapper */
$aclMapper = $container->query(AclMapper::class);
$acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_USER, $user->getUID());
foreach ($acls as $acl) {
$aclMapper->delete($acl);
}
// delete existing user assignments
$assignmentMapper = $container->query(AssignmentMapper::class);
$assignments = $assignmentMapper->findByParticipant($user->getUID());
foreach ($assignments as $assignment) {
$assignmentMapper->delete($assignment);
}
// Event listening for realtime updates via notify_push
$context->registerEventListener(SessionCreatedEvent::class, LiveUpdateListener::class);
$context->registerEventListener(SessionClosedEvent::class, LiveUpdateListener::class);
$context->registerEventListener(BoardUpdatedEvent::class, LiveUpdateListener::class);
$context->registerEventListener(CardCreatedEvent::class, LiveUpdateListener::class);
$context->registerEventListener(CardUpdatedEvent::class, LiveUpdateListener::class);
$context->registerEventListener(CardDeletedEvent::class, LiveUpdateListener::class);
$context->registerEventListener(AclCreatedEvent::class, LiveUpdateListener::class);
$context->registerEventListener(AclUpdatedEvent::class, LiveUpdateListener::class);
$context->registerEventListener(AclDeletedEvent::class, LiveUpdateListener::class);
/** @var BoardMapper $boardMapper */
$boardMapper = $container->query(BoardMapper::class);
$boards = $boardMapper->findAllByOwner($user->getUID());
foreach ($boards as $board) {
$boardMapper->delete($board);
}
});
$context->registerNotifierService(Notifier::class);
$context->registerEventListener(LoadAdditionalScriptsEvent::class, ResourceAdditionalScriptsListener::class);
$groupManager->listen('\OC\Group', 'postDelete', static function (IGroup $group) use ($container) {
/** @var AclMapper $aclMapper */
$aclMapper = $container->query(AclMapper::class);
$aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID());
$acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID());
foreach ($acls as $acl) {
$aclMapper->delete($acl);
}
});
}
public function registerCommentsEntity(IEventDispatcher $eventDispatcher): void {
@@ -172,7 +181,6 @@ class Application extends App implements IBootstrap {
$event->addEntityCollection(self::COMMENT_ENTITY_TYPE, function ($name) {
/** @var CardMapper */
$cardMapper = $this->getContainer()->get(CardMapper::class);
/** @var PermissionService $permissionService */
$permissionService = $this->getContainer()->get(PermissionService::class);
try {
@@ -190,8 +198,16 @@ class Application extends App implements IBootstrap {
});
}
protected function registerCollaborationResources(IProviderManager $resourceManager): void {
protected function registerCollaborationResources(IProviderManager $resourceManager, SymfonyAdapter $symfonyAdapter): void {
$resourceManager->registerResourceProvider(ResourceProvider::class);
$resourceManager->registerResourceProvider(ResourceProviderCard::class);
$symfonyAdapter->addListener('\OCP\Collaboration\Resources::loadAdditionalScripts', static function () {
if (strpos(\OC::$server->getRequest()->getPathInfo(), '/call/') === 0) {
// Talk integration has its own entrypoint which already includes collections handling
return;
}
Util::addScript('deck', 'deck-collections');
});
}
}

View File

@@ -32,23 +32,20 @@ use OCP\AppFramework\QueryException;
use OCP\Collaboration\Resources\IManager;
use OCP\Collaboration\Resources\IProvider;
use OCP\Collaboration\Resources\IResource;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\Server;
class ResourceProvider implements IProvider {
public const RESOURCE_TYPE = 'deck';
private BoardMapper $boardMapper;
private PermissionService $permissionService;
private IURLGenerator $urlGenerator;
private $boardMapper;
private $permissionService;
protected array $nodes = [];
/** @var array */
protected $nodes = [];
public function __construct(BoardMapper $boardMapper, PermissionService $permissionService, IURLGenerator $urlGenerator) {
public function __construct(BoardMapper $boardMapper, PermissionService $permissionService) {
$this->boardMapper = $boardMapper;
$this->permissionService = $permissionService;
$this->urlGenerator = $urlGenerator;
}
/**
@@ -73,14 +70,14 @@ class ResourceProvider implements IProvider {
*/
public function getResourceRichObject(IResource $resource): array {
$board = $this->getBoard($resource);
$link = $this->urlGenerator->linkToRoute('deck.page.index') . '#/board/' . $resource->getId();
$link = \OC::$server->getURLGenerator()->linkToRoute('deck.page.index') . '#/board/' . $resource->getId();
return [
'type' => self::RESOURCE_TYPE,
'id' => $resource->getId(),
'name' => $board->getTitle(),
'link' => $link,
'iconUrl' => $this->urlGenerator->imagePath('deck', 'deck-dark.svg')
'iconUrl' => \OC::$server->getURLGenerator()->imagePath('deck', 'deck-dark.svg')
];
}
@@ -121,7 +118,7 @@ class ResourceProvider implements IProvider {
public function invalidateAccessCache($boardId = null) {
try {
/** @var IManager $resourceManager */
$resourceManager = Server::get(IManager::class);
$resourceManager = \OC::$server->query(IManager::class);
} catch (QueryException $e) {
}
if ($boardId !== null) {

View File

@@ -37,16 +37,24 @@ use OCP\Collaboration\Resources\IResource;
use OCP\Collaboration\Resources\ResourceException;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\Server;
class ResourceProviderCard implements IProvider {
public const RESOURCE_TYPE = 'deck-card';
private CardMapper $cardMapper;
private BoardMapper $boardMapper;
private PermissionService $permissionService;
private IURLGenerator $urlGenerator;
protected array $nodes = [];
/** @var CardMapper */
private $cardMapper;
/** @var BoardMapper */
private $boardMapper;
/** @var PermissionService */
private $permissionService;
/** @var IURLGenerator */
private $urlGenerator;
/** @var array */
protected $nodes = [];
public function __construct(CardMapper $cardMapper, BoardMapper $boardMapper, PermissionService $permissionService, IURLGenerator $urlGenerator) {
$this->cardMapper = $cardMapper;
@@ -139,7 +147,7 @@ class ResourceProviderCard implements IProvider {
public function invalidateAccessCache($cardId = null) {
try {
/** @var IManager $resourceManager */
$resourceManager = Server::get(IManager::class);
$resourceManager = \OC::$server->query(IManager::class);
} catch (QueryException $e) {
}
if ($cardId !== null) {

View File

@@ -30,7 +30,8 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class BoardImport extends Command {
private BoardImportCommandService $boardImportCommandService;
/** @var BoardImportCommandService */
private $boardImportCommandService;
public function __construct(
BoardImportCommandService $boardImportCommandService

View File

@@ -27,7 +27,6 @@ use OCA\Deck\Db\AssignmentMapper;
use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\CardMapper;
use OCA\Deck\Db\StackMapper;
use OCA\Deck\Model\CardDetails;
use OCA\Deck\Service\BoardService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
@@ -102,9 +101,7 @@ class UserExport extends Command {
$fullCard = $this->cardMapper->find($card->getId());
$assignedUsers = $this->assignedUsersMapper->findAll($card->getId());
$fullCard->setAssignedUsers($assignedUsers);
$cardDetails = new CardDetails($fullCard, $fullBoard);
$data[$board->getId()]['stacks'][$stack->getId()]['cards'][] = $cardDetails->jsonSerialize();
$data[$board->getId()]['stacks'][$stack->getId()]['cards'][] = (array)$fullCard->jsonSerialize();
}
}
}

View File

@@ -53,7 +53,7 @@ class AttachmentController extends Controller {
* @throws \OCA\Deck\NotFoundException
*/
public function display($cardId, $attachmentId) {
if (!str_contains($attachmentId, ':')) {
if (strpos($attachmentId, ':') === false) {
$type = 'deck_file';
} else {
[$type, $attachmentId] = explode(':', $attachmentId);
@@ -76,7 +76,7 @@ class AttachmentController extends Controller {
* @NoAdminRequired
*/
public function update($cardId, $attachmentId) {
if (!str_contains($attachmentId, ':')) {
if (strpos($attachmentId, ':') === false) {
$type = 'deck_file';
} else {
[$type, $attachmentId] = explode(':', $attachmentId);
@@ -88,7 +88,7 @@ class AttachmentController extends Controller {
* @NoAdminRequired
*/
public function delete($cardId, $attachmentId) {
if (!str_contains($attachmentId, ':')) {
if (strpos($attachmentId, ':') === false) {
$type = 'deck_file';
} else {
[$type, $attachmentId] = explode(':', $attachmentId);
@@ -100,7 +100,7 @@ class AttachmentController extends Controller {
* @NoAdminRequired
*/
public function restore($cardId, $attachmentId) {
if (!str_contains($attachmentId, ':')) {
if (strpos($attachmentId, ':') === false) {
$type = 'deck_file';
} else {
[$type, $attachmentId] = explode(':', $attachmentId);

View File

@@ -60,14 +60,12 @@ class BoardApiController extends ApiController {
* @NoCSRFRequired
*
* Return all of the boards that the current user has access to.
*
* @param bool $details
* @throws StatusException
*/
public function index(bool $details = false) {
public function index($details = null) {
$modified = $this->request->getHeader('If-Modified-Since');
if ($modified === null || $modified === '') {
$boards = $this->boardService->findAll(0, $details === true);
$boards = $this->boardService->findAll(0, $details);
} else {
$date = Util::parseHTTPDate($modified);
if (!$date) {

View File

@@ -169,15 +169,4 @@ class BoardController extends ApiController {
return new DataResponse([], HTTP::STATUS_UNAUTHORIZED);
}
/**
* @NoAdminRequired
* @param $boardId
* @return Board
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
*/
public function export($boardId) {
return $this->boardService->export($boardId);
}
}

View File

@@ -27,12 +27,9 @@ use OCA\Deck\AppInfo\Application;
use OCA\Deck\Service\ConfigService;
use OCA\Deck\Service\PermissionService;
use OCA\Files\Event\LoadSidebar;
use OCA\Text\Event\LoadEditor;
use OCA\Viewer\Event\LoadViewer;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent as CollaborationResourcesEvent;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IConfig;
use OCP\IInitialStateService;
use OCP\IRequest;
use OCP\AppFramework\Http\TemplateResponse;
@@ -44,17 +41,16 @@ use OCA\Deck\Db\Acl;
use OCA\Deck\Service\CardService;
class PageController extends Controller {
private PermissionService $permissionService;
private IInitialStateService $initialState;
private ConfigService $configService;
private IEventDispatcher $eventDispatcher;
private CardMapper $cardMapper;
private IURLGenerator $urlGenerator;
private CardService $cardService;
private IConfig $config;
private $permissionService;
private $initialState;
private $configService;
private $eventDispatcher;
private $cardMapper;
private $urlGenerator;
private $cardService;
public function __construct(
string $AppName,
$AppName,
IRequest $request,
PermissionService $permissionService,
IInitialStateService $initialStateService,
@@ -62,8 +58,7 @@ class PageController extends Controller {
IEventDispatcher $eventDispatcher,
CardMapper $cardMapper,
IURLGenerator $urlGenerator,
CardService $cardService,
IConfig $config
CardService $cardService
) {
parent::__construct($AppName, $request);
@@ -74,7 +69,6 @@ class PageController extends Controller {
$this->cardMapper = $cardMapper;
$this->urlGenerator = $urlGenerator;
$this->cardService = $cardService;
$this->config = $config;
}
/**
@@ -90,20 +84,13 @@ class PageController extends Controller {
$this->initialState->provideInitialState(Application::APP_ID, 'config', $this->configService->getAll());
$this->eventDispatcher->dispatchTyped(new LoadSidebar());
$this->eventDispatcher->dispatchTyped(new CollaborationResourcesEvent());
if (class_exists(LoadEditor::class)) {
$this->eventDispatcher->dispatchTyped(new LoadEditor());
}
if (class_exists(LoadViewer::class)) {
$this->eventDispatcher->dispatchTyped(new LoadViewer());
}
$response = new TemplateResponse('deck', 'main', [
'id-app-content' => '#app-content-vue',
'id-app-navigation' => '#app-navigation-vue',
]);
$response = new TemplateResponse('deck', 'main');
if ($this->config->getSystemValueBool('debug', false)) {
if (\OC::$server->getConfig()->getSystemValueBool('debug', false)) {
$csp = new ContentSecurityPolicy();
$csp->addAllowedConnectDomain('*');
$csp->addAllowedScriptDomain('*');

View File

@@ -27,7 +27,6 @@ declare(strict_types=1);
namespace OCA\Deck\Controller;
use OCA\Deck\Db\Card;
use OCA\Deck\Model\CardDetails;
use OCA\Deck\Service\SearchService;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
@@ -51,12 +50,9 @@ class SearchController extends OCSController {
public function search(string $term, ?int $limit = null, ?int $cursor = null): DataResponse {
$cards = $this->searchService->searchCards($term, $limit, $cursor);
return new DataResponse(array_map(function (Card $card) {
$board = $card->getRelatedBoard();
$json = (new CardDetails($card, $board))->jsonSerialize();
$json['relatedBoard'] = $board;
$json = $card->jsonSerialize();
$json['relatedStack'] = $card->getRelatedStack();
$json['relatedBoard'] = $card->getRelatedBoard();
return $json;
}, $cards));
}

View File

@@ -1,91 +0,0 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022, chandi Langecker (git@chandi.it)
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Controller;
use OCA\Deck\Service\SessionService;
use OCA\Deck\Service\PermissionService;
use OCA\Deck\Db\BoardMapper;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\IRequest;
use OCA\Deck\Db\Acl;
class SessionController extends OCSController {
private SessionService $sessionService;
private PermissionService $permissionService;
private BoardMapper $boardMapper;
public function __construct($appName,
IRequest $request,
SessionService $sessionService,
PermissionService $permissionService,
BoardMapper $boardMapper
) {
parent::__construct($appName, $request);
$this->sessionService = $sessionService;
$this->permissionService = $permissionService;
$this->boardMapper = $boardMapper;
}
/**
* @NoAdminRequired
*/
public function create(int $boardId): DataResponse {
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
$session = $this->sessionService->initSession($boardId);
return new DataResponse([
'token' => $session->getToken(),
]);
}
/**
* notifies the server that the session is still active
* @NoAdminRequired
* @param $boardId
*/
public function sync(int $boardId, string $token): DataResponse {
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
try {
$this->sessionService->syncSession($boardId, $token);
return new DataResponse([]);
} catch (DoesNotExistException $e) {
return new DataResponse([], 404);
}
}
/**
* delete a session if existing
* @NoAdminRequired
* @NoCSRFRequired
* @param $boardId
*/
public function close(int $boardId, string $token) {
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
$this->sessionService->closeSession($boardId, $token);
return new DataResponse();
}
}

View File

@@ -1,56 +0,0 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022, chandi Langecker (git@chandi.it)
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Cron;
use OCA\Deck\Service\SessionService;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\TimedJob;
use OCP\ILogger;
class SessionsCleanup extends TimedJob {
private $sessionService;
private $documentService;
private $logger;
private $imageService;
public function __construct(ITimeFactory $time,
SessionService $sessionService,
ILogger $logger) {
parent::__construct($time);
$this->sessionService = $sessionService;
$this->logger = $logger;
$this->setInterval(SessionService::SESSION_VALID_TIME);
}
protected function run($argument) {
$this->logger->debug('Run cleanup job for deck sessions');
$removedSessions = $this->sessionService->removeInactiveSessions();
$this->logger->debug('Removed ' . $removedSessions . ' inactive sessions');
}
}

View File

@@ -59,21 +59,20 @@ class Calendar extends ExternalCalendar {
}
public function getACL() {
// the calendar should always have the read and the write-properties permissions
// write-properties is needed to allow the user to toggle the visibility of shared deck calendars
$acl = [
[
'privilege' => '{DAV:}read',
'principal' => $this->getOwner(),
'protected' => true,
],
[
]
];
if ($this->backend->checkBoardPermission($this->board->getId(), Acl::PERMISSION_MANAGE)) {
$acl[] = [
'privilege' => '{DAV:}write-properties',
'principal' => $this->getOwner(),
'protected' => true,
]
];
];
}
return $acl;
}
@@ -188,18 +187,12 @@ class Calendar extends ExternalCalendar {
foreach ($properties as $key => $value) {
switch ($key) {
case '{DAV:}displayname':
if (!$this->backend->checkBoardPermission($this->board->getId(), Acl::PERMISSION_MANAGE)) {
throw new Forbidden('no permission to change the displayname');
}
if (mb_strpos($value, 'Deck: ') === 0) {
$value = mb_substr($value, strlen('Deck: '));
}
$this->board->setTitle($value);
break;
case '{http://apple.com/ns/ical/}calendar-color':
if (!$this->backend->checkBoardPermission($this->board->getId(), Acl::PERMISSION_MANAGE)) {
throw new Forbidden('no permission to change the calendar color');
}
$color = substr($value, 1, 6);
if (!preg_match('/[a-f0-9]{6}/i', $color)) {
throw new InvalidDataException('No valid color provided');

View File

@@ -59,7 +59,7 @@ class DeckCalendarBackend {
}
public function getBoards(): array {
return $this->boardService->findAll(-1, false, false);
return $this->boardService->findAll(-1, null, false);
}
public function getBoard(int $id): Board {

View File

@@ -26,34 +26,18 @@ declare(strict_types=1);
namespace OCA\Deck\Dashboard;
use DateTime;
use OCA\Deck\AppInfo\Application;
use OCA\Deck\Db\Label;
use OCA\Deck\Service\OverviewService;
use OCP\Dashboard\IAPIWidget;
use OCP\Dashboard\IButtonWidget;
use OCP\Dashboard\IIconWidget;
use OCP\Dashboard\Model\WidgetButton;
use OCP\Dashboard\Model\WidgetItem;
use OCP\IDateTimeFormatter;
use OCP\Dashboard\IWidget;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\Util;
class DeckWidget implements IAPIWidget, IButtonWidget, IIconWidget {
private IL10N $l10n;
private OverviewService $dashboardService;
private IURLGenerator $urlGenerator;
private IDateTimeFormatter $dateTimeFormatter;
class DeckWidget implements IWidget {
public function __construct(IL10N $l10n,
OverviewService $dashboardService,
IDateTimeFormatter $dateTimeFormatter,
IURLGenerator $urlGenerator) {
/**
* @var IL10N
*/
private $l10n;
public function __construct(IL10N $l10n) {
$this->l10n = $l10n;
$this->dashboardService = $dashboardService;
$this->urlGenerator = $urlGenerator;
$this->dateTimeFormatter = $dateTimeFormatter;
}
/**
@@ -84,88 +68,17 @@ class DeckWidget implements IAPIWidget, IButtonWidget, IIconWidget {
return 'icon-deck';
}
/**
* @inheritDoc
*/
public function getIconUrl(): string {
return $this->urlGenerator->getAbsoluteURL(
$this->urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg')
);
}
/**
* @inheritDoc
*/
public function getUrl(): ?string {
return $this->urlGenerator->getAbsoluteURL(
$this->urlGenerator->linkToRoute(Application::APP_ID . '.page.index')
);
return null;
}
/**
* @inheritDoc
*/
public function load(): void {
Util::addScript('deck', 'deck-dashboard');
}
/**
* @inheritDoc
*/
public function getItems(string $userId, ?string $since = null, int $limit = 7): array {
$upcomingCards = $this->dashboardService->findUpcomingCards($userId);
$nowTimestamp = (new Datetime())->getTimestamp();
$sinceTimestamp = $since !== null ? (new Datetime($since))->getTimestamp() : null;
$upcomingCards = array_filter($upcomingCards, static function (array $card) use ($nowTimestamp, $sinceTimestamp) {
if (isset($card['duedate'])) {
$ts = (new Datetime($card['duedate']))->getTimestamp();
return $ts > $nowTimestamp && ($sinceTimestamp === null || $ts > $sinceTimestamp);
}
return false;
});
usort($upcomingCards, static function ($a, $b) {
$a = new Datetime($a['duedate']);
$ta = $a->getTimestamp();
$b = new Datetime($b['duedate']);
$tb = $b->getTimestamp();
return ($ta > $tb) ? 1 : -1;
});
$upcomingCards = array_slice($upcomingCards, 0, $limit);
$urlGenerator = $this->urlGenerator;
$dateTimeFormatter = $this->dateTimeFormatter;
return array_map(static function (array $card) use ($urlGenerator, $dateTimeFormatter) {
$formattedDueDate = $dateTimeFormatter->formatDateTime(new DateTime($card['duedate']));
return new WidgetItem(
$card['title'] . ' (' . $formattedDueDate . ')',
implode(
', ',
array_map(static function (Label $label) {
return $label->jsonSerialize()['title'];
}, $card['labels'])
),
$urlGenerator->getAbsoluteURL(
$urlGenerator->linkToRoute(Application::APP_ID . '.page.redirectToCard', ['cardId' => $card['id']])
),
$urlGenerator->getAbsoluteURL(
$urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg')
),
$card['duedate']
);
}, $upcomingCards);
}
/**
* @inheritDoc
*/
public function getWidgetButtons(string $userId): array {
return [
new WidgetButton(
WidgetButton::TYPE_MORE,
$this->urlGenerator->getAbsoluteURL(
$this->urlGenerator->linkToRoute(Application::APP_ID . '.page.index')
),
$this->l10n->t('Load more')
),
];
\OCP\Util::addScript('deck', 'deck-dashboard');
}
}

View File

@@ -28,66 +28,23 @@ use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
/** @template-extends DeckMapper<Acl> */
class AclMapper extends DeckMapper implements IPermissionMapper {
public function __construct(IDBConnection $db) {
parent::__construct($db, 'deck_board_acl', Acl::class);
}
/**
* @param numeric $boardId
* @param int|null $limit
* @param int|null $offset
* @return Acl[]
* @throws \OCP\DB\Exception
*/
public function findAll($boardId, $limit = null, $offset = null) {
$qb = $this->db->getQueryBuilder();
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage')
->from('deck_board_acl')
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
->setMaxResults($limit)
->setFirstResult($offset);
return $this->findEntities($qb);
$sql = 'SELECT id, board_id, type, participant, permission_edit, permission_share, permission_manage FROM `*PREFIX*deck_board_acl` WHERE `board_id` = ? ';
return $this->findEntities($sql, [$boardId], $limit, $offset);
}
public function findIn(array $boardIds, ?int $limit = null, ?int $offset = null): array {
$qb = $this->db->getQueryBuilder();
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage')
->from('deck_board_acl')
->where($qb->expr()->in('board_id', $qb->createParameter('boardIds')))
->setMaxResults($limit)
->setFirstResult($offset);
return iterator_to_array($this->chunkQuery($boardIds, function (array $ids) use ($qb) {
$qb->setParameter('boardIds', $ids, IQueryBuilder::PARAM_INT_ARRAY);
return $this->findEntities($qb);
}));
public function isOwner($userId, $aclId): bool {
$sql = 'SELECT owner FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_board_acl` WHERE id = ?)';
$stmt = $this->execute($sql, [$aclId]);
$row = $stmt->fetch();
return ($row['owner'] === $userId);
}
/**
* @param numeric $userId
* @param numeric $id
* @return bool
* @throws \OCP\DB\Exception
*/
public function isOwner($userId, $id): bool {
$aclId = $id;
$qb = $this->db->getQueryBuilder();
$qb->select('acl.id')
->from($this->getTableName(), 'acl')
->innerJoin('acl', 'deck_boards', 'b', 'acl.board_id = b.id')
->where($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)))
->andWhere($qb->expr()->eq('acl.id', $qb->createNamedParameter($aclId, IQueryBuilder::PARAM_INT)));
return count($qb->executeQuery()->fetchAll()) > 0;
}
/**
* @param numeric $id
* @return int|null
*/
public function findBoardId($id): ?int {
try {
$entity = $this->find($id);
@@ -97,21 +54,9 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
return null;
}
/**
* @param int $type
* @param string $participant
* @return Acl[]
* @throws \OCP\DB\Exception
*/
public function findByParticipant($type, $participant): array {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->where($qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('participant', $qb->createNamedParameter($participant, IQueryBuilder::PARAM_STR)));
return $this->findEntities($qb);
$sql = 'SELECT * from *PREFIX*deck_board_acl WHERE type = ? AND participant = ?';
return $this->findEntities($sql, [$type, $participant]);
}
/**
@@ -125,12 +70,4 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
->andWhere($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)));
$qb->executeStatement();
}
public function findByType(int $type): array {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from('deck_board_acl')
->where($qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
return $this->findEntities($qb);
}
}

View File

@@ -28,13 +28,14 @@ namespace OCA\Deck\Db;
use OCA\Deck\NotFoundException;
use OCA\Deck\Service\CirclesService;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IUserManager;
use PDO;
/** @template-extends DeckMapper<Assignment> */
class AssignmentMapper extends DeckMapper implements IPermissionMapper {
class AssignmentMapper extends QBMapper implements IPermissionMapper {
/** @var CardMapper */
private $cardMapper;
@@ -54,11 +55,14 @@ class AssignmentMapper extends DeckMapper implements IPermissionMapper {
$this->circleService = $circleService;
}
/**
* @return Assignment[]
*/
public function findAll(int $cardId): array {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from('deck_assigned_users')
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)));
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, PDO::PARAM_INT)));
$users = $this->findEntities($qb);
foreach ($users as $user) {
$this->mapParticipant($user);
@@ -66,35 +70,18 @@ class AssignmentMapper extends DeckMapper implements IPermissionMapper {
return $users;
}
public function findIn(array $cardIds): array {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from('deck_assigned_users')
->where($qb->expr()->in('card_id', $qb->createParameter('cardIds')));
$users = iterator_to_array($this->chunkQuery($cardIds, function (array $ids) use ($qb) {
$qb->setParameter('cardIds', $ids, IQueryBuilder::PARAM_INT_ARRAY);
return $this->findEntities($qb);
}));
foreach ($users as $user) {
$this->mapParticipant($user);
}
return $users;
}
public function findByParticipant(string $participant, $type = Assignment::TYPE_USER): array {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from('deck_assigned_users')
->where($qb->expr()->eq('participant', $qb->createNamedParameter($participant, IQueryBuilder::PARAM_STR)))
->andWhere($qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
->where($qb->expr()->eq('participant', $qb->createNamedParameter($participant, PDO::PARAM_STR)))
->andWhere($qb->expr()->eq('type', $qb->createNamedParameter($type, PDO::PARAM_INT)));
return $this->findEntities($qb);
}
public function isOwner($userId, $id): bool {
return $this->cardMapper->isOwner($userId, $id);
public function isOwner($userId, $cardId): bool {
return $this->cardMapper->isOwner($userId, $cardId);
}
public function findBoardId($id): ?int {
@@ -147,8 +134,8 @@ class AssignmentMapper extends DeckMapper implements IPermissionMapper {
private function getOrigin(Assignment $assignment) {
if ($assignment->getType() === Assignment::TYPE_USER) {
$origin = $this->userManager->userExists($assignment->getParticipant());
return $origin ? new User($assignment->getParticipant(), $this->userManager) : null;
$origin = $this->userManager->get($assignment->getParticipant());
return $origin ? new User($origin) : null;
}
if ($assignment->getType() === Assignment::TYPE_GROUP) {
$origin = $this->groupManager->get($assignment->getParticipant());

View File

@@ -30,8 +30,8 @@ use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IUserManager;
use PDO;
/** @template-extends DeckMapper<Attachment> */
class AttachmentMapper extends DeckMapper implements IPermissionMapper {
private $cardMapper;
private $userManager;
@@ -52,53 +52,70 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
}
/**
* @param int $id
* @return Attachment
* @throws DoesNotExistException
* @throws MultipleObjectsReturnedException
* @throws \OCP\DB\Exception
* @param $id
* @return Entity|Attachment
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
*/
public function find($id) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->from('deck_attachment')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
return $this->findEntity($qb);
$cursor = $qb->execute();
$row = $cursor->fetch(PDO::FETCH_ASSOC);
if ($row === false) {
$cursor->closeCursor();
throw new DoesNotExistException('Did expect one result but found none when executing query: ' . $qb->getSQL());
}
$row2 = $cursor->fetch();
$cursor->closeCursor();
if ($row2 !== false) {
throw new MultipleObjectsReturnedException('Did not expect more than one result when executing query: ' . $qb->getSQL());
}
return $this->mapRowToEntity($row);
}
/**
* @param int $cardId
* @param string $data
* @return Attachment
* @throws DoesNotExistException
* @throws MultipleObjectsReturnedException
* @throws \OCP\DB\Exception
*/
public function findByData($cardId, $data) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->from('deck_attachment')
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('data', $qb->createNamedParameter($data, IQueryBuilder::PARAM_STR)));
return $this->findEntity($qb);
$cursor = $qb->execute();
$row = $cursor->fetch(PDO::FETCH_ASSOC);
if ($row === false) {
$cursor->closeCursor();
throw new DoesNotExistException('Did expect one result but found none when executing query: ' . $qb->getSQL());
}
$cursor->closeCursor();
return $this->mapRowToEntity($row);
}
/**
* Find all attachments for a card
*
* @param $cardId
* @return Entity[]
* @throws \OCP\DB\Exception
* @return array
*/
public function findAll($cardId) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->from('deck_attachment')
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
return $this->findEntities($qb);
$entities = [];
$cursor = $qb->execute();
while ($row = $cursor->fetch()) {
$entities[] = $this->mapRowToEntity($row);
}
$cursor->closeCursor();
return $entities;
}
/**
@@ -111,7 +128,7 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
$timeLimit = time() - (60 * 5);
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->from('deck_attachment')
->where($qb->expr()->gt('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
if ($withOffset) {
$qb
@@ -122,7 +139,13 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
->andWhere($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)));
}
return $this->findEntities($qb);
$entities = [];
$cursor = $qb->execute();
while ($row = $cursor->fetch()) {
$entities[] = $this->mapRowToEntity($row);
}
$cursor->closeCursor();
return $entities;
}

View File

@@ -23,14 +23,6 @@
namespace OCA\Deck\Db;
/**
* @method int getId()
* @method string getTitle()
* @method int getShared()
* @method bool getArchived()
* @method int getDeletedAt()
* @method int getLastModified()
*/
class Board extends RelationalEntity {
protected $title;
protected $owner;
@@ -44,7 +36,6 @@ class Board extends RelationalEntity {
protected $users = [];
protected $shared;
protected $stacks = [];
protected $activeSessions = [];
protected $deletedAt = 0;
protected $lastModified = 0;
@@ -60,7 +51,6 @@ class Board extends RelationalEntity {
$this->addRelation('acl');
$this->addRelation('shared');
$this->addRelation('users');
$this->addRelation('activeSessions');
$this->addRelation('permissions');
$this->addRelation('stacks');
$this->addRelation('settings');

View File

@@ -33,7 +33,6 @@ use OCP\IUserManager;
use OCP\IGroupManager;
use Psr\Log\LoggerInterface;
/** @template-extends QBMapper<Board> */
class BoardMapper extends QBMapper implements IPermissionMapper {
private $labelMapper;
private $aclMapper;
@@ -43,9 +42,9 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
private $circlesService;
private $logger;
/** @var CappedMemoryCache<Board[]> */
/** @var CappedMemoryCache */
private $userBoardCache;
/** @var CappedMemoryCache<Board> */
/** @var CappedMemoryCache */
private $boardCache;
public function __construct(
@@ -90,6 +89,9 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
$this->boardCache[$id] = $this->findEntity($qb);
}
// FIXME is this necessary? it was NOT done with the old mapper
// $this->mapOwner($board);
// Add labels
if ($withLabels && $this->boardCache[$id]->getLabels() === null) {
$labels = $this->labelMapper->findAll($id);
@@ -105,47 +107,6 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
return $this->boardCache[$id];
}
public function findBoardIds(string $userId): array {
$qb = $this->db->getQueryBuilder();
$qb->selectDistinct('b.id')
->from($this->getTableName(), 'b')
->leftJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'));
// Owned by the user
$qb->where($qb->expr()->andX(
$qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)),
));
// Shared to the user
$qb->orWhere($qb->expr()->andX(
$qb->expr()->eq('acl.participant', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)),
$qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_USER, IQueryBuilder::PARAM_INT)),
));
// Shared to user groups of the user
$groupIds = $this->groupManager->getUserGroupIds($this->userManager->get($userId));
if (count($groupIds) !== 0) {
$qb->orWhere($qb->expr()->andX(
$qb->expr()->in('acl.participant', $qb->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)),
$qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
));
}
// Shared to circles of the user
$circles = $this->circlesService->getUserCircles($userId);
if (count($circles) !== 0) {
$qb->orWhere($qb->expr()->andX(
$qb->expr()->in('acl.participant', $qb->createNamedParameter($circles, IQueryBuilder::PARAM_STR_ARRAY)),
$qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_CIRCLE, IQueryBuilder::PARAM_INT)),
));
}
$result = $qb->executeQuery();
return array_map(function (string $id) {
return (int)$id;
}, $result->fetchAll(\PDO::FETCH_COLUMN));
}
public function findAllForUser(string $userId, ?int $since = null, bool $includeArchived = true, ?int $before = null,
?string $term = null): array {
$useCache = ($since === -1 && $includeArchived === true && $before === null && $term === null);
@@ -156,21 +117,7 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
$userBoards = $this->findAllByUser($userId, null, null, $since, $includeArchived, $before, $term);
$groupBoards = $this->findAllByGroups($userId, $groups, null, null, $since, $includeArchived, $before, $term);
$circleBoards = $this->findAllByCircles($userId, null, null, $since, $includeArchived, $before, $term);
$allBoards = array_values(array_unique(array_merge($userBoards, $groupBoards, $circleBoards)));
// Could be moved outside
$acls = $this->aclMapper->findIn(array_map(function ($board) {
return $board->getId();
}, $allBoards));
/* @var Board $entry */
foreach ($allBoards as $entry) {
$boardAcls = array_values(array_filter($acls, function ($acl) use ($entry) {
return $acl->getBoardId() === $entry->getId();
}));
$entry->setAcl($boardAcls);
}
$allBoards = array_unique(array_merge($userBoards, $groupBoards, $circleBoards));
foreach ($allBoards as $board) {
$this->boardCache[$board->getId()] = $board;
}
@@ -184,9 +131,14 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
/**
* Find all boards for a given user
*
* @param $userId
* @param null $limit
* @param null $offset
* @return array
*/
public function findAllByUser(string $userId, ?int $limit = null, ?int $offset = null, ?int $since = null,
bool $includeArchived = true, ?int $before = null, ?string $term = null): array {
bool $includeArchived = true, ?int $before = null, ?string $term = null) {
// FIXME this used to be a UNION to get boards owned by $userId and the user shares in one single query
// Is it possible with the query builder?
$qb = $this->db->getQueryBuilder();
@@ -270,7 +222,11 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
$entry->setShared(1);
}
$entries = array_merge($entries, $sharedEntries);
/* @var Board $entry */
foreach ($entries as $entry) {
$acl = $this->aclMapper->findAll($entry->id);
$entry->setAcl($acl);
}
return $entries;
}
@@ -291,9 +247,15 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
/**
* Find all boards for a given user
*
* @param $userId
* @param $groups
* @param null $limit
* @param null $offset
* @return array
*/
public function findAllByGroups(string $userId, array $groups, ?int $limit = null, ?int $offset = null, ?int $since = null,
bool $includeArchived = true, ?int $before = null, ?string $term = null): array {
bool $includeArchived = true, ?int $before = null, ?string $term = null) {
if (count($groups) <= 0) {
return [];
}
@@ -343,6 +305,11 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
foreach ($entries as $entry) {
$entry->setShared(2);
}
/* @var Board $entry */
foreach ($entries as $entry) {
$acl = $this->aclMapper->findAll($entry->id);
$entry->setAcl($acl);
}
return $entries;
}
@@ -399,6 +366,11 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
foreach ($entries as $entry) {
$entry->setShared(2);
}
/* @var Board $entry */
foreach ($entries as $entry) {
$acl = $this->aclMapper->findAll($entry->id);
$entry->setAcl($acl);
}
return $entries;
}
@@ -442,8 +414,8 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
return parent::delete($entity);
}
public function isOwner($userId, $id): bool {
$board = $this->find($id);
public function isOwner($userId, $boardId): bool {
$board = $this->find($boardId);
return ($board->getOwner() === $userId);
}
@@ -452,11 +424,13 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
}
public function mapAcl(Acl &$acl) {
$userManager = $this->userManager;
$groupManager = $this->groupManager;
$acl->resolveRelation('participant', function ($participant) use (&$acl, &$userManager, &$groupManager) {
if ($acl->getType() === Acl::PERMISSION_TYPE_USER) {
if ($this->userManager->userExists($acl->getParticipant())) {
return new User($acl->getParticipant(), $this->userManager);
$user = $userManager->get($participant);
if ($user !== null) {
return new User($user);
}
$this->logger->debug('User ' . $acl->getId() . ' not found when mapping acl ' . $acl->getParticipant());
return null;
@@ -494,8 +468,9 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
public function mapOwner(Board &$board) {
$userManager = $this->userManager;
$board->resolveRelation('owner', function ($owner) use (&$userManager) {
if ($this->userManager->userExists($owner)) {
return new User($owner, $userManager);
$user = $userManager->get($owner);
if ($user !== null) {
return new User($user);
}
return null;
});

View File

@@ -27,44 +27,6 @@ use DateTime;
use DateTimeZone;
use Sabre\VObject\Component\VCalendar;
/**
* @method string getTitle()
* @method string getDescription()
* @method string getDescriptionPrev()
* @method int getStackId()
* @method int getOrder()
* @method int getLastModified()
* @method int getCreatedAt()
* @method bool getArchived()
* @method bool getNotified()
*
* @method void setLabels(Label[] $labels)
* @method null|Label[] getLabels()
*
* @method void setAssignedUsers(Assignment[] $users)
* @method null|User[] getAssignedUsers()
*
* @method void setAttachments(Attachment[] $attachments)
* @method null|Attachment[] getAttachments()
*
* @method void setAttachmentCount(int $count)
* @method null|int getAttachmentCount()
*
* @method void setCommentsUnread(int $count)
* @method null|int getCommentsUnread()
*
* @method void setCommentsCount(int $count)
* @method null|int getCommentsCount()
*
* @method void setOwner(string $user)
* @method null|string getOwner()
*
* @method void setRelatedStack(Stack $stack)
* @method null|Stack getRelatedStack()
*
* @method void setRelatedBoard(Board $board)
* @method null|Board getRelatedBoard()
*/
class Card extends RelationalEntity {
public const TITLE_MAX_LENGTH = 255;
@@ -108,7 +70,6 @@ class Card extends RelationalEntity {
$this->addType('archived', 'boolean');
$this->addType('notified', 'boolean');
$this->addType('deletedAt', 'integer');
$this->addType('duedate', 'datetime');
$this->addRelation('labels');
$this->addRelation('assignedUsers');
$this->addRelation('attachments');
@@ -126,6 +87,50 @@ class Card extends RelationalEntity {
$this->databaseType = $type;
}
public function getDuedate($isoFormat = false) {
if ($this->duedate === null) {
return null;
}
$dt = new DateTime($this->duedate);
if (!$isoFormat && $this->databaseType === 'mysql') {
return $dt->format('Y-m-d H:i:s');
}
return $dt->format('c');
}
public function jsonSerialize(): array {
$json = parent::jsonSerialize();
$json['overdue'] = self::DUEDATE_FUTURE;
$due = $this->duedate ? strtotime($this->duedate) : false;
if ($due !== false) {
$today = new DateTime();
$today->setTime(0, 0);
$match_date = new DateTime($this->duedate);
$match_date->setTime(0, 0);
$diff = $today->diff($match_date);
$diffDays = (integer) $diff->format('%R%a'); // Extract days count in interval
if ($diffDays === 1) {
$json['overdue'] = self::DUEDATE_NEXT;
}
if ($diffDays === 0) {
$json['overdue'] = self::DUEDATE_NOW;
}
if ($diffDays < 0) {
$json['overdue'] = self::DUEDATE_OVERDUE;
}
}
$json['duedate'] = $this->getDuedate(true);
unset($json['notified']);
unset($json['descriptionPrev']);
unset($json['relatedStack']);
unset($json['relatedBoard']);
return $json;
}
public function getCalendarObject(): VCalendar {
$calendar = new VCalendar();
$event = $calendar->createComponent('VTODO');
@@ -134,7 +139,7 @@ class Card extends RelationalEntity {
$creationDate = new DateTime();
$creationDate->setTimestamp($this->createdAt);
$event->DTSTAMP = $creationDate;
$event->DUE = new DateTime($this->getDuedate()->format('c'), new DateTimeZone('UTC'));
$event->DUE = new DateTime($this->getDuedate(true), new DateTimeZone('UTC'));
}
$event->add('RELATED-TO', 'deck-stack-' . $this->getStackId());
@@ -158,21 +163,6 @@ class Card extends RelationalEntity {
return $calendar;
}
public function getDaysUntilDue(): ?int {
if ($this->getDuedate() === null) {
return null;
}
$today = new DateTime();
$today->setTime(0, 0);
$matchDate = DateTime::createFromInterface($this->getDuedate());
$matchDate->setTime(0, 0);
$diff = $today->diff($matchDate);
return (int) $diff->format('%R%a'); // Extract days count in interval
}
public function getCalendarPrefix(): string {
return 'card';
}

View File

@@ -38,7 +38,6 @@ use OCP\IUser;
use OCP\IUserManager;
use OCP\Notification\IManager;
/** @template-extends QBMapper<Card> */
class CardMapper extends QBMapper implements IPermissionMapper {
/** @var LabelMapper */
@@ -239,28 +238,13 @@ class CardMapper extends QBMapper implements IPermissionMapper {
return $this->findEntities($qb);
}
public function findAllByBoardId(int $boardId, ?int $limit = null, ?int $offset = null): array {
public function findAllWithDue($boardId) {
$qb = $this->db->getQueryBuilder();
$qb->select('c.*')
->from('deck_cards', 'c')
->innerJoin('c', 'deck_stacks', 's', 's.id = c.stack_id')
->innerJoin('s', 'deck_boards', 'b', 'b.id = s.board_id')
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('archived', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
->setMaxResults($limit)
->setFirstResult($offset)
->orderBy('c.lastmodified')
->addOrderBy('c.id');
return $this->findEntities($qb);
}
public function findAllWithDue(array $boardIds) {
$qb = $this->db->getQueryBuilder();
$qb->select('c.*')
->from('deck_cards', 'c')
->innerJoin('c', 'deck_stacks', 's', 's.id = c.stack_id')
->innerJoin('s', 'deck_boards', 'b', 'b.id = s.board_id')
->where($qb->expr()->in('s.board_id', $qb->createNamedParameter($boardIds, IQueryBuilder::PARAM_INT_ARRAY)))
->where($qb->expr()->eq('s.board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->isNotNull('c.duedate'))
->andWhere($qb->expr()->eq('c.archived', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
->andWhere($qb->expr()->eq('c.deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
@@ -270,14 +254,14 @@ class CardMapper extends QBMapper implements IPermissionMapper {
return $this->findEntities($qb);
}
public function findToMeOrNotAssignedCards(array $boardIds, string $username) {
public function findToMeOrNotAssignedCards($boardId, $username) {
$qb = $this->db->getQueryBuilder();
$qb->select('c.*')
->from('deck_cards', 'c')
->innerJoin('c', 'deck_stacks', 's', 's.id = c.stack_id')
->innerJoin('s', 'deck_boards', 'b', 'b.id = s.board_id')
->leftJoin('c', 'deck_assigned_users', 'u', 'c.id = u.card_id')
->where($qb->expr()->in('s.board_id', $qb->createNamedParameter($boardIds, IQueryBuilder::PARAM_INT_ARRAY)))
->where($qb->expr()->eq('s.board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->orX(
$qb->expr()->eq('u.participant', $qb->createNamedParameter($username, IQueryBuilder::PARAM_STR)),
$qb->expr()->isNull('u.participant'))
@@ -576,10 +560,10 @@ class CardMapper extends QBMapper implements IPermissionMapper {
$qb->execute();
}
public function isOwner($userId, $id): bool {
public function isOwner($userId, $cardId): bool {
$sql = 'SELECT owner FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_stacks` WHERE id IN (SELECT stack_id FROM `*PREFIX*deck_cards` WHERE id = ?))';
$stmt = $this->db->prepare($sql);
$stmt->bindParam(1, $id, \PDO::PARAM_INT, 0);
$stmt->bindParam(1, $cardId, \PDO::PARAM_INT, 0);
$stmt->execute();
$row = $stmt->fetch();
return ($row['owner'] === $userId);
@@ -607,8 +591,9 @@ class CardMapper extends QBMapper implements IPermissionMapper {
public function mapOwner(Card &$card) {
$userManager = $this->userManager;
$card->resolveRelation('owner', function ($owner) use (&$userManager) {
if ($userManager->userExists($owner)) {
return new User($owner, $this->userManager);
$user = $userManager->get($owner);
if ($user !== null) {
return new User($user);
}
return null;
});

View File

@@ -24,7 +24,6 @@
namespace OCA\Deck\Db;
use OCP\ICacheFactory;
use OCP\ICache;
use OCP\IDBConnection;
use OCP\IRequest;
@@ -32,16 +31,13 @@ class ChangeHelper {
public const TYPE_BOARD = 'boardChanged';
public const TYPE_CARD = 'cardChanged';
private IDBConnection $db;
private ICache $cache;
private IRequest $request;
private ?string $userId;
private $db;
public function __construct(
IDBConnection $db,
ICacheFactory $cacheFactory,
IRequest $request,
?string $userId
$userId
) {
$this->db = $db;
$this->cache = $cacheFactory->createDistributed('deck_changes');

View File

@@ -23,46 +23,30 @@
namespace OCA\Deck\Db;
use Generator;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\AppFramework\Db\Mapper;
/**
* @template T of Entity
* @template-extends QBMapper<T>
* Class DeckMapper
*
* @package OCA\Deck\Db
* @deprecated use QBMapper
*
* TODO: Move to QBMapper once Nextcloud 14 is a minimum requirement
*/
abstract class DeckMapper extends QBMapper {
class DeckMapper extends Mapper {
/**
* @param $id
* @return T
* @return \OCP\AppFramework\Db\Entity if not found
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws \OCP\AppFramework\Db\DoesNotExistException
*/
public function find($id) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
return $this->findEntity($qb);
$sql = 'SELECT * FROM `' . $this->tableName . '` ' . 'WHERE `id` = ?';
return $this->findEntity($sql, [$id]);
}
/**
* Helper function to split passed array into chunks of 1000 elements and
* call a given callback for fetching query results
*
* Can be useful to limit to 1000 results per query for oracle compatiblity
* but still iterate over all results
*/
public function chunkQuery(array $ids, callable $callback): Generator {
$limit = 1000;
while (!empty($ids)) {
$slice = array_splice($ids, 0, $limit);
foreach ($callback($slice) as $item) {
yield $item;
}
}
protected function execute($sql, array $params = [], $limit = null, $offset = null) {
return parent::execute($sql, $params, $limit, $offset);
}
}

View File

@@ -26,111 +26,48 @@ namespace OCA\Deck\Db;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
/** @template-extends DeckMapper<Label> */
class LabelMapper extends DeckMapper implements IPermissionMapper {
public function __construct(IDBConnection $db) {
parent::__construct($db, 'deck_labels', Label::class);
}
/**
* @param numeric $boardId
* @param int|null $limit
* @param int|null $offset
* @return Label[]
* @throws \OCP\DB\Exception
*/
public function findAll($boardId, $limit = null, $offset = null): array {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
->setMaxResults($limit)
->setFirstResult($offset);
return $this->findEntities($qb);
public function findAll($boardId, $limit = null, $offset = null) {
$sql = 'SELECT * FROM `*PREFIX*deck_labels` WHERE `board_id` = ? ORDER BY `id`';
return $this->findEntities($sql, [$boardId], $limit, $offset);
}
public function delete(Entity $entity): Entity {
public function delete(\OCP\AppFramework\Db\Entity $entity) {
// delete assigned labels
$this->deleteLabelAssignments($entity->getId());
// delete label
return parent::delete($entity);
}
/**
* @param numeric $cardId
* @param int|null $limit
* @param int|null $offset
* @return Label[]
* @throws \OCP\DB\Exception
*/
public function findAssignedLabelsForCard($cardId, $limit = null, $offset = null): array {
$qb = $this->db->getQueryBuilder();
$qb->select('l.*', 'card_id')
->from($this->getTableName(), 'l')
->innerJoin('l', 'deck_assigned_labels', 'al', 'l.id = al.label_id')
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)))
->orderBy('l.id')
->setMaxResults($limit)
->setFirstResult($offset);
return $this->findEntities($qb);
public function findAssignedLabelsForCard($cardId, $limit = null, $offset = null) {
$sql = 'SELECT l.*,card_id FROM `*PREFIX*deck_assigned_labels` as al INNER JOIN *PREFIX*deck_labels as l ON l.id = al.label_id WHERE `card_id` = ? ORDER BY l.id';
return $this->findEntities($sql, [$cardId], $limit, $offset);
}
public function findAssignedLabelsForBoard($boardId, $limit = null, $offset = null) {
$sql = 'SELECT c.id as card_id, l.id as id, l.title as title, l.color as color FROM `*PREFIX*deck_cards` as c ' .
' INNER JOIN `*PREFIX*deck_assigned_labels` as al ON al.card_id = c.id INNER JOIN `*PREFIX*deck_labels` as l ON al.label_id = l.id WHERE board_id=? ORDER BY l.id';
return $this->findEntities($sql, [$boardId], $limit, $offset);
}
public function findAssignedLabelsForCards($cardIds, $limit = null, $offset = null): array {
$qb = $this->db->getQueryBuilder();
$qb->select('l.*', 'card_id')
->from($this->getTableName(), 'l')
->innerJoin('l', 'deck_assigned_labels', 'al', 'l.id = al.label_id')
->where($qb->expr()->in('card_id', $qb->createNamedParameter($cardIds, IQueryBuilder::PARAM_INT_ARRAY)))
->orderBy('l.id')
->setMaxResults($limit)
->setFirstResult($offset);
return $this->findEntities($qb);
}
/**
* @param numeric $boardId
* @param int|null $limit
* @param int|null $offset
* @return Label[]
* @throws \OCP\DB\Exception
*/
public function findAssignedLabelsForBoard($boardId, $limit = null, $offset = null): array {
$qb = $this->db->getQueryBuilder();
$qb->select('l.id as id', 'l.title as title', 'l.color as color')
->selectAlias('c.id', 'card_id')
->from($this->getTableName(), 'l')
->innerJoin('l', 'deck_assigned_labels', 'al', 'al.label_id = l.id')
->innerJoin('l', 'deck_cards', 'c', 'al.card_id = c.id')
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
->orderBy('l.id')
->setMaxResults($limit)
->setFirstResult($offset);
return $this->findEntities($qb);
}
public function insert(Entity $entity): Entity {
public function insert(Entity $entity) {
$entity->setLastModified(time());
return parent::insert($entity);
}
public function update(Entity $entity, bool $updateModified = true): Entity {
public function update(Entity $entity, $updateModified = true) {
if ($updateModified) {
$entity->setLastModified(time());
}
return parent::update($entity);
}
/**
* @param numeric $boardId
* @return array
* @throws \OCP\DB\Exception
*/
public function getAssignedLabelsForBoard($boardId) {
$labels = $this->findAssignedLabelsForBoard($boardId);
$result = [];
@@ -143,51 +80,27 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
return $result;
}
/**
* @param numeric $labelId
* @return void
* @throws \OCP\DB\Exception
*/
public function deleteLabelAssignments($labelId) {
$qb = $this->db->getQueryBuilder();
$qb->delete('deck_assigned_labels')
->where($qb->expr()->eq('label_id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT)));
$qb->executeStatement();
$sql = 'DELETE FROM `*PREFIX*deck_assigned_labels` WHERE label_id = ?';
$stmt = $this->db->prepare($sql);
$stmt->bindParam(1, $labelId, \PDO::PARAM_INT, 0);
$stmt->execute();
}
/**
* @param numeric $cardId
* @return void
* @throws \OCP\DB\Exception
*/
public function deleteLabelAssignmentsForCard($cardId) {
$qb = $this->db->getQueryBuilder();
$qb->delete('deck_assigned_labels')
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)));
$qb->executeStatement();
$sql = 'DELETE FROM `*PREFIX*deck_assigned_labels` WHERE card_id = ?';
$stmt = $this->db->prepare($sql);
$stmt->bindParam(1, $cardId, \PDO::PARAM_INT, 0);
$stmt->execute();
}
/**
* @param string $userId
* @param numeric $labelId
* @return bool
* @throws \OCP\DB\Exception
*/
public function isOwner($userId, $labelId): bool {
$qb = $this->db->getQueryBuilder();
$qb->select('l.id')
->from($this->getTableName(), 'l')
->innerJoin('l', 'deck_boards', 'b', 'l.board_id = b.id')
->where($qb->expr()->eq('l.id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('b.owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
return count($qb->executeQuery()->fetchAll()) > 0;
$sql = 'SELECT owner FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_labels` WHERE id = ?)';
$stmt = $this->execute($sql, [$labelId]);
$row = $stmt->fetch();
return ($row['owner'] === $userId);
}
/**
* @param numeric $id
* @return int|null
*/
public function findBoardId($id): ?int {
try {
$entity = $this->find($id);

View File

@@ -53,7 +53,7 @@ class RelationalEntity extends Entity implements \JsonSerializable {
* @param string $attribute the name of the attribute
* @since 7.0.0
*/
protected function markFieldUpdated(string $attribute): void {
protected function markFieldUpdated($attribute) {
if (!in_array($attribute, $this->_relations, true)) {
parent::markFieldUpdated($attribute);
}
@@ -68,13 +68,10 @@ class RelationalEntity extends Entity implements \JsonSerializable {
$reflection = new \ReflectionClass($this);
$json = [];
foreach ($properties as $property => $value) {
if (!str_starts_with($property, '_') && $reflection->hasProperty($property)) {
if (strpos($property, '_') !== 0 && $reflection->hasProperty($property)) {
$propertyReflection = $reflection->getProperty($property);
if (!$propertyReflection->isPrivate() && !in_array($property, $this->_resolvedProperties, true)) {
$json[$property] = $this->getter($property);
if ($json[$property] instanceof \DateTimeInterface) {
$json[$property] = $json[$property]->format('c');
}
}
}
}
@@ -127,9 +124,9 @@ class RelationalEntity extends Entity implements \JsonSerializable {
}
}
public function __call(string $methodName, array $args) {
public function __call($methodName, $args) {
$attr = lcfirst(substr($methodName, 7));
if (array_key_exists($attr, $this->_resolvedProperties) && str_starts_with($methodName, 'resolve')) {
if (array_key_exists($attr, $this->_resolvedProperties) && strpos($methodName, 'resolve') === 0) {
if ($this->_resolvedProperties[$attr] !== null) {
return $this->_resolvedProperties[$attr];
}
@@ -137,7 +134,7 @@ class RelationalEntity extends Entity implements \JsonSerializable {
}
$attr = lcfirst(substr($methodName, 3));
if (array_key_exists($attr, $this->_resolvedProperties) && str_starts_with($methodName, 'set')) {
if (array_key_exists($attr, $this->_resolvedProperties) && strpos($methodName, 'set') === 0) {
if (!is_scalar($args[0])) {
$args[0] = $args[0]['primaryKey'];
}

View File

@@ -33,7 +33,7 @@ class RelationalObject implements JsonSerializable {
* RelationalObject constructor.
*
* @param $primaryKey string
* @param callable|mixed $object
* @param $object
*/
public function __construct($primaryKey, $object) {
$this->primaryKey = $primaryKey;
@@ -47,24 +47,16 @@ class RelationalObject implements JsonSerializable {
);
}
public function getObject() {
if (is_callable($this->object)) {
$this->object = call_user_func($this->object, $this);
}
return $this->object;
}
/**
* This method should be overwritten if object doesn't implement \JsonSerializable
*
* @throws \Exception
*/
public function getObjectSerialization() {
if ($this->getObject() instanceof JsonSerializable) {
return $this->getObject()->jsonSerialize();
if ($this->object instanceof JsonSerializable) {
return $this->object->jsonSerialize();
} else {
throw new \Exception('jsonSerialize is not implemented on ' . get_class($this->getObject()));
throw new \Exception('jsonSerialize is not implemented on ' . get_class($this));
}
}

View File

@@ -1,51 +0,0 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2022, chandi Langecker (git@chandi.it)
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Db;
use OCP\AppFramework\Db\Entity;
class Session extends Entity implements \JsonSerializable {
public $id;
protected $userId;
protected $token;
protected $lastContact;
protected $boardId;
public function __construct() {
$this->addType('id', 'integer');
$this->addType('boardId', 'integer');
$this->addType('lastContact', 'integer');
}
public function jsonSerialize(): array {
return [
'id' => $this->id,
'userId' => $this->userId,
'token' => $this->token,
'lastContact' => $this->lastContact,
'boardId' => $this->boardId,
];
}
}

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