Compare commits

...

55 Commits

Author SHA1 Message Date
Julius Härtl
40ac9b6c3e fix: Avoid double tap on iOS and close navigation on click
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 08:09:29 +02:00
Julius Härtl
06fcf8f2cd fix: Auto-scroll horizontally
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 08:09:28 +02:00
Julius Härtl
2f0241df2e fix: Hide navigation initially on mobile
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 08:09:28 +02:00
Julius Härtl
34ff6f4aac fix: Proper drag zone height (fix #6264)
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 08:09:28 +02:00
Julius Härtl
40f7f0907a fix: Fix modal sizing, focus error and cover image sizing
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 08:09:28 +02:00
Julius Härtl
0e5006616e fix: Set proper name on modal
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 08:09:28 +02:00
Julius Härtl
792a513bb5 fix: Fix focus and emptycontent titles
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 08:09:28 +02:00
Julius Härtl
a9b65de341 fix: Move card create input to the bottom
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 08:09:27 +02:00
Julius Härtl
a0fc1bbeb8 fix: Fix empty board view design
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 08:09:27 +02:00
Julius Härtl
482bcb3149 fix: Fix styling of navigation input fields
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 08:09:27 +02:00
Julius Härtl
cf0b90369a fix: Adapt spacing to new compact design
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 07:59:42 +02:00
Julius Härtl
a0bcbc5cc6 fix: Proper slots for card selector dialog
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 07:59:42 +02:00
Julius Härtl
e73eec8ba4 fix: Avoid swipe navigation while scrolling
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 07:59:42 +02:00
Julius Härtl
c1ed33848c fix: Properly scroll on mobile devices
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-09-02 07:59:42 +02:00
github-actions[bot]
d9d75fdfe4 Merge pull request #6284 from nextcloud/automated/noid/main-update-nextcloud-ocp
[main] Update nextcloud/ocp dependency
2024-09-01 04:57:53 +00:00
nextcloud-command
c348b824c8 chore(dev-deps): Bump nextcloud/ocp package
Signed-off-by: GitHub <noreply@github.com>
2024-09-01 03:02:56 +00:00
Nextcloud bot
39987a0303 Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-09-01 00:41:40 +00:00
dependabot[bot]
0906b06192 Merge pull request #6270 from nextcloud/dependabot/npm_and_yarn/main/cypress-13.14.1 2024-08-31 03:38:18 +00:00
dependabot[bot]
434f59d06d 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 02:56:18 +00:00
dependabot[bot]
af4c01abd4 Merge pull request #6268 from nextcloud/dependabot/npm_and_yarn/main/babel/runtime-7.25.6 2024-08-31 02:55:55 +00:00
dependabot[bot]
516bc6d5fc Merge pull request #6269 from nextcloud/dependabot/npm_and_yarn/main/nextcloud/vue-8.17.1 2024-08-31 02:55:38 +00:00
dependabot[bot]
d7b3aedab4 Merge pull request #6267 from nextcloud/dependabot/npm_and_yarn/main/relative-ci/agent-4.2.11 2024-08-31 02:55:26 +00:00
dependabot[bot]
fb641946d6 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:39:08 +00:00
dependabot[bot]
b3bc532e81 Chore(deps): Bump @babel/runtime from 7.25.4 to 7.25.6
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.25.4 to 7.25.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.25.6/packages/babel-runtime)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-31 01:38:48 +00:00
dependabot[bot]
fe1006d643 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:38:32 +00:00
Julius Härtl
9a37d6dbfc Merge pull request #6266 from nextcloud/dependabot/npm_and_yarn/webpack-5.94.0 2024-08-30 20:15:19 +02:00
dependabot[bot]
bf704309ad Chore(deps-dev): Bump webpack from 5.88.2 to 5.94.0
Bumps [webpack](https://github.com/webpack/webpack) from 5.88.2 to 5.94.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.88.2...v5.94.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-30 17:49:09 +00:00
Nextcloud bot
635cf3962f Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-08-30 00:56:02 +00:00
Julius Härtl
43a0fec9a6 Merge pull request #6257 from nextcloud/fix/no-cross-referencing-in-labels
copy labels when moving cards between boards
2024-08-29 12:30:17 +02:00
Julius Härtl
c6c41c59d2 Merge pull request #6232 from nextcloud/fix/nextcloud-30-design-issues
fix: 30 design issues
2024-08-29 12:28:53 +02:00
Julius Härtl
fb54b8126a fix: Avoid duplicate scrollbars
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-08-29 11:36:23 +02:00
Luka Trovic
a4f2a99776 fix: 30 design issues
Signed-off-by: Luka Trovic <luka@nextcloud.com>
2024-08-29 11:19:30 +02:00
grnd-alt
dbca6bc0d7 copy labels when moving cards between boards
Signed-off-by: grnd-alt <salimbelakkaf@outlook.de>
2024-08-28 11:59:34 +02:00
Nextcloud bot
e647faf31c Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-08-28 00:41:42 +00:00
Julius Härtl
fdd05853af Merge pull request #6260 from nextcloud/Jerome-Herbinet-translation-call-fix
Translation call fix
2024-08-26 13:19:55 +02:00
Jérôme Herbinet
afd8372baa Translation call fix
Signed-off-by: Jérôme Herbinet <33763786+Jerome-Herbinet@users.noreply.github.com>
2024-08-26 13:12:35 +02:00
Julius Härtl
f99d1f516c Merge pull request #6259 from Dinock/patch-1
Fixed a typo in Markdown.md
2024-08-26 13:01:54 +02:00
Dinock
1aa23407f1 Update Markdown.md
Fixed a typo in the sentence "Markdown comes in may flavors.". (old="may", new="many")

Signed-off-by: Dinock <54438803+Dinock@users.noreply.github.com>
2024-08-26 12:44:19 +02:00
Julius Härtl
83d59dd3a9 Merge pull request #6235 from nextcloud/fix/ui
Fix UI with the new compact design
2024-08-26 12:43:24 +02:00
dependabot[bot]
2233786605 Merge pull request #6236 from nextcloud/dependabot/composer/nextcloud/coding-standard-1.2.3 2024-08-26 06:21:33 +00:00
Julius Härtl
2d2f7c6772 Merge pull request #6240 from nextcloud/dependabot/github_actions/mdecoleman/pr-branch-name-3.0.0
Chore(deps): Bump mdecoleman/pr-branch-name from 2.0.0 to 3.0.0
2024-08-26 08:15:21 +02:00
dependabot[bot]
ba3e97b73d Chore(deps-dev): Bump nextcloud/coding-standard from 1.2.1 to 1.2.3
Bumps [nextcloud/coding-standard](https://github.com/nextcloud/coding-standard) from 1.2.1 to 1.2.3.
- [Release notes](https://github.com/nextcloud/coding-standard/releases)
- [Changelog](https://github.com/nextcloud/coding-standard/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/coding-standard/compare/v1.2.1...v1.2.3)

---
updated-dependencies:
- dependency-name: nextcloud/coding-standard
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 08:14:42 +02:00
Julius Härtl
4107481b07 Merge pull request #6237 from nextcloud/dependabot/npm_and_yarn/main/chroma-js-3.0.0
Chore(deps): Bump chroma-js from 2.6.0 to 3.0.0
2024-08-26 08:11:37 +02:00
Julius Härtl
6e158992dc Merge pull request #6253 from nextcloud/automated/noid/main-fix-npm-audit
[main] Fix npm audit
2024-08-26 08:11:18 +02:00
nextcloud-command
0e4c60c23f fix(deps): Fix npm audit
Signed-off-by: GitHub <noreply@github.com>
2024-08-25 03:08:35 +00:00
dependabot[bot]
702672de28 Chore(deps): Bump chroma-js from 2.6.0 to 3.0.0
Bumps [chroma-js](https://github.com/gka/chroma.js) from 2.6.0 to 3.0.0.
- [Release notes](https://github.com/gka/chroma.js/releases)
- [Changelog](https://github.com/gka/chroma.js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/gka/chroma.js/compare/v2.6.0...v3.0.0)

---
updated-dependencies:
- dependency-name: chroma-js
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-24 08:12:19 +00:00
Julius Härtl
48bdf83887 Merge pull request #6238 from nextcloud/dependabot/npm_and_yarn/main/nextcloud/vue-8.17.0 2024-08-24 10:11:32 +02:00
dependabot[bot]
520a0f8c26 Merge pull request #6239 from nextcloud/dependabot/npm_and_yarn/main/babel/runtime-7.25.4 2024-08-24 02:16:38 +00:00
dependabot[bot]
b84564b0f7 Chore(deps): Bump mdecoleman/pr-branch-name from 2.0.0 to 3.0.0
Bumps [mdecoleman/pr-branch-name](https://github.com/mdecoleman/pr-branch-name) from 2.0.0 to 3.0.0.
- [Release notes](https://github.com/mdecoleman/pr-branch-name/releases)
- [Commits](bab4c71506...55795d86b4)

---
updated-dependencies:
- dependency-name: mdecoleman/pr-branch-name
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-24 01:19:34 +00:00
dependabot[bot]
ba33a83e9f 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:11:07 +00:00
dependabot[bot]
b645c1e974 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:10:48 +00:00
Nextcloud bot
3daad1b9bc Fix(l10n): Update translations from Transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-08-24 00:38:58 +00:00
Julius Härtl
5416a2b3a1 fix: Adjust UI to be more consistent with new Nextcloud compact UI
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-08-23 20:13:09 +02:00
Julius Härtl
5c3098afa1 fix: Hide inline search box as the global one is working now
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2024-08-23 20:11:48 +02:00
Julius Härtl
e25470ece3 Merge pull request #6234 from nextcloud/automated/update-workflows/default 2024-08-23 09:26:53 +02:00
77 changed files with 739 additions and 457 deletions

View File

@@ -39,7 +39,7 @@ jobs:
echo 'Can not approve PRs from forks' echo 'Can not approve PRs from forks'
exit 1 exit 1
- uses: mdecoleman/pr-branch-name@bab4c71506bcd299fb350af63bb8e53f2940a599 # v2.0.0 - uses: mdecoleman/pr-branch-name@55795d86b4566d300d237883103f052125cc7508 # v3.0.0
id: branchname id: branchname
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}

32
composer.lock generated
View File

@@ -399,16 +399,16 @@
}, },
{ {
"name": "nextcloud/coding-standard", "name": "nextcloud/coding-standard",
"version": "v1.2.1", "version": "v1.2.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nextcloud/coding-standard.git", "url": "https://github.com/nextcloud/coding-standard.git",
"reference": "cf5f18d989ec62fb4cdc7fc92a36baf34b3d829e" "reference": "bc9c53a5306114b60c4363057aff9c2ed10a54da"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/cf5f18d989ec62fb4cdc7fc92a36baf34b3d829e", "url": "https://api.github.com/repos/nextcloud/coding-standard/zipball/bc9c53a5306114b60c4363057aff9c2ed10a54da",
"reference": "cf5f18d989ec62fb4cdc7fc92a36baf34b3d829e", "reference": "bc9c53a5306114b60c4363057aff9c2ed10a54da",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -434,9 +434,9 @@
"description": "Nextcloud coding standards for the php cs fixer", "description": "Nextcloud coding standards for the php cs fixer",
"support": { "support": {
"issues": "https://github.com/nextcloud/coding-standard/issues", "issues": "https://github.com/nextcloud/coding-standard/issues",
"source": "https://github.com/nextcloud/coding-standard/tree/v1.2.1" "source": "https://github.com/nextcloud/coding-standard/tree/v1.2.3"
}, },
"time": "2024-02-01T14:54:37+00:00" "time": "2024-08-23T14:32:32+00:00"
}, },
{ {
"name": "nextcloud/ocp", "name": "nextcloud/ocp",
@@ -444,12 +444,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nextcloud-deps/ocp.git", "url": "https://github.com/nextcloud-deps/ocp.git",
"reference": "b0127d6fd2932bf1fdffe334ae59fdd6c8272029" "reference": "b6538d7f14472c2ef6182c51df6be34cae033099"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/b0127d6fd2932bf1fdffe334ae59fdd6c8272029", "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/b6538d7f14472c2ef6182c51df6be34cae033099",
"reference": "b0127d6fd2932bf1fdffe334ae59fdd6c8272029", "reference": "b6538d7f14472c2ef6182c51df6be34cae033099",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -481,7 +481,7 @@
"issues": "https://github.com/nextcloud-deps/ocp/issues", "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/master"
}, },
"time": "2024-08-14T08:51:54+00:00" "time": "2024-08-31T00:39:40+00:00"
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
@@ -661,16 +661,16 @@
}, },
{ {
"name": "php-cs-fixer/shim", "name": "php-cs-fixer/shim",
"version": "v3.49.0", "version": "v3.62.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/PHP-CS-Fixer/shim.git", "url": "https://github.com/PHP-CS-Fixer/shim.git",
"reference": "f7d3219cac46632f12362c9aa7c2ac0d2fe92c52" "reference": "7a91d5ce45c486f5b445d95901228507a02f60ae"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/f7d3219cac46632f12362c9aa7c2ac0d2fe92c52", "url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/7a91d5ce45c486f5b445d95901228507a02f60ae",
"reference": "f7d3219cac46632f12362c9aa7c2ac0d2fe92c52", "reference": "7a91d5ce45c486f5b445d95901228507a02f60ae",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -707,9 +707,9 @@
"description": "A tool to automatically fix PHP code style", "description": "A tool to automatically fix PHP code style",
"support": { "support": {
"issues": "https://github.com/PHP-CS-Fixer/shim/issues", "issues": "https://github.com/PHP-CS-Fixer/shim/issues",
"source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.49.0" "source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.62.0"
}, },
"time": "2024-02-02T00:42:09+00:00" "time": "2024-08-07T17:03:46+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",

View File

@@ -35,7 +35,7 @@ describe('Board', function() {
.type(board, { force: true }) .type(board, { force: true })
// Submit // Submit
cy.get('.board-create form input[type=submit]') cy.get('.board-create form button[type=submit]')
.first().click({ force: true }) .first().click({ force: true })
cy.wait('@createBoardRequest').its('response.statusCode').should('equal', 200) 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 ## Supported Markdown
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. 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.
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. 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/) [CommonMark Markdown Reference](http://commonmark.org/help/)

View File

@@ -34,9 +34,14 @@ OC.L10N.register(
"Later" : "Después", "Later" : "Después",
"copy" : "copiar", "copy" : "copiar",
"Done" : "Hecho", "Done" : "Hecho",
"The file was uploaded" : "El archivo ha sido subido",
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "El archivo cargado excede el valor establecido en la directiva upload_max_filesize en el archivo php.ini",
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "El archivo subido sobrepasa el valor MAX_FILE_SIZE especificada en el formulario HTML", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "El archivo subido sobrepasa el valor MAX_FILE_SIZE especificada en el formulario HTML",
"The file was only partially uploaded" : "El archivo sólo fue cargado parcialmente",
"No file was uploaded" : "No se subió ningún archivo ", "No file was uploaded" : "No se subió ningún archivo ",
"Missing a temporary folder" : "Falta un directorio temporal", "Missing a temporary folder" : "Falta un directorio temporal",
"Could not write file to disk" : "No se pudo escribir el archivo en el disco",
"A PHP extension stopped the file upload" : "Una extensión de PHP detuvo la carga del archivo",
"Card not found" : "Tarjeta no encontrada", "Card not found" : "Tarjeta no encontrada",
"Invalid date, date format must be YYYY-MM-DD" : "La fecha es inválida, favor de seguir el formato AAAA-MM-DD", "Invalid date, date format must be YYYY-MM-DD" : "La fecha es inválida, favor de seguir el formato AAAA-MM-DD",
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck es una herramienta de organización de estilo kanban dirigida a la planificación personal y la organización de proyectos para equipos integrados con Nextcloud.\n\n\n- 📥 Agrega tus tareas a las tarjetas y ordénalas.\n- 📄 Escriba notas adicionales\n- 🔖 Asignar etiquetas para una organización mejor\n- 👥 Comparte con tu equipo, amigos o familia.\n- 📎 Adjuntar archivos e incrustarlos en su descripción\n- 💬 Discuta con su equipo usando comentarios.\n- ⚡ Mantenga un registro de los cambios en el flujo de actividad\n- 🚀 Organiza tu proyecto", "Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck es una herramienta de organización de estilo kanban dirigida a la planificación personal y la organización de proyectos para equipos integrados con Nextcloud.\n\n\n- 📥 Agrega tus tareas a las tarjetas y ordénalas.\n- 📄 Escriba notas adicionales\n- 🔖 Asignar etiquetas para una organización mejor\n- 👥 Comparte con tu equipo, amigos o familia.\n- 📎 Adjuntar archivos e incrustarlos en su descripción\n- 💬 Discuta con su equipo usando comentarios.\n- ⚡ Mantenga un registro de los cambios en el flujo de actividad\n- 🚀 Organiza tu proyecto",

View File

@@ -32,9 +32,14 @@
"Later" : "Después", "Later" : "Después",
"copy" : "copiar", "copy" : "copiar",
"Done" : "Hecho", "Done" : "Hecho",
"The file was uploaded" : "El archivo ha sido subido",
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "El archivo cargado excede el valor establecido en la directiva upload_max_filesize en el archivo php.ini",
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "El archivo subido sobrepasa el valor MAX_FILE_SIZE especificada en el formulario HTML", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "El archivo subido sobrepasa el valor MAX_FILE_SIZE especificada en el formulario HTML",
"The file was only partially uploaded" : "El archivo sólo fue cargado parcialmente",
"No file was uploaded" : "No se subió ningún archivo ", "No file was uploaded" : "No se subió ningún archivo ",
"Missing a temporary folder" : "Falta un directorio temporal", "Missing a temporary folder" : "Falta un directorio temporal",
"Could not write file to disk" : "No se pudo escribir el archivo en el disco",
"A PHP extension stopped the file upload" : "Una extensión de PHP detuvo la carga del archivo",
"Card not found" : "Tarjeta no encontrada", "Card not found" : "Tarjeta no encontrada",
"Invalid date, date format must be YYYY-MM-DD" : "La fecha es inválida, favor de seguir el formato AAAA-MM-DD", "Invalid date, date format must be YYYY-MM-DD" : "La fecha es inválida, favor de seguir el formato AAAA-MM-DD",
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck es una herramienta de organización de estilo kanban dirigida a la planificación personal y la organización de proyectos para equipos integrados con Nextcloud.\n\n\n- 📥 Agrega tus tareas a las tarjetas y ordénalas.\n- 📄 Escriba notas adicionales\n- 🔖 Asignar etiquetas para una organización mejor\n- 👥 Comparte con tu equipo, amigos o familia.\n- 📎 Adjuntar archivos e incrustarlos en su descripción\n- 💬 Discuta con su equipo usando comentarios.\n- ⚡ Mantenga un registro de los cambios en el flujo de actividad\n- 🚀 Organiza tu proyecto", "Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck es una herramienta de organización de estilo kanban dirigida a la planificación personal y la organización de proyectos para equipos integrados con Nextcloud.\n\n\n- 📥 Agrega tus tareas a las tarjetas y ordénalas.\n- 📄 Escriba notas adicionales\n- 🔖 Asignar etiquetas para una organización mejor\n- 👥 Comparte con tu equipo, amigos o familia.\n- 📎 Adjuntar archivos e incrustarlos en su descripción\n- 💬 Discuta con su equipo usando comentarios.\n- ⚡ Mantenga un registro de los cambios en el flujo de actividad\n- 🚀 Organiza tu proyecto",

View File

@@ -257,6 +257,7 @@ OC.L10N.register(
"Shift" : "تغییر مکان", "Shift" : "تغییر مکان",
"Ctrl" : "Ctrl", "Ctrl" : "Ctrl",
"Search" : "جستجو", "Search" : "جستجو",
"Show help dialog" : "نمایش پنجرهٔ راهنما",
"Enter" : "Enter", "Enter" : "Enter",
"Space" : "Space", "Space" : "Space",
"All boards" : "همه تخته‌ها", "All boards" : "همه تخته‌ها",

View File

@@ -255,6 +255,7 @@
"Shift" : "تغییر مکان", "Shift" : "تغییر مکان",
"Ctrl" : "Ctrl", "Ctrl" : "Ctrl",
"Search" : "جستجو", "Search" : "جستجو",
"Show help dialog" : "نمایش پنجرهٔ راهنما",
"Enter" : "Enter", "Enter" : "Enter",
"Space" : "Space", "Space" : "Space",
"All boards" : "همه تخته‌ها", "All boards" : "همه تخته‌ها",

View File

@@ -149,8 +149,9 @@ OC.L10N.register(
"Filter by tag" : "Filtrer par étiquette", "Filter by tag" : "Filtrer par étiquette",
"Filter by assigned user" : "Filtrer par utilisateur", "Filter by assigned user" : "Filtrer par utilisateur",
"Unassigned" : "Non attribué", "Unassigned" : "Non attribué",
"Filter by status" : "Filtrer par statut",
"Open and completed" : "Ouvert et terminé", "Open and completed" : "Ouvert et terminé",
"Open" : "Ouvrir", "Open" : "Ouvert",
"Completed" : "Terminé", "Completed" : "Terminé",
"Filter by due date" : "Filtrer par échéance", "Filter by due date" : "Filtrer par échéance",
"Overdue" : "En retard", "Overdue" : "En retard",

View File

@@ -147,8 +147,9 @@
"Filter by tag" : "Filtrer par étiquette", "Filter by tag" : "Filtrer par étiquette",
"Filter by assigned user" : "Filtrer par utilisateur", "Filter by assigned user" : "Filtrer par utilisateur",
"Unassigned" : "Non attribué", "Unassigned" : "Non attribué",
"Filter by status" : "Filtrer par statut",
"Open and completed" : "Ouvert et terminé", "Open and completed" : "Ouvert et terminé",
"Open" : "Ouvrir", "Open" : "Ouvert",
"Completed" : "Terminé", "Completed" : "Terminé",
"Filter by due date" : "Filtrer par échéance", "Filter by due date" : "Filtrer par échéance",
"Overdue" : "En retard", "Overdue" : "En retard",

View File

@@ -247,6 +247,7 @@ OC.L10N.register(
"Choose a date" : "Válasszon dátumot", "Choose a date" : "Válasszon dátumot",
"Remove due date" : "Határidő eltávolítása", "Remove due date" : "Határidő eltávolítása",
"Mark as done" : "Megjelölés készként", "Mark as done" : "Megjelölés készként",
"Not done" : "Nincs kész",
"Unarchive card" : "Kártya archiválásának visszavonása", "Unarchive card" : "Kártya archiválásának visszavonása",
"Archive card" : "Kártya archiválása", "Archive card" : "Kártya archiválása",
"Select Date" : "Dátum kiválasztása", "Select Date" : "Dátum kiválasztása",

View File

@@ -245,6 +245,7 @@
"Choose a date" : "Válasszon dátumot", "Choose a date" : "Válasszon dátumot",
"Remove due date" : "Határidő eltávolítása", "Remove due date" : "Határidő eltávolítása",
"Mark as done" : "Megjelölés készként", "Mark as done" : "Megjelölés készként",
"Not done" : "Nincs kész",
"Unarchive card" : "Kártya archiválásának visszavonása", "Unarchive card" : "Kártya archiválásának visszavonása",
"Archive card" : "Kártya archiválása", "Archive card" : "Kártya archiválása",
"Select Date" : "Dátum kiválasztása", "Select Date" : "Dátum kiválasztása",

View File

@@ -72,17 +72,17 @@ final class TransferOwnership extends Command {
try { try {
$board = $boardId ? $this->boardMapper->find($boardId) : null; $board = $boardId ? $this->boardMapper->find($boardId) : null;
} catch (\Exception $e) { } 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; return 1;
} }
if ($boardId !== null && $board->getOwner() !== $owner) { 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; return 1;
} }
if ($boardId) { 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 { } else {
$output->writeln("Transfer all boards from $owner to $newOwner"); $output->writeln("Transfer all boards from $owner to $newOwner");
} }
@@ -94,12 +94,12 @@ final class TransferOwnership extends Command {
if ($boardId) { if ($boardId) {
$this->boardService->transferBoardOwnership($boardId, $newOwner, $remapAssignment); $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; return 0;
} }
foreach ($this->boardService->transferOwnership($owner, $newOwner, $remapAssignment) as $board) { 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>"); $output->writeln("<info>All boards from $owner to $newOwner transferred</info>");

View File

@@ -410,7 +410,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
foreach ($query->getDuedate() as $duedate) { foreach ($query->getDuedate() as $duedate) {
$dueDateColumn = $this->databaseType === 'sqlite3' ? $qb->createFunction('DATETIME(`c`.`duedate`)') : 'c.duedate'; $dueDateColumn = $this->databaseType === 'sqlite3' ? $qb->createFunction('DATETIME(`c`.`duedate`)') : 'c.duedate';
$date = $duedate->getValue(); $date = $duedate->getValue();
if ($date === "") { if ($date === '') {
$qb->andWhere($qb->expr()->isNotNull('c.duedate')); $qb->andWhere($qb->expr()->isNotNull('c.duedate'));
continue; continue;
} }
@@ -461,7 +461,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
foreach ($query->getAssigned() as $index => $assignment) { foreach ($query->getAssigned() as $index => $assignment) {
$qb->innerJoin('c', 'deck_assigned_users', 'au' . $index, $qb->expr()->eq('c.id', 'au' . $index . '.card_id')); $qb->innerJoin('c', 'deck_assigned_users', 'au' . $index, $qb->expr()->eq('c.id', 'au' . $index . '.card_id'));
$assignedQueryValue = $assignment->getValue(); $assignedQueryValue = $assignment->getValue();
if ($assignedQueryValue === "") { if ($assignedQueryValue === '') {
$qb->andWhere($qb->expr()->isNotNull('au' . $index . '.participant')); $qb->andWhere($qb->expr()->isNotNull('au' . $index . '.participant'));
continue; continue;
} }

View File

@@ -40,6 +40,7 @@ class CardService {
private StackMapper $stackMapper; private StackMapper $stackMapper;
private BoardMapper $boardMapper; private BoardMapper $boardMapper;
private LabelMapper $labelMapper; private LabelMapper $labelMapper;
private LabelService $labelService;
private PermissionService $permissionService; private PermissionService $permissionService;
private BoardService $boardService; private BoardService $boardService;
private NotificationHelper $notificationHelper; private NotificationHelper $notificationHelper;
@@ -61,6 +62,7 @@ class CardService {
StackMapper $stackMapper, StackMapper $stackMapper,
BoardMapper $boardMapper, BoardMapper $boardMapper,
LabelMapper $labelMapper, LabelMapper $labelMapper,
LabelService $labelService,
PermissionService $permissionService, PermissionService $permissionService,
BoardService $boardService, BoardService $boardService,
NotificationHelper $notificationHelper, NotificationHelper $notificationHelper,
@@ -81,6 +83,7 @@ class CardService {
$this->stackMapper = $stackMapper; $this->stackMapper = $stackMapper;
$this->boardMapper = $boardMapper; $this->boardMapper = $boardMapper;
$this->labelMapper = $labelMapper; $this->labelMapper = $labelMapper;
$this->labelService = $labelService;
$this->permissionService = $permissionService; $this->permissionService = $permissionService;
$this->boardService = $boardService; $this->boardService = $boardService;
$this->notificationHelper = $notificationHelper; $this->notificationHelper = $notificationHelper;
@@ -349,8 +352,34 @@ class CardService {
} }
$card->setDescription($description); $card->setDescription($description);
// @var Card $card
$card = $this->cardMapper->update($card); $card = $this->cardMapper->update($card);
$oldBoardId = $this->stackMapper->findBoardId($changes->getBefore()->getStackId());
$boardId = $this->cardMapper->findBoardId($card->getId());
if($boardId !== $oldBoardId) {
$stack = $this->stackMapper->find($card->getStackId());
$board = $this->boardService->find($this->cardMapper->findBoardId($card->getId()));
$boardLabels = $board->getLabels() ?? [];
foreach($card->getLabels() as $cardLabel) {
$this->removeLabel($card->getId(), $cardLabel->getId());
$label = $this->labelMapper->find($cardLabel->getId());
$filteredLabels = array_values(array_filter($boardLabels, fn ($item) => $item->getTitle() === $label->getTitle()));
// clone labels that are assigned to card but don't exist in new board
if (empty($filteredLabels)) {
if ($this->permissionService->getPermissions($boardId)[Acl::PERMISSION_MANAGE] === true) {
$newLabel = $this->labelService->create($label->getTitle(), $label->getColor(), $board->getId());
$boardLabels[] = $label;
$this->assignLabel($card->getId(), $newLabel->getId());
}
} else {
$this->assignLabel($card->getId(), $filteredLabels[0]->getId());
}
}
$board->setLabels($boardLabels);
$this->boardMapper->update($board);
$this->changeHelper->boardChanged($board->getId());
}
if ($resetDuedateNotification) { if ($resetDuedateNotification) {
$this->notificationHelper->markDuedateAsRead($card); $this->notificationHelper->markDuedateAsRead($card);
} }

View File

@@ -106,7 +106,7 @@ class DeckJsonService extends ABoardImportService {
public function getComments(): array { public function getComments(): array {
$comments = []; $comments = [];
foreach ($this->tmpCards as $sourceCard) { foreach ($this->tmpCards as $sourceCard) {
if (!property_exists($sourceCard, "comments")) { if (!property_exists($sourceCard, 'comments')) {
continue; continue;
} }
$commentsOriginal = $sourceCard->comments; $commentsOriginal = $sourceCard->comments;
@@ -125,10 +125,12 @@ class DeckJsonService extends ABoardImportService {
foreach ($this->tmpCards as $sourceCard) { foreach ($this->tmpCards as $sourceCard) {
foreach ($sourceCard->labels as $label) { foreach ($sourceCard->labels as $label) {
$cardId = $this->cards[$sourceCard->id]->getId(); $cardId = $this->cards[$sourceCard->id]->getId();
if ($this->getImportService()->getData()->id === $label->boardId) {
$labelId = $this->labels[$label->id]->getId(); $labelId = $this->labels[$label->id]->getId();
$cardsLabels[$cardId][] = $labelId; $cardsLabels[$cardId][] = $labelId;
} }
} }
}
return $cardsLabels; return $cardsLabels;
} }

View File

@@ -141,7 +141,7 @@ class TrelloJsonService extends ABoardImportService {
$message = $this->l10n->t( $message = $this->l10n->t(
"This comment has more than %s characters.\n" . "This comment has more than %s characters.\n" .
"Added as an attachment to the card with name %s.\n" . "Added as an attachment to the card with name %s.\n" .
"Accessible on URL: %s.", 'Accessible on URL: %s.',
[ [
IComment::MAX_MESSAGE_LENGTH, IComment::MAX_MESSAGE_LENGTH,
'comment_' . $commentId . '.md', 'comment_' . $commentId . '.md',

View File

@@ -45,7 +45,7 @@ abstract class BaseValidator {
} else { } else {
if (!$this->{$rule}($value)) { if (!$this->{$rule}($value)) {
throw new BadRequestException( 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 { private function max($value, $limit): bool {
if (!$limit || !is_numeric($limit)) { 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; return $this->getSize($value) <= $limit;
} }
@@ -121,7 +121,7 @@ abstract class BaseValidator {
*/ */
private function min($value, $limit): bool { private function min($value, $limit): bool {
if (!$limit || !is_numeric($limit)) { 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; return $this->getSize($value) >= $limit;
} }
@@ -158,6 +158,6 @@ abstract class BaseValidator {
: $field . ' must be at least '. $parameter . ' characters long '; : $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);
} }
} }

332
package-lock.json generated
View File

@@ -10,7 +10,7 @@
"license": "agpl", "license": "agpl",
"dependencies": { "dependencies": {
"@babel/polyfill": "^7.12.1", "@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.25.0", "@babel/runtime": "^7.25.6",
"@nextcloud/auth": "^2.4.0", "@nextcloud/auth": "^2.4.0",
"@nextcloud/axios": "^2.5.0", "@nextcloud/axios": "^2.5.0",
"@nextcloud/capabilities": "^1.2.0", "@nextcloud/capabilities": "^1.2.0",
@@ -22,9 +22,9 @@
"@nextcloud/moment": "^1.3.1", "@nextcloud/moment": "^1.3.1",
"@nextcloud/notify_push": "^1.3.0", "@nextcloud/notify_push": "^1.3.0",
"@nextcloud/router": "^3.0.1", "@nextcloud/router": "^3.0.1",
"@nextcloud/vue": "^8.16.0", "@nextcloud/vue": "^8.17.1",
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"chroma-js": "^2.6.0", "chroma-js": "^3.0.0",
"dompurify": "^3.1.6", "dompurify": "^3.1.6",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
@@ -52,10 +52,10 @@
"@nextcloud/eslint-config": "^8.4.1", "@nextcloud/eslint-config": "^8.4.1",
"@nextcloud/stylelint-config": "^3.0.1", "@nextcloud/stylelint-config": "^3.0.1",
"@nextcloud/webpack-vue-config": "^6.0.0", "@nextcloud/webpack-vue-config": "^6.0.0",
"@relative-ci/agent": "^4.2.10", "@relative-ci/agent": "^4.2.11",
"@vue/test-utils": "^2.4.6", "@vue/test-utils": "^2.4.6",
"@vue/vue2-jest": "^29.2.6", "@vue/vue2-jest": "^29.2.6",
"cypress": "^13.13.3", "cypress": "^13.14.1",
"eslint-plugin-cypress": "^3.5.0", "eslint-plugin-cypress": "^3.5.0",
"eslint-webpack-plugin": "^4.2.0", "eslint-webpack-plugin": "^4.2.0",
"jest": "^29.7.0", "jest": "^29.7.0",
@@ -1917,9 +1917,9 @@
"peer": true "peer": true
}, },
"node_modules/@babel/runtime": { "node_modules/@babel/runtime": {
"version": "7.25.0", "version": "7.25.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz",
"integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==",
"dependencies": { "dependencies": {
"regenerator-runtime": "^0.14.0" "regenerator-runtime": "^0.14.0"
}, },
@@ -1994,9 +1994,9 @@
"dev": true "dev": true
}, },
"node_modules/@bundle-stats/plugin-webpack-validate": { "node_modules/@bundle-stats/plugin-webpack-validate": {
"version": "4.14.0", "version": "4.15.0",
"resolved": "https://registry.npmjs.org/@bundle-stats/plugin-webpack-validate/-/plugin-webpack-validate-4.14.0.tgz", "resolved": "https://registry.npmjs.org/@bundle-stats/plugin-webpack-validate/-/plugin-webpack-validate-4.15.0.tgz",
"integrity": "sha512-VLXk50dAriPXM4i1HfH3rX6rKXKqnU7EKI/xkUaRfGgSCiMWsLfNpA/T+gv3CYYXM/HqCM2tXOy3dc9V5OIh8w==", "integrity": "sha512-AKj6okcTFgQMFnJg3rSrLDw4dQ2U9I0WGecKf4qzeW3MsoSgnTW58ZBCebIoODEatw7bhawBlXhkl6tvjkjY4A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"lodash": "4.17.21", "lodash": "4.17.21",
@@ -3340,14 +3340,14 @@
} }
}, },
"node_modules/@jridgewell/source-map": { "node_modules/@jridgewell/source-map": {
"version": "0.3.5", "version": "0.3.6",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
"integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.9" "@jridgewell/trace-mapping": "^0.3.25"
} }
}, },
"node_modules/@jridgewell/sourcemap-codec": { "node_modules/@jridgewell/sourcemap-codec": {
@@ -3895,9 +3895,9 @@
} }
}, },
"node_modules/@nextcloud/vue": { "node_modules/@nextcloud/vue": {
"version": "8.16.0", "version": "8.17.1",
"resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-8.16.0.tgz", "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-8.17.1.tgz",
"integrity": "sha512-xkoR2VeWk+WTTmXC01Z7hI0yztSf222XMPXhy9OkDNQBXmCl/idEjNnMWmxezJMyqALtFD/csouW+GS7JUVoFw==", "integrity": "sha512-DC7nI04pp69vS5VxMDhpwPFhb5TWvyJgtmFciAx6j8RFrTPutdjNfOxOCncGaNXOlodaIpg/6EYV8YHU9DR9ng==",
"dependencies": { "dependencies": {
"@floating-ui/dom": "^1.1.0", "@floating-ui/dom": "^1.1.0",
"@linusborg/vue-simple-portal": "^0.1.5", "@linusborg/vue-simple-portal": "^0.1.5",
@@ -3913,8 +3913,8 @@
"@nextcloud/sharing": "^0.2.2", "@nextcloud/sharing": "^0.2.2",
"@nextcloud/timezones": "^0.1.1", "@nextcloud/timezones": "^0.1.1",
"@nextcloud/vue-select": "^3.25.0", "@nextcloud/vue-select": "^3.25.0",
"@vueuse/components": "^10.9.0", "@vueuse/components": "^11.0.0",
"@vueuse/core": "^10.9.0", "@vueuse/core": "^11.0.0",
"clone": "^2.1.2", "clone": "^2.1.2",
"debounce": "2.1.0", "debounce": "2.1.0",
"dompurify": "^3.0.5", "dompurify": "^3.0.5",
@@ -4180,14 +4180,14 @@
} }
}, },
"node_modules/@relative-ci/agent": { "node_modules/@relative-ci/agent": {
"version": "4.2.10", "version": "4.2.11",
"resolved": "https://registry.npmjs.org/@relative-ci/agent/-/agent-4.2.10.tgz", "resolved": "https://registry.npmjs.org/@relative-ci/agent/-/agent-4.2.11.tgz",
"integrity": "sha512-w3aMOrSEyrL6s8i69o6Jjo58WYMz51cI3MuCuoQDKJANew08lXpaQEBI6cyf/gQrVH/ixy9MQhOcESKUqwexEQ==", "integrity": "sha512-EnX0yiSWUkHUnuWzvmysqJJk44EsSmCD7TuXGMgJ9EGxHkAFdEg/+d3+r0UHdThSJ1tDKX6C0h9S4DoOIl8BSQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@bundle-stats/plugin-webpack-filter": "4.14.0", "@bundle-stats/plugin-webpack-filter": "4.15.0",
"@bundle-stats/plugin-webpack-validate": "4.14.0", "@bundle-stats/plugin-webpack-validate": "4.15.0",
"core-js": "3.38.0", "core-js": "3.38.1",
"cosmiconfig": "9.0.0", "cosmiconfig": "9.0.0",
"debug": "4.3.6", "debug": "4.3.6",
"dotenv": "16.4.5", "dotenv": "16.4.5",
@@ -4213,9 +4213,9 @@
} }
}, },
"node_modules/@relative-ci/agent/node_modules/@bundle-stats/plugin-webpack-filter": { "node_modules/@relative-ci/agent/node_modules/@bundle-stats/plugin-webpack-filter": {
"version": "4.14.0", "version": "4.15.0",
"resolved": "https://registry.npmjs.org/@bundle-stats/plugin-webpack-filter/-/plugin-webpack-filter-4.14.0.tgz", "resolved": "https://registry.npmjs.org/@bundle-stats/plugin-webpack-filter/-/plugin-webpack-filter-4.15.0.tgz",
"integrity": "sha512-/p8kMPHyFNcmpgQIOIFkSYObQQUf5F5Gbzsy+dgH+QXSGEppyI1m5Os4BJEBzqS8jUewwzcKVDIQCg2pWoKNAw==", "integrity": "sha512-DQIFkcAkH4VjrDiaoe02c7n5ShGYHIdSMihwDAvRk/4x4PQ1v0/W1kyPxs71glj+6iSddumqNIE28G0DQ4mTQA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 14.0" "node": ">= 14.0"
@@ -4225,9 +4225,9 @@
} }
}, },
"node_modules/@relative-ci/agent/node_modules/core-js": { "node_modules/@relative-ci/agent/node_modules/core-js": {
"version": "3.38.0", "version": "3.38.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.0.tgz", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz",
"integrity": "sha512-XPpwqEodRljce9KswjZShh95qJ1URisBeKCjUdq27YdenkslVe7OO0ZJhlYXAChW7OhXaRLl8AAba7IBfoIHug==", "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"funding": { "funding": {
@@ -4420,21 +4420,10 @@
"@types/json-schema": "*" "@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": { "node_modules/@types/estree": {
"version": "1.0.1", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
}, },
"node_modules/@types/express": { "node_modules/@types/express": {
"version": "4.17.17", "version": "4.17.17",
@@ -5128,19 +5117,19 @@
} }
}, },
"node_modules/@vueuse/components": { "node_modules/@vueuse/components": {
"version": "10.9.0", "version": "11.0.1",
"resolved": "https://registry.npmjs.org/@vueuse/components/-/components-10.9.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-11.0.1.tgz",
"integrity": "sha512-BHQpA0yIi3y7zKa1gYD0FUzLLkcRTqVhP8smnvsCK6GFpd94Nziq1XVPD7YpFeho0k5BzbBiNZF7V/DpkJ967A==", "integrity": "sha512-iZYHc7XcZ2NqpEaSiDXF6qcVcCzAwnA74s+ZV8aHJhdxO61BFpACGuT32Jb5oR+pVc6dfrUUspcCoYzLcFtOOA==",
"dependencies": { "dependencies": {
"@vueuse/core": "10.9.0", "@vueuse/core": "11.0.1",
"@vueuse/shared": "10.9.0", "@vueuse/shared": "11.0.1",
"vue-demi": ">=0.14.7" "vue-demi": ">=0.14.10"
} }
}, },
"node_modules/@vueuse/components/node_modules/vue-demi": { "node_modules/@vueuse/components/node_modules/vue-demi": {
"version": "0.14.7", "version": "0.14.10",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-fix": "bin/vue-demi-fix.js",
@@ -5163,23 +5152,23 @@
} }
}, },
"node_modules/@vueuse/core": { "node_modules/@vueuse/core": {
"version": "10.9.0", "version": "11.0.1",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-11.0.1.tgz",
"integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==", "integrity": "sha512-YTrekI18WwEyP3h168Fir94G/HNC27wvXJI21Alm0sPOwvhihfkrvHIe+5PNJq+MpgWdRcsjvE/38JaoKrgZhQ==",
"dependencies": { "dependencies": {
"@types/web-bluetooth": "^0.0.20", "@types/web-bluetooth": "^0.0.20",
"@vueuse/metadata": "10.9.0", "@vueuse/metadata": "11.0.1",
"@vueuse/shared": "10.9.0", "@vueuse/shared": "11.0.1",
"vue-demi": ">=0.14.7" "vue-demi": ">=0.14.10"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
} }
}, },
"node_modules/@vueuse/core/node_modules/vue-demi": { "node_modules/@vueuse/core/node_modules/vue-demi": {
"version": "0.14.7", "version": "0.14.10",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-fix": "bin/vue-demi-fix.js",
@@ -5202,28 +5191,28 @@
} }
}, },
"node_modules/@vueuse/metadata": { "node_modules/@vueuse/metadata": {
"version": "10.9.0", "version": "11.0.1",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-11.0.1.tgz",
"integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==", "integrity": "sha512-dTFvuHFAjLYOiSd+t9Sk7xUiuL6jbfay/eX+g+jaipXXlwKur2VCqBCZX+jfu+2vROUGcUsdn3fJR9KkpadIOg==",
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
} }
}, },
"node_modules/@vueuse/shared": { "node_modules/@vueuse/shared": {
"version": "10.9.0", "version": "11.0.1",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz", "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-11.0.1.tgz",
"integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==", "integrity": "sha512-eAPf5CQB3HR0S76HqrhjBqFYstZfiHWZq8xF9EQmobGBkrhPfErJEhr8aMNQMqd6MkENIx2pblIEfJGlHpClug==",
"dependencies": { "dependencies": {
"vue-demi": ">=0.14.7" "vue-demi": ">=0.14.10"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
} }
}, },
"node_modules/@vueuse/shared/node_modules/vue-demi": { "node_modules/@vueuse/shared/node_modules/vue-demi": {
"version": "0.14.7", "version": "0.14.10",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
"hasInstallScript": true, "hasInstallScript": true,
"bin": { "bin": {
"vue-demi-fix": "bin/vue-demi-fix.js", "vue-demi-fix": "bin/vue-demi-fix.js",
@@ -5246,9 +5235,9 @@
} }
}, },
"node_modules/@webassemblyjs/ast": { "node_modules/@webassemblyjs/ast": {
"version": "1.11.6", "version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
"integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@@ -5271,9 +5260,9 @@
"peer": true "peer": true
}, },
"node_modules/@webassemblyjs/helper-buffer": { "node_modules/@webassemblyjs/helper-buffer": {
"version": "1.11.6", "version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
"integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==",
"dev": true, "dev": true,
"peer": true "peer": true
}, },
@@ -5297,16 +5286,16 @@
"peer": true "peer": true
}, },
"node_modules/@webassemblyjs/helper-wasm-section": { "node_modules/@webassemblyjs/helper-wasm-section": {
"version": "1.11.6", "version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
"integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@webassemblyjs/ast": "1.11.6", "@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.11.6", "@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/wasm-gen": "1.11.6" "@webassemblyjs/wasm-gen": "1.12.1"
} }
}, },
"node_modules/@webassemblyjs/ieee754": { "node_modules/@webassemblyjs/ieee754": {
@@ -5337,30 +5326,30 @@
"peer": true "peer": true
}, },
"node_modules/@webassemblyjs/wasm-edit": { "node_modules/@webassemblyjs/wasm-edit": {
"version": "1.11.6", "version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
"integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@webassemblyjs/ast": "1.11.6", "@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.11.6", "@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/helper-wasm-section": "1.11.6", "@webassemblyjs/helper-wasm-section": "1.12.1",
"@webassemblyjs/wasm-gen": "1.11.6", "@webassemblyjs/wasm-gen": "1.12.1",
"@webassemblyjs/wasm-opt": "1.11.6", "@webassemblyjs/wasm-opt": "1.12.1",
"@webassemblyjs/wasm-parser": "1.11.6", "@webassemblyjs/wasm-parser": "1.12.1",
"@webassemblyjs/wast-printer": "1.11.6" "@webassemblyjs/wast-printer": "1.12.1"
} }
}, },
"node_modules/@webassemblyjs/wasm-gen": { "node_modules/@webassemblyjs/wasm-gen": {
"version": "1.11.6", "version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
"integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@webassemblyjs/ast": "1.11.6", "@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/ieee754": "1.11.6", "@webassemblyjs/ieee754": "1.11.6",
"@webassemblyjs/leb128": "1.11.6", "@webassemblyjs/leb128": "1.11.6",
@@ -5368,26 +5357,26 @@
} }
}, },
"node_modules/@webassemblyjs/wasm-opt": { "node_modules/@webassemblyjs/wasm-opt": {
"version": "1.11.6", "version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
"integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@webassemblyjs/ast": "1.11.6", "@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.11.6", "@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/wasm-gen": "1.11.6", "@webassemblyjs/wasm-gen": "1.12.1",
"@webassemblyjs/wasm-parser": "1.11.6" "@webassemblyjs/wasm-parser": "1.12.1"
} }
}, },
"node_modules/@webassemblyjs/wasm-parser": { "node_modules/@webassemblyjs/wasm-parser": {
"version": "1.11.6", "version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
"integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@webassemblyjs/ast": "1.11.6", "@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-api-error": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/ieee754": "1.11.6", "@webassemblyjs/ieee754": "1.11.6",
@@ -5396,13 +5385,13 @@
} }
}, },
"node_modules/@webassemblyjs/wast-printer": { "node_modules/@webassemblyjs/wast-printer": {
"version": "1.11.6", "version": "1.12.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
"integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@webassemblyjs/ast": "1.11.6", "@webassemblyjs/ast": "1.12.1",
"@xtuc/long": "4.2.2" "@xtuc/long": "4.2.2"
} }
}, },
@@ -5516,10 +5505,10 @@
"node": ">=0.4.0" "node": ">=0.4.0"
} }
}, },
"node_modules/acorn-import-assertions": { "node_modules/acorn-import-attributes": {
"version": "1.9.0", "version": "1.9.5",
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
"integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"peerDependencies": { "peerDependencies": {
@@ -6899,9 +6888,9 @@
"dev": true "dev": true
}, },
"node_modules/chroma-js": { "node_modules/chroma-js": {
"version": "2.6.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.6.0.tgz", "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-3.0.0.tgz",
"integrity": "sha512-BLHvCB9s8Z1EV4ethr6xnkl/P2YRFOGqfgvuMG/MyCbZPrTA+NeiByY6XvgF0zP4/2deU2CXnWyMa3zu1LqQ3A==" "integrity": "sha512-ZFn4qxtZTvRJ7XatOLgaHGJYN10LoS6T0EMsu7IVayFG5+b6Yw8wCGQL5qLgo4B+wrRZ9niCrozOQ4a584bvaA=="
}, },
"node_modules/chrome-trace-event": { "node_modules/chrome-trace-event": {
"version": "1.0.3", "version": "1.0.3",
@@ -7730,9 +7719,9 @@
"integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA=="
}, },
"node_modules/cypress": { "node_modules/cypress": {
"version": "13.13.3", "version": "13.14.1",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.3.tgz", "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.14.1.tgz",
"integrity": "sha512-hUxPrdbJXhUOTzuML+y9Av7CKoYznbD83pt8g3klgpioEha0emfx4WNIuVRx0C76r0xV2MIwAW9WYiXfVJYFQw==", "integrity": "sha512-Wo+byPmjps66hACEH5udhXINEiN3qS3jWNGRzJOjrRJF3D0+YrcP2LVB1T7oYaVQM/S+eanqEvBWYc8cf7Vcbg==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
@@ -8582,9 +8571,9 @@
} }
}, },
"node_modules/enhanced-resolve": { "node_modules/enhanced-resolve": {
"version": "5.15.0", "version": "5.17.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
"integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@@ -10513,6 +10502,21 @@
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.1", "version": "1.1.1",
"dev": true, "dev": true,
@@ -10810,9 +10814,9 @@
} }
}, },
"node_modules/graceful-fs": { "node_modules/graceful-fs": {
"version": "4.2.9", "version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"dev": true "dev": true
}, },
"node_modules/graphemer": { "node_modules/graphemer": {
@@ -15432,12 +15436,13 @@
] ]
}, },
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "4.0.5", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"braces": "^3.0.2", "braces": "^3.0.3",
"picomatch": "^2.3.1" "picomatch": "^2.3.1"
}, },
"engines": { "engines": {
@@ -17937,9 +17942,9 @@
"peer": true "peer": true
}, },
"node_modules/serialize-javascript": { "node_modules/serialize-javascript": {
"version": "6.0.1", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@@ -19187,9 +19192,9 @@
} }
}, },
"node_modules/terser": { "node_modules/terser": {
"version": "5.19.2", "version": "5.31.6",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz",
"integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==", "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@@ -19206,17 +19211,17 @@
} }
}, },
"node_modules/terser-webpack-plugin": { "node_modules/terser-webpack-plugin": {
"version": "5.3.9", "version": "5.3.10",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
"integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@jridgewell/trace-mapping": "^0.3.17", "@jridgewell/trace-mapping": "^0.3.20",
"jest-worker": "^27.4.5", "jest-worker": "^27.4.5",
"schema-utils": "^3.1.1", "schema-utils": "^3.1.1",
"serialize-javascript": "^6.0.1", "serialize-javascript": "^6.0.1",
"terser": "^5.16.8" "terser": "^5.26.0"
}, },
"engines": { "engines": {
"node": ">= 10.13.0" "node": ">= 10.13.0"
@@ -20508,9 +20513,9 @@
} }
}, },
"node_modules/watchpack": { "node_modules/watchpack": {
"version": "2.4.0", "version": "2.4.2",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@@ -20623,35 +20628,34 @@
} }
}, },
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.88.2", "version": "5.94.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
"integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
"dev": true, "dev": true,
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5",
"@types/estree": "^1.0.0", "@webassemblyjs/ast": "^1.12.1",
"@webassemblyjs/ast": "^1.11.5", "@webassemblyjs/wasm-edit": "^1.12.1",
"@webassemblyjs/wasm-edit": "^1.11.5", "@webassemblyjs/wasm-parser": "^1.12.1",
"@webassemblyjs/wasm-parser": "^1.11.5",
"acorn": "^8.7.1", "acorn": "^8.7.1",
"acorn-import-assertions": "^1.9.0", "acorn-import-attributes": "^1.9.5",
"browserslist": "^4.14.5", "browserslist": "^4.21.10",
"chrome-trace-event": "^1.0.2", "chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.15.0", "enhanced-resolve": "^5.17.1",
"es-module-lexer": "^1.2.1", "es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1", "eslint-scope": "5.1.1",
"events": "^3.2.0", "events": "^3.2.0",
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.9", "graceful-fs": "^4.2.11",
"json-parse-even-better-errors": "^2.3.1", "json-parse-even-better-errors": "^2.3.1",
"loader-runner": "^4.2.0", "loader-runner": "^4.2.0",
"mime-types": "^2.1.27", "mime-types": "^2.1.27",
"neo-async": "^2.6.2", "neo-async": "^2.6.2",
"schema-utils": "^3.2.0", "schema-utils": "^3.2.0",
"tapable": "^2.1.1", "tapable": "^2.1.1",
"terser-webpack-plugin": "^5.3.7", "terser-webpack-plugin": "^5.3.10",
"watchpack": "^2.4.0", "watchpack": "^2.4.1",
"webpack-sources": "^3.2.3" "webpack-sources": "^3.2.3"
}, },
"bin": { "bin": {

View File

@@ -31,7 +31,7 @@
}, },
"dependencies": { "dependencies": {
"@babel/polyfill": "^7.12.1", "@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.25.0", "@babel/runtime": "^7.25.6",
"@nextcloud/auth": "^2.4.0", "@nextcloud/auth": "^2.4.0",
"@nextcloud/axios": "^2.5.0", "@nextcloud/axios": "^2.5.0",
"@nextcloud/capabilities": "^1.2.0", "@nextcloud/capabilities": "^1.2.0",
@@ -43,9 +43,9 @@
"@nextcloud/moment": "^1.3.1", "@nextcloud/moment": "^1.3.1",
"@nextcloud/notify_push": "^1.3.0", "@nextcloud/notify_push": "^1.3.0",
"@nextcloud/router": "^3.0.1", "@nextcloud/router": "^3.0.1",
"@nextcloud/vue": "^8.16.0", "@nextcloud/vue": "^8.17.1",
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"chroma-js": "^2.6.0", "chroma-js": "^3.0.0",
"dompurify": "^3.1.6", "dompurify": "^3.1.6",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
@@ -80,10 +80,10 @@
"@nextcloud/eslint-config": "^8.4.1", "@nextcloud/eslint-config": "^8.4.1",
"@nextcloud/stylelint-config": "^3.0.1", "@nextcloud/stylelint-config": "^3.0.1",
"@nextcloud/webpack-vue-config": "^6.0.0", "@nextcloud/webpack-vue-config": "^6.0.0",
"@relative-ci/agent": "^4.2.10", "@relative-ci/agent": "^4.2.11",
"@vue/test-utils": "^2.4.6", "@vue/test-utils": "^2.4.6",
"@vue/vue2-jest": "^29.2.6", "@vue/vue2-jest": "^29.2.6",
"cypress": "^13.13.3", "cypress": "^13.14.1",
"eslint-plugin-cypress": "^3.5.0", "eslint-plugin-cypress": "^3.5.0",
"eslint-webpack-plugin": "^4.2.0", "eslint-webpack-plugin": "^4.2.0",
"jest": "^29.7.0", "jest": "^29.7.0",

View File

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

View File

@@ -92,7 +92,6 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.modal__content { .modal__content {
width: 25vw;
min-width: 250px; min-width: 250px;
min-height: 120px; min-height: 120px;
margin: 20px 20px 100px 20px; margin: 20px 20px 100px 20px;

View File

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

View File

@@ -31,7 +31,8 @@
<div class="board-actions"> <div class="board-actions">
<SessionList v-if="isNotifyPushEnabled && presentUsers.length" <SessionList v-if="isNotifyPushEnabled && presentUsers.length"
:sessions="presentUsers" /> :sessions="presentUsers" />
<div v-if="searchQuery || true" class="deck-search"> <!-- Hide but not remove for now as search might change in the future -->
<div v-if="false" class="deck-search">
<input id="deck-search-input" <input id="deck-search-input"
ref="search" ref="search"
:tabindex="0" :tabindex="0"
@@ -46,8 +47,11 @@
id="stack-add" id="stack-add"
v-click-outside="hideAddStack"> v-click-outside="hideAddStack">
<NcActions v-if="!isAddStackVisible"> <NcActions v-if="!isAddStackVisible">
<NcActionButton icon="icon-add" @click.stop="showAddStack"> <NcActionButton @click.stop="showAddStack">
{{ t('deck', 'Add list') }} {{ t('deck', 'Add list') }}
<template #icon>
<TableColumnPlusAfter :size="20" />
</template>
</NcActionButton> </NcActionButton>
</NcActions> </NcActions>
<form v-else @submit.prevent="addNewStack()"> <form v-else @submit.prevent="addNewStack()">
@@ -263,6 +267,7 @@ import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import ImageIcon from 'vue-material-design-icons/ImageMultiple.vue' import ImageIcon from 'vue-material-design-icons/ImageMultiple.vue'
import FilterIcon from 'vue-material-design-icons/Filter.vue' import FilterIcon from 'vue-material-design-icons/Filter.vue'
import FilterOffIcon from 'vue-material-design-icons/FilterOff.vue' import FilterOffIcon from 'vue-material-design-icons/FilterOff.vue'
import TableColumnPlusAfter from 'vue-material-design-icons/TableColumnPlusAfter.vue'
import ArrowCollapseVerticalIcon from 'vue-material-design-icons/ArrowCollapseVertical.vue' import ArrowCollapseVerticalIcon from 'vue-material-design-icons/ArrowCollapseVertical.vue'
import ArrowExpandVerticalIcon from 'vue-material-design-icons/ArrowExpandVertical.vue' import ArrowExpandVerticalIcon from 'vue-material-design-icons/ArrowExpandVertical.vue'
import SessionList from './SessionList.vue' import SessionList from './SessionList.vue'
@@ -286,6 +291,7 @@ export default {
FilterOffIcon, FilterOffIcon,
ArrowCollapseVerticalIcon, ArrowCollapseVerticalIcon,
ArrowExpandVerticalIcon, ArrowExpandVerticalIcon,
TableColumnPlusAfter,
SessionList, SessionList,
}, },
mixins: [labelStyle], mixins: [labelStyle],
@@ -475,7 +481,7 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.controls { .controls {
display: flex; display: flex;
margin: 5px; margin: calc(var(--default-grid-baseline) * 2);
height: var(--default-clickable-area); height: var(--default-clickable-area);
padding-left: var(--default-clickable-area); padding-left: var(--default-clickable-area);
@@ -486,17 +492,17 @@ export default {
h2 { h2 {
margin: 0; margin: 0;
margin-right: 10px; margin-right: 10px;
font-size: 18px;
} }
.board-bullet { .board-bullet {
display: inline-block; display: inline-block;
width: 20px; width: 16px;
height: 20px; height: 16px;
border: none; border: none;
border-radius: 50%; border-radius: 50%;
background-color: transparent; background-color: transparent;
margin: 12px; margin: var(--default-grid-baseline);
margin-left: -4px;
} }
} }
@@ -538,7 +544,7 @@ export default {
.filter--item { .filter--item {
input + label { input + label {
display: block; display: block;
padding: 6px 0; padding: var(--default-grid-baseline) 0;
.avatardiv { .avatardiv {
vertical-align: middle; vertical-align: middle;
margin-bottom: 2px; margin-bottom: 2px;

View File

@@ -4,7 +4,7 @@
--> -->
<template> <template>
<div :title="t('text', 'Currently present people')" <div :title="t('deck', 'Currently present people')"
class="avatar-list"> class="avatar-list">
<div v-for="session in sessionsVisible" <div v-for="session in sessionsVisible"
:key="session.uid" :key="session.uid"

View File

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

View File

@@ -57,8 +57,11 @@
</NcActionButton> </NcActionButton>
</NcActions> </NcActions>
<NcActions v-if="canEdit && !showArchived && !isArchived"> <NcActions v-if="canEdit && !showArchived && !isArchived">
<NcActionButton icon="icon-add" data-cy="action:add-card" @click.stop="showAddCard=true"> <NcActionButton data-cy="action:add-card" @click.stop="showAddCard=true">
{{ t('deck', 'Add card') }} {{ t('deck', 'Add card') }}
<template #icon>
<CardPlusOutline :size="20" />
</template>
</NcActionButton> </NcActionButton>
</NcActions> </NcActions>
</div> </div>
@@ -85,15 +88,33 @@
</div> </div>
</NcModal> </NcModal>
<transition name="slide-top" appear> <Container :get-child-payload="payloadForCard(stack.id)"
<div v-if="showAddCard" class="stack__card-add"> 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">
<form :class="{ 'icon-loading-small': stateCardCreating }" <form :class="{ 'icon-loading-small': stateCardCreating }"
@submit.prevent.stop="clickAddCard()"> @submit.prevent.stop="clickAddCard()">
<label for="new-stack-input-main" class="hidden-visually">{{ t('deck', 'Add a new card') }}</label> <label for="new-stack-input-main" class="hidden-visually">{{ t('deck', 'Add a new card') }}</label>
<input id="new-stack-input-main" <input id="new-stack-input-main"
ref="newCardInput" ref="newCardInput"
v-model="newCardTitle" v-model="newCardTitle"
v-focus
type="text" type="text"
class="no-close" class="no-close"
:disabled="stateCardCreating" :disabled="stateCardCreating"
@@ -109,25 +130,6 @@
</form> </form>
</div> </div>
</transition> </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> </div>
</template> </template>
@@ -136,6 +138,7 @@ import ClickOutside from 'vue-click-outside'
import { mapGetters, mapState } from 'vuex' import { mapGetters, mapState } from 'vuex'
import { Container, Draggable } from 'vue-smooth-dnd' import { Container, Draggable } from 'vue-smooth-dnd'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue' import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import CardPlusOutline from 'vue-material-design-icons/CardPlusOutline.vue'
import { NcActions, NcActionButton, NcModal } from '@nextcloud/vue' import { NcActions, NcActionButton, NcModal } from '@nextcloud/vue'
import { showError, showUndo } from '@nextcloud/dialogs' import { showError, showUndo } from '@nextcloud/dialogs'
@@ -153,6 +156,7 @@ export default {
Draggable, Draggable,
NcModal, NcModal,
ArchiveIcon, ArchiveIcon,
CardPlusOutline,
}, },
directives: { directives: {
ClickOutside, ClickOutside,
@@ -216,10 +220,18 @@ export default {
showAddCard(newValue) { showAddCard(newValue) {
if (!newValue) { if (!newValue) {
this.$store.dispatch('toggleShortcutLock', false) this.$store.dispatch('toggleShortcutLock', false)
} else {
this.$nextTick(() => {
this.$refs.newCardInput.focus()
})
} }
}, },
}, },
mounted() {
this.setupAutoscrollOnDrag()
},
methods: { methods: {
stopCardCreation(e) { stopCardCreation(e) {
// For some reason the submit event triggers a MouseEvent that is bubbling to the outside // For some reason the submit event triggers a MouseEvent that is bubbling to the outside
@@ -298,6 +310,7 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.newCardInput.focus() this.$refs.newCardInput.focus()
this.animate = false this.animate = false
this.$refs.card[(this.$refs.card.length - 1)].scrollIntoView()
}) })
if (!this.cardDetailsInModal) { if (!this.cardDetailsInModal) {
this.$router.push({ name: 'card', params: { cardId: newCard.id } }) this.$router.push({ name: 'card', params: { cardId: newCard.id } })
@@ -311,6 +324,36 @@ export default {
onCreateCardFocus() { onCreateCardFocus() {
this.$store.dispatch('toggleShortcutLock', true) 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> </script>
@@ -332,8 +375,10 @@ export default {
z-index: 100; z-index: 100;
padding-left: $card-spacing; padding-left: $card-spacing;
padding-right: $card-spacing; padding-right: $card-spacing;
margin: 6px;
margin-top: 0;
cursor: grab; cursor: grab;
min-height: var(--default-clickable-area); background-color: var(--color-main-background);
// Smooth fade out of the cards at the top // Smooth fade out of the cards at the top
&:before { &:before {
@@ -353,14 +398,6 @@ export default {
} }
} }
&--add:before {
height: 80px;
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; position: relative;
z-index: 100; z-index: 100;
@@ -383,9 +420,8 @@ export default {
text-overflow: ellipsis; text-overflow: ellipsis;
max-width: calc($stack-width - 60px); max-width: calc($stack-width - 60px);
border-radius: 3px; border-radius: 3px;
margin: 6px;
padding: 4px 4px; padding: 4px 4px;
font-size: 120%; font-size: var(--default-font-size);
&:focus-visible { &:focus-visible {
outline: 2px solid var(--color-border-dark); outline: 2px solid var(--color-border-dark);
@@ -394,7 +430,15 @@ export default {
} }
form { form {
margin: 2px 0; margin: -4px;
input {
font-weight: bold;
padding: 0 6px;
}
input[type="submit"] {
border-style: solid;
border-left-style: none;
}
} }
:deep { :deep {
@@ -406,20 +450,19 @@ export default {
} }
.stack__card-add { .stack__card-add {
height: var(--default-clickable-area);
flex-shrink: 0; flex-shrink: 0;
z-index: 100; z-index: 100;
display: flex; display: flex;
margin-top: 5px; margin-bottom: 5px;
margin-bottom: 8px; padding-top: var(--default-grid-baseline);
background-color: var(--color-main-background); background-color: var(--color-main-background);
form { form {
display: flex; display: flex;
margin-left: 12px; margin-left: $stack-spacing;
margin-right: 12px; margin-right: $stack-spacing;
width: 100%; width: 100%;
border: 2px solid var(--color-border); border: 2px solid var(--color-border-maxcontrast);
border-radius: var(--border-radius-large); border-radius: var(--border-radius-large);
overflow: hidden; overflow: hidden;
padding: 2px; padding: 2px;
@@ -436,6 +479,8 @@ export default {
input { input {
border: none; border: none;
margin: 0;
padding: 4px;
} }
} }
@@ -451,7 +496,16 @@ export default {
.slide-top-enter, .slide-top-leave-to { .slide-top-enter, .slide-top-leave-to {
transform: translateY(-10px); transform: translateY(-10px);
opacity: 0; opacity: 0;
height: 0px; }
.slide-bottom-enter-active,
.slide-bottom-leave-active {
transition: all 100ms ease;
}
.slide-bottom-enter, .slide-bottom-leave-to {
transform: translateY(20px);
opacity: 0;
} }
.modal__content { .modal__content {

View File

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

View File

@@ -162,7 +162,9 @@ export default {
}, },
methods: { methods: {
focusHeader() { focusHeader() {
this.$refs.cardSidebar.$el.querySelector('.app-sidebar-header__mainname').focus() this.$nextTick(() => {
this.$refs?.cardSidebar.$el.querySelector('.app-sidebar-header__mainname')?.focus()
})
}, },
handleUpdateTitleEditable(value) { handleUpdateTitleEditable(value) {
this.titleEditable = value this.titleEditable = value
@@ -209,6 +211,10 @@ section.app-sidebar__tab--active {
height: 100%; height: 100%;
} }
.modal-container {
overflow: hidden;
}
// FIXME: Obivously we should at some point not randomly reuse the sidebar component // FIXME: Obivously we should at some point not randomly reuse the sidebar component
// since this is not oficially supported // since this is not oficially supported
.modal__card .app-sidebar { .modal__card .app-sidebar {
@@ -220,12 +226,26 @@ section.app-sidebar__tab--active {
left: 0; left: 0;
right: 0; right: 0;
max-width: calc(100% - #{$modal-padding * 2}); max-width: calc(100% - #{$modal-padding * 2});
min-height: calc(100vh - var(--header-height) * 4);
padding: 0 14px; padding: 0 14px;
height: 97%; height: 97%;
overflow: initial; overflow: hidden !important;
user-select: text; user-select: text;
-webkit-user-select: text; -webkit-user-select: text;
.app-sidebar-header__mainname-container {
padding-top: calc(var(--default-grid-baseline, 4px) * 2);
}
.app-sidebar-tabs {
max-height: 90%;
}
.app-sidebar__tab {
min-height: calc(100% - 20px);
max-height: calc(100% - 20px);
}
// FIXME: test // FIXME: test
&:deep { &:deep {
.app-sidebar-header { .app-sidebar-header {

View File

@@ -247,7 +247,6 @@ export default defineComponent({
.done-info--duedate, .done-info--duedate,
.done-info--done { .done-info--done {
display: flex; display: flex;
padding-top: 10px;
&.dimmed { &.dimmed {
color: var(--color-text-maxcontrast); color: var(--color-text-maxcontrast);
} }

View File

@@ -168,13 +168,13 @@ export default {
} }
.badge-left { .badge-left {
align-self: end;
margin-bottom: 8px;
flex-basis: auto; flex-basis: auto;
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-shrink: 1;
flex-wrap: wrap; flex-wrap: wrap;
align-content: flex-end; align-content: flex-end;
align-items: center;
align-self: center;
gap: 3px; gap: 3px;
} }
@@ -196,6 +196,10 @@ export default {
opacity: 0; opacity: 0;
} }
.avatars:deep(button) {
margin: 0;
}
@media print { @media print {
.badges { .badges {
align-items: flex-start; align-items: flex-start;

View File

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

View File

@@ -6,7 +6,7 @@
<template> <template>
<AttachmentDragAndDrop v-if="card" :card-id="card.id" class="drop-upload--card"> <AttachmentDragAndDrop v-if="card" :card-id="card.id" class="drop-upload--card">
<div :ref="`card${card.id}`" <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 }" :class="{'compact': compactMode, 'current-card': currentCard, 'has-labels': card.labels && card.labels.length > 0, 'card__editable': canEdit, 'card__archived': card.archived, 'card__highlight': highlight}"
tag="div" tag="div"
:tabindex="0" :tabindex="0"
class="card" class="card"
@@ -19,10 +19,10 @@
</div> </div>
<CardCover v-if="showCardCover" :card-id="card.id" /> <CardCover v-if="showCardCover" :card-id="card.id" />
<div class="card-upper"> <div class="card-upper">
<h3 v-if="inlineEditingBlocked" dir="auto"> <h4 v-if="inlineEditingBlocked" dir="auto">
{{ card.title }} {{ card.title }}
</h3> </h4>
<h3 v-else <h4 v-else
dir="auto" dir="auto"
class="editable" class="editable"
:aria-label="t('deck', 'Edit card title')"> :aria-label="t('deck', 'Edit card title')">
@@ -35,7 +35,7 @@
@click.stop @click.stop
@keyup.esc="cancelEdit" @keyup.esc="cancelEdit"
@keyup.stop>{{ card.title }}</span> @keyup.stop>{{ card.title }}</span>
</h3> </h4>
<DueDate v-if="compactMode" :card="card" /> <DueDate v-if="compactMode" :card="card" />
<CardMenu v-if="showMenuAtTitle" :card="card" class="right card-menu" /> <CardMenu v-if="showMenuAtTitle" :card="card" class="right card-menu" />
@@ -103,6 +103,11 @@ export default {
default: false, default: false,
}, },
}, },
data() {
return {
highlight: false,
}
},
computed: { computed: {
...mapState({ ...mapState({
compactMode: state => state.compactMode, compactMode: state => state.compactMode,
@@ -270,6 +275,14 @@ export default {
}, },
}) })
}, },
scrollIntoView() {
this.$el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' })
this.focus()
this.highlight = true
setTimeout(() => {
this.highlight = false
}, 2000)
},
}, },
} }
</script> </script>
@@ -290,11 +303,10 @@ export default {
background-color: var(--color-main-background); background-color: var(--color-main-background);
margin-bottom: $card-spacing; margin-bottom: $card-spacing;
padding: var(--default-grid-baseline) $card-padding; padding: var(--default-grid-baseline) $card-padding;
border: 2px solid var(--color-border); border: 2px solid var(--color-border-dark);
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6px;
&:deep(*) { &:deep(*) {
cursor: pointer; cursor: pointer;
@@ -314,9 +326,10 @@ export default {
.card-upper { .card-upper {
display: flex; display: flex;
h3 { h4 {
font-weight: normal;
margin: 0; margin: 0;
padding: 6px; padding: var(--default-grid-baseline);
flex-grow: 1; flex-grow: 1;
font-size: 100%; font-size: 100%;
overflow: hidden; overflow: hidden;
@@ -359,10 +372,28 @@ export default {
&.card__archived { &.card__archived {
background-color: var(--color-background-dark); 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 { .card-labels {
display: flex; display: flex;
align-items: end; align-items: end;
margin-bottom: var(--default-grid-baseline); padding-left: var(--default-grid-baseline);
padding-top: var(--default-grid-baseline);
.labels { .labels {
flex-wrap: wrap; flex-wrap: wrap;
@@ -402,7 +433,6 @@ export default {
display: flex; display: flex;
height: 32px; height: 32px;
width: 32px; width: 32px;
margin-top: 6px;
} }
&.has-labels { &.has-labels {
padding-bottom: $card-padding; padding-bottom: $card-padding;

View File

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

View File

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

View File

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

View File

@@ -9,9 +9,13 @@
margin-top: 10px; margin-top: 10px;
&--icon { &--icon {
width: 38px; width: var(--default-clickable-area);
padding-top: 12px; height: var(--default-clickable-area);
flex-shrink: 0; flex-shrink: 0;
display: flex;
align-items: center;
align-content: center;
justify-content: center;
} }
&--selector { &--selector {
@@ -21,5 +25,6 @@
&--content { &--content {
display: flex; display: flex;
flex-grow: 1; flex-grow: 1;
align-items: center;
} }
} }

View File

@@ -2,8 +2,8 @@
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */
$card-spacing: 16px; $card-spacing: 8px;
$card-padding: 8px; $card-padding: 4px;
$stack-spacing: 12px; $stack-spacing: 12px;
$stack-width: 280px; $stack-width: 280px;
$board-spacing: 16px; $board-spacing: 16px;

View File

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

View File

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

View File

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

View File

@@ -32,7 +32,7 @@ class SessionContext implements Context {
'boardId' => $board['id'], 'boardId' => $board['id'],
]); ]);
$res = json_decode((string)$this->getResponse()->getBody(), true); $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 // store token
$user = $this->serverContext->getCurrentUser(); $user = $this->serverContext->getCurrentUser();
@@ -44,7 +44,7 @@ class SessionContext implements Context {
*/ */
public function theResponseShouldHaveActiveSessions($length) { public function theResponseShouldHaveActiveSessions($length) {
$board = $this->boardContext->getLastUsedBoard(); $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) { public function theUserShouldBeInTheListOfActiveSessions($user) {
$board = $this->boardContext->getLastUsedBoard(); $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(); $user = $this->serverContext->getCurrentUser();
$token = $this->tokens[$user]; $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', [ $this->requestContext->sendOCSRequest('POST', '/apps/deck/api/v1.0/session/close', [
'boardId' => $board['id'], 'boardId' => $board['id'],
'token' => $token 'token' => $token

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -69,8 +69,8 @@ class ExceptionMiddlewareTest extends \Test\TestCase {
public function testAfterException($exception, $status, $message) { public function testAfterException($exception, $status, $message) {
$result = $this->exceptionMiddleware->afterException($this->controller, 'bar', $exception); $result = $this->exceptionMiddleware->afterException($this->controller, 'bar', $exception);
$expected = new JSONResponse([ $expected = new JSONResponse([
"status" => $status, 'status' => $status,
"message" => $message 'message' => $message
], $status); ], $status);
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
} }

View File

@@ -68,6 +68,8 @@ class CardServiceTest extends TestCase {
private $boardService; private $boardService;
/** @var LabelMapper|MockObject */ /** @var LabelMapper|MockObject */
private $labelMapper; private $labelMapper;
/** @var LabelService|MockObject */
private $labelService;
private $boardMapper; private $boardMapper;
/** @var AttachmentService|MockObject */ /** @var AttachmentService|MockObject */
private $attachmentService; private $attachmentService;
@@ -96,6 +98,7 @@ class CardServiceTest extends TestCase {
$this->stackMapper = $this->createMock(StackMapper::class); $this->stackMapper = $this->createMock(StackMapper::class);
$this->boardMapper = $this->createMock(BoardMapper::class); $this->boardMapper = $this->createMock(BoardMapper::class);
$this->labelMapper = $this->createMock(LabelMapper::class); $this->labelMapper = $this->createMock(LabelMapper::class);
$this->labelService = $this->createMock(LabelService::class);
$this->permissionService = $this->createMock(PermissionService::class); $this->permissionService = $this->createMock(PermissionService::class);
$this->boardService = $this->createMock(BoardService::class); $this->boardService = $this->createMock(BoardService::class);
$this->notificationHelper = $this->createMock(NotificationHelper::class); $this->notificationHelper = $this->createMock(NotificationHelper::class);
@@ -118,6 +121,7 @@ class CardServiceTest extends TestCase {
$this->stackMapper, $this->stackMapper,
$this->boardMapper, $this->boardMapper,
$this->labelMapper, $this->labelMapper,
$this->labelService,
$this->permissionService, $this->permissionService,
$this->boardService, $this->boardService,
$this->notificationHelper, $this->notificationHelper,

View File

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