Compare commits

..

44 Commits

Author SHA1 Message Date
grnd-alt
c846880a1e copy labels when moving cards between boards
Signed-off-by: grnd-alt <salimbelakkaf@outlook.de>
2024-09-02 07:37:39 +00:00
Julius Härtl
acaaccda05 Merge pull request #6283 from nextcloud/automated/noid/stable30-update-nextcloud-ocp
[stable30] Update nextcloud/ocp dependency
2024-09-02 08:14:26 +02:00
nextcloud-command
67b378fda5 chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2024-09-01 02:59:42 +00:00
Nextcloud bot
827b7da7c2 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-09-01 00:41:42 +00:00
Julius Härtl
e01149cd81 chore(release): Bump version to 1.14.0-beta.2
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-08-31 08:44:08 +02:00
dependabot[bot]
4b594be8f0 Merge pull request #6274 from nextcloud/dependabot/npm_and_yarn/stable30/relative-ci/agent-4.2.11 2024-08-31 03:03:29 +00:00
dependabot[bot]
b570dd8880 Merge pull request #6271 from nextcloud/dependabot/npm_and_yarn/stable30/cypress-13.14.1 2024-08-31 03:03:04 +00:00
dependabot[bot]
afc92908fd Merge pull request #6272 from nextcloud/dependabot/npm_and_yarn/stable30/nextcloud/vue-8.17.1 2024-08-31 03:02:28 +00:00
dependabot[bot]
58bc1a87b1 Chore(deps-dev): Bump @relative-ci/agent from 4.2.10 to 4.2.11
Bumps [@relative-ci/agent](https://github.com/relative-ci/agent) from 4.2.10 to 4.2.11.
- [Release notes](https://github.com/relative-ci/agent/releases)
- [Commits](https://github.com/relative-ci/agent/compare/v4.2.10...v4.2.11)

---
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>
2024-08-31 01:52:00 +00:00
dependabot[bot]
dbbd57e443 Chore(deps): Bump @nextcloud/vue from 8.17.0 to 8.17.1
Bumps [@nextcloud/vue](https://github.com/nextcloud-libraries/nextcloud-vue) from 8.17.0 to 8.17.1.
- [Release notes](https://github.com/nextcloud-libraries/nextcloud-vue/releases)
- [Changelog](https://github.com/nextcloud-libraries/nextcloud-vue/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud-libraries/nextcloud-vue/compare/v8.17.0...v8.17.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-31 01:51:39 +00:00
dependabot[bot]
0d42750d19 Chore(deps-dev): Bump cypress from 13.13.3 to 13.14.1
Bumps [cypress](https://github.com/cypress-io/cypress) from 13.13.3 to 13.14.1.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cypress-io/cypress/compare/v13.13.3...v13.14.1)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-31 01:51:28 +00:00
Julius Härtl
c56170f76f Merge pull request #6265 from nextcloud/backport/6232/stable30 2024-08-30 20:16:00 +02:00
Julius Härtl
c56aeba3d3 fix: Avoid duplicate scrollbars
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-08-30 17:35:58 +00:00
Luka Trovic
ca4e0c122b fix: 30 design issues
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2024-08-30 17:35:58 +00:00
Nextcloud bot
05939792a1 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-08-30 00:56:05 +00:00
Nextcloud bot
5cbd91649b Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-08-28 00:41:44 +00:00
Julius Härtl
61d58fb4eb Merge pull request #6261 from nextcloud/backport/6260/stable30 2024-08-26 13:43:12 +02:00
Julius Härtl
5aa2428e2d Merge pull request #6258 from nextcloud/backport/6235/stable30
[stable30] Fix UI with the new compact design
2024-08-26 13:37:13 +02:00
Jérôme Herbinet
d35d8e5a50 Translation call fix
Signed-off-by: Jérôme Herbinet <33763786+Jerome-Herbinet@users.noreply.github.com>
2024-08-26 11:20:08 +00:00
Julius Härtl
71fe340fad fix: Adjust UI to be more consistent with new Nextcloud compact UI
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-08-26 10:43:38 +00:00
Julius Härtl
6f3f391a04 fix: Hide inline search box as the global one is working now
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-08-26 10:43:38 +00:00
Julius Härtl
50dea78147 Merge pull request #6256 from nextcloud/automated/noid/stable30-fix-npm-audit
[stable30] Fix npm audit
2024-08-26 08:11:01 +02:00
nextcloud-command
3f3b1a11d7 fix(deps): Fix npm audit
Signed-off-by: GitHub <noreply@github.com>
2024-08-25 03:12:45 +00:00
Julius Härtl
c29686feec Merge pull request #6244 from nextcloud/dependabot/npm_and_yarn/stable30/nextcloud/vue-8.17.0 2024-08-24 10:10:50 +02:00
dependabot[bot]
086617563d Merge pull request #6246 from nextcloud/dependabot/npm_and_yarn/stable30/nextcloud/dialogs-5.3.7 2024-08-24 03:14:33 +00:00
dependabot[bot]
c7d7f2e5fe Merge pull request #6245 from nextcloud/dependabot/npm_and_yarn/stable30/babel/runtime-7.25.4 2024-08-24 03:13:33 +00:00
dependabot[bot]
ac19f517c5 Chore(deps): Bump @nextcloud/dialogs from 5.3.6 to 5.3.7
Bumps [@nextcloud/dialogs](https://github.com/nextcloud-libraries/nextcloud-dialogs) from 5.3.6 to 5.3.7.
- [Release notes](https://github.com/nextcloud-libraries/nextcloud-dialogs/releases)
- [Changelog](https://github.com/nextcloud-libraries/nextcloud-dialogs/blob/v5.3.7/CHANGELOG.md)
- [Commits](https://github.com/nextcloud-libraries/nextcloud-dialogs/compare/v5.3.6...v5.3.7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-24 01:32:05 +00:00
dependabot[bot]
9a738ee7ac Chore(deps): Bump @babel/runtime from 7.25.0 to 7.25.4
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.25.0 to 7.25.4.
- [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.25.4/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>
2024-08-24 01:31:55 +00:00
dependabot[bot]
b81c249164 Chore(deps): Bump @nextcloud/vue from 8.16.0 to 8.17.0
Bumps [@nextcloud/vue](https://github.com/nextcloud-libraries/nextcloud-vue) from 8.16.0 to 8.17.0.
- [Release notes](https://github.com/nextcloud-libraries/nextcloud-vue/releases)
- [Changelog](https://github.com/nextcloud-libraries/nextcloud-vue/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud-libraries/nextcloud-vue/compare/v8.16.0...v8.17.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>
2024-08-24 01:31:46 +00:00
Nextcloud bot
20f74812ea Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-08-24 00:39:00 +00:00
Julius Härtl
63709be9ad Merge pull request #6210 from nextcloud/dependabot/npm_and_yarn/stable30/babel/runtime-7.25.0
Chore(deps): Bump @babel/runtime from 7.24.8 to 7.25.0
2024-08-22 17:41:55 +02:00
Nextcloud bot
a94efb4905 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-08-22 00:38:06 +00:00
dependabot[bot]
412a5d183e Merge pull request #6224 from nextcloud/dependabot/npm_and_yarn/stable30/nextcloud/dialogs-5.3.6 2024-08-17 04:04:45 +00:00
dependabot[bot]
e144303e26 Merge pull request #6223 from nextcloud/dependabot/npm_and_yarn/stable30/cypress-13.13.3 2024-08-17 04:02:03 +00:00
dependabot[bot]
fdb3a29256 Chore(deps): Bump @nextcloud/dialogs from 5.3.5 to 5.3.6
Bumps [@nextcloud/dialogs](https://github.com/nextcloud-libraries/nextcloud-dialogs) from 5.3.5 to 5.3.6.
- [Release notes](https://github.com/nextcloud-libraries/nextcloud-dialogs/releases)
- [Changelog](https://github.com/nextcloud-libraries/nextcloud-dialogs/blob/v5.3.6/CHANGELOG.md)
- [Commits](https://github.com/nextcloud-libraries/nextcloud-dialogs/compare/v5.3.5...v5.3.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-17 02:43:53 +00:00
dependabot[bot]
de760ac6fa Chore(deps-dev): Bump cypress from 13.13.2 to 13.13.3
Bumps [cypress](https://github.com/cypress-io/cypress) from 13.13.2 to 13.13.3.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cypress-io/cypress/compare/v13.13.2...v13.13.3)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-17 02:43:20 +00:00
dependabot[bot]
1e20832cd6 Merge pull request #6207 from nextcloud/dependabot/npm_and_yarn/stable30/nextcloud/auth-2.4.0 2024-08-16 18:59:29 +00:00
dependabot[bot]
8e77849027 Merge pull request #6213 from nextcloud/dependabot/npm_and_yarn/stable30/eslint-plugin-cypress-3.5.0 2024-08-16 18:59:02 +00:00
dependabot[bot]
147dadd1ab Chore(deps-dev): Bump eslint-plugin-cypress from 3.3.0 to 3.5.0
Bumps [eslint-plugin-cypress](https://github.com/cypress-io/eslint-plugin-cypress) from 3.3.0 to 3.5.0.
- [Release notes](https://github.com/cypress-io/eslint-plugin-cypress/releases)
- [Commits](https://github.com/cypress-io/eslint-plugin-cypress/compare/v3.3.0...v3.5.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-cypress
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-16 20:50:47 +02:00
dependabot[bot]
bd39df04f6 Chore(deps): Bump @babel/runtime from 7.24.8 to 7.25.0
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.24.8 to 7.25.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.25.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>
2024-08-16 20:50:40 +02:00
dependabot[bot]
12f30e946e Chore(deps): Bump @nextcloud/auth from 2.3.0 to 2.4.0
Bumps [@nextcloud/auth](https://github.com/nextcloud/nextcloud-auth) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/nextcloud/nextcloud-auth/releases)
- [Changelog](https://github.com/nextcloud-libraries/nextcloud-auth/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/nextcloud-auth/compare/v2.3.0...v2.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-16 20:50:34 +02:00
Julius Härtl
01a6f93730 Merge pull request #6205 from nextcloud/update-stable30-target-versions
chore(CI): Adjust testing matrix for Nextcloud 30 on stable30
2024-08-16 20:50:16 +02:00
Joas Schilling
c72bec7220 chore(CI): Adjust testing matrix for Nextcloud 30 on stable30
Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-08-16 20:06:30 +02:00
Nextcloud bot
c9a5f9e79b Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-08-15 00:45:54 +00:00
73 changed files with 552 additions and 650 deletions

View File

@@ -13,23 +13,6 @@ updates:
- juliushaertl
- luka-nextcloud
- package-ecosystem: npm
target-branch: stable30
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: stable29
versioning-strategy: lockfile-only
@@ -64,6 +47,23 @@ updates:
- 3. to review
- dependencies
- package-ecosystem: npm
target-branch: stable27
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

@@ -22,7 +22,7 @@ jobs:
node-version: [20.x]
# containers: [1, 2, 3]
php-versions: [ '8.2' ]
server-versions: [ 'master' ]
server-versions: [ 'stable30' ]
env:
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, zip, gd, apcu

View File

@@ -28,7 +28,7 @@ jobs:
matrix:
php-versions: ['8.1']
databases: ['sqlite', 'mysql', 'pgsql']
server-versions: ['master']
server-versions: ['stable30']
name: php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }}

View File

@@ -21,7 +21,7 @@ jobs:
strategy:
fail-fast: false
matrix:
branches: ['main', 'master', 'stable30', 'stable29', 'stable28']
branches: ['main', 'master', 'stable29', 'stable28', 'stable27']
name: npm-audit-fix-${{ matrix.branches }}

View File

@@ -20,7 +20,7 @@ jobs:
strategy:
fail-fast: false
matrix:
branches: ['main', 'master', 'stable30', 'stable29', 'stable28']
branches: ['main', 'master', 'stable29', 'stable28', 'stable27']
name: update-nextcloud-ocp-${{ matrix.branches }}

View File

@@ -20,17 +20,17 @@
- 🚀 Get your project organized
</description>
<version>2.0.0-dev.0</version>
<version>1.14.0-beta.2</version>
<licence>agpl</licence>
<author>Julius Härtl</author>
<namespace>Deck</namespace>
<types>
<dav/>
</types>
<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/>
</types>
<category>organization</category>
<category>office</category>
<website>https://github.com/nextcloud/deck</website>
@@ -42,7 +42,7 @@
<database min-version="9.4">pgsql</database>
<database>sqlite</database>
<database min-version="8.0">mysql</database>
<nextcloud min-version="31" max-version="31"/>
<nextcloud min-version="30" max-version="30"/>
</dependencies>
<background-jobs>
<job>OCA\Deck\Cron\DeleteCron</job>

View File

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

41
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ee1c5b69795943e43d6277064d284ae0",
"content-hash": "7242ec950e99240a95e6b6d877fdd8d2",
"packages": [
{
"name": "icecave/parity",
@@ -399,16 +399,16 @@
},
{
"name": "nextcloud/coding-standard",
"version": "v1.2.3",
"version": "v1.2.1",
"source": {
"type": "git",
"url": "https://github.com/nextcloud/coding-standard.git",
"reference": "bc9c53a5306114b60c4363057aff9c2ed10a54da"
"reference": "cf5f18d989ec62fb4cdc7fc92a36baf34b3d829e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/bc9c53a5306114b60c4363057aff9c2ed10a54da",
"reference": "bc9c53a5306114b60c4363057aff9c2ed10a54da",
"url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/cf5f18d989ec62fb4cdc7fc92a36baf34b3d829e",
"reference": "cf5f18d989ec62fb4cdc7fc92a36baf34b3d829e",
"shasum": ""
},
"require": {
@@ -434,22 +434,22 @@
"description": "Nextcloud coding standards for the php cs fixer",
"support": {
"issues": "https://github.com/nextcloud/coding-standard/issues",
"source": "https://github.com/nextcloud/coding-standard/tree/v1.2.3"
"source": "https://github.com/nextcloud/coding-standard/tree/v1.2.1"
},
"time": "2024-08-23T14:32:32+00:00"
"time": "2024-02-01T14:54:37+00:00"
},
{
"name": "nextcloud/ocp",
"version": "dev-master",
"version": "dev-stable30",
"source": {
"type": "git",
"url": "https://github.com/nextcloud-deps/ocp.git",
"reference": "b6538d7f14472c2ef6182c51df6be34cae033099"
"reference": "65bc71ed71b10f60394e3a3165f27e78e6b087cb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/b6538d7f14472c2ef6182c51df6be34cae033099",
"reference": "b6538d7f14472c2ef6182c51df6be34cae033099",
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/65bc71ed71b10f60394e3a3165f27e78e6b087cb",
"reference": "65bc71ed71b10f60394e3a3165f27e78e6b087cb",
"shasum": ""
},
"require": {
@@ -459,11 +459,10 @@
"psr/event-dispatcher": "^1.0",
"psr/log": "^1.1.4"
},
"default-branch": true,
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "31.0.0-dev"
"dev-stable30": "30.0.0-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -479,9 +478,9 @@
"description": "Composer package containing Nextcloud's public API (classes, interfaces)",
"support": {
"issues": "https://github.com/nextcloud-deps/ocp/issues",
"source": "https://github.com/nextcloud-deps/ocp/tree/master"
"source": "https://github.com/nextcloud-deps/ocp/tree/stable30"
},
"time": "2024-08-31T00:39:40+00:00"
"time": "2024-08-31T00:39:39+00:00"
},
{
"name": "nikic/php-parser",
@@ -661,16 +660,16 @@
},
{
"name": "php-cs-fixer/shim",
"version": "v3.62.0",
"version": "v3.49.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/shim.git",
"reference": "7a91d5ce45c486f5b445d95901228507a02f60ae"
"reference": "f7d3219cac46632f12362c9aa7c2ac0d2fe92c52"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/7a91d5ce45c486f5b445d95901228507a02f60ae",
"reference": "7a91d5ce45c486f5b445d95901228507a02f60ae",
"url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/f7d3219cac46632f12362c9aa7c2ac0d2fe92c52",
"reference": "f7d3219cac46632f12362c9aa7c2ac0d2fe92c52",
"shasum": ""
},
"require": {
@@ -707,9 +706,9 @@
"description": "A tool to automatically fix PHP code style",
"support": {
"issues": "https://github.com/PHP-CS-Fixer/shim/issues",
"source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.62.0"
"source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.49.0"
},
"time": "2024-08-07T17:03:46+00:00"
"time": "2024-02-02T00:42:09+00:00"
},
{
"name": "phpunit/php-code-coverage",

View File

@@ -35,7 +35,7 @@ describe('Board', function() {
.type(board, { force: true })
// Submit
cy.get('.board-create form button[type=submit]')
cy.get('.board-create form input[type=submit]')
.first().click({ force: true })
cy.wait('@createBoardRequest').its('response.statusCode').should('equal', 200)

View File

@@ -13,7 +13,7 @@ The Deck application plugin uses the [markdown-it](https://github.com/markdown-i
## Supported Markdown
Markdown comes in many flavors. The best way to learn markdown and understand how to use it, is simply to [try it](https://markdown-it.github.io) on the original script official playground.
Markdown comes in may flavors. The best way to learn markdown and understand how to use it, is simply to [try it](https://markdown-it.github.io) on the original script official playground.
That same link offers also a comprehensive list of what is supported, and what is not - rendering it unnecessary to duplicate that content in here.
[CommonMark Markdown Reference](http://commonmark.org/help/)

View File

@@ -39,8 +39,8 @@ class Filter implements \OCP\Activity\IFilter {
/**
* @return int whether the filter should be rather on the top or bottom of
* the admin section. The filters are arranged in ascending order of the
* priority values. It is required to return a value between 0 and 100.
* the admin section. The filters are arranged in ascending order of the
* priority values. It is required to return a value between 0 and 100.
* @since 11.0.0
*/
public function getPriority(): int {

View File

@@ -47,8 +47,8 @@ abstract class SettingBase extends ActivitySettings {
/**
* @return int whether the filter should be rather on the top or bottom of
* the admin section. The filters are arranged in ascending order of the
* priority values. It is required to return a value between 0 and 100.
* the admin section. The filters are arranged in ascending order of the
* priority values. It is required to return a value between 0 and 100.
* @since 11.0.0
*/
public function getPriority(): int {

View File

@@ -25,8 +25,8 @@ class SettingChanges extends SettingBase {
/**
* @return int whether the filter should be rather on the top or bottom of
* the admin section. The filters are arranged in ascending order of the
* priority values. It is required to return a value between 0 and 100.
* the admin section. The filters are arranged in ascending order of the
* priority values. It is required to return a value between 0 and 100.
* @since 11.0.0
*/
public function getPriority(): int {

View File

@@ -176,7 +176,7 @@ class Application extends App implements IBootstrap {
$permissionService = $this->getContainer()->get(PermissionService::class);
try {
return $permissionService->checkPermission($cardMapper, (int)$name, Acl::PERMISSION_READ);
return $permissionService->checkPermission($cardMapper, (int) $name, Acl::PERMISSION_READ);
} catch (\Exception $e) {
return false;
}

View File

@@ -14,7 +14,7 @@ class Capabilities implements ICapability {
/** @var IAppManager */
private $appManager;
/** @var PermissionService */
/** @var PermissionService */
private $permissionService;

View File

@@ -72,17 +72,17 @@ final class TransferOwnership extends Command {
try {
$board = $boardId ? $this->boardMapper->find($boardId) : null;
} catch (\Exception $e) {
$output->writeln('Could not find a board for the provided id.');
$output->writeln("Could not find a board for the provided id.");
return 1;
}
if ($boardId !== null && $board->getOwner() !== $owner) {
$output->writeln("$owner is not the owner of the board $boardId (" . $board->getTitle() . ')');
$output->writeln("$owner is not the owner of the board $boardId (" . $board->getTitle() . ")");
return 1;
}
if ($boardId) {
$output->writeln('Transfer board ' . $board->getTitle() . ' from '. $board->getOwner() ." to $newOwner");
$output->writeln("Transfer board " . $board->getTitle() . " from ". $board->getOwner() ." to $newOwner");
} else {
$output->writeln("Transfer all boards from $owner to $newOwner");
}
@@ -94,12 +94,12 @@ final class TransferOwnership extends Command {
if ($boardId) {
$this->boardService->transferBoardOwnership($boardId, $newOwner, $remapAssignment);
$output->writeln('<info>Board ' . $board->getTitle() . ' from '. $board->getOwner() ." transferred to $newOwner completed</info>");
$output->writeln("<info>Board " . $board->getTitle() . " from ". $board->getOwner() ." transferred to $newOwner completed</info>");
return 0;
}
foreach ($this->boardService->transferOwnership($owner, $newOwner, $remapAssignment) as $board) {
$output->writeln(' - ' . $board->getTitle() . ' transferred');
$output->writeln(" - " . $board->getTitle() . " transferred");
}
$output->writeln("<info>All boards from $owner to $newOwner transferred</info>");

View File

@@ -12,17 +12,27 @@ use OCA\Deck\Notification\NotificationHelper;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\Job;
use Psr\Log\LoggerInterface;
use OCP\ILogger;
class ScheduledNotifications extends Job {
/** @var CardMapper */
protected $cardMapper;
/** @var NotificationHelper */
protected $notificationHelper;
/** @var ILogger */
protected $logger;
public function __construct(
ITimeFactory $time,
protected CardMapper $cardMapper,
protected NotificationHelper $notificationHelper,
protected LoggerInterface $logger
CardMapper $cardMapper,
NotificationHelper $notificationHelper,
ILogger $logger
) {
parent::__construct($time);
$this->cardMapper = $cardMapper;
$this->notificationHelper = $notificationHelper;
$this->logger = $logger;
}
/**

View File

@@ -14,19 +14,21 @@ namespace OCA\Deck\Cron;
use OCA\Deck\Service\SessionService;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\BackgroundJob\TimedJob;
use Psr\Log\LoggerInterface;
use OCP\ILogger;
class SessionsCleanup extends TimedJob {
private $sessionService;
private $documentService;
private $logger;
private $imageService;
public function __construct(
ITimeFactory $time,
private SessionService $sessionService,
private LoggerInterface $logger,
) {
public function __construct(ITimeFactory $time,
SessionService $sessionService,
ILogger $logger) {
parent::__construct($time);
$this->sessionService = $sessionService;
$this->logger = $logger;
$this->setInterval(SessionService::SESSION_VALID_TIME);
}

View File

@@ -25,7 +25,7 @@ class Calendar extends ExternalCalendar {
private $children;
/** @var DeckCalendarBackend */
private $backend;
/** @var Board */
/** @var Board */
private $board;
public function __construct(string $principalUri, string $calendarUri, Board $board, DeckCalendarBackend $backend) {

View File

@@ -75,7 +75,7 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
try {
$entity = $this->find($id);
return $entity->getBoardId();
} catch (DoesNotExistException|MultipleObjectsReturnedException $e) {
} catch (DoesNotExistException | MultipleObjectsReturnedException $e) {
}
return null;
}

View File

@@ -61,9 +61,9 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
public function findByData($cardId, $data) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('data', $qb->createNamedParameter($data, IQueryBuilder::PARAM_STR)));
->from($this->getTableName())
->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);
}

View File

@@ -165,7 +165,7 @@ class Card extends RelationalEntity {
$matchDate->setTime(0, 0);
$diff = $today->diff($matchDate);
return (int)$diff->format('%R%a'); // Extract days count in interval
return (int) $diff->format('%R%a'); // Extract days count in interval
}
public function getCalendarPrefix(): string {

View File

@@ -410,7 +410,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
foreach ($query->getDuedate() as $duedate) {
$dueDateColumn = $this->databaseType === 'sqlite3' ? $qb->createFunction('DATETIME(`c`.`duedate`)') : 'c.duedate';
$date = $duedate->getValue();
if ($date === '') {
if ($date === "") {
$qb->andWhere($qb->expr()->isNotNull('c.duedate'));
continue;
}
@@ -461,7 +461,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
foreach ($query->getAssigned() as $index => $assignment) {
$qb->innerJoin('c', 'deck_assigned_users', 'au' . $index, $qb->expr()->eq('c.id', 'au' . $index . '.card_id'));
$assignedQueryValue = $assignment->getValue();
if ($assignedQueryValue === '') {
if ($assignedQueryValue === "") {
$qb->andWhere($qb->expr()->isNotNull('au' . $index . '.participant'));
continue;
}
@@ -589,7 +589,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
}
$this->cache->set('findBoardId:' . $id, $result);
}
return $result !== false ? (int)$result : null;
return $result !== false ? (int) $result : null;
}
public function mapOwner(Card &$card) {

View File

@@ -10,17 +10,27 @@ use OCA\Deck\Service\DefaultBoardService;
use OCA\Deck\Service\PermissionService;
use OCP\AppFramework\Middleware;
use OCP\IL10N;
use Psr\Log\LoggerInterface;
use OCP\ILogger;
class DefaultBoardMiddleware extends Middleware {
public function __construct(
private LoggerInterface $logger,
private IL10N $l10n,
private DefaultBoardService $defaultBoardService,
private PermissionService $permissionService,
private ?string $userId,
) {
/** @var ILogger */
private $logger;
/** @var IL10N */
private $l10n;
/** @var DefaultBoardService */
private $defaultBoardService;
/** @var PermissionService */
private $permissionService;
/** @var string|null */
private $userId;
public function __construct(ILogger $logger, IL10N $l10n, DefaultBoardService $defaultBoardService, PermissionService $permissionService, $userId) {
$this->logger = $logger;
$this->l10n = $l10n;
$this->defaultBoardService = $defaultBoardService;
$this->permissionService = $permissionService;
$this->userId = $userId;
}
public function beforeController($controller, $methodName) {
@@ -29,7 +39,7 @@ class DefaultBoardMiddleware extends Middleware {
$this->defaultBoardService->createDefaultBoard($this->l10n->t('Personal'), $this->userId, '0087C5');
}
} catch (\Throwable $e) {
$this->logger->error('Could not create default board', ['exception' => $e]);
$this->logger->logException($e);
}
}
}

View File

@@ -15,19 +15,28 @@ use OCP\AppFramework\Middleware;
use OCP\AppFramework\OCS\OCSException;
use OCP\AppFramework\OCSController;
use OCP\IConfig;
use OCP\ILogger;
use OCP\IRequest;
use Psr\Log\LoggerInterface;
class ExceptionMiddleware extends Middleware {
/** @var ILogger */
private $logger;
/** @var IConfig */
private $config;
/** @var IRequest */
private $request;
/**
* SharingMiddleware constructor.
*
* @param ILogger $logger
* @param IConfig $config
*/
public function __construct(
private LoggerInterface $logger,
private IConfig $config,
private IRequest $request,
) {
public function __construct(ILogger $logger, IConfig $config, IRequest $request) {
$this->logger = $logger;
$this->config = $config;
$this->request = $request;
}
/**
@@ -60,7 +69,9 @@ class ExceptionMiddleware extends Middleware {
}
if ($exception instanceof StatusException) {
$this->logger->debug($exception->getMessage(), ['exception' => $exception]);
if ($this->config->getSystemValue('loglevel', ILogger::WARN) === ILogger::DEBUG) {
$this->logger->logException($exception);
}
if ($exception instanceof ConflictException) {
return new JSONResponse([
@@ -87,9 +98,9 @@ class ExceptionMiddleware extends Middleware {
'message' => $exceptionMessage,
'requestId' => $this->request->getId(),
];
$this->logger->error($exception->getMessage(), ['exception' => $exception]);
$this->logger->logException($exception);
if ($debugMode === true) {
$response['exception'] = (array)$exception;
$response['exception'] = (array) $exception;
}
return new JSONResponse($response, 500);
}

View File

@@ -142,11 +142,11 @@ class NotificationHelper {
->setUser($userId)
->setDateTime(new DateTime())
->setObject('card', (string)$card->getId())
->setSubject('card-assigned', [
$card->getTitle(),
$board->getTitle(),
$this->currentUser
]);
->setSubject('card-assigned', [
$card->getTitle(),
$board->getTitle(),
$this->currentUser
]);
$this->notificationManager->notify($notification);
}
@@ -206,9 +206,9 @@ class NotificationHelper {
$notification = $this->notificationManager->createNotification();
$notification
->setApp('deck')
->setUser((string)$mention['id'])
->setUser((string) $mention['id'])
->setDateTime(new DateTime())
->setObject('card', (string)$card->getId())
->setObject('card', (string) $card->getId())
->setSubject('card-comment-mentioned', [$card->getTitle(), $boardId, $this->currentUser])
->setMessage('{message}', ['message' => $comment->getMessage()]);
$this->notificationManager->notify($notification);

View File

@@ -97,7 +97,7 @@ class BoardReferenceProvider implements IReferenceProvider {
preg_match('/^' . preg_quote($startIndex, '/') . '(?:\/#!?)?\/board\/([0-9]+)$/', $url, $matches);
}
if ($matches && count($matches) > 1) {
return (int)$matches[1];
return (int) $matches[1];
}
return null;
@@ -106,7 +106,7 @@ class BoardReferenceProvider implements IReferenceProvider {
public function getCachePrefix(string $referenceId): string {
$boardId = $this->getBoardId($referenceId);
if ($boardId !== null) {
return (string)$boardId;
return (string) $boardId;
}
return $referenceId;

View File

@@ -111,9 +111,9 @@ class CardReferenceProvider extends ADiscoverableReferenceProvider implements IS
if ($ids !== null) {
[, $cardId] = $ids;
try {
$card = $this->cardService->find((int)$cardId)->jsonSerialize();
$stack = $this->stackService->find((int)$card['stackId'])->jsonSerialize();
$board = $this->boardService->find((int)$stack['boardId'])->jsonSerialize();
$card = $this->cardService->find((int) $cardId)->jsonSerialize();
$stack = $this->stackService->find((int) $card['stackId'])->jsonSerialize();
$board = $this->boardService->find((int) $stack['boardId'])->jsonSerialize();
} catch (NoPermissionException $e) {
// Skip throwing if user has no permissions
return null;

View File

@@ -73,7 +73,7 @@ class CommentReferenceProvider implements IReferenceProvider {
try {
$card = $this->cardService->find($cardId)->jsonSerialize();
$board = $this->boardService->find($boardId)->jsonSerialize();
$stack = $this->stackService->find((int)$card['stackId'])->jsonSerialize();
$stack = $this->stackService->find((int) $card['stackId'])->jsonSerialize();
} catch (NoPermissionException $e) {
// Skip throwing if user has no permissions
return null;
@@ -162,9 +162,9 @@ class CommentReferenceProvider implements IReferenceProvider {
}
if ($matches && count($matches) > 3) {
return [
(int)$matches[1],
(int)$matches[2],
(int)$matches[3],
(int) $matches[1],
(int) $matches[2],
(int) $matches[3],
];
}

View File

@@ -17,22 +17,26 @@ use OCP\Comments\IComment;
use OCP\Comments\ICommentsManager;
use OCP\Comments\MessageTooLongException;
use OCP\Comments\NotFoundException as CommentNotFoundException;
use OCP\ILogger;
use OCP\IUserManager;
use OutOfBoundsException;
use Psr\Log\LoggerInterface;
use function is_numeric;
class CommentService {
private ICommentsManager $commentsManager;
private IUserManager $userManager;
private CardMapper $cardMapper;
private PermissionService $permissionService;
private ILogger $logger;
private ?string $userId;
public function __construct(
private ICommentsManager $commentsManager,
private PermissionService $permissionService,
private CardMapper $cardMapper,
private IUserManager $userManager,
private LoggerInterface $logger,
private ?string $userId,
) {
public function __construct(ICommentsManager $commentsManager, PermissionService $permissionService, CardMapper $cardMapper, IUserManager $userManager, ILogger $logger, ?string $userId) {
$this->commentsManager = $commentsManager;
$this->permissionService = $permissionService;
$this->cardMapper = $cardMapper;
$this->userManager = $userManager;
$this->logger = $logger;
$this->userId = $userId;
}
public function list(string $cardId, int $limit = 20, int $offset = 0): DataResponse {
@@ -65,8 +69,8 @@ class CommentService {
private function get(int $cardId, int $commentId): IComment {
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
try {
$comment = $this->commentsManager->get((string)$commentId);
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || (int)$comment->getObjectId() !== $cardId) {
$comment = $this->commentsManager->get((string) $commentId);
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || (int) $comment->getObjectId() !== $cardId) {
throw new CommentNotFoundException();
}
} catch (CommentNotFoundException $e) {
@@ -134,7 +138,7 @@ class CommentService {
if (!is_numeric($commentId)) {
throw new BadRequestException('A valid comment id must be provided');
}
$comment = $this->get((int)$cardId, (int)$commentId);
$comment = $this->get((int) $cardId, (int) $commentId);
if ($comment->getActorType() !== 'users' || $comment->getActorId() !== $this->userId) {
throw new NoPermissionException('Only authors are allowed to edit their comment.');
}
@@ -183,8 +187,8 @@ class CommentService {
try {
$displayName = $this->commentsManager->resolveDisplayName($mention['type'], $mention['id']);
} catch (OutOfBoundsException $e) {
$this->logger->warning('Mention type not registered, can not resolve display name.', ['exception' => $e, 'mention_type' => $mention['type']]);
// No display name, upon client's discretion what to display.
$this->logger->logException($e);
// No displayname, upon client's discretion what to display.
$displayName = '';
}

View File

@@ -20,21 +20,37 @@ use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\ISimpleFolder;
use OCP\IConfig;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IRequest;
use Psr\Log\LoggerInterface;
class FileService implements IAttachmentService {
private $l10n;
private $appData;
private $request;
private $logger;
private $rootFolder;
private $config;
private $attachmentMapper;
private $mimeTypeDetector;
public function __construct(
private IL10N $l10n,
private IAppData $appData,
private IRequest $request,
private LoggerInterface $logger,
private IRootFolder $rootFolder,
private IConfig $config,
private AttachmentMapper $attachmentMapper,
private IMimeTypeDetector $mimeTypeDetector
IL10N $l10n,
IAppData $appData,
IRequest $request,
ILogger $logger,
IRootFolder $rootFolder,
IConfig $config,
AttachmentMapper $attachmentMapper,
IMimeTypeDetector $mimeTypeDetector
) {
$this->l10n = $l10n;
$this->appData = $appData;
$this->request = $request;
$this->logger = $logger;
$this->rootFolder = $rootFolder;
$this->config = $config;
$this->attachmentMapper = $attachmentMapper;
$this->mimeTypeDetector = $mimeTypeDetector;
}
/**
@@ -177,7 +193,6 @@ class FileService implements IAttachmentService {
/**
* Workaround until ISimpleFile can be fetched as a resource
*
* @return \OCP\Files\File
* @throws \Exception
*/
private function getFileFromRootFolder(Attachment $attachment) {

View File

@@ -404,7 +404,7 @@ class BoardImportService {
* @return void
*/
public function setConfig(string $configName, $value): void {
if (empty((array)$this->config)) {
if (empty((array) $this->config)) {
$this->setConfigInstance(new \stdClass);
}
$this->config->$configName = $value;

View File

@@ -51,7 +51,7 @@ class DeckJsonService extends ABoardImportService {
if (!is_string($nextcloudUid) && !is_numeric($nextcloudUid)) {
throw new \LogicException('User on setting uidRelation is invalid');
}
$nextcloudUid = (string)$nextcloudUid;
$nextcloudUid = (string) $nextcloudUid;
$this->getImportService()->getConfig('uidRelation')->$exportUid = $this->userManager->get($nextcloudUid);
if (!$this->getImportService()->getConfig('uidRelation')->$exportUid) {
throw new \LogicException('User on setting uidRelation not found: ' . $nextcloudUid);
@@ -106,7 +106,7 @@ class DeckJsonService extends ABoardImportService {
public function getComments(): array {
$comments = [];
foreach ($this->tmpCards as $sourceCard) {
if (!property_exists($sourceCard, 'comments')) {
if (!property_exists($sourceCard, "comments")) {
continue;
}
$commentsOriginal = $sourceCard->comments;

View File

@@ -71,7 +71,7 @@ class TrelloJsonService extends ABoardImportService {
if (!is_string($nextcloudUid) && !is_numeric($nextcloudUid)) {
throw new \LogicException('User on setting uidRelation is invalid');
}
$nextcloudUid = (string)$nextcloudUid;
$nextcloudUid = (string) $nextcloudUid;
$this->getImportService()->getConfig('uidRelation')->$trelloUid = $this->userManager->get($nextcloudUid);
if (!$this->getImportService()->getConfig('uidRelation')->$trelloUid) {
throw new \LogicException('User on setting uidRelation not found: ' . $nextcloudUid);
@@ -141,7 +141,7 @@ class TrelloJsonService extends ABoardImportService {
$message = $this->l10n->t(
"This comment has more than %s characters.\n" .
"Added as an attachment to the card with name %s.\n" .
'Accessible on URL: %s.',
"Accessible on URL: %s.",
[
IComment::MAX_MESSAGE_LENGTH,
'comment_' . $commentId . '.md',

View File

@@ -143,7 +143,7 @@ class PermissionService {
try {
$board = $this->getBoard($boardId);
return $userId === $board->getOwner();
} catch (DoesNotExistException|MultipleObjectsReturnedException $e) {
} catch (DoesNotExistException | MultipleObjectsReturnedException $e) {
}
return false;
}
@@ -205,8 +205,8 @@ class PermissionService {
*/
public function findUsers($boardId, $refresh = false) {
// cache users of a board so we don't query them for every cards
if (array_key_exists((string)$boardId, $this->users) && !$refresh) {
return $this->users[(string)$boardId];
if (array_key_exists((string) $boardId, $this->users) && !$refresh) {
return $this->users[(string) $boardId];
}
try {
@@ -269,8 +269,8 @@ class PermissionService {
}
}
}
$this->users[(string)$boardId] = $users;
return $this->users[(string)$boardId];
$this->users[(string) $boardId] = $users;
return $this->users[(string) $boardId];
}
public function canCreate() {

View File

@@ -110,7 +110,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
try {
$board = $this->boardMapper->find($boardId);
$valid = $valid && !$board->getArchived();
} catch (DoesNotExistException|MultipleObjectsReturnedException $e) {
} catch (DoesNotExistException | MultipleObjectsReturnedException $e) {
$valid = false;
}
@@ -966,8 +966,8 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
protected function filterSharesOfUser(array $shares): array {
// Deck shares when the user has a share exception
foreach ($shares as $id => $share) {
$type = (int)$share['share_type'];
$permissions = (int)$share['permissions'];
$type = (int) $share['share_type'];
$permissions = (int) $share['permissions'];
if ($type === self::SHARE_TYPE_DECK_USER) {
unset($shares[$share['parent']]);

View File

@@ -45,7 +45,7 @@ abstract class BaseValidator {
} else {
if (!$this->{$rule}($value)) {
throw new BadRequestException(
$field . ' must be provided and must be '. str_replace('_', ' ', $rule));
$field . ' must be provided and must be '. str_replace("_", " ", $rule));
}
}
}
@@ -111,7 +111,7 @@ abstract class BaseValidator {
*/
private function max($value, $limit): bool {
if (!$limit || !is_numeric($limit)) {
throw new Exception('Validation rule max requires at least 1 parameter. ' . json_encode($limit));
throw new Exception("Validation rule max requires at least 1 parameter. " . json_encode($limit));
}
return $this->getSize($value) <= $limit;
}
@@ -121,7 +121,7 @@ abstract class BaseValidator {
*/
private function min($value, $limit): bool {
if (!$limit || !is_numeric($limit)) {
throw new Exception('Validation rule max requires at least 1 parameter.');
throw new Exception("Validation rule max requires at least 1 parameter.");
}
return $this->getSize($value) >= $limit;
}
@@ -129,7 +129,7 @@ abstract class BaseValidator {
/**
* Get the size of an attribute.
*
* @param mixed $value
* @param mixed $value
* @return int
*/
protected function getSize($value): int {
@@ -158,6 +158,6 @@ abstract class BaseValidator {
: $field . ' must be at least '. $parameter . ' characters long ';
}
return $field . ' must be provided and must be '. str_replace('_', ' ', $rule);
return $field . ' must be provided and must be '. str_replace("_", " ", $rule);
}
}

232
package-lock.json generated
View File

@@ -1,20 +1,20 @@
{
"name": "deck",
"version": "2.0.0-dev.0",
"version": "1.14.0-beta.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "deck",
"version": "2.0.0-dev.0",
"version": "1.14.0-beta.1",
"license": "agpl",
"dependencies": {
"@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.25.6",
"@nextcloud/auth": "^2.4.0",
"@babel/runtime": "^7.24.8",
"@nextcloud/auth": "^2.3.0",
"@nextcloud/axios": "^2.5.0",
"@nextcloud/capabilities": "^1.2.0",
"@nextcloud/dialogs": "^6.0.0",
"@nextcloud/dialogs": "^5.3.5",
"@nextcloud/event-bus": "^3.3.1",
"@nextcloud/files": "^3.8.0",
"@nextcloud/initial-state": "^2.2.0",
@@ -22,9 +22,9 @@
"@nextcloud/moment": "^1.3.1",
"@nextcloud/notify_push": "^1.3.0",
"@nextcloud/router": "^3.0.1",
"@nextcloud/vue": "^8.17.1",
"@nextcloud/vue": "^8.16.0",
"blueimp-md5": "^2.19.0",
"chroma-js": "^3.0.0",
"chroma-js": "^2.6.0",
"dompurify": "^3.1.6",
"lodash": "^4.17.21",
"markdown-it": "^14.1.0",
@@ -52,11 +52,11 @@
"@nextcloud/eslint-config": "^8.4.1",
"@nextcloud/stylelint-config": "^3.0.1",
"@nextcloud/webpack-vue-config": "^6.0.0",
"@relative-ci/agent": "^4.2.11",
"@relative-ci/agent": "^4.2.10",
"@vue/test-utils": "^2.4.6",
"@vue/vue2-jest": "^29.2.6",
"cypress": "^13.14.1",
"eslint-plugin-cypress": "^3.5.0",
"cypress": "^13.13.2",
"eslint-plugin-cypress": "^3.3.0",
"eslint-webpack-plugin": "^4.2.0",
"jest": "^29.7.0",
"jest-serializer-vue": "^3.1.0",
@@ -1917,9 +1917,9 @@
"peer": true
},
"node_modules/@babel/runtime": {
"version": "7.25.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz",
"integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==",
"version": "7.25.4",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.4.tgz",
"integrity": "sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -3340,14 +3340,14 @@
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
"integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
"dev": true,
"peer": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
@@ -3526,9 +3526,9 @@
}
},
"node_modules/@nextcloud/dialogs": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-6.0.0.tgz",
"integrity": "sha512-Yoye/BezFN/hQCic+OHNPSESNI3k7D85YQJU1fW4s/yMi+P6VVNLixp4lbQ7xHF+po5lXZbJhultrOyoNhqaGw==",
"version": "5.3.7",
"resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-5.3.7.tgz",
"integrity": "sha512-//pRF2GJNhW3VbVzSoE97J+DR9nZ/+IkzOzgKKDdMr65JYYMAdOs9Iew4nMf+OruDgZanGyXrfubSMVNI+1svQ==",
"dependencies": {
"@mdi/js": "^7.4.47",
"@nextcloud/auth": "^2.3.0",
@@ -3552,7 +3552,7 @@
"npm": "^10.0.0"
},
"peerDependencies": {
"@nextcloud/vue": "^8.16.0",
"@nextcloud/vue": "^8.9.1",
"vue": "^2.7.16"
}
},
@@ -4420,10 +4420,21 @@
"@types/json-schema": "*"
}
},
"node_modules/@types/eslint-scope": {
"version": "3.7.4",
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz",
"integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==",
"dev": true,
"peer": true,
"dependencies": {
"@types/eslint": "*",
"@types/estree": "*"
}
},
"node_modules/@types/estree": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
"integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA=="
},
"node_modules/@types/express": {
"version": "4.17.17",
@@ -5235,9 +5246,9 @@
}
},
"node_modules/@webassemblyjs/ast": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
"integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz",
"integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==",
"dev": true,
"peer": true,
"dependencies": {
@@ -5260,9 +5271,9 @@
"peer": true
},
"node_modules/@webassemblyjs/helper-buffer": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
"integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==",
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz",
"integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==",
"dev": true,
"peer": true
},
@@ -5286,16 +5297,16 @@
"peer": true
},
"node_modules/@webassemblyjs/helper-wasm-section": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
"integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz",
"integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==",
"dev": true,
"peer": true,
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/wasm-gen": "1.12.1"
"@webassemblyjs/wasm-gen": "1.11.6"
}
},
"node_modules/@webassemblyjs/ieee754": {
@@ -5326,30 +5337,30 @@
"peer": true
},
"node_modules/@webassemblyjs/wasm-edit": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
"integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz",
"integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==",
"dev": true,
"peer": true,
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/helper-wasm-section": "1.12.1",
"@webassemblyjs/wasm-gen": "1.12.1",
"@webassemblyjs/wasm-opt": "1.12.1",
"@webassemblyjs/wasm-parser": "1.12.1",
"@webassemblyjs/wast-printer": "1.12.1"
"@webassemblyjs/helper-wasm-section": "1.11.6",
"@webassemblyjs/wasm-gen": "1.11.6",
"@webassemblyjs/wasm-opt": "1.11.6",
"@webassemblyjs/wasm-parser": "1.11.6",
"@webassemblyjs/wast-printer": "1.11.6"
}
},
"node_modules/@webassemblyjs/wasm-gen": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
"integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz",
"integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==",
"dev": true,
"peer": true,
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/ieee754": "1.11.6",
"@webassemblyjs/leb128": "1.11.6",
@@ -5357,26 +5368,26 @@
}
},
"node_modules/@webassemblyjs/wasm-opt": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
"integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz",
"integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==",
"dev": true,
"peer": true,
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/wasm-gen": "1.12.1",
"@webassemblyjs/wasm-parser": "1.12.1"
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-buffer": "1.11.6",
"@webassemblyjs/wasm-gen": "1.11.6",
"@webassemblyjs/wasm-parser": "1.11.6"
}
},
"node_modules/@webassemblyjs/wasm-parser": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
"integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz",
"integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==",
"dev": true,
"peer": true,
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/ast": "1.11.6",
"@webassemblyjs/helper-api-error": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/ieee754": "1.11.6",
@@ -5385,13 +5396,13 @@
}
},
"node_modules/@webassemblyjs/wast-printer": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
"integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz",
"integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==",
"dev": true,
"peer": true,
"dependencies": {
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/ast": "1.11.6",
"@xtuc/long": "4.2.2"
}
},
@@ -5505,10 +5516,10 @@
"node": ">=0.4.0"
}
},
"node_modules/acorn-import-attributes": {
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
"integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
"node_modules/acorn-import-assertions": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz",
"integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==",
"dev": true,
"peer": true,
"peerDependencies": {
@@ -5952,9 +5963,10 @@
"dev": true
},
"node_modules/axios": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
"integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz",
"integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
@@ -6888,9 +6900,9 @@
"dev": true
},
"node_modules/chroma-js": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-3.0.0.tgz",
"integrity": "sha512-ZFn4qxtZTvRJ7XatOLgaHGJYN10LoS6T0EMsu7IVayFG5+b6Yw8wCGQL5qLgo4B+wrRZ9niCrozOQ4a584bvaA=="
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.6.0.tgz",
"integrity": "sha512-BLHvCB9s8Z1EV4ethr6xnkl/P2YRFOGqfgvuMG/MyCbZPrTA+NeiByY6XvgF0zP4/2deU2CXnWyMa3zu1LqQ3A=="
},
"node_modules/chrome-trace-event": {
"version": "1.0.3",
@@ -8483,6 +8495,7 @@
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz",
"integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"bn.js": "^4.11.9",
@@ -8571,9 +8584,9 @@
}
},
"node_modules/enhanced-resolve": {
"version": "5.17.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
"integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
"version": "5.15.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
"integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
"dev": true,
"peer": true,
"dependencies": {
@@ -10814,9 +10827,9 @@
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
"dev": true
},
"node_modules/graphemer": {
@@ -17942,9 +17955,9 @@
"peer": true
},
"node_modules/serialize-javascript": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
"integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
"dev": true,
"peer": true,
"dependencies": {
@@ -19192,9 +19205,9 @@
}
},
"node_modules/terser": {
"version": "5.31.6",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz",
"integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==",
"version": "5.19.2",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz",
"integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==",
"dev": true,
"peer": true,
"dependencies": {
@@ -19211,17 +19224,17 @@
}
},
"node_modules/terser-webpack-plugin": {
"version": "5.3.10",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
"integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
"version": "5.3.9",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz",
"integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==",
"dev": true,
"peer": true,
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.20",
"@jridgewell/trace-mapping": "^0.3.17",
"jest-worker": "^27.4.5",
"schema-utils": "^3.1.1",
"serialize-javascript": "^6.0.1",
"terser": "^5.26.0"
"terser": "^5.16.8"
},
"engines": {
"node": ">= 10.13.0"
@@ -20513,9 +20526,9 @@
}
},
"node_modules/watchpack": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
"integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
"dev": true,
"peer": true,
"dependencies": {
@@ -20628,34 +20641,35 @@
}
},
"node_modules/webpack": {
"version": "5.94.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
"integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
"version": "5.88.2",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
"integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
"dev": true,
"peer": true,
"dependencies": {
"@types/estree": "^1.0.5",
"@webassemblyjs/ast": "^1.12.1",
"@webassemblyjs/wasm-edit": "^1.12.1",
"@webassemblyjs/wasm-parser": "^1.12.1",
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.0",
"@webassemblyjs/ast": "^1.11.5",
"@webassemblyjs/wasm-edit": "^1.11.5",
"@webassemblyjs/wasm-parser": "^1.11.5",
"acorn": "^8.7.1",
"acorn-import-attributes": "^1.9.5",
"browserslist": "^4.21.10",
"acorn-import-assertions": "^1.9.0",
"browserslist": "^4.14.5",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.17.1",
"enhanced-resolve": "^5.15.0",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
"glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.11",
"graceful-fs": "^4.2.9",
"json-parse-even-better-errors": "^2.3.1",
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
"schema-utils": "^3.2.0",
"tapable": "^2.1.1",
"terser-webpack-plugin": "^5.3.10",
"watchpack": "^2.4.1",
"terser-webpack-plugin": "^5.3.7",
"watchpack": "^2.4.0",
"webpack-sources": "^3.2.3"
},
"bin": {

View File

@@ -1,7 +1,7 @@
{
"name": "deck",
"description": "",
"version": "2.0.0-dev.0",
"version": "1.14.0-beta.2",
"authors": [
{
"name": "Julius Härtl",
@@ -31,11 +31,11 @@
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.25.6",
"@nextcloud/auth": "^2.4.0",
"@babel/runtime": "^7.24.8",
"@nextcloud/auth": "^2.3.0",
"@nextcloud/axios": "^2.5.0",
"@nextcloud/capabilities": "^1.2.0",
"@nextcloud/dialogs": "^6.0.0",
"@nextcloud/dialogs": "^5.3.5",
"@nextcloud/event-bus": "^3.3.1",
"@nextcloud/files": "^3.8.0",
"@nextcloud/initial-state": "^2.2.0",
@@ -43,9 +43,9 @@
"@nextcloud/moment": "^1.3.1",
"@nextcloud/notify_push": "^1.3.0",
"@nextcloud/router": "^3.0.1",
"@nextcloud/vue": "^8.17.1",
"@nextcloud/vue": "^8.16.0",
"blueimp-md5": "^2.19.0",
"chroma-js": "^3.0.0",
"chroma-js": "^2.6.0",
"dompurify": "^3.1.6",
"lodash": "^4.17.21",
"markdown-it": "^14.1.0",
@@ -80,11 +80,11 @@
"@nextcloud/eslint-config": "^8.4.1",
"@nextcloud/stylelint-config": "^3.0.1",
"@nextcloud/webpack-vue-config": "^6.0.0",
"@relative-ci/agent": "^4.2.11",
"@relative-ci/agent": "^4.2.10",
"@vue/test-utils": "^2.4.6",
"@vue/vue2-jest": "^29.2.6",
"cypress": "^13.14.1",
"eslint-plugin-cypress": "^3.5.0",
"cypress": "^13.13.2",
"eslint-plugin-cypress": "^3.3.0",
"eslint-webpack-plugin": "^4.2.0",
"jest": "^29.7.0",
"jest-serializer-vue": "^3.1.0",
@@ -107,4 +107,4 @@
"<rootDir>/node_modules/jest-serializer-vue"
]
}
}
}

View File

@@ -6,13 +6,12 @@
<template>
<NcContent app-name="deck" :class="{ 'nav-hidden': !navShown, 'sidebar-hidden': !sidebarRouterView }">
<AppNavigation />
<NcAppContent :allow-swipe-navigation="false">
<NcAppContent>
<router-view />
</NcAppContent>
<div v-if="$route.params.id || $route.params.cardId">
<NcModal v-if="cardDetailsInModal && $route.params.cardId"
:name="t('deck', 'Card details')"
:clear-view-delay="0"
:close-button-contained="true"
size="large"
@@ -33,7 +32,7 @@
import { mapState } from 'vuex'
import AppNavigation from './components/navigation/AppNavigation.vue'
import KeyboardShortcuts from './components/KeyboardShortcuts.vue'
import { NcModal, NcContent, NcAppContent, isMobile } from '@nextcloud/vue'
import { NcModal, NcContent, NcAppContent } from '@nextcloud/vue'
import { BoardApi } from './services/BoardApi.js'
import { emit, subscribe } from '@nextcloud/event-bus'
import { loadState } from '@nextcloud/initial-state'
@@ -51,7 +50,6 @@ export default {
NcAppContent,
KeyboardShortcuts,
},
mixins: [isMobile],
provide() {
return {
boardApi,
@@ -108,7 +106,7 @@ export default {
},
mounted() {
// Set navigation to initial state and update in case it gets toggled
emit('toggle-navigation', { open: !this.isMobile && this.navShown, _initial: true })
emit('toggle-navigation', { open: this.navShown, _initial: true })
this.$nextTick(() => {
subscribe('navigation-toggled', (navState) => {
this.$store.dispatch('toggleNav', navState.open)

View File

@@ -13,16 +13,16 @@
:disabled="loading"
label="title"
@option:selected="fetchCardsFromBoard">
<template #selected-option="props">
<template slot="singleLabel" slot-scope="props">
<span>
<span :style="{ 'backgroundColor': '#' + props.color }" class="board-bullet" />
<span>{{ props.title }}</span>
<span :style="{ 'backgroundColor': '#' + props.option.color }" class="board-bullet" />
<span>{{ props.option.title }}</span>
</span>
</template>
<template #option="props">
<template slot="option" slot-scope="props">
<span>
<span :style="{ 'backgroundColor': '#' + props.color }" class="board-bullet" />
<span>{{ props.title }}</span>
<span :style="{ 'backgroundColor': '#' + props.option.color }" class="board-bullet" />
<span>{{ props.option.title }}</span>
</span>
</template>
</NcSelect>

View File

@@ -544,7 +544,7 @@ export default {
.filter--item {
input + label {
display: block;
padding: var(--default-grid-baseline) 0;
padding: 6px 0;
.avatardiv {
vertical-align: middle;
margin-bottom: 2px;

View File

@@ -4,7 +4,7 @@
-->
<template>
<div class="board-wrapper" :tabindex="-1" @touchend="fixActionRestriction">
<div class="board-wrapper" :tabindex="-1">
<Controls :board="board" />
<transition name="fade" mode="out-in">
@@ -22,27 +22,23 @@
<template #icon>
<DeckIcon />
</template>
<template #name>
<template #title>
{{ t('deck', 'No lists available') }}
</template>
<template v-if="canManage" #action>
{{ t('deck', 'Create a new list to add cards to this board') }}
<form @submit.prevent="addNewStack()">
<NcTextField ref="newStackInput"
:disable="loading"
:value.sync="newStackTitle"
<input id="new-stack-input-main"
v-model="newStackTitle"
v-focus
type="text"
class="no-close"
:placeholder="t('deck', 'List name')"
type="text" />
<NcButton type="secondary"
native-type="submit"
:disabled="loading"
:title="t('deck', 'Add list')">
<template #icon>
<CheckIcon v-if="!loading" :size="20" />
<NcLoadingIcon v-else :size="20" />
</template>
{{ t('deck', 'Add list') }}
</NcButton>
required>
<input title="t('deck', 'Add list')"
class="icon-confirm"
type="submit"
value="">
</form>
</template>
</NcEmptyContent>
@@ -86,9 +82,8 @@ import { Container, Draggable } from 'vue-smooth-dnd'
import { mapState, mapGetters } from 'vuex'
import Controls from '../Controls.vue'
import DeckIcon from '../icons/DeckIcon.vue'
import CheckIcon from 'vue-material-design-icons/Check.vue'
import Stack from './Stack.vue'
import { NcEmptyContent, NcModal, NcButton, NcTextField, NcLoadingIcon } from '@nextcloud/vue'
import { NcEmptyContent, NcModal } from '@nextcloud/vue'
import GlobalSearchResults from '../search/GlobalSearchResults.vue'
import { showError } from '../../helpers/errors.js'
import { createSession } from '../../sessions.js'
@@ -104,10 +99,6 @@ export default {
Stack,
NcEmptyContent,
NcModal,
NcTextField,
NcButton,
NcLoadingIcon,
CheckIcon,
CardSidebar,
},
inject: [
@@ -140,7 +131,7 @@ export default {
'canManage',
]),
stacksByBoard() {
return this.board?.id ? this.$store.getters.stacksByBoard(this.board.id) : []
return this.$store.getters.stacksByBoard(this.board.id)
},
dragHandleSelector() {
return this.canEdit ? '.stack__title' : '.no-drag'
@@ -156,11 +147,6 @@ export default {
showArchived() {
this.fetchData()
},
isEmpty(newValue) {
newValue && this.$nextTick(() => {
this.$refs?.newStackInput?.focus()
})
},
},
created() {
this.session = createSession(this.id)
@@ -231,13 +217,6 @@ export default {
window.removeEventListener('mouseup', this.stopMouseDrag)
window.removeEventListener('mouseleave', this.stopMouseDrag)
},
fixActionRestriction() {
document.body.classList.remove(
'smooth-dnd-no-user-select',
'smooth-dnd-disable-touch-action',
)
},
},
}
</script>
@@ -250,16 +229,13 @@ export default {
text-align: center;
display: flex;
width: 100%;
max-width: 200px;
margin: auto;
margin-top: calc(var(--default-grid-baseline) * 4);
gap: var(--default-grid-baseline);
margin-top: 20px;
input[type="text"] {
input[type=text] {
flex-grow: 1;
}
button[type="submit"] {
flex-shrink: 0;
}
}
.board-wrapper {
@@ -302,9 +278,7 @@ export default {
flex-grow: 1;
display: flex;
flex-direction: column;
// Margin left instead of padidng to avoid jumps on dropping a card
margin-left: $stack-spacing;
padding-right: $stack-spacing;
padding: $stack-spacing;
overflow-x: hidden;
overflow-y: auto;
padding-top: 15px;

View File

@@ -88,33 +88,15 @@
</div>
</NcModal>
<Container :get-child-payload="payloadForCard(stack.id)"
group-name="stack"
data-click-closes-sidebar="true"
non-drag-area-selector=".dragDisabled"
:drag-handle-selector="dragHandleSelector"
data-dragscroll-enabled
@should-accept-drop="canEdit"
@drag-start="draggingCard = true"
@drag-end="draggingCard = false"
@drop="($event) => onDropCard(stack.id, $event)">
<Draggable v-for="card in cardsByStack" :key="card.id">
<transition :appear="animate && !card.animated && (card.animated=true)"
:appear-class="'zoom-appear-class'"
:appear-active-class="'zoom-appear-active-class'">
<CardItem :id="card.id" ref="card" :dragging="draggingCard" />
</transition>
</Draggable>
</Container>
<transition name="slide-bottom" appear>
<div v-show="showAddCard" class="stack__card-add">
<transition name="slide-top" appear>
<div v-if="showAddCard" class="stack__card-add">
<form :class="{ 'icon-loading-small': stateCardCreating }"
@submit.prevent.stop="clickAddCard()">
<label for="new-stack-input-main" class="hidden-visually">{{ t('deck', 'Add a new card') }}</label>
<input id="new-stack-input-main"
ref="newCardInput"
v-model="newCardTitle"
v-focus
type="text"
class="no-close"
:disabled="stateCardCreating"
@@ -130,6 +112,25 @@
</form>
</div>
</transition>
<Container :get-child-payload="payloadForCard(stack.id)"
group-name="stack"
data-click-closes-sidebar="true"
non-drag-area-selector=".dragDisabled"
:drag-handle-selector="dragHandleSelector"
data-dragscroll-enabled
@should-accept-drop="canEdit"
@drag-start="draggingCard = true"
@drag-end="draggingCard = false"
@drop="($event) => onDropCard(stack.id, $event)">
<Draggable v-for="card in cardsByStack" :key="card.id">
<transition :appear="animate && !card.animated && (card.animated=true)"
:appear-class="'zoom-appear-class'"
:appear-active-class="'zoom-appear-active-class'">
<CardItem :id="card.id" :dragging="draggingCard" />
</transition>
</Draggable>
</Container>
</div>
</template>
@@ -220,18 +221,10 @@ export default {
showAddCard(newValue) {
if (!newValue) {
this.$store.dispatch('toggleShortcutLock', false)
} else {
this.$nextTick(() => {
this.$refs.newCardInput.focus()
})
}
},
},
mounted() {
this.setupAutoscrollOnDrag()
},
methods: {
stopCardCreation(e) {
// For some reason the submit event triggers a MouseEvent that is bubbling to the outside
@@ -310,7 +303,6 @@ export default {
this.$nextTick(() => {
this.$refs.newCardInput.focus()
this.animate = false
this.$refs.card[(this.$refs.card.length - 1)].scrollIntoView()
})
if (!this.cardDetailsInModal) {
this.$router.push({ name: 'card', params: { cardId: newCard.id } })
@@ -324,36 +316,6 @@ export default {
onCreateCardFocus() {
this.$store.dispatch('toggleShortcutLock', true)
},
setupAutoscrollOnDrag() {
let timer
const autoscroll = (event) => {
const viewportX = event.clientX
const boardElement = document.querySelector('.board')
const viewportWidth = boardElement.clientWidth
const offset = viewportWidth - viewportX
const scrollMultiplier = 10
const scrollBoundary = window.innerWidth * 0.15
if (offset < 100) {
const scrollToX = boardElement.scrollLeft + scrollMultiplier * (1 - offset / scrollBoundary)
boardElement.scrollTo(scrollToX, boardElement.scrollTop)
}
if (boardElement.scrollLeft > 0 && viewportX < scrollBoundary) {
const scrollToX = boardElement.scrollLeft - scrollMultiplier * (1 - viewportX / scrollBoundary)
boardElement.scrollTo(scrollToX, boardElement.scrollTop)
}
}
window.addEventListener('mousemove', (e) => {
if (!this.draggingCard) {
timer && clearInterval(timer)
return
}
clearInterval(timer)
timer = window.setInterval(() => autoscroll(e), 25)
})
},
},
}
</script>
@@ -376,7 +338,6 @@ export default {
padding-left: $card-spacing;
padding-right: $card-spacing;
margin: 6px;
margin-top: 0;
cursor: grab;
background-color: var(--color-main-background);
@@ -398,6 +359,14 @@ export default {
}
}
&--add:before {
height: 78px;
background-image: linear-gradient(180deg, var(--color-main-background) 68px, rgba(255, 255, 255, 0) 100%);
body.theme--dark & {
background-image: linear-gradient(180deg, var(--color-main-background) 68px, rgba(0, 0, 0, 0) 100%);
}
}
& > * {
position: relative;
z-index: 100;
@@ -453,14 +422,13 @@ export default {
flex-shrink: 0;
z-index: 100;
display: flex;
margin-bottom: 5px;
padding-top: var(--default-grid-baseline);
margin-top: 5px;
background-color: var(--color-main-background);
form {
display: flex;
margin-left: $stack-spacing;
margin-right: $stack-spacing;
margin-right: $card-spacing + $stack-spacing + 4px;
width: 100%;
border: 2px solid var(--color-border-maxcontrast);
border-radius: var(--border-radius-large);
@@ -496,16 +464,7 @@ export default {
.slide-top-enter, .slide-top-leave-to {
transform: translateY(-10px);
opacity: 0;
}
.slide-bottom-enter-active,
.slide-bottom-leave-active {
transition: all 100ms ease;
}
.slide-bottom-enter, .slide-bottom-leave-to {
transform: translateY(20px);
opacity: 0;
height: 0px;
}
.modal__content {

View File

@@ -248,10 +248,6 @@ export default {
<style lang="scss" scoped>
.drop-upload--sidebar {
min-height: 100%;
}
.button-group {
display: flex;
gap: calc(var(--default-grid-baseline) * 3);

View File

@@ -162,9 +162,7 @@ export default {
},
methods: {
focusHeader() {
this.$nextTick(() => {
this.$refs?.cardSidebar.$el.querySelector('.app-sidebar-header__mainname')?.focus()
})
this.$refs.cardSidebar.$el.querySelector('.app-sidebar-header__mainname').focus()
},
handleUpdateTitleEditable(value) {
this.titleEditable = value
@@ -226,7 +224,6 @@ section.app-sidebar__tab--active {
left: 0;
right: 0;
max-width: calc(100% - #{$modal-padding * 2});
min-height: calc(100vh - var(--header-height) * 4);
padding: 0 14px;
height: 97%;
overflow: hidden !important;

View File

@@ -66,11 +66,11 @@ export default {
@import '../../css/variables';
.card-cover {
height: 90px;
height: 100px;
display: flex;
margin-top: -4px;
margin-left: -4px;
margin-right: -4px;
margin-top: -8px;
margin-left: -8px;
margin-right: -8px;
.image-wrapper {
flex: 1;
@@ -79,10 +79,10 @@ export default {
background-repeat: no-repeat;
background-position: center center;
&.rounded-left {
border-top-left-radius: calc(var(--border-radius-large) - 1px);
border-top-left-radius: 10px;
}
&.rounded-right {
border-top-right-radius: calc(var(--border-radius-large) - 1px);
border-top-right-radius: 10px;
}
}
}

View File

@@ -6,7 +6,7 @@
<template>
<AttachmentDragAndDrop v-if="card" :card-id="card.id" class="drop-upload--card">
<div :ref="`card${card.id}`"
:class="{'compact': compactMode, 'current-card': currentCard, 'has-labels': card.labels && card.labels.length > 0, 'card__editable': canEdit, 'card__archived': card.archived, 'card__highlight': highlight}"
:class="{'compact': compactMode, 'current-card': currentCard, 'has-labels': card.labels && card.labels.length > 0, 'card__editable': canEdit, 'card__archived': card.archived }"
tag="div"
:tabindex="0"
class="card"
@@ -103,11 +103,6 @@ export default {
default: false,
},
},
data() {
return {
highlight: false,
}
},
computed: {
...mapState({
compactMode: state => state.compactMode,
@@ -275,14 +270,6 @@ export default {
},
})
},
scrollIntoView() {
this.$el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' })
this.focus()
this.highlight = true
setTimeout(() => {
this.highlight = false
}, 2000)
},
},
}
</script>
@@ -303,10 +290,11 @@ export default {
background-color: var(--color-main-background);
margin-bottom: $card-spacing;
padding: var(--default-grid-baseline) $card-padding;
border: 2px solid var(--color-border-dark);
border: 2px solid var(--color-border);
width: 100%;
display: flex;
flex-direction: column;
gap: var(--default-grid-baseline);
&:deep(*) {
cursor: pointer;
@@ -329,7 +317,7 @@ export default {
h4 {
font-weight: normal;
margin: 0;
padding: var(--default-grid-baseline);
padding: 6px;
flex-grow: 1;
font-size: 100%;
overflow: hidden;
@@ -372,28 +360,10 @@ export default {
&.card__archived {
background-color: var(--color-background-dark);
}
@keyframes highlight {
0% {
border-color: var(--color-border-dark);
}
20% {
border-color: var(--color-primary-element);
}
70% {
border-color: var(--color-primary-element);
}
100% {
border-color: var(--color-border-dark);
}
}
&.card__highlight {
animation: highlight 2s;
}
.card-labels {
display: flex;
align-items: end;
padding-left: var(--default-grid-baseline);
padding-top: var(--default-grid-baseline);
margin-bottom: var(--default-grid-baseline);
.labels {
flex-wrap: wrap;
@@ -433,6 +403,7 @@ export default {
display: flex;
height: 32px;
width: 32px;
margin-top: 6px;
}
&.has-labels {
padding-bottom: $card-padding;

View File

@@ -8,41 +8,19 @@
icon="icon-add"
@click.prevent.stop="startCreateBoard" />
<div v-else class="board-create">
<NcColorPicker v-model="color" class="app-navigation-entry-bullet-wrapper" :disabled="loading">
<NcColorPicker v-model="color" class="app-navigation-entry-bullet-wrapper">
<div :style="{ backgroundColor: color }" class="color0 icon-colorpicker app-navigation-entry-bullet" />
</NcColorPicker>
<form @submit.prevent.stop="createBoard">
<NcTextField ref="inputField"
:disable="loading"
:value.sync="value"
:placeholder="t('deck', 'Board name')"
type="text"
required />
<NcButton type="tertiary"
:disabled="loading"
:title="t('deck', 'Cancel edit')"
@click.stop.prevent="cancelEdit">
<template #icon>
<CloseIcon :size="20" />
</template>
</NcButton>
<NcButton type="tertiary"
native-type="submit"
:disabled="loading"
:title="t('deck', 'Save board')">
<template #icon>
<CheckIcon v-if="!loading" :size="20" />
<NcLoadingIcon v-else :size="20" />
</template>
</NcButton>
<input :placeholder="t('deck', 'Board name')" type="text" required>
<input type="submit" value="" class="icon-confirm">
<NcActions><NcActionButton icon="icon-close" @click.stop.prevent="cancelEdit" /></NcActions>
</form>
</div>
</template>
<script>
import { NcButton, NcColorPicker, NcAppNavigationItem, NcLoadingIcon, NcTextField } from '@nextcloud/vue'
import CheckIcon from 'vue-material-design-icons/Check.vue'
import CloseIcon from 'vue-material-design-icons/Close.vue'
import { NcColorPicker, NcActionButton, NcActions, NcAppNavigationItem } from '@nextcloud/vue'
/**
*
@@ -57,33 +35,30 @@ function randomColor() {
export default {
name: 'AppNavigationAddBoard',
components: { NcButton, NcColorPicker, NcAppNavigationItem, NcLoadingIcon, NcTextField, CheckIcon, CloseIcon },
components: { NcColorPicker, NcAppNavigationItem, NcActionButton, NcActions },
directives: {},
props: {},
data() {
return {
value: '',
classes: [],
editing: false,
loading: false,
color: randomColor(),
}
},
computed: {},
watch: {},
mounted() {},
methods: {
startCreateBoard(e) {
this.editing = true
this.$nextTick(() => {
this.$refs?.inputField.focus()
})
},
async createBoard(e) {
this.loading = true
const title = this.value.trim()
const title = e.currentTarget.childNodes[0].value
await this.$store.dispatch('createBoard', {
title,
color: this.color.substring(1),
})
this.loading = false
this.editing = false
this.color = randomColor()
},
@@ -114,9 +89,10 @@ export default {
width: var(--default-clickable-area);
height: var(--default-clickable-area);
.color0 {
width: 24px !important;
margin: var(--default-grid-baseline);
height: 24px;
width: 30px !important;
margin: 5px;
margin-left: 7px;
height: 30px;
border-radius: 50%;
background-size: 14px;
}

View File

@@ -9,8 +9,6 @@
:to="routeTo"
:undo="deleted"
:menu-placement="'auto'"
:force-display-actions="isTouchDevice"
@click="onNavigate"
@undo="unDelete">
<NcAppNavigationIconBullet slot="icon" :color="board.color" />
@@ -116,47 +114,24 @@
<div :style="{ backgroundColor: getColor }" class="color0 icon-colorpicker app-navigation-entry-bullet" />
</NcColorPicker>
<form @submit.prevent.stop="applyEdit">
<NcTextField ref="inputField"
:disable="loading"
:value.sync="editTitle"
:placeholder="t('deck', 'Board name')"
<input v-model="editTitle"
v-focus
dir="auto"
type="text"
required />
<NcButton type="tertiary"
:disabled="loading"
native-type="submit"
:title="t('deck', 'Cancel edit')"
@click.stop.prevent="cancelEdit">
<template #icon>
<CloseIcon :size="20" />
</template>
</NcButton>
<NcButton type="tertiary"
native-type="submit"
:disabled="loading"
:title="t('deck', 'Save board')">
<template #icon>
<CheckIcon v-if="!loading" :size="20" />
<NcLoadingIcon v-else :size="20" />
</template>
</NcButton>
required>
<input type="submit" value="" class="icon-confirm">
<NcActions><NcActionButton icon="icon-close" @click.stop.prevent="cancelEdit" /></NcActions>
</form>
</div>
</template>
<script>
import { NcAppNavigationIconBullet, NcAppNavigationItem, NcColorPicker, NcButton, NcTextField, NcActionButton } from '@nextcloud/vue'
import { NcAppNavigationIconBullet, NcAppNavigationItem, NcColorPicker, NcActions, NcActionButton } from '@nextcloud/vue'
import ClickOutside from 'vue-click-outside'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import CloneIcon from 'vue-material-design-icons/ContentDuplicate.vue'
import AccountIcon from 'vue-material-design-icons/Account.vue'
import CloseIcon from 'vue-material-design-icons/Close.vue'
import CheckIcon from 'vue-material-design-icons/Check.vue'
import { loadState } from '@nextcloud/initial-state'
import { emit } from '@nextcloud/event-bus'
import isTouchDevice from '../../mixins/isTouchDevice.js'
const canCreateState = loadState('deck', 'canCreate')
@@ -166,19 +141,15 @@ export default {
NcAppNavigationIconBullet,
NcAppNavigationItem,
NcColorPicker,
NcButton,
NcTextField,
NcActions,
NcActionButton,
AccountIcon,
ArchiveIcon,
CloneIcon,
CloseIcon,
CheckIcon,
},
directives: {
ClickOutside,
},
mixins: [isTouchDevice],
inject: [
'boardApi',
],
@@ -342,20 +313,13 @@ export default {
actionExport() {
this.boardApi.exportBoard(this.board)
},
onNavigate() {
if (this.isTouchDevice) {
emit('toggle-navigation', {
open: false,
})
}
},
},
}
</script>
<style lang="scss" scoped>
.board-edit {
margin-left: calc(var(--default-clickable-area) / 2);
margin-left: var(--default-clickable-area);
order: 1;
display: flex;
height: var(--default-clickable-area);
@@ -374,9 +338,10 @@ export default {
width: var(--default-clickable-area);
height: var(--default-clickable-area);
.color0 {
width: 24px !important;
margin: var(--default-grid-baseline);
height: 24px;
width: 30px !important;
margin: 5px;
margin-left: 7px;
height: 30px;
border-radius: 50%;
background-size: 14px;
}

View File

@@ -168,13 +168,11 @@ export default {
.dashboard-column {
display: flex;
flex-direction: column;
min-width: $stack-width;
width: $stack-width;
margin-left: $stack-spacing;
margin-right: $stack-spacing;
h3 {
font-size: var(--default-font-size);
margin: -6px;
margin-bottom: 12px;
padding: 6px 13px;

View File

@@ -1,12 +0,0 @@
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
export default {
computed: {
isTouchDevice() {
return ('ontouchstart' in window) || (navigator.maxTouchPoints > 0)
},
},
}

View File

@@ -93,7 +93,7 @@
<template #icon>
<NcLoadingIcon />
</template>
<template #name>
<template #title>
{{ t('deck', 'Creating the new card …') }}
</template>
</NcEmptyContent>
@@ -101,7 +101,7 @@
<template #icon>
<CardPlusOutline />
</template>
<template #name>
<template #title>
{{ t('deck', 'Card "{card}" was added to "{board}"', { card: card.title, board: selectedBoard.title }) }}
</template>
<template #action>

View File

@@ -31,11 +31,11 @@ use OCP\Server;
* @group DB
*/
class BoardDatabaseTest extends \Test\TestCase {
public const TEST_USER1 = 'test-share-user1';
public const TEST_USER2 = 'test-share-user2';
public const TEST_USER3 = 'test-share-user3';
public const TEST_USER4 = 'test-share-user4';
public const TEST_GROUP1 = 'test-share-group1';
public const TEST_USER1 = "test-share-user1";
public const TEST_USER2 = "test-share-user2";
public const TEST_USER3 = "test-share-user3";
public const TEST_USER4 = "test-share-user4";
public const TEST_GROUP1 = "test-share-group1";
/** @var BoardService */
private $boardService;

View File

@@ -71,7 +71,7 @@ class BoardContext implements Context {
break;
}
}
Assert::assertNotNull($id, 'Could not find board named '.$boardName);
Assert::assertNotNull($id, "Could not find board named ".$boardName);
} else {
$id = $this->board['id'];
}

View File

@@ -36,7 +36,7 @@ class SearchContext implements Context {
/**
* @When /^searching for "([^"]*)" in comments in unified search$/
* @param string $term
* https://cloud.nextcloud.com/ocs/v2.php/search/providers/talk-conversations/search?term=an&from=%2Fapps%2Fdashboard%2F
* https://cloud.nextcloud.com/ocs/v2.php/search/providers/talk-conversations/search?term=an&from=%2Fapps%2Fdashboard%2F
*/
public function searchingForComments(string $term) {
$this->requestContext->sendOCSRequest('GET', '/search/providers/search-deck-comment/search?term=' . urlencode($term), []);

View File

@@ -32,7 +32,7 @@ class SessionContext implements Context {
'boardId' => $board['id'],
]);
$res = json_decode((string)$this->getResponse()->getBody(), true);
Assert::assertArrayHasKey('token', $res['ocs']['data'], 'session creation did not respond with a token');
Assert::assertArrayHasKey('token', $res['ocs']['data'], "session creation did not respond with a token");
// store token
$user = $this->serverContext->getCurrentUser();
@@ -44,7 +44,7 @@ class SessionContext implements Context {
*/
public function theResponseShouldHaveActiveSessions($length) {
$board = $this->boardContext->getLastUsedBoard();
Assert::assertEquals($length, count($board['activeSessions']), 'unexpected count of active sessions');
Assert::assertEquals($length, count($board['activeSessions']), "unexpected count of active sessions");
}
/**
@@ -52,7 +52,7 @@ class SessionContext implements Context {
*/
public function theUserShouldBeInTheListOfActiveSessions($user) {
$board = $this->boardContext->getLastUsedBoard();
Assert::assertContains($user, $board['activeSessions'], 'user is not found in the list of active sessions');
Assert::assertContains($user, $board['activeSessions'], "user is not found in the list of active sessions");
}
/**
@@ -67,7 +67,7 @@ class SessionContext implements Context {
$user = $this->serverContext->getCurrentUser();
$token = $this->tokens[$user];
Assert::assertNotEmpty($token, 'no token for the user found');
Assert::assertNotEmpty($token, "no token for the user found");
$this->requestContext->sendOCSRequest('POST', '/apps/deck/api/v1.0/session/close', [
'boardId' => $board['id'],
'token' => $token

View File

@@ -88,8 +88,8 @@ class UserExportTest extends \Test\TestCase {
public function getComment($id) {
$comment = new Comment();
$comment->setActor('users', 'admin');
$comment->setMessage('fake comment' . $id);
$comment->setActor("users", "admin");
$comment->setMessage("fake comment" . $id);
return $comment;
}
public function testExecute() {

View File

@@ -27,24 +27,29 @@ use OCA\Deck\Db\Card;
use OCA\Deck\Db\CardMapper;
use OCA\Deck\Notification\NotificationHelper;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\ILogger;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Test\TestCase;
class ScheduledNoificationsTest extends TestCase {
protected ITimeFactory&MockObject $timeFactory;
protected CardMapper&MockObject $cardMapper;
protected NotificationHelper&MockObject $notificationHelper;
protected LoggerInterface&MockObject $logger;
protected ScheduledNotifications $scheduledNotifications;
/** @var ITimeFactory|MockObject */
protected $timeFactory;
/** @var CardMapper|MockObject */
protected $cardMapper;
/** @var NotificationHelper|MockObject */
protected $notificationHelper;
/** @var ILogger|MockObject */
protected $logger;
/** @var ScheduledNotifications */
protected $scheduledNotifications;
public function setUp(): void {
parent::setUp();
$this->timeFactory = $this->createMock(ITimeFactory::class);
$this->cardMapper = $this->createMock(CardMapper::class);
$this->notificationHelper = $this->createMock(NotificationHelper::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->logger = $this->createMock(ILogger::class);
$this->scheduledNotifications = new ScheduledNotifications($this->timeFactory, $this->cardMapper, $this->notificationHelper, $this->logger);
}

View File

@@ -27,7 +27,7 @@ class AclTest extends \Test\TestCase {
private function createAclUser() {
$acl = new Acl();
$acl->setId(1);
$acl->setParticipant('admin');
$acl->setParticipant("admin");
$acl->setType(Acl::PERMISSION_TYPE_USER);
$acl->setBoardId(1);
$acl->setPermissionEdit(true);
@@ -39,7 +39,7 @@ class AclTest extends \Test\TestCase {
private function createAclGroup() {
$acl = new Acl();
$acl->setId(1);
$acl->setParticipant('administrators');
$acl->setParticipant("administrators");
$acl->setType(Acl::PERMISSION_TYPE_GROUP);
$acl->setBoardId(1);
$acl->setPermissionEdit(true);

View File

@@ -28,7 +28,7 @@ class AttachmentTest extends \Test\TestCase {
$attachment = new Attachment();
$attachment->setId(1);
$attachment->setCardId(123);
$attachment->setData('blob');
$attachment->setData("blob");
$attachment->setCreatedBy('admin');
$attachment->setType('deck_file');
return $attachment;

View File

@@ -8,9 +8,9 @@ class BoardTest extends TestCase {
private function createBoard() {
$board = new Board();
$board->setId(1);
$board->setTitle('My Board');
$board->setOwner('admin');
$board->setColor('000000');
$board->setTitle("My Board");
$board->setOwner("admin");
$board->setColor("000000");
$board->setArchived(false);
// TODO: relation shared labels acl
return $board;
@@ -20,9 +20,9 @@ class BoardTest extends TestCase {
$board->setUsers(['user1', 'user2']);
$this->assertEquals([
'id' => 1,
'title' => 'My Board',
'owner' => 'admin',
'color' => '000000',
'title' => "My Board",
'owner' => "admin",
'color' => "000000",
'labels' => [],
'permissions' => [],
'stacks' => [],
@@ -44,9 +44,9 @@ class BoardTest extends TestCase {
self::assertNull($board->getLabels());
$this->assertEquals([
'id' => 1,
'title' => 'My Board',
'owner' => 'admin',
'color' => '000000',
'title' => "My Board",
'owner' => "admin",
'color' => "000000",
'labels' => [],
'permissions' => [],
'stacks' => [],
@@ -63,13 +63,13 @@ class BoardTest extends TestCase {
public function testSetLabels() {
$board = $this->createBoard();
$board->setLabels(['foo', 'bar']);
$board->setLabels(["foo", "bar"]);
$this->assertEquals([
'id' => 1,
'title' => 'My Board',
'owner' => 'admin',
'color' => '000000',
'labels' => ['foo', 'bar'],
'title' => "My Board",
'owner' => "admin",
'color' => "000000",
'labels' => ["foo", "bar"],
'permissions' => [],
'stacks' => [],
'deletedAt' => 0,
@@ -95,9 +95,9 @@ class BoardTest extends TestCase {
$board->setShared(1);
$this->assertEquals([
'id' => 1,
'title' => 'My Board',
'owner' => 'admin',
'color' => '000000',
'title' => "My Board",
'owner' => "admin",
'color' => "000000",
'labels' => [],
'permissions' => [],
'stacks' => [],

View File

@@ -32,13 +32,13 @@ class CardTest extends TestCase {
private function createCard() {
$card = new Card();
$card->setId(1);
$card->setTitle('My Card');
$card->setDescription('a long description');
$card->setTitle("My Card");
$card->setDescription("a long description");
$card->setStackId(1);
$card->setType('text');
$card->setLastModified(234);
$card->setCreatedAt(123);
$card->setOwner('admin');
$card->setOwner("admin");
$card->setOrder(12);
$card->setArchived(false);
$card->setDone(null);
@@ -68,8 +68,8 @@ class CardTest extends TestCase {
$card = $this->createCard();
$this->assertEquals([
'id' => 1,
'title' => 'My Card',
'description' => 'a long description',
'title' => "My Card",
'description' => "a long description",
'type' => 'text',
'lastModified' => 234,
'createdAt' => 123,
@@ -96,8 +96,8 @@ class CardTest extends TestCase {
$card->setLabels([]);
$this->assertEquals([
'id' => 1,
'title' => 'My Card',
'description' => 'a long description',
'title' => "My Card",
'description' => "a long description",
'type' => 'text',
'lastModified' => 234,
'createdAt' => 123,
@@ -126,8 +126,8 @@ class CardTest extends TestCase {
$card->setLabels([]);
$this->assertEquals([
'id' => 1,
'title' => 'My Card',
'description' => 'a long description',
'title' => "My Card",
'description' => "a long description",
'type' => 'text',
'lastModified' => 234,
'createdAt' => 123,

View File

@@ -29,8 +29,8 @@ class LabelTest extends TestCase {
private function createLabel() {
$label = new Label();
$label->setId(1);
$label->setTitle('My Label');
$label->setColor('000000');
$label->setTitle("My Label");
$label->setColor("000000");
return $label;
}
public function testJsonSerializeBoard() {

View File

@@ -27,7 +27,7 @@ class StackTest extends \Test\TestCase {
private function createStack() {
$board = new Stack();
$board->setId(1);
$board->setTitle('My Stack');
$board->setTitle("My Stack");
$board->setBoardId(1);
$board->setOrder(1);
return $board;
@@ -36,7 +36,7 @@ class StackTest extends \Test\TestCase {
$stack = $this->createStack();
$this->assertEquals([
'id' => 1,
'title' => 'My Stack',
'title' => "My Stack",
'order' => 1,
'boardId' => 1,
'deletedAt' => 0,
@@ -45,15 +45,15 @@ class StackTest extends \Test\TestCase {
], $stack->jsonSerialize());
}
public function testJsonSerializeWithCards() {
$cards = ['foo', 'bar'];
$cards = ["foo", "bar"];
$stack = $this->createStack();
$stack->setCards($cards);
$this->assertEquals([
'id' => 1,
'title' => 'My Stack',
'title' => "My Stack",
'order' => 1,
'boardId' => 1,
'cards' => ['foo', 'bar'],
'cards' => ["foo", "bar"],
'deletedAt' => 0,
'lastModified' => 0,
'ETag' => $stack->getETag(),

View File

@@ -32,20 +32,21 @@ use OCA\Deck\Service\PermissionService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IConfig;
use OCP\ILogger;
use OCP\IRequest;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
class ExceptionMiddlewareTest extends \Test\TestCase {
private LoggerInterface&MockObject $logger;
private IConfig&MockObject $config;
private IRequest&MockObject $request;
private Controller&MockObject $controller;
/** @var ILogger */
private $logger;
/** @var IConfig */
private $config;
private $request;
private $controller;
private $exceptionMiddleware;
public function setUp(): void {
$this->logger = $this->createMock(LoggerInterface::class);
$this->logger = $this->createMock(ILogger::class);
$this->config = $this->createMock(IConfig::class);
$this->request = $this->createMock(IRequest::class);
$this->controller = $this->createMock(Controller::class);
@@ -69,8 +70,8 @@ class ExceptionMiddlewareTest extends \Test\TestCase {
public function testAfterException($exception, $status, $message) {
$result = $this->exceptionMiddleware->afterException($this->controller, 'bar', $exception);
$expected = new JSONResponse([
'status' => $status,
'message' => $message
"status" => $status,
"message" => $message
], $status);
$this->assertEquals($expected, $result);
}

View File

@@ -60,7 +60,7 @@ class NotificationHelperTest extends \Test\TestCase {
protected $cardMapper;
/** @var BoardMapper|MockObject */
protected $boardMapper;
/** @var AssignmentMapper|MockObject */
/** @var AssignmentMapper|MockObject */
protected $assignedUsersMapper;
/** @var PermissionService|MockObject */
protected $permissionService;

View File

@@ -78,7 +78,7 @@ class AssignmentServiceTest extends TestCase {
*/
private $assignmentService;
/**
* @var AssignmentServiceValidator
* @var AssignmentServiceValidator
*/
private $assignmentServiceValidator;

View File

@@ -70,7 +70,7 @@ class AttachmentServiceTest extends TestCase {
private $cardMapper;
/** @var PermissionService|MockObject */
private $permissionService;
/** @var string */
/** @var string */
private $userId = 'admin';
/** @var Application|MockObject */
private $application;
@@ -79,7 +79,7 @@ class AttachmentServiceTest extends TestCase {
private $attachmentService;
/** @var MockObject */
private $attachmentServiceImpl;
/** @var ActivityManager */
/** @var ActivityManager */
private $activityManager;
private $appContainer;
/** @var IL10N */
@@ -91,7 +91,7 @@ class AttachmentServiceTest extends TestCase {
*/
private $filesAppServiceImpl;
/**
* @var AttachmentServiceValidator
* @var AttachmentServiceValidator
*/
private $attachmentServiceValidator;

View File

@@ -34,29 +34,38 @@ use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\ISimpleFolder;
use OCP\IConfig;
use OCP\IL10N;
use OCP\ILogger;
use OCP\IRequest;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;
use Test\TestCase;
class FileServiceTest extends TestCase {
private IL10N&MockObject $l10n;
private IAppData&MockObject $appData;
private IRequest&MockObject $request;
private LoggerInterface&MockObject $logger;
private IRootFolder&MockObject $rootFolder;
private IConfig&MockObject $config;
private AttachmentMapper&MockObject $attachmentMapper;
private IMimeTypeDetector&MockObject $mimeTypeDetector;
private FileService $fileService;
/** @var IL10N|MockObject */
private $l10n;
/** @var IAppData|MockObject */
private $appData;
/** @var IRequest|MockObject */
private $request;
/** @var ILogger|MockObject */
private $logger;
/** @var FileService */
private $fileService;
/** @var IRootFolder */
private $rootFolder;
/** @var IConfig */
private $config;
/** @var AttachmentMapper|MockObject */
private $attachmentMapper;
/** @var IMimeTypeDetector|MockObject */
private $mimeTypeDetector;
public function setUp(): void {
parent::setUp();
$this->request = $this->createMock(IRequest::class);
$this->appData = $this->createMock(IAppData::class);
$this->l10n = $this->createMock(IL10N::class);
$this->logger = $this->createMock(LoggerInterface::class);
$this->logger = $this->createMock(ILogger::class);
$this->rootFolder = $this->createMock(IRootFolder::class);
$this->config = $this->createMock(IConfig::class);
$this->attachmentMapper = $this->createMock(AttachmentMapper::class);

View File

@@ -31,17 +31,17 @@ use Test\TestCase;
class LabelServiceTest extends TestCase {
/** @var LabelMapper|\PHPUnit\Framework\MockObject\MockObject */
/** @var LabelMapper|\PHPUnit\Framework\MockObject\MockObject */
private $labelMapper;
/** @var PermissionService|\PHPUnit\Framework\MockObject\MockObject */
/** @var PermissionService|\PHPUnit\Framework\MockObject\MockObject */
private $permissionService;
/** @var LabelService */
/** @var LabelService */
private $labelService;
/** @var BoardService|\PHPUnit\Framework\MockObject\MockObject */
private $boardService;
/** @var ChangeHelper|\PHPUnit\Framework\MockObject\MockObject */
private $changeHelper;
/** @var LabelServiceValidator\MockObject */
/** @var LabelServiceValidator\MockObject */
private $labelServiceValidator;
public function setUp(): void {

View File

@@ -212,8 +212,8 @@ class StackServiceTest extends TestCase {
$this->stackMapper->expects($this->once())->method('update')->willReturn($stackToBeDeleted);
$this->cardMapper->expects($this->once())->method('findAll')->willReturn([]);
$this->stackService->delete(123);
$this->assertTrue($stackToBeDeleted->getDeletedAt() <= time(), 'deletedAt is in the past');
$this->assertTrue($stackToBeDeleted->getDeletedAt() > 0, 'deletedAt is set');
$this->assertTrue($stackToBeDeleted->getDeletedAt() <= time(), "deletedAt is in the past");
$this->assertTrue($stackToBeDeleted->getDeletedAt() > 0, "deletedAt is set");
}
public function testUpdate() {

View File

@@ -111,8 +111,8 @@ class CardApiControllerTest extends \Test\TestCase {
$this->stackExample['id']);
$this->cardService->expects($this->once())
->method('update')
->willReturn($card);
->method('update')
->willReturn($card);
$expected = new DataResponse($card, HTTP::STATUS_OK);
$actual = $this->controller->update('title', 'plain', 0, 'description', $this->userId, null);