Compare commits
274 Commits
dependabot
...
automated/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c547411d06 | ||
|
|
4c1243363a | ||
|
|
16ccc79bb4 | ||
|
|
df4fd1de2f | ||
|
|
8e03f8cc64 | ||
|
|
f1e5038756 | ||
|
|
ba6902e470 | ||
|
|
5674887b61 | ||
|
|
3bc0ddcca2 | ||
|
|
48e904c37b | ||
|
|
44a5eadb73 | ||
|
|
7b7221b3e1 | ||
|
|
b19872e56c | ||
|
|
cb1819cf10 | ||
|
|
7d6d41a5d1 | ||
|
|
aa6c488845 | ||
|
|
a14aa1b5d4 | ||
|
|
e2e14d88be | ||
|
|
2546ff981d | ||
|
|
a2e5e9fe5b | ||
|
|
985eaa0133 | ||
|
|
db48deb4f8 | ||
|
|
173ec28c6d | ||
|
|
9d18b08325 | ||
|
|
7775ddd9f7 | ||
|
|
d5fb6cb4b0 | ||
|
|
a5245b41ac | ||
|
|
e34f4f081c | ||
|
|
0292b0307e | ||
|
|
913a2fac8f | ||
|
|
aac7f0c943 | ||
|
|
5f0a55b5cd | ||
|
|
95958e5465 | ||
|
|
19bb3aba97 | ||
|
|
1345b9cfee | ||
|
|
646cf7f0c6 | ||
|
|
6d29ef0607 | ||
|
|
c27bc874eb | ||
|
|
bdb8f1845b | ||
|
|
75f6af1e6b | ||
|
|
81bd239dec | ||
|
|
4d4fbd8fc9 | ||
|
|
d46b554576 | ||
|
|
3dc52816eb | ||
|
|
2799bc3bb8 | ||
|
|
f275dcc5be | ||
|
|
19ef846692 | ||
|
|
75542efab4 | ||
|
|
b41a7eac8b | ||
|
|
9e07995011 | ||
|
|
348e10bb6c | ||
|
|
ff5db11e9c | ||
|
|
b30e742114 | ||
|
|
aefdcb70e9 | ||
|
|
dbc350cd4b | ||
|
|
7e2fb648b0 | ||
|
|
2773208eb5 | ||
|
|
d1559ac674 | ||
|
|
eafd6eeff0 | ||
|
|
b0a77ac025 | ||
|
|
9744ae04d6 | ||
|
|
d0e177bb41 | ||
|
|
7478e5c1d6 | ||
|
|
0bce7f0ea9 | ||
|
|
8bed62debc | ||
|
|
1b9ddf9ebc | ||
|
|
1770e8ee7e | ||
|
|
fe0c4361f3 | ||
|
|
6a3553404b | ||
|
|
5b494738fd | ||
|
|
79db1d3275 | ||
|
|
d91c53669f | ||
|
|
cbb67b30b6 | ||
|
|
39f00e0e68 | ||
|
|
a0e9494ff1 | ||
|
|
8658c7dfca | ||
|
|
427fe4e87d | ||
|
|
e38e7bb027 | ||
|
|
6993fc906f | ||
|
|
6685341d9c | ||
|
|
05733dad96 | ||
|
|
dbdfe16e9f | ||
|
|
bf40a4b23b | ||
|
|
42d52c519d | ||
|
|
1c3c7c730a | ||
|
|
ccb6fb3187 | ||
|
|
ef3db3eec0 | ||
|
|
59e003df21 | ||
|
|
5847735557 | ||
|
|
e2cc6918cb | ||
|
|
61a5b4b331 | ||
|
|
9bd00803d8 | ||
|
|
59a2dff228 | ||
|
|
c0f4c94d30 | ||
|
|
d414de4012 | ||
|
|
8dc9240681 | ||
|
|
8a27a799cb | ||
|
|
eb994fea12 | ||
|
|
4e1f65b10d | ||
|
|
97aa84f03d | ||
|
|
04511acef2 | ||
|
|
9be47f6d5d | ||
|
|
46f723cc98 | ||
|
|
a242d5551a | ||
|
|
0cdd972722 | ||
|
|
84c1d828da | ||
|
|
5df6b1caf4 | ||
|
|
74342d7581 | ||
|
|
4beba4f7d3 | ||
|
|
73d57e3ee1 | ||
|
|
530774c9e6 | ||
|
|
149d273c35 | ||
|
|
d3fa2b018f | ||
|
|
1e132bb1fa | ||
|
|
730a6c89ea | ||
|
|
78819da98d | ||
|
|
b8898e7f96 | ||
|
|
f32df15d90 | ||
|
|
e147939157 | ||
|
|
26b98d726f | ||
|
|
50d029e50e | ||
|
|
31634ab57e | ||
|
|
2bff37c3b4 | ||
|
|
482555ac6d | ||
|
|
3d3b8d72bf | ||
|
|
367a20e7af | ||
|
|
376bd46de7 | ||
|
|
fe30fa95aa | ||
|
|
1b40ad9797 | ||
|
|
5bb3a21b80 | ||
|
|
c55b980d96 | ||
|
|
c93b4a09cb | ||
|
|
0bc8a0f3ba | ||
|
|
6368d965ec | ||
|
|
591a894b7e | ||
|
|
c5e5715a0c | ||
|
|
80828f7674 | ||
|
|
1acdf9e716 | ||
|
|
0fd7dd9d68 | ||
|
|
e670ede7b4 | ||
|
|
d0eb16c242 | ||
|
|
50c43aed6d | ||
|
|
d2ad7bdc29 | ||
|
|
8e7e9d85ac | ||
|
|
53f5fbdadd | ||
|
|
fbccabceaf | ||
|
|
d33305b77c | ||
|
|
dba232041d | ||
|
|
2b17403129 | ||
|
|
5cfc3a7a3a | ||
|
|
60f250d69a | ||
|
|
bb60f7f57b | ||
|
|
1219d52b02 | ||
|
|
5c769aa82d | ||
|
|
7c615f2607 | ||
|
|
64d3a69f28 | ||
|
|
26494eee86 | ||
|
|
336b6f3348 | ||
|
|
380184af50 | ||
|
|
16aa9c954b | ||
|
|
01842c7f92 | ||
|
|
1c38638ee8 | ||
|
|
dd534fbea1 | ||
|
|
b7cb1f7d05 | ||
|
|
c9d45f4a96 | ||
|
|
dfc61453c4 | ||
|
|
4dd48d18c7 | ||
|
|
ee51cb8e3c | ||
|
|
4aaaca52c6 | ||
|
|
ee67476581 | ||
|
|
1f82d386e0 | ||
|
|
d7d6009070 | ||
|
|
263f9c8bbe | ||
|
|
92b641c52d | ||
|
|
26da5a17a6 | ||
|
|
e6a3e1a7bf | ||
|
|
339c13447a | ||
|
|
3e674381ca | ||
|
|
5479bc16af | ||
|
|
96fdacc46d | ||
|
|
a1a5aa9bd2 | ||
|
|
e7a4eec911 | ||
|
|
0191d54369 | ||
|
|
3e69070e8c | ||
|
|
240ea42a51 | ||
|
|
15e019fd03 | ||
|
|
ca9bf74434 | ||
|
|
c3362a8584 | ||
|
|
6764873d66 | ||
|
|
a692b8c512 | ||
|
|
0d23cc0951 | ||
|
|
b7f5648e63 | ||
|
|
ec292df849 | ||
|
|
63e39bcc51 | ||
|
|
878f9caf87 | ||
|
|
1156688517 | ||
|
|
8d2e018b9c | ||
|
|
b66d6c5b46 | ||
|
|
8dbfd37fe0 | ||
|
|
04e16e003d | ||
|
|
91b9b8804e | ||
|
|
0a415b97df | ||
|
|
9e36a9ebe2 | ||
|
|
c70d089ca7 | ||
|
|
53acec7372 | ||
|
|
5ca18b1d32 | ||
|
|
3a454b75e0 | ||
|
|
79ab6a16af | ||
|
|
62dd2e29cd | ||
|
|
00a63e59ae | ||
|
|
4b6540880c | ||
|
|
a735d85c25 | ||
|
|
b93bb93895 | ||
|
|
77d4126aa9 | ||
|
|
647b9dece2 | ||
|
|
a931433475 | ||
|
|
726e62527a | ||
|
|
24bb353a74 | ||
|
|
fba3b030ac | ||
|
|
a868425dd3 | ||
|
|
3033cb4d8c | ||
|
|
c4ea019eee | ||
|
|
6a19934ace | ||
|
|
2fd7586902 | ||
|
|
77b0602833 | ||
|
|
715b8fc6aa | ||
|
|
f1d3631d22 | ||
|
|
3e05e88a6b | ||
|
|
238f5674ab | ||
|
|
0ddefff9c1 | ||
|
|
91aaf3d6b0 | ||
|
|
48b25da3ea | ||
|
|
4059042a9c | ||
|
|
e6b29b7cb1 | ||
|
|
d934867381 | ||
|
|
f130baff43 | ||
|
|
6f8baba8c5 | ||
|
|
3badc5c90c | ||
|
|
c6b04b9abf | ||
|
|
3ec8ff3d1f | ||
|
|
a721fe27a6 | ||
|
|
1d848e0fc4 | ||
|
|
9e8c1e982f | ||
|
|
11276ea5e1 | ||
|
|
f0840641ba | ||
|
|
f53de9a269 | ||
|
|
9b5bdc3d02 | ||
|
|
e9e5234925 | ||
|
|
81c8aad66f | ||
|
|
7cc43c706b | ||
|
|
19b0d60b21 | ||
|
|
b1b38e05eb | ||
|
|
687414a7a2 | ||
|
|
35a6c4d783 | ||
|
|
c863c78623 | ||
|
|
affcbf7287 | ||
|
|
aab45b764d | ||
|
|
3288e0e002 | ||
|
|
cca9cc08f0 | ||
|
|
508dddc7cd | ||
|
|
fd75f66624 | ||
|
|
7635cde5cd | ||
|
|
5b48075bc2 | ||
|
|
fb0096b113 | ||
|
|
d9ce467c98 | ||
|
|
ccd10248f7 | ||
|
|
2473117892 | ||
|
|
e729bdcd04 | ||
|
|
58de28909f | ||
|
|
eda6bca538 | ||
|
|
aa90c0b2d4 | ||
|
|
5a08e57de8 | ||
|
|
75067a0695 | ||
|
|
00d63692c8 |
76
.github/dependabot.yml
vendored
76
.github/dependabot.yml
vendored
@@ -13,40 +13,6 @@ updates:
|
||||
- juliushaertl
|
||||
- luka-nextcloud
|
||||
|
||||
- package-ecosystem: npm
|
||||
target-branch: stable32
|
||||
versioning-strategy: lockfile-only
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:15"
|
||||
timezone: Europe/Paris
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
open-pull-requests-limit: 30
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
|
||||
- package-ecosystem: npm
|
||||
target-branch: stable31
|
||||
versioning-strategy: lockfile-only
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:15"
|
||||
timezone: Europe/Paris
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
open-pull-requests-limit: 30
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
|
||||
- package-ecosystem: npm
|
||||
target-branch: stable30
|
||||
versioning-strategy: lockfile-only
|
||||
@@ -54,7 +20,41 @@ updates:
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:30"
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
open-pull-requests-limit: 30
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
|
||||
- package-ecosystem: npm
|
||||
target-branch: stable29
|
||||
versioning-strategy: lockfile-only
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
open-pull-requests-limit: 30
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
|
||||
- package-ecosystem: npm
|
||||
target-branch: stable28
|
||||
versioning-strategy: lockfile-only
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
@@ -69,7 +69,7 @@ updates:
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:45"
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
@@ -81,7 +81,7 @@ updates:
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "04:00"
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
@@ -93,7 +93,7 @@ updates:
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "04:15"
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
|
||||
4
.github/workflows/appbuild.yml
vendored
4
.github/workflows/appbuild.yml
vendored
@@ -18,13 +18,13 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v4.1.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Set up npm7
|
||||
run: npm i -g npm@7
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@2.34.1
|
||||
uses: shivammathur/setup-php@2.31.1
|
||||
with:
|
||||
php-version: '7.4'
|
||||
tools: composer
|
||||
|
||||
6
.github/workflows/appstore-build-publish.yml
vendored
6
.github/workflows/appstore-build-publish.yml
vendored
@@ -71,7 +71,7 @@ jobs:
|
||||
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||
# Skip if no package.json
|
||||
if: ${{ steps.versions.outputs.nodeVersion }}
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
filename: ${{ env.APP_NAME }}/appinfo/info.xml
|
||||
|
||||
- name: Set up php ${{ steps.php-versions.outputs.php-min }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
|
||||
with:
|
||||
php-version: ${{ steps.php-versions.outputs.php-min }}
|
||||
coverage: none
|
||||
@@ -173,7 +173,7 @@ jobs:
|
||||
tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }}
|
||||
|
||||
- name: Attach tarball to github release
|
||||
uses: svenstaro/upload-release-action@81c65b7cd4de9b2570615ce3aad67a41de5b1a13 # v2
|
||||
uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # v2
|
||||
id: attach_to_release
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
6
.github/workflows/cypress-e2e.yml
vendored
6
.github/workflows/cypress-e2e.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
node-version: [20.x]
|
||||
# containers: [1, 2, 3]
|
||||
php-versions: [ '8.2' ]
|
||||
server-versions: [ 'master' ]
|
||||
server-versions: [ 'stable31' ]
|
||||
|
||||
env:
|
||||
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, zip, gd, apcu
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v4.1.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
@@ -91,7 +91,7 @@ jobs:
|
||||
restore-keys: ${{ steps.extcache.outputs.key }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@2.34.1
|
||||
uses: shivammathur/setup-php@2.31.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: ${{ env.extensions }}
|
||||
|
||||
2
.github/workflows/integration.yml
vendored
2
.github/workflows/integration.yml
vendored
@@ -78,7 +78,7 @@ jobs:
|
||||
path: apps/activity
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@2.34.1
|
||||
uses: shivammathur/setup-php@2.31.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, mysql, pdo_mysql, pgsql, pdo_pgsql, apcu, gd
|
||||
|
||||
2
.github/workflows/lint-eslint.yml
vendored
2
.github/workflows/lint-eslint.yml
vendored
@@ -68,7 +68,7 @@ jobs:
|
||||
fallbackNpm: '^10'
|
||||
|
||||
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||
|
||||
|
||||
4
.github/workflows/lint-php-cs.yml
vendored
4
.github/workflows/lint-php-cs.yml
vendored
@@ -33,8 +33,8 @@ jobs:
|
||||
id: versions
|
||||
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
|
||||
|
||||
- name: Set up php${{ steps.versions.outputs.php-min }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
- name: Set up php${{ steps.versions.outputs.php-available }}
|
||||
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
|
||||
with:
|
||||
php-version: ${{ steps.versions.outputs.php-min }}
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
|
||||
2
.github/workflows/lint-php.yml
vendored
2
.github/workflows/lint-php.yml
vendored
@@ -48,7 +48,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
|
||||
2
.github/workflows/lint-stylelint.yml
vendored
2
.github/workflows/lint-stylelint.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
fallbackNpm: '^10'
|
||||
|
||||
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||
|
||||
|
||||
2
.github/workflows/nodejs.yml
vendored
2
.github/workflows/nodejs.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.4.0
|
||||
uses: actions/setup-node@v4.1.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Set up npm7
|
||||
|
||||
18
.github/workflows/npm-audit-fix.yml
vendored
18
.github/workflows/npm-audit-fix.yml
vendored
@@ -14,9 +14,6 @@ on:
|
||||
# At 2:30 on Sundays
|
||||
- cron: '30 2 * * 0'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -24,18 +21,15 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
branches: ['main', 'master', 'stable32', 'stable31', 'stable30']
|
||||
branches: ['main', 'master', 'stable30', 'stable29', 'stable28']
|
||||
|
||||
name: npm-audit-fix-${{ matrix.branches }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ matrix.branches }}
|
||||
continue-on-error: true
|
||||
|
||||
- name: Read package.json node and npm engines version
|
||||
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
|
||||
@@ -45,7 +39,7 @@ jobs:
|
||||
fallbackNpm: '^10'
|
||||
|
||||
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.1.0
|
||||
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||
with:
|
||||
node-version: ${{ steps.versions.outputs.nodeVersion }}
|
||||
|
||||
@@ -54,10 +48,10 @@ jobs:
|
||||
|
||||
- name: Fix npm audit
|
||||
id: npm-audit
|
||||
uses: nextcloud-libraries/npm-audit-action@1b1728b2b4a7a78d69de65608efcf4db0e3e42d0 # v0.2.0
|
||||
uses: nextcloud-libraries/npm-audit-action@2a60bd2e79cc77f2cc4d9a3fe40f1a69896f3a87 # v0.1.0
|
||||
|
||||
- name: Run npm ci and npm run build
|
||||
if: steps.checkout.outcome == 'success'
|
||||
if: always()
|
||||
env:
|
||||
CYPRESS_INSTALL_BINARY: 0
|
||||
run: |
|
||||
@@ -65,8 +59,8 @@ jobs:
|
||||
npm run build --if-present
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.checkout.outcome == 'success'
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||
if: always()
|
||||
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
commit-message: 'fix(deps): Fix npm audit'
|
||||
|
||||
2
.github/workflows/phpunit-mysql.yml
vendored
2
.github/workflows/phpunit-mysql.yml
vendored
@@ -103,7 +103,7 @@ jobs:
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
|
||||
|
||||
2
.github/workflows/phpunit-pgsql.yml
vendored
2
.github/workflows/phpunit-pgsql.yml
vendored
@@ -106,7 +106,7 @@ jobs:
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
|
||||
|
||||
2
.github/workflows/phpunit-sqlite.yml
vendored
2
.github/workflows/phpunit-sqlite.yml
vendored
@@ -95,7 +95,7 @@ jobs:
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
|
||||
|
||||
5
.github/workflows/pr-feedback.yml
vendored
5
.github/workflows/pr-feedback.yml
vendored
@@ -15,13 +15,8 @@ on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
pr-feedback:
|
||||
if: ${{ github.repository_owner == 'nextcloud' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: The get-github-handles-from-website action
|
||||
|
||||
4
.github/workflows/psalm.yml
vendored
4
.github/workflows/psalm.yml
vendored
@@ -35,8 +35,8 @@ jobs:
|
||||
- name: Check enforcement of minimum PHP version ${{ steps.versions.outputs.php-min }} in psalm.xml
|
||||
run: grep 'phpVersion="${{ steps.versions.outputs.php-min }}' psalm.xml
|
||||
|
||||
- name: Set up php${{ steps.versions.outputs.php-min }}
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
- name: Set up php${{ steps.versions.outputs.php-available }}
|
||||
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
|
||||
with:
|
||||
php-version: ${{ steps.versions.outputs.php-min }}
|
||||
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
|
||||
|
||||
2
.github/workflows/reuse.yml
vendored
2
.github/workflows/reuse.yml
vendored
@@ -16,7 +16,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
reuse-compliance-check:
|
||||
runs-on: ubuntu-latest-low
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
6
.github/workflows/update-nextcloud-ocp.yml
vendored
6
.github/workflows/update-nextcloud-ocp.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
branches: ['main', 'master', 'stable32', 'stable31', 'stable30']
|
||||
branches: ['main', 'master', 'stable30', 'stable29', 'stable28']
|
||||
|
||||
name: update-nextcloud-ocp-${{ matrix.branches }}
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
- name: Set up php8.2
|
||||
if: steps.checkout.outcome == 'success'
|
||||
uses: shivammathur/setup-php@0f7f1d08e3e32076e51cae65eb0b0c871405b16e # v2.34.1
|
||||
uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2.31.1
|
||||
with:
|
||||
php-version: 8.2
|
||||
# https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
|
||||
@@ -107,7 +107,7 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.checkout.outcome == 'success'
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
commit-message: 'chore(dev-deps): Bump nextcloud/ocp package'
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
- Adrian Missy <adrian.missy@onewavestudios.com>
|
||||
- Alexandru Puiu <alexpuiu20@yahoo.com>
|
||||
- Arne Bartelt <arne.bartelt@gmail.com>
|
||||
- Chandi Langecker <git@chandi.it>
|
||||
- Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||
- Gary Kim <gary@garykim.dev>
|
||||
|
||||
62
CHANGELOG.md
62
CHANGELOG.md
@@ -5,16 +5,64 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 1.16.0-beta.1
|
||||
# 1.15.3
|
||||
### Fixed
|
||||
* [stable31] fix: Use getId() method for card ID retrieval by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7144
|
||||
* [stable31]fix: ensure correct type when filtering events by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7148
|
||||
* [stable31] fix: do not change focus when card id stays the same by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7173
|
||||
* [stable31] fix(darkmode): Fix activity icon colors by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7240
|
||||
* [stable31] fix: make comments with mention editable @backportbot[bot] in https://github.com/nextcloud/deck/pull/7198
|
||||
* [stable31] fix: redirect to cleaner URL if RewriteBase is enabled by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7267
|
||||
* [stable31] fix: missing push notifications by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7269
|
||||
* [stable31] fix: use text cursor for card title on dashboard by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7274
|
||||
* [stable31] fix: parse arguments to CardService.reorder correctly to int by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7275
|
||||
|
||||
### Improvements
|
||||
* [stable31] Clean attachment sharing records after permanent deleted by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7180
|
||||
* Chore(deps): Bump @nextcloud/vue from 8.22.0 to 8.31.0 by @luka-nextcloud in https://github.com/nextcloud/deck/pull/7272
|
||||
|
||||
# 1.15.2
|
||||
### Fixed
|
||||
* [stable31] fix: update DeleteCron to remove deleted lists by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7029
|
||||
* [stable31] fix: not show Share with a Deck card for unauthorized users by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7061
|
||||
* [stable31] fix: unstable cypress test by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7063
|
||||
* [stable31] fix: add retry and show warning on description saving error by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7091
|
||||
* [stable31] fix: styling for new stack input field by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7113
|
||||
* [stable31] fix:allow foreign label deletion by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7130
|
||||
* [stable31] fix: acl check when delete, update board acl by @backportbot[bot] in https://github.com/nextcloud/deck/pull/7132
|
||||
|
||||
### Improvements
|
||||
* [stable31] perf: don't enrich cards when finding calendar entries by @backportbot[bot] in https://github.com/nextcloud/deck/pull/6959
|
||||
|
||||
## 1.15.1
|
||||
### Fixed
|
||||
* [stable31] fix: Properly show attachment extension by @backportbot in https://github.com/nextcloud/deck/pull/6701
|
||||
* [stable31] Clear selected stack when selected board changed by @backportbot in https://github.com/nextcloud/deck/pull/6915
|
||||
* [stable31] fix: Use strings as rich object ids by @backportbot in https://github.com/nextcloud/deck/pull/6951
|
||||
* [stable31] fix: Limit label actions to labels of the cards board by @backportbot in https://github.com/nextcloud/deck/pull/6954
|
||||
* [stable31] fix: only delete assignments on unshared board by @grnd-alt in https://github.com/nextcloud/deck/pull/6934
|
||||
|
||||
### Improvements
|
||||
* [stable31] perf: Skip doing a query just to check if a board is deleted by @backportbot in https://github.com/nextcloud/deck/pull/6894
|
||||
|
||||
## 1.15.0
|
||||
### Fixed
|
||||
- Fix: Adapt URLs generated in the backend to new routes #6743
|
||||
- Fix npm audit #6719
|
||||
- Fix: skip exporting a deleted card #6723
|
||||
|
||||
## 1.15.0-beta.2
|
||||
|
||||
### Added
|
||||
- feat: update default content @luka-nextcloud [#6740](https://github.com/nextcloud/deck/pull/6740)
|
||||
- feat: add board import and export @luka-nextcloud [#6872](https://github.com/nextcloud/deck/pull/6872)
|
||||
- feat: use outline icons @luka-nextcloud [#7114](https://github.com/nextcloud/deck/pull/7114)
|
||||
- Add OCC commands for global calendar feature opt-in and opt-out in Deck @Fledermaus-20 [#7080](https://github.com/nextcloud/deck/pull/7080)
|
||||
|
||||
### Fixed
|
||||
- CSV export fixes @gidan80 [#6800](https://github.com/nextcloud/deck/pull/6800)
|
||||
- feat: Implement reference resolving for cards that have a link in the title @juliusknorr [#6286](https://github.com/nextcloud/deck/pull/6286)
|
||||
|
||||
### Other
|
||||
|
||||
- Remove old project from README @edent [#6658](https://github.com/nextcloud/deck/pull/6658)
|
||||
- devcontainer(image): Fix package path @niclasheinz [#6653](https://github.com/nextcloud/deck/pull/6653)
|
||||
- remove deprecated nextcloud-vue-collections @grnd-alt [#6664](https://github.com/nextcloud/deck/pull/6664)
|
||||
- fix: set cypress ci server version to stable31 @grnd-alt [#6705](https://github.com/nextcloud/deck/pull/6705)
|
||||
|
||||
## 1.15.0-beta.1
|
||||
### Fixed
|
||||
|
||||
@@ -12,7 +12,7 @@ SPDX-FileCopyrightText = "none"
|
||||
SPDX-License-Identifier = "CC0-1.0"
|
||||
|
||||
[[annotations]]
|
||||
path = ["l10n/**.js", "l10n/**.json", "js/**.js.map", "js/**.js", "js/**.mjs", "js/**.mjs.map", "js/templates/**.handlebars", "lib/Service/Importer/fixtures/config-deckJson-schema.json", "lib/Service/Importer/fixtures/config-trelloApi-schema.json", "lib/Service/Importer/fixtures/config-trelloJson-schema.json", "lib/Service/fixtures/default-board.json", "screenshots/screenshot1.png", "src/assets/file-placeholder.svg", "img/favicon.ico", "img/favicon.png", "img/favicon.svg", "img/activity.svg", "img/activity-dark.svg", "img/deck.svg", "img/deck-current.svg", "img/deck-dark.svg", "img/details-white.svg", "img/card.svg", "img/sample-image.jpg"]
|
||||
path = ["l10n/**.js", "l10n/**.json", "js/**.js.map", "js/**.js", "js/**.mjs", "js/**.mjs.map", "js/templates/**.handlebars", "lib/Service/Importer/fixtures/config-deckJson-schema.json", "lib/Service/Importer/fixtures/config-trelloApi-schema.json", "lib/Service/Importer/fixtures/config-trelloJson-schema.json", "screenshots/screenshot1.png", "src/assets/file-placeholder.svg", "img/favicon.ico", "img/favicon.png", "img/favicon.svg", "img/activity.svg", "img/activity-dark.svg", "img/deck.svg", "img/deck-current.svg", "img/deck-dark.svg", "img/details-white.svg", "img/card.svg"]
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "2019 Nextcloud GmbH and Nextcloud contributors"
|
||||
SPDX-License-Identifier = "AGPL-3.0-or-later"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
- 🚀 Get your project organized
|
||||
|
||||
</description>
|
||||
<version>2.0.0-dev.0</version>
|
||||
<version>1.15.3</version>
|
||||
<licence>agpl</licence>
|
||||
<author>Julius Härtl</author>
|
||||
<namespace>Deck</namespace>
|
||||
@@ -42,7 +42,7 @@
|
||||
<database min-version="9.4">pgsql</database>
|
||||
<database>sqlite</database>
|
||||
<database min-version="8.0">mysql</database>
|
||||
<nextcloud min-version="33" max-version="33"/>
|
||||
<nextcloud min-version="31" max-version="31"/>
|
||||
</dependencies>
|
||||
<background-jobs>
|
||||
<job>OCA\Deck\Cron\DeleteCron</job>
|
||||
@@ -54,15 +54,11 @@
|
||||
<live-migration>
|
||||
<step>OCA\Deck\Migration\DeletedCircleCleanup</step>
|
||||
</live-migration>
|
||||
<post-migration>
|
||||
<step>OCA\Deck\Migration\LabelMismatchCleanup</step>
|
||||
</post-migration>
|
||||
</repair-steps>
|
||||
<commands>
|
||||
<command>OCA\Deck\Command\UserExport</command>
|
||||
<command>OCA\Deck\Command\BoardImport</command>
|
||||
<command>OCA\Deck\Command\TransferOwnership</command>
|
||||
<command>OCA\Deck\Command\CalendarToggle</command>
|
||||
</commands>
|
||||
<activity>
|
||||
<settings>
|
||||
|
||||
@@ -29,7 +29,6 @@ return [
|
||||
['name' => 'board#clone', 'url' => '/boards/{boardId}/clone', 'verb' => 'POST'],
|
||||
['name' => 'board#transferOwner', 'url' => '/boards/{boardId}/transferOwner', 'verb' => 'PUT'],
|
||||
['name' => 'board#export', 'url' => '/boards/{boardId}/export', 'verb' => 'GET'],
|
||||
['name' => 'board#import', 'url' => '/boards/import', 'verb' => 'POST'],
|
||||
|
||||
// stacks
|
||||
['name' => 'stack#index', 'url' => '/stacks/{boardId}', 'verb' => 'GET'],
|
||||
|
||||
@@ -9,35 +9,31 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"justinrainbow/json-schema": "^6.0",
|
||||
"bamarni/composer-bin-plugin": "^1.8"
|
||||
"justinrainbow/json-schema": "^6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"roave/security-advisories": "dev-master",
|
||||
"phpunit/phpunit": "^9",
|
||||
"nextcloud/coding-standard": "^1.1",
|
||||
"nextcloud/ocp": "dev-master"
|
||||
"nextcloud/ocp": "dev-stable31",
|
||||
"psalm/phar": "^5.13"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"bamarni/composer-bin-plugin": true
|
||||
"composer/package-versions-deprecated": true
|
||||
},
|
||||
"platform": {
|
||||
"php": "8.1"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": [
|
||||
"@composer bin all install --ansi"
|
||||
],
|
||||
"lint": "find . -name \\*.php -not -path './vendor/*' -print0 | xargs -0 -n1 php -l",
|
||||
"cs:check": "php-cs-fixer fix --dry-run --diff",
|
||||
"cs:fix": "php-cs-fixer fix",
|
||||
"psalm": "psalm",
|
||||
"psalm:update-baseline": "psalm --threads=$(nproc) --no-cache --update-baseline",
|
||||
"psalm:fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType",
|
||||
"psalm": "psalm.phar",
|
||||
"psalm:update-baseline": "psalm.phar --update-baseline",
|
||||
"psalm:fix": "psalm.phar --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType",
|
||||
"test": [
|
||||
"@test:unit",
|
||||
"@test:integration"
|
||||
|
||||
203
composer.lock
generated
203
composer.lock
generated
@@ -4,91 +4,146 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "263f9ff9e6a13d50ab09bc9f4e06b749",
|
||||
"content-hash": "c89537a172cee5c19093b4ea0cb5365c",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bamarni/composer-bin-plugin",
|
||||
"version": "1.8.2",
|
||||
"name": "icecave/parity",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bamarni/composer-bin-plugin.git",
|
||||
"reference": "92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880"
|
||||
"url": "https://github.com/icecave/parity.git",
|
||||
"reference": "0109fef58b3230d23b20b2ac52ecdf477218d300"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880",
|
||||
"reference": "92fd7b1e6e9cdae19b0d57369d8ad31a37b6a880",
|
||||
"url": "https://api.github.com/repos/icecave/parity/zipball/0109fef58b3230d23b20b2ac52ecdf477218d300",
|
||||
"reference": "0109fef58b3230d23b20b2ac52ecdf477218d300",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-plugin-api": "^2.0",
|
||||
"php": "^7.2.5 || ^8.0"
|
||||
"icecave/repr": "~1",
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"composer/composer": "^2.0",
|
||||
"ext-json": "*",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^1.8",
|
||||
"phpstan/phpstan-phpunit": "^1.1",
|
||||
"phpunit/phpunit": "^8.5 || ^9.5",
|
||||
"symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
|
||||
"symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0",
|
||||
"symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0"
|
||||
"eloquent/liberator": "~1",
|
||||
"icecave/archer": "~1"
|
||||
},
|
||||
"type": "composer-plugin",
|
||||
"extra": {
|
||||
"class": "Bamarni\\Composer\\Bin\\BamarniBinPlugin"
|
||||
"suggest": {
|
||||
"eloquent/asplode": "Drop-in exception-based error handling."
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Bamarni\\Composer\\Bin\\": "src"
|
||||
"psr-0": {
|
||||
"Icecave\\Parity": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "No conflicts for your bin dependencies",
|
||||
"authors": [
|
||||
{
|
||||
"name": "James Harris",
|
||||
"email": "james.harris@icecave.com.au",
|
||||
"homepage": "https://github.com/jmalloc"
|
||||
}
|
||||
],
|
||||
"description": "A customizable deep comparison library.",
|
||||
"homepage": "https://github.com/IcecaveStudios/parity",
|
||||
"keywords": [
|
||||
"composer",
|
||||
"conflict",
|
||||
"dependency",
|
||||
"executable",
|
||||
"isolation",
|
||||
"tool"
|
||||
"compare",
|
||||
"comparison",
|
||||
"equal",
|
||||
"equality",
|
||||
"greater",
|
||||
"less",
|
||||
"sort",
|
||||
"sorting"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/bamarni/composer-bin-plugin/issues",
|
||||
"source": "https://github.com/bamarni/composer-bin-plugin/tree/1.8.2"
|
||||
"issues": "https://github.com/icecave/parity/issues",
|
||||
"source": "https://github.com/icecave/parity/tree/1.0.0"
|
||||
},
|
||||
"time": "2022-10-31T08:38:03+00:00"
|
||||
"time": "2014-01-17T05:56:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "justinrainbow/json-schema",
|
||||
"version": "6.4.2",
|
||||
"name": "icecave/repr",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jsonrainbow/json-schema.git",
|
||||
"reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02"
|
||||
"url": "https://github.com/icecave/repr.git",
|
||||
"reference": "8a3d2953adf5f464a06e3e2587aeacc97e2bed07"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/ce1fd2d47799bb60668643bc6220f6278a4c1d02",
|
||||
"reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02",
|
||||
"url": "https://api.github.com/repos/icecave/repr/zipball/8a3d2953adf5f464a06e3e2587aeacc97e2bed07",
|
||||
"reference": "8a3d2953adf5f464a06e3e2587aeacc97e2bed07",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"marc-mabe/php-enum": "^4.0",
|
||||
"php": "^7.2 || ^8.0"
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "3.3.0",
|
||||
"icecave/archer": "~1"
|
||||
},
|
||||
"suggest": {
|
||||
"eloquent/asplode": "Drop-in exception-based error handling."
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Icecave\\Repr\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "James Harris",
|
||||
"email": "james.harris@icecave.com.au",
|
||||
"homepage": "https://github.com/jmalloc"
|
||||
}
|
||||
],
|
||||
"description": "A library for generating string representations of any value, inspired by Python's reprlib library.",
|
||||
"homepage": "https://github.com/IcecaveStudios/repr",
|
||||
"keywords": [
|
||||
"human",
|
||||
"readable",
|
||||
"repr",
|
||||
"representation",
|
||||
"string"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/icecave/repr/issues",
|
||||
"source": "https://github.com/icecave/repr/tree/1.0.1"
|
||||
},
|
||||
"time": "2014-07-25T05:44:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "justinrainbow/json-schema",
|
||||
"version": "6.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jsonrainbow/json-schema.git",
|
||||
"reference": "a38c6198d53b09c0702f440585a4f4a5d9137bd9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/a38c6198d53b09c0702f440585a4f4a5d9137bd9",
|
||||
"reference": "a38c6198d53b09c0702f440585a4f4a5d9137bd9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"icecave/parity": "1.0.0",
|
||||
"marc-mabe/php-enum": "^2.0 || ^3.0 || ^4.0",
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "~2.2.20 || ~2.19.0",
|
||||
"json-schema/json-schema-test-suite": "1.2.0",
|
||||
"marc-mabe/php-enum-phpstan": "^2.0",
|
||||
"phpspec/prophecy": "^1.19",
|
||||
"phpstan/phpstan": "^1.12",
|
||||
"phpunit/phpunit": "^8.5"
|
||||
"phpunit/phpunit": "^4.8.35"
|
||||
},
|
||||
"bin": [
|
||||
"bin/validate-json"
|
||||
@@ -134,9 +189,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/jsonrainbow/json-schema/issues",
|
||||
"source": "https://github.com/jsonrainbow/json-schema/tree/6.4.2"
|
||||
"source": "https://github.com/jsonrainbow/json-schema/tree/6.0.0"
|
||||
},
|
||||
"time": "2025-06-03T18:27:04+00:00"
|
||||
"time": "2024-07-30T17:49:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "marc-mabe/php-enum",
|
||||
@@ -433,16 +488,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nextcloud/ocp",
|
||||
"version": "dev-master",
|
||||
"version": "dev-stable31",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nextcloud-deps/ocp.git",
|
||||
"reference": "9a2e6c0bf6f2d87e1db8d18063a5bedf85040bb2"
|
||||
"reference": "4a55dcdbff0ae2062a8e3cdb905fc4d6076240b9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/9a2e6c0bf6f2d87e1db8d18063a5bedf85040bb2",
|
||||
"reference": "9a2e6c0bf6f2d87e1db8d18063a5bedf85040bb2",
|
||||
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/4a55dcdbff0ae2062a8e3cdb905fc4d6076240b9",
|
||||
"reference": "4a55dcdbff0ae2062a8e3cdb905fc4d6076240b9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -452,11 +507,10 @@
|
||||
"psr/event-dispatcher": "^1.0",
|
||||
"psr/log": "^3.0.2"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "33.0.0-dev"
|
||||
"dev-stable31": "31.0.0-dev"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
@@ -476,9 +530,9 @@
|
||||
"description": "Composer package containing Nextcloud's public OCP API and the unstable NCU API",
|
||||
"support": {
|
||||
"issues": "https://github.com/nextcloud-deps/ocp/issues",
|
||||
"source": "https://github.com/nextcloud-deps/ocp/tree/master"
|
||||
"source": "https://github.com/nextcloud-deps/ocp/tree/stable31"
|
||||
},
|
||||
"time": "2025-09-27T00:45:05+00:00"
|
||||
"time": "2025-10-03T00:46:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
@@ -1130,6 +1184,41 @@
|
||||
],
|
||||
"time": "2024-12-05T13:48:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psalm/phar",
|
||||
"version": "5.26.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/psalm/phar.git",
|
||||
"reference": "8a38e7ad04499a0ccd2c506fd1da6fc01fff4547"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/psalm/phar/zipball/8a38e7ad04499a0ccd2c506fd1da6fc01fff4547",
|
||||
"reference": "8a38e7ad04499a0ccd2c506fd1da6fc01fff4547",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"vimeo/psalm": "*"
|
||||
},
|
||||
"bin": [
|
||||
"psalm.phar"
|
||||
],
|
||||
"type": "library",
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Composer-based Psalm Phar",
|
||||
"support": {
|
||||
"issues": "https://github.com/psalm/phar/issues",
|
||||
"source": "https://github.com/psalm/phar/tree/5.26.1"
|
||||
},
|
||||
"time": "2024-09-09T16:22:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/clock",
|
||||
"version": "1.0.0",
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
input[type=submit].icon-confirm {
|
||||
border-color: var(--color-border-maxcontrast) !important;
|
||||
border-style: solid;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,81 +129,3 @@ describe('Board cloning', function() {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Board export', function() {
|
||||
before(function() {
|
||||
cy.createUser(user)
|
||||
})
|
||||
|
||||
it('Exports a board as JSON', function() {
|
||||
const boardName = 'Export JSON board'
|
||||
const board = sampleBoard(boardName)
|
||||
cy.createExampleBoard({ user, board }).then((board) => {
|
||||
const boardId = board.id
|
||||
cy.visit(`/apps/deck/board/${boardId}`)
|
||||
cy.get('.app-navigation__list .app-navigation-entry:contains("' + boardName + '")')
|
||||
.parent()
|
||||
.find('button[aria-label="Actions"]')
|
||||
.click()
|
||||
cy.get('button:contains("Export board")')
|
||||
.click()
|
||||
cy.get('.modal-container .checkbox-radio-switch__text:contains("Export as JSON")')
|
||||
.click()
|
||||
cy.get('.modal-container button:contains("Export")')
|
||||
.click()
|
||||
|
||||
const downloadsFolder = Cypress.config('downloadsFolder')
|
||||
cy.readFile(`${downloadsFolder}/${boardName}.json`)
|
||||
})
|
||||
})
|
||||
|
||||
it('Exports a board as CSV', function() {
|
||||
const boardName = 'Export CSV board'
|
||||
const board = sampleBoard(boardName)
|
||||
cy.createExampleBoard({ user, board }).then((board) => {
|
||||
const boardId = board.id
|
||||
cy.visit(`/apps/deck/board/${boardId}`)
|
||||
cy.get('.app-navigation__list .app-navigation-entry:contains("' + boardName + '")')
|
||||
.parent()
|
||||
.find('button[aria-label="Actions"]')
|
||||
.click()
|
||||
cy.get('button:contains("Export board")')
|
||||
.click()
|
||||
cy.get('.modal-container .checkbox-radio-switch__text:contains("Export as CSV")')
|
||||
.click()
|
||||
cy.get('.modal-container button:contains("Export")')
|
||||
.click()
|
||||
|
||||
const downloadsFolder = Cypress.config('downloadsFolder')
|
||||
cy.readFile(`${downloadsFolder}/${boardName}.csv`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('Board import', function() {
|
||||
before(function () {
|
||||
cy.createUser(user)
|
||||
})
|
||||
beforeEach(function() {
|
||||
cy.login(user)
|
||||
cy.visit('/apps/deck')
|
||||
})
|
||||
|
||||
it('Imports a board from JSON', function() {
|
||||
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry:contains("Import board")')
|
||||
.should('be.visible')
|
||||
.click()
|
||||
|
||||
// Upload a JSON file
|
||||
cy.get('input[type="file"]')
|
||||
.selectFile([
|
||||
{
|
||||
contents: 'cypress/fixtures/import-board.json',
|
||||
fileName: 'import-board.json',
|
||||
},
|
||||
], { force: true })
|
||||
|
||||
cy.get('.app-navigation__list .app-navigation-entry:contains("Imported board")')
|
||||
.should('be.visible')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -302,9 +302,6 @@ describe('Card', function () {
|
||||
.first().click()
|
||||
cy.get(`.card:contains("${newCardTitle}")`).should('be.visible').click()
|
||||
|
||||
// Add delay to ensure the events are bound
|
||||
cy.wait(1000)
|
||||
|
||||
cy.get('#app-sidebar-vue [data-test="tag-selector"] .vs__dropdown-toggle').should('be.visible').click()
|
||||
cy.get('.vs__dropdown-menu .tag:contains("Action needed")').should('be.visible').click()
|
||||
cy.get('.vs__dropdown-menu .tag:contains("Later")').should('be.visible').click()
|
||||
|
||||
@@ -22,10 +22,10 @@ describe('Deck dashboard', function() {
|
||||
.should($el => expect($el.text().trim()).to.equal('Upcoming cards'))
|
||||
})
|
||||
|
||||
it('Can see the default "Welcome Board" created for user by default', function() {
|
||||
it('Can see the default "Personal Board" created for user by default', function() {
|
||||
cy.visit('/apps/deck')
|
||||
|
||||
const defaultBoard = 'Welcome to Nextcloud Deck!'
|
||||
const defaultBoard = 'Personal'
|
||||
|
||||
cy.get('.app-navigation-entry-wrapper[icon=icon-deck]')
|
||||
.find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + defaultBoard + ')')
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
{
|
||||
"boards": [
|
||||
{
|
||||
"id": 70,
|
||||
"title": "Imported board",
|
||||
"owner": "unvjrmwuag",
|
||||
"color": "00ff00",
|
||||
"archived": false,
|
||||
"labels": [
|
||||
{
|
||||
"id": 293,
|
||||
"title": "Finished",
|
||||
"color": "31CC7C",
|
||||
"boardId": 70,
|
||||
"cardId": null,
|
||||
"lastModified": 0,
|
||||
"ETag": "cfcd208495d565ef66e7dff9f98764da"
|
||||
},
|
||||
{
|
||||
"id": 294,
|
||||
"title": "To review",
|
||||
"color": "317CCC",
|
||||
"boardId": 70,
|
||||
"cardId": null,
|
||||
"lastModified": 0,
|
||||
"ETag": "cfcd208495d565ef66e7dff9f98764da"
|
||||
},
|
||||
{
|
||||
"id": 295,
|
||||
"title": "Action needed",
|
||||
"color": "FF7A66",
|
||||
"boardId": 70,
|
||||
"cardId": null,
|
||||
"lastModified": 0,
|
||||
"ETag": "cfcd208495d565ef66e7dff9f98764da"
|
||||
},
|
||||
{
|
||||
"id": 296,
|
||||
"title": "Later",
|
||||
"color": "F1DB50",
|
||||
"boardId": 70,
|
||||
"cardId": null,
|
||||
"lastModified": 0,
|
||||
"ETag": "cfcd208495d565ef66e7dff9f98764da"
|
||||
}
|
||||
],
|
||||
"acl": [],
|
||||
"permissions": [],
|
||||
"users": [],
|
||||
"stacks": {
|
||||
"114": {
|
||||
"id": 114,
|
||||
"title": "TestList",
|
||||
"boardId": 70,
|
||||
"deletedAt": 0,
|
||||
"lastModified": 1743495533,
|
||||
"cards": [
|
||||
{
|
||||
"id": 124,
|
||||
"title": "Hello world",
|
||||
"description": "# Hello world",
|
||||
"descriptionPrev": null,
|
||||
"stackId": 114,
|
||||
"type": "plain",
|
||||
"lastModified": 1743495533,
|
||||
"lastEditor": null,
|
||||
"createdAt": 1743495533,
|
||||
"labels": [],
|
||||
"assignedUsers": null,
|
||||
"attachments": null,
|
||||
"attachmentCount": null,
|
||||
"owner": {
|
||||
"primaryKey": "unvjrmwuag",
|
||||
"uid": "unvjrmwuag",
|
||||
"displayname": "unvjrmwuag",
|
||||
"type": 0
|
||||
},
|
||||
"order": 999,
|
||||
"archived": false,
|
||||
"done": null,
|
||||
"duedate": null,
|
||||
"notified": false,
|
||||
"deletedAt": 0,
|
||||
"commentsUnread": 0,
|
||||
"commentsCount": 0,
|
||||
"relatedStack": null,
|
||||
"relatedBoard": null,
|
||||
"ETag": "aa85bb973089e7fbc0bbf122e926c23f"
|
||||
}
|
||||
],
|
||||
"order": 0,
|
||||
"ETag": "aa85bb973089e7fbc0bbf122e926c23f"
|
||||
}
|
||||
},
|
||||
"activeSessions": [],
|
||||
"deletedAt": 0,
|
||||
"lastModified": 1743495533,
|
||||
"settings": [],
|
||||
"ETag": "aa85bb973089e7fbc0bbf122e926c23f"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -102,11 +102,7 @@ Cypress.Commands.add('shareBoardWithUi', (query, userId=query) => {
|
||||
cy.intercept({ method: 'GET', url: `**/ocs/v2.php/apps/files_sharing/api/v1/sharees?search=${query}*` }).as('fetchRecipients')
|
||||
cy.get('[aria-label="Open details"]').click()
|
||||
cy.get('.app-sidebar').should('be.visible')
|
||||
|
||||
// Add delay to ensure the events are bound
|
||||
cy.wait(1000)
|
||||
|
||||
cy.get('.select input').click().type(`${query}`)
|
||||
cy.get('.select input').type(`${query}`)
|
||||
cy.wait('@fetchRecipients', { timeout: 7000 })
|
||||
|
||||
cy.get('.vs__dropdown-menu .option').first().contains(query)
|
||||
|
||||
24
docs/API.md
24
docs/API.md
@@ -6,7 +6,7 @@ The REST API provides access for authenticated users to their data inside the De
|
||||
|
||||
# Prerequisites
|
||||
|
||||
- All requests require a `OCS-APIRequest` HTTP header to be set to `true` and a `Content-Type` of `application/json`. This does not apply to the endpoint for uploading attachments, which consumes `multipart/form-data`.
|
||||
- All requests require a `OCS-APIRequest` HTTP header to be set to `true` and a `Content-Type` of `application/json`.
|
||||
- The API is located at https://nextcloud.local/index.php/apps/deck/api/v1.0
|
||||
- All request parameters are required, unless otherwise specified
|
||||
|
||||
@@ -733,7 +733,6 @@ The board list endpoint supports setting an `If-Modified-Since` header to limit
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ------- | --------------------------------------- |
|
||||
| labelId | Integer | The label id to assign to the card |
|
||||
|
||||
#### Response
|
||||
|
||||
##### 200 Success
|
||||
@@ -998,12 +997,10 @@ The request can fail with a bad request response for the following reasons:
|
||||
|
||||
#### Request data
|
||||
|
||||
The request is performed as `multipart/form-data`.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ------- | ----------------------------------------------------------------------------------------------- |
|
||||
| type | String | The type of the attachement. Use `file` or `deck_file`. |
|
||||
| file | Binary | File data to add as an attachment together with the `filename` parameter according to RFC 7578. |
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ------- | --------------------------------------------- |
|
||||
| type | String | The type of the attachement |
|
||||
| file | Binary | File data to add as an attachment |
|
||||
|
||||
- Prior to Deck version v1.3.0 (API v1.0), attachments were stored within deck. For this type of attachments `deck_file` was used as the default type of attachments
|
||||
- Starting with Deck version 1.3.0 (API v1.1) files are stored within the users regular Nextcloud files and the type `file` has been introduced for that
|
||||
@@ -1025,13 +1022,12 @@ The request is performed as `multipart/form-data`.
|
||||
|
||||
#### Request data
|
||||
|
||||
The request is performed as `multipart/form-data`.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ------- | ----------------------------------------------------------------------------------------------- |
|
||||
| type | String | The type of the attachement. For now only `deck_file` is supported as an attachment type. |
|
||||
| file | Binary | File data to add as an attachment together with the `filename` parameter according to RFC 7578. |
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ------- | --------------------------------------------- |
|
||||
| type | String | The type of the attachement |
|
||||
| file | Binary | File data to add as an attachment |
|
||||
|
||||
For now only `deck_file` is supported as an attachment type.
|
||||
|
||||
#### Response
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 188 KiB |
@@ -516,7 +516,7 @@ class ActivityManager {
|
||||
];
|
||||
}
|
||||
|
||||
private function findDetailsForCard(int $cardId, ?string $subject = null): array {
|
||||
private function findDetailsForCard($cardId, $subject = null) {
|
||||
$card = $this->cardMapper->find($cardId);
|
||||
$stack = $this->stackMapper->find($card->getStackId());
|
||||
$board = $this->boardMapper->find($stack->getBoardId());
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
|
||||
namespace OCA\Deck\Activity;
|
||||
|
||||
/**
|
||||
* @psalm-api SettingComment
|
||||
*/
|
||||
class SettingComment extends SettingBase {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\Deck\Command;
|
||||
|
||||
use OCP\IConfig;
|
||||
use OCP\IUserManager;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class CalendarToggle extends Command {
|
||||
private IUserManager $userManager;
|
||||
private IConfig $config;
|
||||
|
||||
public function __construct(IUserManager $userManager, IConfig $config) {
|
||||
parent::__construct();
|
||||
$this->userManager = $userManager;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
protected function configure() {
|
||||
$this
|
||||
->setName('deck:calendar-toggle')
|
||||
->setDescription('Enable or disable Deck calendar/tasks integration for all existing users. Users can still change their own setting afterwards. Only affects users that already exist at the time of execution.')
|
||||
->addOption(
|
||||
'on',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'Enable calendar/tasks integration for all existing users (users can opt-out later)'
|
||||
)
|
||||
->addOption(
|
||||
'off',
|
||||
null,
|
||||
InputOption::VALUE_NONE,
|
||||
'Disable calendar/tasks integration for all existing users (users can opt-in later)'
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int {
|
||||
$enable = $input->getOption('on');
|
||||
$disable = $input->getOption('off');
|
||||
if ($enable && $disable) {
|
||||
$output->writeln('<error>Cannot use --on and --off together.</error>');
|
||||
return 1;
|
||||
}
|
||||
if (!$enable && !$disable) {
|
||||
$output->writeln('<error>Please specify either --on or --off.</error>');
|
||||
return 1;
|
||||
}
|
||||
$value = $enable ? 'yes' : '';
|
||||
$users = $this->userManager->search('');
|
||||
$count = 0;
|
||||
foreach ($users as $user) {
|
||||
$uid = $user->getUID();
|
||||
$this->config->setUserValue($uid, 'deck', 'calendar', $value);
|
||||
$output->writeln("Set calendar integration to '" . ($enable ? 'on' : 'off') . "' for user: $uid");
|
||||
$count++;
|
||||
}
|
||||
$output->writeln("Done. Updated $count existing users.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -6,13 +6,9 @@
|
||||
*/
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Attachment;
|
||||
use OCA\Deck\Service\AttachmentService;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
@@ -25,52 +21,72 @@ class AttachmentApiController extends ApiController {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function getAll(string $apiVersion): DataResponse {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function getAll($apiVersion) {
|
||||
$attachment = $this->attachmentService->findAll($this->request->getParam('cardId'), true);
|
||||
if ($apiVersion === '1.0') {
|
||||
$attachment = array_filter($attachment, fn (Attachment $attachment): bool => $attachment->getType() === 'deck_file');
|
||||
$attachment = array_filter($attachment, function ($attachment) {
|
||||
return $attachment->getType() === 'deck_file';
|
||||
});
|
||||
}
|
||||
return new DataResponse($attachment, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function display(int $cardId, int $attachmentId, string $type = 'deck_file') {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function display($cardId, $attachmentId, $type = 'deck_file') {
|
||||
return $this->attachmentService->display($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function create(int $cardId, string $type, string $data): DataResponse {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function create($cardId, $type, $data) {
|
||||
$attachment = $this->attachmentService->create($cardId, $type, $data);
|
||||
return new DataResponse($attachment, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function update(int $cardId, int $attachmentId, string $data, string $type = 'deck_file'): DataResponse {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function update($cardId, $attachmentId, $data, $type = 'deck_file') {
|
||||
$attachment = $this->attachmentService->update($cardId, $attachmentId, $data, $type);
|
||||
return new DataResponse($attachment, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function delete(int $cardId, int $attachmentId, string $type = 'deck_file'): DataResponse {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function delete($cardId, $attachmentId, $type = 'deck_file') {
|
||||
$attachment = $this->attachmentService->delete($cardId, $attachmentId, $type);
|
||||
return new DataResponse($attachment, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function restore(int $cardId, int $attachmentId, string $type = 'deck_file'): DataResponse {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*/
|
||||
public function restore($cardId, $attachmentId, $type = 'deck_file') {
|
||||
$attachment = $this->attachmentService->restore($cardId, $attachmentId, $type);
|
||||
return new DataResponse($attachment, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
@@ -7,13 +7,8 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\BadRequestException;
|
||||
use OCA\Deck\Db\Attachment;
|
||||
use OCA\Deck\Service\AttachmentService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCP\IRequest;
|
||||
|
||||
class AttachmentController extends Controller {
|
||||
@@ -25,66 +20,74 @@ class AttachmentController extends Controller {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function getAll(int $cardId): array {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function getAll($cardId) {
|
||||
return $this->attachmentService->findAll($cardId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $attachmentId
|
||||
* @NoCSRFRequired
|
||||
* @NoAdminRequired
|
||||
* @return \OCP\AppFramework\Http\Response
|
||||
* @throws \OCA\Deck\NotFoundException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
public function display(int $cardId, string $attachmentId): Response {
|
||||
['type' => $type, 'attachmentId' => $attachmentId] = $this->extractTypeAndAttachmentId($attachmentId);
|
||||
return $this->attachmentService->display($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function create(int $cardId): Attachment {
|
||||
return $this->attachmentService->create(
|
||||
$cardId,
|
||||
$this->request->getParam('type'),
|
||||
$this->request->getParam('data') ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function update(int $cardId, string $attachmentId): Attachment {
|
||||
['type' => $type, 'attachmentId' => $attachmentId] = $this->extractTypeAndAttachmentId($attachmentId);
|
||||
return $this->attachmentService->update($cardId, $attachmentId, $this->request->getParam('data') ?? '', $type);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $cardId, string $attachmentId): Attachment {
|
||||
['type' => $type, 'attachmentId' => $attachmentId] = $this->extractTypeAndAttachmentId($attachmentId);
|
||||
return $this->attachmentService->delete($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function restore(int $cardId, string $attachmentId): Attachment {
|
||||
['type' => $type, 'attachmentId' => $attachmentId] = $this->extractTypeAndAttachmentId($attachmentId);
|
||||
return $this->attachmentService->restore($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{type: string, attachmentId: int}
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
private function extractTypeAndAttachmentId(string $attachmentId): array {
|
||||
public function display($cardId, $attachmentId) {
|
||||
if (!str_contains($attachmentId, ':')) {
|
||||
$type = 'deck_file';
|
||||
} else {
|
||||
[$type, $attachmentId] = [...explode(':', $attachmentId), '', ''];
|
||||
[$type, $attachmentId] = explode(':', $attachmentId);
|
||||
}
|
||||
return $this->attachmentService->display($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
if ($type === '' || !is_numeric($attachmentId)) {
|
||||
throw new BadRequestException('Invalid attachment id');
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function create($cardId) {
|
||||
return $this->attachmentService->create(
|
||||
$cardId,
|
||||
$this->request->getParam('type'),
|
||||
$this->request->getParam('data')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function update($cardId, $attachmentId) {
|
||||
if (!str_contains($attachmentId, ':')) {
|
||||
$type = 'deck_file';
|
||||
} else {
|
||||
[$type, $attachmentId] = explode(':', $attachmentId);
|
||||
}
|
||||
return $this->attachmentService->update($cardId, $attachmentId, $this->request->getParam('data'), $type);
|
||||
}
|
||||
|
||||
return [
|
||||
'type' => $type,
|
||||
'attachmentId' => (int)$attachmentId,
|
||||
];
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function delete($cardId, $attachmentId) {
|
||||
if (!str_contains($attachmentId, ':')) {
|
||||
$type = 'deck_file';
|
||||
} else {
|
||||
[$type, $attachmentId] = explode(':', $attachmentId);
|
||||
}
|
||||
return $this->attachmentService->delete($cardId, $attachmentId, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function restore($cardId, $attachmentId) {
|
||||
if (!str_contains($attachmentId, ':')) {
|
||||
$type = 'deck_file';
|
||||
} else {
|
||||
[$type, $attachmentId] = explode(':', $attachmentId);
|
||||
}
|
||||
return $this->attachmentService->restore($cardId, $attachmentId, $type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,10 @@ use OCA\Deck\Service\BoardService;
|
||||
use OCA\Deck\StatusException;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
use function Sabre\HTTP\parseDate;
|
||||
use OCP\IRequest;
|
||||
use Sabre\HTTP\Util;
|
||||
|
||||
/**
|
||||
* Class BoardApiController
|
||||
@@ -39,18 +36,21 @@ class BoardApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the boards that the current user has access to.
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Return all of the boards that the current user has access to.
|
||||
*
|
||||
* @param bool $details
|
||||
* @throws StatusException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function index(bool $details = false): DataResponse {
|
||||
public function index(bool $details = false) {
|
||||
$modified = $this->request->getHeader('If-Modified-Since');
|
||||
if ($modified === '') {
|
||||
if ($modified === null || $modified === '') {
|
||||
$boards = $this->boardService->findAll(0, $details === true);
|
||||
} else {
|
||||
$date = parseDate($modified);
|
||||
$date = Util::parseHTTPDate($modified);
|
||||
if (!$date) {
|
||||
throw new StatusException('Invalid If-Modified-Since header provided.');
|
||||
}
|
||||
@@ -64,12 +64,14 @@ class BoardApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*
|
||||
* Return the board specified by $this->request->getParam('boardId').
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function get(): DataResponse {
|
||||
public function get() {
|
||||
$board = $this->boardService->find($this->request->getParam('boardId'));
|
||||
$response = new DataResponse($board, HTTP::STATUS_OK);
|
||||
$response->setETag($board->getEtag());
|
||||
@@ -77,53 +79,68 @@ class BoardApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $color
|
||||
*
|
||||
* Create a board with the specified title and color.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function create(string $title, string $color): DataResponse {
|
||||
public function create($title, $color) {
|
||||
$board = $this->boardService->create($title, $this->userId, $color);
|
||||
return new DataResponse($board, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $color
|
||||
* @params $archived
|
||||
*
|
||||
* Update a board with the specified boardId, title and color, and archived state.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function update(string $title, string $color, bool $archived = false): DataResponse {
|
||||
public function update($title, $color, $archived = false) {
|
||||
$board = $this->boardService->update($this->request->getParam('boardId'), $title, $color, $archived);
|
||||
return new DataResponse($board, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*
|
||||
* Delete the board specified by $boardId. Return the board that was deleted.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function delete(): DataResponse {
|
||||
public function delete() {
|
||||
$board = $this->boardService->delete($this->request->getParam('boardId'));
|
||||
return new DataResponse($board, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*
|
||||
* Undo the deletion of the board specified by $boardId.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function undoDelete(): DataResponse {
|
||||
public function undoDelete() {
|
||||
$board = $this->boardService->deleteUndo($this->request->getParam('boardId'));
|
||||
return new DataResponse($board, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function addAcl(int $boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage) {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage) {
|
||||
$acl = $this->boardService->addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage);
|
||||
return new DataResponse($acl, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
@@ -10,13 +10,10 @@ namespace OCA\Deck\Controller;
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Service\BoardService;
|
||||
use OCA\Deck\Service\Importer\BoardImportService;
|
||||
use OCA\Deck\Service\PermissionService;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IL10N;
|
||||
use OCP\IRequest;
|
||||
|
||||
class BoardController extends ApiController {
|
||||
@@ -25,45 +22,73 @@ class BoardController extends ApiController {
|
||||
IRequest $request,
|
||||
private BoardService $boardService,
|
||||
private PermissionService $permissionService,
|
||||
private BoardImportService $boardImportService,
|
||||
private IL10N $l10n,
|
||||
private $userId,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function index() {
|
||||
return $this->boardService->findAll();
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function read(int $boardId): Board {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function read(int $boardId) {
|
||||
return $this->boardService->find($boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function create(string $title, string $color): Board {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function create($title, $color) {
|
||||
return $this->boardService->create($title, $this->userId, $color);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function update(int $id, string $title, string $color, bool $archived): Board {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @param $archived
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function update($id, $title, $color, $archived) {
|
||||
return $this->boardService->update($id, $title, $color, $archived);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $boardId): Board {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function delete($boardId) {
|
||||
return $this->boardService->delete($boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function deleteUndo(int $boardId): Board {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function deleteUndo($boardId) {
|
||||
return $this->boardService->deleteUndo($boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function getUserPermissions(int $boardId): array {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return array|bool
|
||||
* @internal param $userId
|
||||
*/
|
||||
public function getUserPermissions($boardId) {
|
||||
$permissions = $this->permissionService->getPermissions($boardId);
|
||||
return [
|
||||
'PERMISSION_READ' => $permissions[Acl::PERMISSION_READ],
|
||||
@@ -74,10 +99,16 @@ class BoardController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @param $type
|
||||
* @param $participant
|
||||
* @param $permissionEdit
|
||||
* @param $permissionShare
|
||||
* @param $permissionManage
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function addAcl(int $boardId, int $type, $participant, bool $permissionEdit, bool $permissionShare, bool $permissionManage): Acl {
|
||||
public function addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage) {
|
||||
return $this->boardService->addAcl($boardId, $type, $participant, $permissionEdit, $permissionShare, $permissionManage);
|
||||
}
|
||||
|
||||
@@ -132,62 +163,4 @@ class BoardController extends ApiController {
|
||||
public function export($boardId) {
|
||||
return $this->boardService->export($boardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function import(): DataResponse {
|
||||
$file = $this->request->getUploadedFile('file');
|
||||
$error = null;
|
||||
$phpFileUploadErrors = [
|
||||
UPLOAD_ERR_OK => $this->l10n->t('The file was uploaded'),
|
||||
UPLOAD_ERR_INI_SIZE => $this->l10n->t('The uploaded file exceeds the upload_max_filesize directive in php.ini'),
|
||||
UPLOAD_ERR_FORM_SIZE => $this->l10n->t('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'),
|
||||
UPLOAD_ERR_PARTIAL => $this->l10n->t('The file was only partially uploaded'),
|
||||
UPLOAD_ERR_NO_FILE => $this->l10n->t('No file was uploaded'),
|
||||
UPLOAD_ERR_NO_TMP_DIR => $this->l10n->t('Missing a temporary folder'),
|
||||
UPLOAD_ERR_CANT_WRITE => $this->l10n->t('Could not write file to disk'),
|
||||
UPLOAD_ERR_EXTENSION => $this->l10n->t('A PHP extension stopped the file upload'),
|
||||
];
|
||||
|
||||
if (empty($file)) {
|
||||
$error = $this->l10n->t('No file uploaded or file size exceeds maximum of %s', [\OCP\Util::humanFileSize(\OCP\Util::uploadLimit())]);
|
||||
}
|
||||
if (!empty($file) && array_key_exists('error', $file) && $file['error'] !== UPLOAD_ERR_OK) {
|
||||
$error = $phpFileUploadErrors[$file['error']];
|
||||
}
|
||||
if (!empty($file) && $file['error'] === UPLOAD_ERR_OK && !in_array($file['type'], ['application/json', 'text/plain'])) {
|
||||
$error = $this->l10n->t('Invalid file type. Only JSON files are allowed.');
|
||||
}
|
||||
if ($error !== null) {
|
||||
return new DataResponse([
|
||||
'status' => 'error',
|
||||
'message' => $error,
|
||||
], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$fileContent = file_get_contents($file['tmp_name']);
|
||||
$this->boardImportService->setSystem('DeckJson');
|
||||
$config = new \stdClass();
|
||||
$config->owner = $this->userId;
|
||||
$this->boardImportService->setConfigInstance($config);
|
||||
$this->boardImportService->setData(json_decode($fileContent));
|
||||
$this->boardImportService->import();
|
||||
$importedBoard = $this->boardImportService->getBoard();
|
||||
$board = $this->boardService->find($importedBoard->getId());
|
||||
|
||||
return new DataResponse($board, Http::STATUS_OK);
|
||||
} catch (\TypeError $e) {
|
||||
return new DataResponse([
|
||||
'status' => 'error',
|
||||
'message' => $this->l10n->t('Invalid JSON data'),
|
||||
], Http::STATUS_BAD_REQUEST);
|
||||
} catch (\Exception $e) {
|
||||
return new DataResponse([
|
||||
'status' => 'error',
|
||||
'message' => $this->l10n->t('Failed to import board'),
|
||||
], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,6 @@ namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\Importer\BoardImportService;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\IRequest;
|
||||
@@ -26,9 +23,11 @@ class BoardImportApiController extends OCSController {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function import(string $system, array $config, array $data): DataResponse {
|
||||
$this->boardImportService->setSystem($system);
|
||||
$config = json_decode(json_encode($config));
|
||||
@@ -39,17 +38,21 @@ class BoardImportApiController extends OCSController {
|
||||
return new DataResponse($this->boardImportService->getBoard(), Http::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getAllowedSystems(): DataResponse {
|
||||
$allowedSystems = $this->boardImportService->getAllowedImportSystems();
|
||||
return new DataResponse($allowedSystems, Http::STATUS_OK);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getConfigSchema(string $name): DataResponse {
|
||||
$this->boardImportService->setSystem($name);
|
||||
$this->boardImportService->validateSystem();
|
||||
|
||||
@@ -12,9 +12,6 @@ use OCA\Deck\Service\AssignmentService;
|
||||
use OCA\Deck\Service\CardService;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
@@ -30,7 +27,7 @@ class CardApiController extends ApiController {
|
||||
* @param IRequest $request
|
||||
* @param CardService $cardService
|
||||
* @param AssignmentService $assignmentService
|
||||
* @param string $userId
|
||||
* @param $userId
|
||||
*/
|
||||
public function __construct(
|
||||
string $appName,
|
||||
@@ -83,102 +80,112 @@ class CardApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
*
|
||||
* Update a card
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function update(string $title, $type, string $owner, string $description = '', int $order = 0, $duedate = null, $archived = null): DataResponse {
|
||||
public function update($title, $type, $owner, $description = '', $order = 0, $duedate = null, $archived = null) {
|
||||
$done = array_key_exists('done', $this->request->getParams()) ? new OptionalNullableValue($this->request->getParam('done', null)) : null;
|
||||
$card = $this->cardService->update($this->request->getParam('cardId'), $title, $this->request->getParam('stackId'), $type, $owner, $description, $order, $duedate, 0, $archived, $done);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Delete a specific card.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function delete(): DataResponse {
|
||||
public function delete() {
|
||||
$card = $this->cardService->delete($this->request->getParam('cardId'));
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Assign a label to a card.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function assignLabel(int $labelId): DataResponse {
|
||||
public function assignLabel($labelId) {
|
||||
$card = $this->cardService->assignLabel($this->request->getParam('cardId'), $labelId);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Assign a label to a card.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function removeLabel(int $labelId): DataResponse {
|
||||
public function removeLabel($labelId) {
|
||||
$card = $this->cardService->removeLabel($this->request->getParam('cardId'), $labelId);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Assign a user to a card
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function assignUser(int $cardId, string $userId, int $type = 0): DataResponse {
|
||||
public function assignUser($cardId, $userId, $type = 0) {
|
||||
$card = $this->assignmentService->assignUser($cardId, $userId, $type);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Unassign a user from a card
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function unassignUser(int $cardId, string $userId, int $type = 0): DataResponse {
|
||||
public function unassignUser($cardId, $userId, $type = 0) {
|
||||
$card = $this->assignmentService->unassignUser($cardId, $userId, $type);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Archive card
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function archive(int $cardId): DataResponse {
|
||||
public function archive($cardId) {
|
||||
$card = $this->cardService->archive($cardId);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Unarchive card
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function unarchive(int $cardId): DataResponse {
|
||||
public function unarchive($cardId) {
|
||||
$card = $this->cardService->unarchive($cardId);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Reorder cards
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function reorder(int $stackId, int $order): DataResponse {
|
||||
$card = $this->cardService->reorder((int)$this->request->getParam('cardId'), $stackId, $order);
|
||||
public function reorder($stackId, $order) {
|
||||
$card = $this->cardService->reorder((int)$this->request->getParam('cardId'), (int)$stackId, (int)$order);
|
||||
return new DataResponse($card, HTTP::STATUS_OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,9 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Assignment;
|
||||
use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Service\AssignmentService;
|
||||
use OCA\Deck\Service\CardService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\IRequest;
|
||||
|
||||
class CardController extends Controller {
|
||||
@@ -26,26 +23,45 @@ class CardController extends Controller {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function read(int $cardId): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function read($cardId) {
|
||||
return $this->cardService->find($cardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @param $stackId
|
||||
* @param $order
|
||||
* @return array
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function reorder(int $cardId, int $stackId, int $order): array {
|
||||
return $this->cardService->reorder($cardId, $stackId, $order);
|
||||
public function reorder($cardId, $stackId, $order) {
|
||||
return $this->cardService->reorder((int)$cardId, (int)$stackId, (int)$order);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function rename(int $cardId, string $title): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @param $title
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function rename($cardId, $title) {
|
||||
return $this->cardService->rename($cardId, $title);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function create(string $title, int $stackId, string $type = 'plain', int $order = 999, string $description = '', $duedate = null, array $labels = [], array $users = []): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $title
|
||||
* @param $stackId
|
||||
* @param $type
|
||||
* @param int $order
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function create($title, $stackId, $type = 'plain', $order = 999, string $description = '', $duedate = null, $labels = [], $users = []) {
|
||||
$card = $this->cardService->create($title, $stackId, $type, $order, $this->userId, $description, $duedate);
|
||||
|
||||
foreach ($labels as $label) {
|
||||
@@ -60,68 +76,113 @@ class CardController extends Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $stackId
|
||||
* @param $type
|
||||
* @param $order
|
||||
* @param $description
|
||||
* @param $duedate
|
||||
* @param $deletedAt
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function update(int $id, string $title, int $stackId, string $type, int $order, string $description, $duedate, $deletedAt): Card {
|
||||
public function update($id, $title, $stackId, $type, $order, $description, $duedate, $deletedAt) {
|
||||
return $this->cardService->update($id, $title, $stackId, $type, $this->userId, $description, $order, $duedate, $deletedAt);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function clone(int $cardId, ?int $targetStackId = null): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @param $targetStackId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function clone(int $cardId, ?int $targetStackId = null) {
|
||||
return $this->cardService->cloneCard($cardId, $targetStackId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $cardId): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function delete($cardId) {
|
||||
return $this->cardService->delete($cardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function deleted(int $boardId): array {
|
||||
public function deleted($boardId) {
|
||||
return $this->cardService->fetchDeleted($boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function archive($cardId) {
|
||||
return $this->cardService->archive($cardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function unarchive(int $cardId): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function unarchive($cardId) {
|
||||
return $this->cardService->unarchive($cardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function done(int $cardId): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function done(int $cardId) {
|
||||
return $this->cardService->done($cardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function undone(int $cardId): Card {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function undone(int $cardId) {
|
||||
return $this->cardService->undone($cardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function assignLabel(int $cardId, int $labelId): void {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @param $labelId
|
||||
*/
|
||||
public function assignLabel($cardId, $labelId) {
|
||||
$this->cardService->assignLabel($cardId, $labelId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function removeLabel(int $cardId, int $labelId): void {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $cardId
|
||||
* @param $labelId
|
||||
*/
|
||||
public function removeLabel($cardId, $labelId) {
|
||||
$this->cardService->removeLabel($cardId, $labelId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function assignUser(int $cardId, string $userId, int $type = 0): Assignment {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function assignUser($cardId, $userId, $type = 0) {
|
||||
return $this->assignmentService->assignUser($cardId, $userId, $type);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function unassignUser(int $cardId, string $userId, int $type = 0): Assignment {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function unassignUser($cardId, $userId, $type = 0) {
|
||||
return $this->assignmentService->unassignUser($cardId, $userId, $type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,15 +9,11 @@ namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\CommentService;
|
||||
use OCA\Deck\StatusException;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\IRequest;
|
||||
|
||||
/**
|
||||
* @psalm-api
|
||||
*/
|
||||
class CommentsApiController extends OCSController {
|
||||
public function __construct(
|
||||
string $appName,
|
||||
@@ -31,33 +27,33 @@ class CommentsApiController extends OCSController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @throws StatusException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function list(int $cardId, int $limit = 20, int $offset = 0): DataResponse {
|
||||
public function list(string $cardId, int $limit = 20, int $offset = 0): DataResponse {
|
||||
return $this->commentService->list($cardId, $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @throws StatusException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function create(int $cardId, string $message, int $parentId = 0): DataResponse {
|
||||
return $this->commentService->create($cardId, $message, $parentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @throws StatusException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function update(int $cardId, int $commentId, string $message): DataResponse {
|
||||
return $this->commentService->update($cardId, $commentId, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @throws StatusException
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $cardId, int $commentId): DataResponse {
|
||||
return $this->commentService->delete($cardId, $commentId);
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\ConfigService;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\NotFoundResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
@@ -24,15 +22,19 @@ class ConfigController extends OCSController {
|
||||
parent::__construct($AppName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
/**
|
||||
* @NoCSRFRequired
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function get(): DataResponse {
|
||||
return new DataResponse($this->configService->getAll());
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
public function setValue(string $key, mixed $value): DataResponse|NotFoundResponse {
|
||||
/**
|
||||
* @NoCSRFRequired
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function setValue(string $key, $value) {
|
||||
$result = $this->configService->set($key, $value);
|
||||
if ($result === null) {
|
||||
return new NotFoundResponse();
|
||||
|
||||
@@ -10,9 +10,6 @@ namespace OCA\Deck\Controller;
|
||||
use OCA\Deck\Service\LabelService;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
|
||||
@@ -29,50 +26,59 @@ class LabelApiController extends ApiController {
|
||||
$appName,
|
||||
IRequest $request,
|
||||
private LabelService $labelService,
|
||||
private $userId,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Get a specific label.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function get(): DataResponse {
|
||||
public function get() {
|
||||
$label = $this->labelService->find($this->request->getParam('labelId'));
|
||||
return new DataResponse($label, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $color
|
||||
* Create a new label
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function create(string $title, string $color): DataResponse {
|
||||
public function create($title, $color) {
|
||||
$label = $this->labelService->create($title, $color, $this->request->getParam('boardId'));
|
||||
return new DataResponse($label, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $color
|
||||
* Update a specific label
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function update(string $title, string $color): DataResponse {
|
||||
public function update($title, $color) {
|
||||
$label = $this->labelService->update($this->request->getParam('labelId'), $title, $color);
|
||||
return new DataResponse($label, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Delete a specific label
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[NoCSRFRequired]
|
||||
#[CORS]
|
||||
public function delete(): DataResponse {
|
||||
public function delete() {
|
||||
$label = $this->labelService->delete($this->request->getParam('labelId'));
|
||||
return new DataResponse($label, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,8 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Service\LabelService;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\IRequest;
|
||||
|
||||
class LabelController extends Controller {
|
||||
@@ -22,18 +20,34 @@ class LabelController extends Controller {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function create(string $title, string $color, int $boardId): Label {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function create($title, $color, $boardId) {
|
||||
return $this->labelService->create($title, $color, $boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function update(int $id, string $title, string $color): Label {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function update($id, $title, $color) {
|
||||
return $this->labelService->update($id, $title, $color);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $labelId): Label {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $labelId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function delete($labelId) {
|
||||
return $this->labelService->delete($labelId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ declare(strict_types=1);
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\OverviewService;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\IRequest;
|
||||
@@ -25,7 +24,9 @@ class OverviewApiController extends OCSController {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function upcomingCards(): DataResponse {
|
||||
return new DataResponse($this->dashboardService->findUpcomingCards($this->userId));
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ namespace OCA\Deck\Controller;
|
||||
use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Model\CardDetails;
|
||||
use OCA\Deck\Service\SearchService;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\IRequest;
|
||||
@@ -27,7 +26,9 @@ class SearchController extends OCSController {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function search(string $term, ?int $limit = null, ?int $cursor = null): DataResponse {
|
||||
$cards = $this->searchService->searchCards($term, $limit, $cursor);
|
||||
return new DataResponse(array_map(function (Card $card) {
|
||||
|
||||
@@ -7,16 +7,14 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\BoardService;
|
||||
use OCA\Deck\Service\StackService;
|
||||
use OCA\Deck\StatusException;
|
||||
use OCP\AppFramework\ApiController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\CORS;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\IRequest;
|
||||
use function Sabre\HTTP\parseDate;
|
||||
use Sabre\HTTP\Util;
|
||||
|
||||
/**
|
||||
* Class StackApiController
|
||||
@@ -31,21 +29,23 @@ class StackApiController extends ApiController {
|
||||
$appName,
|
||||
IRequest $request,
|
||||
private StackService $stackService,
|
||||
private BoardService $boardService,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the stacks in the specified board.
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Return all of the stacks in the specified board.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function index(): DataResponse {
|
||||
public function index() {
|
||||
$since = 0;
|
||||
$modified = $this->request->getHeader('If-Modified-Since');
|
||||
if ($modified !== '') {
|
||||
$date = parseDate($modified);
|
||||
if ($modified !== null && $modified !== '') {
|
||||
$date = Util::parseHTTPDate($modified);
|
||||
if (!$date) {
|
||||
throw new StatusException('Invalid If-Modified-Since header provided.');
|
||||
}
|
||||
@@ -56,12 +56,13 @@ class StackApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the stacks in the specified board.
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Return all of the stacks in the specified board.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function get(): DataResponse {
|
||||
public function get() {
|
||||
$stack = $this->stackService->find($this->request->getParam('stackId'));
|
||||
$response = new DataResponse($stack, HTTP::STATUS_OK);
|
||||
$response->setETag($stack->getETag());
|
||||
@@ -69,45 +70,55 @@ class StackApiController extends ApiController {
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $order
|
||||
*
|
||||
* Create a stack with the specified title and order.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function create(string $title, int $order): DataResponse {
|
||||
public function create($title, $order) {
|
||||
$stack = $this->stackService->create($title, $this->request->getParam('boardId'), $order);
|
||||
return new DataResponse($stack, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @params $title
|
||||
* @params $order
|
||||
*
|
||||
* Update a stack by the specified stackId and boardId with the values that were put.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function update(string $title, int $order) {
|
||||
public function update($title, $order) {
|
||||
$stack = $this->stackService->update($this->request->getParam('stackId'), $title, $this->request->getParam('boardId'), $order, 0);
|
||||
return new DataResponse($stack, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* Delete the stack specified by $this->request->getParam('stackId').
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function delete(): DataResponse {
|
||||
public function delete() {
|
||||
$stack = $this->stackService->delete($this->request->getParam('stackId'));
|
||||
return new DataResponse($stack, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stacks that have been archived.
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* get the stacks that have been archived.
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[CORS]
|
||||
#[NoCSRFRequired]
|
||||
public function getArchived(): DataResponse {
|
||||
public function getArchived() {
|
||||
$stacks = $this->stackService->findAllArchived($this->request->getParam('boardId'));
|
||||
return new DataResponse($stacks, HTTP::STATUS_OK);
|
||||
}
|
||||
|
||||
@@ -7,12 +7,10 @@
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Stack;
|
||||
use OCA\Deck\Service\StackService;
|
||||
|
||||
use OCP\AppFramework\Controller;
|
||||
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\IRequest;
|
||||
|
||||
class StackController extends Controller {
|
||||
@@ -20,54 +18,78 @@ class StackController extends Controller {
|
||||
string $appName,
|
||||
IRequest $request,
|
||||
private StackService $stackService,
|
||||
private $userId,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return array
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function index(int $boardId): array {
|
||||
public function index($boardId) {
|
||||
return $this->stackService->findAll($boardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return array
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function archived(int $boardId): array {
|
||||
public function archived($boardId) {
|
||||
return $this->stackService->findAllArchived($boardId);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function create(string $title, int $boardId, int $order = 999): Stack {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $title
|
||||
* @param $boardId
|
||||
* @param int $order
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function create($title, $boardId, $order = 999) {
|
||||
return $this->stackService->create($title, $boardId, $order);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function update(int $id, string $title, int $boardId, int $order, ?int $deletedAt = null): Stack {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $boardId
|
||||
* @param $order
|
||||
* @param $deletedAt
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function update($id, $title, $boardId, $order, $deletedAt) {
|
||||
return $this->stackService->update($id, $title, $boardId, $order, $deletedAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, Stack>
|
||||
* @NoAdminRequired
|
||||
* @param $stackId
|
||||
* @param $order
|
||||
* @return array
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function reorder(int $stackId, int $order): array {
|
||||
return $this->stackService->reorder($stackId, $order);
|
||||
public function reorder($stackId, $order) {
|
||||
return $this->stackService->reorder((int)$stackId, (int)$order);
|
||||
}
|
||||
|
||||
#[NoAdminRequired]
|
||||
public function delete(int $stackId): Stack {
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param $stackId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
public function delete($stackId) {
|
||||
return $this->stackService->delete($stackId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @NoAdminRequired
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
public function deleted(int $boardId): array {
|
||||
public function deleted($boardId) {
|
||||
return $this->stackService->fetchDeleted($boardId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,20 +7,6 @@
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
/**
|
||||
* @method int getBoardId()
|
||||
* @method bool isPermissionEdit()
|
||||
* @method void setPermissionEdit(bool $permissionEdit)
|
||||
* @method bool isPermissionShare()
|
||||
* @method void setPermissionShare(bool $permissionShare)
|
||||
* @method bool isPermissionManage()
|
||||
* @method void setPermissionManage(bool $permissionManage)
|
||||
* @method int getType()
|
||||
* @method void setType(int $type)
|
||||
* @method bool isOwner()
|
||||
* @method void setOwner(int $owner)
|
||||
*
|
||||
*/
|
||||
class Acl extends RelationalEntity {
|
||||
public const PERMISSION_READ = 0;
|
||||
public const PERMISSION_EDIT = 1;
|
||||
@@ -51,13 +37,17 @@ class Acl extends RelationalEntity {
|
||||
$this->addResolvable('participant');
|
||||
}
|
||||
|
||||
public function getPermission(int $permission): bool {
|
||||
return match ($permission) {
|
||||
self::PERMISSION_READ => true,
|
||||
self::PERMISSION_EDIT => $this->getPermissionEdit(),
|
||||
self::PERMISSION_SHARE => $this->getPermissionShare(),
|
||||
self::PERMISSION_MANAGE => $this->getPermissionManage(),
|
||||
default => false,
|
||||
};
|
||||
public function getPermission($permission) {
|
||||
switch ($permission) {
|
||||
case self::PERMISSION_READ:
|
||||
return true;
|
||||
case self::PERMISSION_EDIT:
|
||||
return $this->getPermissionEdit();
|
||||
case self::PERMISSION_SHARE:
|
||||
return $this->getPermissionShare();
|
||||
case self::PERMISSION_MANAGE:
|
||||
return $this->getPermissionManage();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,13 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Acl[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll(int $boardId, ?int $limit = null, ?int $offset = null) {
|
||||
public function findAll($boardId, $limit = null, $offset = null) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage')
|
||||
->from('deck_board_acl')
|
||||
@@ -48,9 +51,12 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $userId
|
||||
* @param numeric $id
|
||||
* @return bool
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
$aclId = $id;
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('acl.id')
|
||||
@@ -62,7 +68,11 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
return count($qb->executeQuery()->fetchAll()) > 0;
|
||||
}
|
||||
|
||||
public function findBoardId(int $id): ?int {
|
||||
/**
|
||||
* @param numeric $id
|
||||
* @return int|null
|
||||
*/
|
||||
public function findBoardId($id): ?int {
|
||||
try {
|
||||
$entity = $this->find($id);
|
||||
return $entity->getBoardId();
|
||||
@@ -77,7 +87,7 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
* @return Acl[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findByParticipant(int $type, string $participant): array {
|
||||
public function findByParticipant($type, $participant): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
|
||||
$qb->select('*')
|
||||
|
||||
@@ -77,41 +77,26 @@ class AssignmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
public function deleteByParticipantOnBoard(string $participant, int $boardId, $type = Assignment::TYPE_USER) {
|
||||
// Step 1: Get all card IDs for the board that have assignments for this participant
|
||||
// This avoids MySQL Error 1093 by separating the SELECT from the DELETE operation
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$cardIdQuery = $this->db->getQueryBuilder();
|
||||
$cardIdQuery->select('a.card_id')
|
||||
->from('deck_assigned_users', 'a')
|
||||
->innerJoin('a', 'deck_cards', 'c', 'c.id = a.card_id')
|
||||
->innerJoin('c', 'deck_stacks', 's', 's.id = c.stack_id')
|
||||
->where($cardIdQuery->expr()->eq('a.participant', $cardIdQuery->createNamedParameter($participant, IQueryBuilder::PARAM_STR)))
|
||||
->andWhere($cardIdQuery->expr()->eq('s.board_id', $cardIdQuery->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($cardIdQuery->expr()->eq('a.type', $cardIdQuery->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
$result = $cardIdQuery->executeQuery();
|
||||
$cardIds = [];
|
||||
while ($row = $result->fetch()) {
|
||||
$cardIds[] = $row['card_id'];
|
||||
}
|
||||
$result->closeCursor();
|
||||
|
||||
// Step 2: If we have card IDs, delete the assignments
|
||||
if (!empty($cardIds)) {
|
||||
$deleteQuery = $this->db->getQueryBuilder();
|
||||
$deleteQuery->delete('deck_assigned_users')
|
||||
->where($deleteQuery->expr()->eq('participant', $deleteQuery->createNamedParameter($participant, IQueryBuilder::PARAM_STR)))
|
||||
->andWhere($deleteQuery->expr()->eq('type', $deleteQuery->createNamedParameter($type, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($deleteQuery->expr()->in('card_id', $deleteQuery->createNamedParameter($cardIds, IQueryBuilder::PARAM_INT_ARRAY)));
|
||||
$deleteQuery->executeStatement();
|
||||
}
|
||||
->where($cardIdQuery->expr()->eq('a.participant', $qb->createNamedParameter($participant, IQueryBuilder::PARAM_STR)))
|
||||
->andWhere($cardIdQuery->expr()->eq('s.board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($cardIdQuery->expr()->eq('a.type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
|
||||
$qb->delete('deck_assigned_users')
|
||||
->where($qb->expr()->in('card_id', $qb->createFunction($cardIdQuery->getSQL()), IQueryBuilder::PARAM_INT_ARRAY));
|
||||
$qb->executeStatement();
|
||||
}
|
||||
|
||||
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
return $this->cardMapper->isOwner($userId, $id);
|
||||
}
|
||||
|
||||
public function findBoardId(int $id): ?int {
|
||||
public function findBoardId($id): ?int {
|
||||
return $this->cardMapper->findBoardId($id);
|
||||
}
|
||||
|
||||
@@ -123,9 +108,6 @@ class AssignmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function insert(Entity $entity): Entity {
|
||||
if (!($entity instanceof Assignment)) {
|
||||
throw new \LogicException('Trying to insert a ' . get_class($entity) . ' in the assignment mapper');
|
||||
}
|
||||
$origin = $this->getOrigin($entity);
|
||||
if ($origin === null) {
|
||||
throw new NotFoundException('No origin found for assignment');
|
||||
@@ -144,7 +126,7 @@ class AssignmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
});
|
||||
}
|
||||
|
||||
public function isUserAssigned(int $cardId, string $userId): bool {
|
||||
public function isUserAssigned($cardId, $userId): bool {
|
||||
$assignments = $this->findAll($cardId);
|
||||
foreach ($assignments as $assignment) {
|
||||
$origin = $this->getOrigin($assignment);
|
||||
|
||||
@@ -36,11 +36,13 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return Attachment
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function find(int $id): Attachment {
|
||||
public function find($id) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -50,11 +52,14 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $cardId
|
||||
* @param string $data
|
||||
* @return Attachment
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findByData(int $cardId, string $data): Attachment {
|
||||
public function findByData($cardId, $data) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -65,10 +70,11 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @return Entity[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll(int $cardId): array {
|
||||
public function findAll($cardId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -80,9 +86,11 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Attachment[]
|
||||
* @param null $cardId
|
||||
* @param bool $withOffset
|
||||
* @return array
|
||||
*/
|
||||
public function findToDelete(?int $cardId = null, bool $withOffset = true): array {
|
||||
public function findToDelete($cardId = null, $withOffset = true) {
|
||||
// add buffer of 5 min
|
||||
$timeLimit = time() - (60 * 5);
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
@@ -104,8 +112,12 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
|
||||
/**
|
||||
* Check if $userId is owner of Entity with $id
|
||||
*
|
||||
* @param $userId string userId
|
||||
* @param $id int|string unique entity identifier
|
||||
* @return boolean
|
||||
*/
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
try {
|
||||
$attachment = $this->find($id);
|
||||
return $this->cardMapper->isOwner($userId, $attachment->getCardId());
|
||||
@@ -118,10 +130,10 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
/**
|
||||
* Query boardId for Entity of given $id
|
||||
*
|
||||
* @param $id int unique entity identifier
|
||||
* @param $id int|string unique entity identifier
|
||||
* @return int|null id of Board
|
||||
*/
|
||||
public function findBoardId(int $id): ?int {
|
||||
public function findBoardId($id): ?int {
|
||||
try {
|
||||
$attachment = $this->find($id);
|
||||
} catch (\Exception $e) {
|
||||
|
||||
@@ -10,20 +10,10 @@ namespace OCA\Deck\Db;
|
||||
/**
|
||||
* @method int getId()
|
||||
* @method string getTitle()
|
||||
* @method void setTitle(string $title)
|
||||
* @method int getShared()
|
||||
* @method void setShared(int $shared)
|
||||
* @method bool isArchived()
|
||||
* @method bool getArchived()
|
||||
* @method void setArchived(bool $archived)
|
||||
* @method int getDeletedAt()
|
||||
* @method void setDeletedAt(int $deletedAt)
|
||||
* @method int getLastModified()
|
||||
* @method void setLastModified(int $lastModified)
|
||||
* @method string getOwner()
|
||||
* @method void setOwner(string $owner)
|
||||
* @method string getColor()
|
||||
* @method void setColor(string $color)
|
||||
*/
|
||||
class Board extends RelationalEntity {
|
||||
protected $title;
|
||||
|
||||
@@ -469,16 +469,16 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
|
||||
return parent::delete($entity);
|
||||
}
|
||||
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
$board = $this->find($id);
|
||||
return ($board->getOwner() === $userId);
|
||||
}
|
||||
|
||||
public function findBoardId(int $id): ?int {
|
||||
public function findBoardId($id): ?int {
|
||||
return $id;
|
||||
}
|
||||
|
||||
public function mapAcl(Acl &$acl): void {
|
||||
public function mapAcl(Acl &$acl) {
|
||||
$acl->resolveRelation('participant', function ($participant) use (&$acl) {
|
||||
if ($acl->getType() === Acl::PERMISSION_TYPE_USER) {
|
||||
if ($this->userManager->userExists($acl->getParticipant())) {
|
||||
|
||||
@@ -15,18 +15,13 @@ use Sabre\VObject\Component\VCalendar;
|
||||
|
||||
/**
|
||||
* @method string getTitle()
|
||||
* @method void setTitle(string $title)
|
||||
* @method string getDescription()
|
||||
* @method string getDescriptionPrev()
|
||||
* @method int getStackId()
|
||||
* @method void setStackId(int $stackId)
|
||||
* @method int getOrder()
|
||||
* @method void setOrder(int $order)
|
||||
* @method int getLastModified()
|
||||
* @method int getCreatedAt()
|
||||
* @method bool getArchived()
|
||||
* @method string getType()
|
||||
* @method void setType(string $type)
|
||||
* @method int getDeletedAt()
|
||||
* @method void setDeletedAt(int $deletedAt)
|
||||
* @method bool getNotified()
|
||||
@@ -73,8 +68,8 @@ class Card extends RelationalEntity {
|
||||
protected $createdAt;
|
||||
protected $labels;
|
||||
protected $assignedUsers;
|
||||
protected array $attachments = [];
|
||||
protected int $attachmentCount = 0;
|
||||
protected $attachments;
|
||||
protected $attachmentCount;
|
||||
protected $owner;
|
||||
protected $order;
|
||||
protected $archived = false;
|
||||
|
||||
@@ -86,15 +86,16 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
$updatedFields = $entity->getUpdatedFields();
|
||||
if (isset($updatedFields['duedate']) && $updatedFields['duedate']) {
|
||||
try {
|
||||
/** @var Card $existing */
|
||||
$existing = $this->find($entity->getId());
|
||||
if ($entity->getDueDate() !== $existing->getDueDate()) {
|
||||
if ($existing && $entity->getDuedate() !== $existing->getDuedate()) {
|
||||
$entity->setNotified(false);
|
||||
}
|
||||
// remove pending notifications
|
||||
$notification = $this->notificationManager->createNotification();
|
||||
$notification
|
||||
->setApp('deck')
|
||||
->setObject('card', (string)$entity->getId());
|
||||
->setObject('card', $entity->getId());
|
||||
$this->notificationManager->markProcessed($notification);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
@@ -130,11 +131,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $card;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll($stackId, ?int $limit = null, int $offset = 0, int $since = -1) {
|
||||
public function findAll($stackId, $limit = null, $offset = null, $since = -1) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from('deck_cards')
|
||||
@@ -149,32 +146,6 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $stackIds
|
||||
* @return array<int, null|Card[]>
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAllForStacks(array $stackIds, ?int $limit = null, int $offset = 0, int $since = -1): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from('deck_cards')
|
||||
->where($qb->expr()->in('stack_id', $qb->createNamedParameter($stackIds, IQueryBuilder::PARAM_INT_ARRAY)))
|
||||
->andWhere($qb->expr()->eq('archived', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
|
||||
->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->gt('last_modified', $qb->createNamedParameter($since, IQueryBuilder::PARAM_INT)))
|
||||
->setMaxResults($limit)
|
||||
->setFirstResult($offset)
|
||||
->orderBy('order')
|
||||
->addOrderBy('id');
|
||||
|
||||
$rawCards = $this->findEntities($qb);
|
||||
$cards = array_fill_keys($stackIds, null);
|
||||
foreach ($rawCards as $card) {
|
||||
$cards[$card->getStackId()][] = $card;
|
||||
}
|
||||
return $cards;
|
||||
}
|
||||
|
||||
public function queryCardsByBoard(int $boardId): IQueryBuilder {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.*')
|
||||
@@ -193,10 +164,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $qb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findToDelete(int $timeLimit, ?int $limit = null): array {
|
||||
public function findToDelete($timeLimit, $limit = null) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'title', 'owner', 'archived', 'deleted_at', 'last_modified')
|
||||
->from('deck_cards')
|
||||
@@ -207,10 +175,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findDeleted(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findDeleted($boardId, $limit = null, $offset = null) {
|
||||
$qb = $this->queryCardsByBoard($boardId);
|
||||
$qb->andWhere($qb->expr()->neq('c.deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
|
||||
->setMaxResults($limit)
|
||||
@@ -220,10 +185,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findCalendarEntries(int $boardId, ?int $limit = null, $offset = 0): array {
|
||||
public function findCalendarEntries($boardId, $limit = null, $offset = null) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.*')
|
||||
->from('deck_cards', 'c')
|
||||
@@ -278,11 +240,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $boardIds
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findAllWithDue(array $boardIds): array {
|
||||
public function findAllWithDue(array $boardIds) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.*')
|
||||
->from('deck_cards', 'c')
|
||||
@@ -299,11 +257,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $boardIds
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findToMeOrNotAssignedCards(array $boardIds, string $username): array {
|
||||
public function findToMeOrNotAssignedCards(array $boardIds, string $username) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.*')
|
||||
->from('deck_cards', 'c')
|
||||
@@ -325,10 +279,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findOverdue(): array {
|
||||
public function findOverdue() {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'title', 'duedate', 'notified')
|
||||
->from('deck_cards')
|
||||
@@ -340,9 +291,6 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findUnexposedDescriptionChances() {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'title', 'duedate', 'notified', 'description_prev', 'last_editor', 'description')
|
||||
@@ -351,9 +299,6 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function search(array $boardIds, SearchQuery $query, ?int $limit = null, ?int $offset = null): array {
|
||||
$qb = $this->queryCardsByBoards($boardIds);
|
||||
$this->extendQueryByFilter($qb, $query);
|
||||
@@ -388,7 +333,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
$qb->andWhere($qb->expr()->lt('c.last_modified', $qb->createNamedParameter($offset, IQueryBuilder::PARAM_INT)));
|
||||
}
|
||||
|
||||
$result = $qb->executeQuery();
|
||||
$result = $qb->execute();
|
||||
$entities = [];
|
||||
while ($row = $result->fetch()) {
|
||||
$entities[] = Card::fromRow($row);
|
||||
@@ -431,7 +376,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
$qb->andWhere($qb->expr()->lt('comments.id', $qb->createNamedParameter($offset, IQueryBuilder::PARAM_INT)));
|
||||
}
|
||||
|
||||
$result = $qb->executeQuery();
|
||||
$result = $qb->execute();
|
||||
$entities = $result->fetchAll();
|
||||
$result->closeCursor();
|
||||
return $entities;
|
||||
@@ -527,7 +472,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
});
|
||||
$groups = $this->groupManager->search($assignment->getValue());
|
||||
foreach ($searchUsers as $user) {
|
||||
$groups = array_merge($groups, $this->groupManager->getUserGroups($user));
|
||||
$groups = array_merge($groups, $this->groupManager->getUserIdGroups($user->getUID()));
|
||||
}
|
||||
|
||||
$assignmentSearches = [];
|
||||
@@ -580,7 +525,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
if ($offset !== null) {
|
||||
$qb->setFirstResult($offset);
|
||||
}
|
||||
$result = $qb->executeQuery();
|
||||
$result = $qb->execute();
|
||||
$all = $result->fetchAll();
|
||||
$result->closeCursor();
|
||||
return $all;
|
||||
@@ -592,32 +537,32 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return parent::delete($entity);
|
||||
}
|
||||
|
||||
public function deleteByStack($stackId): void {
|
||||
public function deleteByStack($stackId) {
|
||||
$cards = $this->findAllByStack($stackId);
|
||||
foreach ($cards as $card) {
|
||||
$this->delete($card);
|
||||
}
|
||||
}
|
||||
|
||||
public function assignLabel(int $card, int $label): void {
|
||||
public function assignLabel($card, $label) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->insert('deck_assigned_labels')
|
||||
->values([
|
||||
'label_id' => $qb->createNamedParameter($label, IQueryBuilder::PARAM_INT),
|
||||
'card_id' => $qb->createNamedParameter($card, IQueryBuilder::PARAM_INT),
|
||||
]);
|
||||
$qb->executeStatement();
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
public function removeLabel(int $card, int $label): void {
|
||||
public function removeLabel($card, $label) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('deck_assigned_labels')
|
||||
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($card, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('label_id', $qb->createNamedParameter($label, IQueryBuilder::PARAM_INT)));
|
||||
$qb->executeStatement();
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.id')
|
||||
->from($this->getTableName(), 'c')
|
||||
@@ -629,7 +574,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return count($qb->executeQuery()->fetchAll()) > 0;
|
||||
}
|
||||
|
||||
public function findBoardId(int $id): ?int {
|
||||
public function findBoardId($id): ?int {
|
||||
$result = $this->cache->get('findBoardId:' . $id);
|
||||
if ($result === null) {
|
||||
try {
|
||||
@@ -659,11 +604,13 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
public function transferOwnership(string $ownerId, string $newOwnerId, ?int $boardId = null): void {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->update($this->getTableName())
|
||||
->set('owner', $qb->createNamedParameter($newOwnerId, IQueryBuilder::PARAM_STR))
|
||||
->where('owner', $qb->createNamedParameter($ownerId, IQueryBuilder::PARAM_STR))
|
||||
->executeStatement();
|
||||
$params = [
|
||||
'owner' => $ownerId,
|
||||
'newOwner' => $newOwnerId
|
||||
];
|
||||
$sql = "UPDATE `*PREFIX*{$this->tableName}` SET `owner` = :newOwner WHERE `owner` = :owner";
|
||||
$stmt = $this->db->executeQuery($sql, $params);
|
||||
$stmt->closeCursor();
|
||||
}
|
||||
|
||||
public function remapCardOwner(int $boardId, string $userId, string $newUserId): void {
|
||||
|
||||
@@ -19,11 +19,12 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
abstract class DeckMapper extends QBMapper {
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return T
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
*/
|
||||
public function find(int $id): Entity {
|
||||
public function find($id) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -36,7 +37,7 @@ abstract class DeckMapper extends QBMapper {
|
||||
* Helper function to split passed array into chunks of 1000 elements and
|
||||
* call a given callback for fetching query results
|
||||
*
|
||||
* Can be useful to limit to 1000 results per query for oracle compatibility
|
||||
* Can be useful to limit to 1000 results per query for oracle compatiblity
|
||||
* but still iterate over all results
|
||||
*/
|
||||
public function chunkQuery(array $ids, callable $callback): Generator {
|
||||
|
||||
@@ -8,25 +8,22 @@
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
interface IPermissionMapper {
|
||||
|
||||
/**
|
||||
* Check if $userId is owner of Entity with $id
|
||||
*
|
||||
* @param $userId string userId
|
||||
* @param $id int unique entity identifier
|
||||
* @param $id int|string unique entity identifier
|
||||
* @return boolean
|
||||
*/
|
||||
public function isOwner(string $userId, int $id): bool;
|
||||
public function isOwner($userId, $id): bool;
|
||||
|
||||
/**
|
||||
* Query boardId for Entity of given $id
|
||||
*
|
||||
* @param $id int unique entity identifier
|
||||
* @return ?int id of Board
|
||||
* @param $id int|string unique entity identifier
|
||||
* @return int|null id of Board
|
||||
*/
|
||||
public function findBoardId(int $id): ?int;
|
||||
public function findBoardId($id): ?int;
|
||||
}
|
||||
|
||||
@@ -8,16 +8,7 @@
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
/**
|
||||
* @method string getTitle()
|
||||
* @method void setTitle(string $title)
|
||||
* @method string getColor()
|
||||
* @method void setColor(string $color)
|
||||
* @method int getBoardId()
|
||||
* @method void setBoardId(int $boardId)
|
||||
* @method int getCardId()
|
||||
* @method void setCardId(int $cardId)
|
||||
* @method int getLastModified()
|
||||
* @method void setLastModified(int $lastModified)
|
||||
* @method getTitle(): string
|
||||
*/
|
||||
class Label extends RelationalEntity {
|
||||
protected $title;
|
||||
@@ -33,7 +24,7 @@ class Label extends RelationalEntity {
|
||||
$this->addType('lastModified', 'integer');
|
||||
}
|
||||
|
||||
public function getETag(): string {
|
||||
public function getETag() {
|
||||
return md5((string)$this->getLastModified());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Label[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAll($boardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -41,10 +44,13 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $cardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Label[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAssignedLabelsForCard(int $cardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAssignedLabelsForCard($cardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.*', 'card_id')
|
||||
->from($this->getTableName(), 'l')
|
||||
@@ -57,7 +63,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
public function findAssignedLabelsForCards(array $cardIds, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAssignedLabelsForCards($cardIds, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.*', 'card_id')
|
||||
->from($this->getTableName(), 'l')
|
||||
@@ -71,10 +77,13 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Label[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAssignedLabelsForBoard(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAssignedLabelsForBoard($boardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.id as id', 'l.title as title', 'l.color as color')
|
||||
->selectAlias('c.id', 'card_id')
|
||||
@@ -104,10 +113,11 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, list<Label>>
|
||||
* @param numeric $boardId
|
||||
* @return array
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function getAssignedLabelsForBoard(int $boardId): array {
|
||||
public function getAssignedLabelsForBoard($boardId) {
|
||||
$labels = $this->findAssignedLabelsForBoard($boardId);
|
||||
$result = [];
|
||||
foreach ($labels as $label) {
|
||||
@@ -120,9 +130,11 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $labelId
|
||||
* @return void
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function deleteLabelAssignments(int $labelId): void {
|
||||
public function deleteLabelAssignments($labelId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('deck_assigned_labels')
|
||||
->where($qb->expr()->eq('label_id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT)));
|
||||
@@ -130,9 +142,11 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $cardId
|
||||
* @return void
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function deleteLabelAssignmentsForCard(int $cardId): void {
|
||||
public function deleteLabelAssignmentsForCard($cardId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('deck_assigned_labels')
|
||||
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)));
|
||||
@@ -140,25 +154,33 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param numeric $labelId
|
||||
* @return bool
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $labelId): bool {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.id')
|
||||
->from($this->getTableName(), 'l')
|
||||
->innerJoin('l', 'deck_boards', 'b', 'l.board_id = b.id')
|
||||
->where($qb->expr()->eq('l.id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)))
|
||||
->where($qb->expr()->eq('l.id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('b.owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
|
||||
|
||||
return count($qb->executeQuery()->fetchAll()) > 0;
|
||||
}
|
||||
|
||||
public function findBoardId(int $id): ?int {
|
||||
/**
|
||||
* @param numeric $id
|
||||
* @return int|null
|
||||
*/
|
||||
public function findBoardId($id): ?int {
|
||||
try {
|
||||
$entity = $this->find($id);
|
||||
return $entity->getBoardId();
|
||||
} catch (DoesNotExistException|MultipleObjectsReturnedException) {
|
||||
return null;
|
||||
} catch (DoesNotExistException $e) {
|
||||
} catch (MultipleObjectsReturnedException $e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,10 @@ use Sabre\VObject\Component\VCalendar;
|
||||
|
||||
/**
|
||||
* @method int getId()
|
||||
* @method string getTitle()
|
||||
* @method void setTitle(string $title)
|
||||
* @method int getBoardId()
|
||||
* @method void setBoardId(int $boardId)
|
||||
* @method int getDeletedAt()
|
||||
* @method void setDeletedAt(int $deletedAt)
|
||||
* @method int getLastModified()
|
||||
* @method void setLastModified(int $lastModified)
|
||||
* @method \int getOrder()
|
||||
* @method void setOrder(int $order)
|
||||
* @method Card[] getCards()
|
||||
* @method int getOrder()
|
||||
*/
|
||||
class Stack extends RelationalEntity {
|
||||
protected $title;
|
||||
|
||||
@@ -35,11 +35,13 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
|
||||
|
||||
/**
|
||||
* @param numeric $id
|
||||
* @return Stack
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function find(int $id): Stack {
|
||||
public function find($id): Stack {
|
||||
if (isset($this->stackCache[(string)$id])) {
|
||||
return $this->stackCache[(string)$id];
|
||||
}
|
||||
@@ -54,9 +56,11 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @return Stack|null
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findStackFromCardId(int $cardId): ?Stack {
|
||||
public function findStackFromCardId($cardId): ?Stack {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('s.*')
|
||||
->from($this->getTableName(), 's')
|
||||
@@ -72,10 +76,13 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Stack[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findAll($boardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -88,9 +95,13 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Stack[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findDeleted(int $boardId, ?int $limit = null, int $offset = 0): array {
|
||||
public function findDeleted($boardId, $limit = null, $offset = null) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
@@ -116,9 +127,12 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $userId
|
||||
* @param numeric $stackId
|
||||
* @return bool
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function isOwner(string $userId, int $id): bool {
|
||||
public function isOwner($userId, $id): bool {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('s.id')
|
||||
->from($this->getTableName(), 's')
|
||||
@@ -130,9 +144,11 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $id
|
||||
* @return int|null
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findBoardId(int $id): ?int {
|
||||
public function findBoardId($id): ?int {
|
||||
$result = $this->cache->get('findBoardId:' . $id);
|
||||
if ($result !== null) {
|
||||
return $result !== false ? $result : null;
|
||||
@@ -149,10 +165,6 @@ class StackMapper extends DeckMapper implements IPermissionMapper {
|
||||
return $result !== false ? $result : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Stack>
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findToDelete(): array {
|
||||
// add buffer of 5 min
|
||||
$timeLimit = time() - (60 * 5);
|
||||
|
||||
@@ -35,10 +35,6 @@ class BeforeTemplateRenderedListener implements IEventListener {
|
||||
Util::addStyle('deck', 'deck');
|
||||
|
||||
$pathInfo = $this->request->getPathInfo();
|
||||
if (!$pathInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (str_starts_with($pathInfo, '/apps/calendar')) {
|
||||
Util::addScript('deck', 'deck-calendar');
|
||||
}
|
||||
|
||||
@@ -18,10 +18,14 @@ use OCP\EventDispatcher\IEventListener;
|
||||
/** @template-implements IEventListener<Event|AclDeletedEvent|AclCreatedEvent> */
|
||||
class ResourceListener implements IEventListener {
|
||||
|
||||
public function __construct(
|
||||
private readonly IManager $resourceManager,
|
||||
private readonly ResourceProviderCard $resourceProviderCard,
|
||||
) {
|
||||
/** @var IManager */
|
||||
private $resourceManager;
|
||||
/** @var ResourceProviderCard */
|
||||
private $resourceProviderCard;
|
||||
|
||||
public function __construct(IManager $resourceManager, ResourceProviderCard $resourceProviderCard) {
|
||||
$this->resourceManager = $resourceManager;
|
||||
$this->resourceProviderCard = $resourceProviderCard;
|
||||
}
|
||||
|
||||
public function handle(Event $event): void {
|
||||
@@ -34,10 +38,10 @@ class ResourceListener implements IEventListener {
|
||||
$this->resourceManager->invalidateAccessCacheForProvider($this->resourceProviderCard);
|
||||
|
||||
try {
|
||||
$resource = $this->resourceManager->getResourceForUser(ResourceProvider::RESOURCE_TYPE, (string)$boardId, null);
|
||||
$resource = $this->resourceManager->getResourceForUser(ResourceProvider::RESOURCE_TYPE, $boardId, null);
|
||||
$this->resourceManager->invalidateAccessCacheForResource($resource);
|
||||
} catch (ResourceException $e) {
|
||||
// If there is no resource we don't need to invalidate anything, but this should not happen anyway
|
||||
// If there is no resource we don't need to invalidate anything, but this should not happen anyways
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class DefaultBoardMiddleware extends Middleware {
|
||||
public function beforeController($controller, $methodName) {
|
||||
try {
|
||||
if ($this->userId !== null && $this->defaultBoardService->checkFirstRun($this->userId) && $this->permissionService->canCreate()) {
|
||||
$this->defaultBoardService->createDefaultBoard($this->l10n->t('Welcome to Nextcloud Deck!'), $this->userId, 'bf678b');
|
||||
$this->defaultBoardService->createDefaultBoard($this->l10n->t('Personal'), $this->userId, '0087C5');
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error('Could not create default board', ['exception' => $e]);
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\Deck\Migration;
|
||||
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\IRepairStep;
|
||||
|
||||
class LabelMismatchCleanup implements IRepairStep {
|
||||
|
||||
public function __construct(
|
||||
private IDBConnection $db,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return 'Migrate labels with wrong board mapping';
|
||||
}
|
||||
|
||||
public function run(IOutput $output) {
|
||||
// Find assingments where a label of another (wrong) board is used
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('al.id', 'al.label_id', 'al.card_id', 's.board_id as actual_board_id', 'l.board_id as wrong_id', 'l.color', 'l.title')
|
||||
->from('deck_assigned_labels', 'al')
|
||||
->innerJoin('al', 'deck_cards', 'c', 'c.id = al.card_id')
|
||||
->innerJoin('c', 'deck_stacks', 's', 'c.stack_id = s.id')
|
||||
->innerJoin('al', 'deck_labels', 'l', 'l.id = al.label_id')
|
||||
->where($qb->expr()->neq('l.board_id', 's.board_id'));
|
||||
|
||||
$labels = $qb->executeQUery()->fetchAll();
|
||||
if (count($labels) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$output->info('Found ' . count($labels) . ' labels with wrong board mapping');
|
||||
|
||||
foreach ($labels as $label) {
|
||||
// Select existing label on the correct board
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id')
|
||||
->from('deck_labels')
|
||||
->where($qb->expr()->eq('title', $qb->createNamedParameter($label['title'])))
|
||||
->andWhere($qb->expr()->eq('color', $qb->createNamedParameter($label['color'])))
|
||||
->andWhere($qb->expr()->eq('board_id', $qb->createNamedParameter($label['actual_board_id'])));
|
||||
$result = $qb->executeQuery();
|
||||
$newLabel = $result->fetchOne();
|
||||
$result->closeCursor();
|
||||
|
||||
if (!$newLabel) {
|
||||
// Create a new label with the same title and color on the correct board
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->insert('deck_labels')
|
||||
->values([
|
||||
'title' => $qb->createNamedParameter($label['title']),
|
||||
'color' => $qb->createNamedParameter($label['color']),
|
||||
'board_id' => $qb->createNamedParameter($label['actual_board_id']),
|
||||
]);
|
||||
$qb->executeStatement();
|
||||
$newLabel = $qb->getLastInsertId();
|
||||
$output->debug('Created new label ' . $label['title'] . ' on board ' . $label['actual_board_id']);
|
||||
} else {
|
||||
$output->debug('Found existing label ' . $label['title'] . ' on board ' . $label['actual_board_id']);
|
||||
}
|
||||
|
||||
// Update the assignment to use the new label
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->update('deck_assigned_labels')
|
||||
->set('label_id', $qb->createNamedParameter($newLabel))
|
||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($label['id'])));
|
||||
$qb->executeStatement();
|
||||
$output->debug('Updated label assignment ' . $label['id'] . ' to use label ' . $newLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ use OCA\Deck\Db\Board;
|
||||
class BoardSummary extends Board {
|
||||
private Board $board;
|
||||
|
||||
/** @psalm-suppress ConstructorSignatureMismatch */
|
||||
public function __construct(Board $board) {
|
||||
parent::__construct();
|
||||
$this->board = $board;
|
||||
@@ -28,7 +27,7 @@ class BoardSummary extends Board {
|
||||
return $this->board->getter($name);
|
||||
}
|
||||
|
||||
public function __call($methodName, $args) {
|
||||
return $this->board->__call($methodName, $args);
|
||||
public function __call($name, $arguments) {
|
||||
return $this->board->__call($name, $arguments);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ class CardDetails extends Card {
|
||||
private ?Board $board;
|
||||
private ?Reference $referenceData = null;
|
||||
|
||||
/** @psalm-suppress ConstructorSignatureMismatch */
|
||||
public function __construct(Card $card, ?Board $board = null) {
|
||||
parent::__construct();
|
||||
$this->card = $card;
|
||||
|
||||
@@ -95,7 +95,7 @@ class NotificationHelper {
|
||||
|
||||
$shouldNotify = $notificationSetting === ConfigService::SETTING_BOARD_NOTIFICATION_DUE_ALL;
|
||||
|
||||
if ($user->getUID() === $board->getOwner() && count($board->getAcl() ?? []) === 0) {
|
||||
if ($user->getUID() === $board->getOwner() && count($board->getAcl()) === 0) {
|
||||
// Notify if all or assigned is configured for unshared boards
|
||||
$shouldNotify = true;
|
||||
} elseif ($notificationSetting === ConfigService::SETTING_BOARD_NOTIFICATION_DUE_ASSIGNED && $this->assignmentMapper->isUserAssigned($card->getId(), $user->getUID())) {
|
||||
|
||||
@@ -64,7 +64,6 @@ class BoardReferenceProvider implements IReferenceProvider {
|
||||
$reference = new Reference($referenceText);
|
||||
$reference->setTitle($this->l10n->t('Deck board') . ': ' . $board['title']);
|
||||
$ownerDisplayName = $board['owner']['displayname'] ?? $board['owner']['uid'] ?? '???';
|
||||
// TRANSLATORS Owned by {boardOwnerName}
|
||||
$reference->setDescription($this->l10n->t('Owned by %1$s', [$ownerDisplayName]));
|
||||
$imageUrl = $this->urlGenerator->getAbsoluteURL(
|
||||
$this->urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg')
|
||||
|
||||
@@ -90,7 +90,6 @@ class CommentReferenceProvider implements IReferenceProvider {
|
||||
$reference->setTitle($comment['message']);
|
||||
$boardOwnerDisplayName = $board['owner']['displayname'] ?? $board['owner']['uid'] ?? '???';
|
||||
$reference->setDescription(
|
||||
// TRANSLATORS From {userName}, in {boardTitle}/{stackTitle}, owned by {boardOwnerName}
|
||||
$this->l10n->t('From %1$s, in %2$s/%3$s, owned by %4$s', [
|
||||
$comment['actorDisplayName'],
|
||||
$board['title'],
|
||||
|
||||
@@ -21,6 +21,7 @@ use OCA\Deck\NotFoundException;
|
||||
use OCA\Deck\Notification\NotificationHelper;
|
||||
use OCA\Deck\Validators\AssignmentServiceValidator;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
|
||||
@@ -91,12 +92,15 @@ class AssignmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $userId
|
||||
* @return bool|null|Entity
|
||||
* @throws BadRequestException
|
||||
* @throws NoPermissionException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws DoesNotExistException
|
||||
*/
|
||||
public function assignUser(int $cardId, string $userId, int $type = Assignment::TYPE_USER): Assignment {
|
||||
public function assignUser($cardId, $userId, int $type = Assignment::TYPE_USER) {
|
||||
$this->assignmentServiceValidator->check(compact('cardId', 'userId'));
|
||||
|
||||
if ($type !== Assignment::TYPE_USER && $type !== Assignment::TYPE_GROUP) {
|
||||
@@ -140,13 +144,16 @@ class AssignmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $userId
|
||||
* @return Entity
|
||||
* @throws BadRequestException
|
||||
* @throws NotFoundException
|
||||
* @throws NoPermissionException
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function unassignUser(int $cardId, string $userId, int $type = 0): Assignment {
|
||||
public function unassignUser($cardId, $userId, $type = 0) {
|
||||
$this->assignmentServiceValidator->check(compact('cardId', 'userId'));
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ use OCP\AppFramework\Db\IMapperException;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCP\IL10N;
|
||||
use OCP\IUserManager;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
|
||||
class AttachmentService {
|
||||
private $attachmentMapper;
|
||||
@@ -81,16 +80,20 @@ class AttachmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerExceptionInterface
|
||||
* @param string $type
|
||||
* @param string $class
|
||||
* @throws \OCP\AppFramework\QueryException
|
||||
*/
|
||||
public function registerAttachmentService(string $type, string $class): void {
|
||||
$this->services[$type] = $this->application->getContainer()->get($class);
|
||||
public function registerAttachmentService($type, $class) {
|
||||
$this->services[$type] = $this->application->getContainer()->query($class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @return IAttachmentService
|
||||
* @throws InvalidAttachmentType
|
||||
*/
|
||||
public function getService(string $type): IAttachmentService {
|
||||
public function getService($type) {
|
||||
if (isset($this->services[$type])) {
|
||||
return $this->services[$type];
|
||||
}
|
||||
@@ -98,11 +101,16 @@ class AttachmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Attachment[]
|
||||
* @param $cardId
|
||||
* @return array
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function findAll(int $cardId, bool $withDeleted = false): array {
|
||||
public function findAll($cardId, $withDeleted = false) {
|
||||
if (is_numeric($cardId) === false) {
|
||||
throw new BadRequestException('card id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
|
||||
$attachments = $this->attachmentMapper->findAll($cardId);
|
||||
@@ -114,7 +122,7 @@ class AttachmentService {
|
||||
/** @var IAttachmentService $service */
|
||||
$service = $this->getService($attachmentType);
|
||||
if ($service instanceof ICustomAttachmentService) {
|
||||
$attachments = array_merge($attachments, $service->listAttachments($cardId));
|
||||
$attachments = array_merge($attachments, $service->listAttachments((int)$cardId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,40 +140,49 @@ class AttachmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @return int|mixed
|
||||
* @throws BadRequestException
|
||||
* @throws InvalidAttachmentType
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function count(int $cardId): int {
|
||||
$count = $this->attachmentCacheHelper->getAttachmentCount($cardId);
|
||||
public function count($cardId) {
|
||||
if (is_numeric($cardId) === false) {
|
||||
throw new BadRequestException('card id must be a number');
|
||||
}
|
||||
|
||||
$count = $this->attachmentCacheHelper->getAttachmentCount((int)$cardId);
|
||||
if ($count === null) {
|
||||
$count = count($this->attachmentMapper->findAll($cardId));
|
||||
|
||||
foreach (array_keys($this->services) as $attachmentType) {
|
||||
$service = $this->getService($attachmentType);
|
||||
if ($service instanceof ICustomAttachmentService) {
|
||||
$count += $service->getAttachmentCount($cardId);
|
||||
$count += $service->getAttachmentCount((int)$cardId);
|
||||
}
|
||||
}
|
||||
|
||||
$this->attachmentCacheHelper->setAttachmentCount($cardId, $count);
|
||||
$this->attachmentCacheHelper->setAttachmentCount((int)$cardId, $count);
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $type
|
||||
* @param $data
|
||||
* @return Attachment|\OCP\AppFramework\Db\Entity
|
||||
* @throws NoPermissionException
|
||||
* @throws StatusException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function create(int $cardId, string $type, string $data) {
|
||||
public function create($cardId, $type, $data) {
|
||||
$this->attachmentServiceValidator->check(compact('cardId', 'type'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
|
||||
|
||||
$this->attachmentCacheHelper->clearAttachmentCount($cardId);
|
||||
$this->attachmentCacheHelper->clearAttachmentCount((int)$cardId);
|
||||
$attachment = new Attachment();
|
||||
$attachment->setCardId($cardId);
|
||||
$attachment->setType($type);
|
||||
@@ -201,10 +218,12 @@ class AttachmentService {
|
||||
/**
|
||||
* Display the attachment
|
||||
*
|
||||
* @param $attachmentId
|
||||
* @return Response
|
||||
* @throws NoPermissionException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function display(int $cardId, int $attachmentId, string $type = 'deck_file'): Response {
|
||||
public function display($cardId, $attachmentId, $type = 'deck_file') {
|
||||
try {
|
||||
$service = $this->getService($type);
|
||||
} catch (InvalidAttachmentType $e) {
|
||||
@@ -238,10 +257,13 @@ class AttachmentService {
|
||||
/**
|
||||
* Update an attachment with custom data
|
||||
*
|
||||
* @param $attachmentId
|
||||
* @param $data
|
||||
* @return mixed
|
||||
* @throws BadRequestException
|
||||
* @throws NoPermissionException
|
||||
*/
|
||||
public function update(int $cardId, int $attachmentId, string $data, string $type = 'deck_file'): Attachment {
|
||||
public function update($cardId, $attachmentId, $data, $type = 'deck_file') {
|
||||
$this->attachmentServiceValidator->check(compact('cardId', 'type', 'data'));
|
||||
|
||||
try {
|
||||
@@ -362,6 +384,8 @@ class AttachmentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attachment $attachment
|
||||
* @return Attachment
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
private function addCreator(Attachment $attachment): Attachment {
|
||||
|
||||
@@ -75,6 +75,8 @@ class BoardService {
|
||||
|
||||
/**
|
||||
* Set a different user than the current one, e.g. when no user is available in occ
|
||||
*
|
||||
* @param string $userId
|
||||
*/
|
||||
public function setUserId(string $userId): void {
|
||||
$this->userId = $userId;
|
||||
@@ -115,18 +117,22 @@ class BoardService {
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||
/** @var Board $board */
|
||||
$board = $this->boardMapper->find($boardId, true, true, $allowDeleted);
|
||||
[$board] = $this->enrichBoards([$board], $fullDetails);
|
||||
return $board;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $mapper
|
||||
* @param $id
|
||||
* @return bool
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function isArchived($mapper, int $id): bool {
|
||||
public function isArchived($mapper, $id) {
|
||||
$this->boardServiceValidator->check(compact('id'));
|
||||
|
||||
try {
|
||||
@@ -145,12 +151,15 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $mapper
|
||||
* @param $id
|
||||
* @return bool
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function isDeleted($mapper, int $id): bool {
|
||||
public function isDeleted($mapper, $id) {
|
||||
$this->boardServiceValidator->check(compact('mapper', 'id'));
|
||||
|
||||
try {
|
||||
@@ -170,9 +179,13 @@ class BoardService {
|
||||
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $userId
|
||||
* @param $color
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function create(string $title, string $userId, string $color): Board {
|
||||
public function create($title, $userId, $color) {
|
||||
$this->boardServiceValidator->check(compact('title', 'userId', 'color'));
|
||||
|
||||
if (!$this->permissionService->canCreate()) {
|
||||
@@ -183,8 +196,7 @@ class BoardService {
|
||||
$board->setTitle($title);
|
||||
$board->setOwner($userId);
|
||||
$board->setColor($color);
|
||||
/** @var Board $board */
|
||||
$board = $this->boardMapper->insert($board);
|
||||
$new_board = $this->boardMapper->insert($board);
|
||||
|
||||
// create new labels
|
||||
$default_labels = [
|
||||
@@ -198,31 +210,33 @@ class BoardService {
|
||||
$label = new Label();
|
||||
$label->setColor($labelColor);
|
||||
$label->setTitle($labelTitle);
|
||||
$label->setBoardId($board->getId());
|
||||
$label->setBoardId($new_board->getId());
|
||||
$labels[] = $this->labelMapper->insert($label);
|
||||
}
|
||||
$board->setLabels($labels);
|
||||
$this->boardMapper->mapOwner($board);
|
||||
$permissions = $this->permissionService->matchPermissions($board);
|
||||
$board->setPermissions([
|
||||
$new_board->setLabels($labels);
|
||||
$this->boardMapper->mapOwner($new_board);
|
||||
$permissions = $this->permissionService->matchPermissions($new_board);
|
||||
$new_board->setPermissions([
|
||||
'PERMISSION_READ' => $permissions[Acl::PERMISSION_READ] ?? false,
|
||||
'PERMISSION_EDIT' => $permissions[Acl::PERMISSION_EDIT] ?? false,
|
||||
'PERMISSION_MANAGE' => $permissions[Acl::PERMISSION_MANAGE] ?? false,
|
||||
'PERMISSION_SHARE' => $permissions[Acl::PERMISSION_SHARE] ?? false
|
||||
]);
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_BOARD, $board, ActivityManager::SUBJECT_BOARD_CREATE, [], $userId);
|
||||
$this->changeHelper->boardChanged($board->getId());
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_BOARD, $new_board, ActivityManager::SUBJECT_BOARD_CREATE, [], $userId);
|
||||
$this->changeHelper->boardChanged($new_board->getId());
|
||||
|
||||
return $board;
|
||||
return $new_board;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return Board
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function delete(int $id): Board {
|
||||
public function delete($id) {
|
||||
$this->boardServiceValidator->check(compact('id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -239,11 +253,13 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
*/
|
||||
public function deleteUndo(int $id): Board {
|
||||
public function deleteUndo($id) {
|
||||
$this->boardServiceValidator->check(compact('id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -257,12 +273,14 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function deleteForce(int $id): Board {
|
||||
public function deleteForce($id) {
|
||||
$this->boardServiceValidator->check(compact('id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -273,12 +291,17 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @param $archived
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function update(int $id, string $title, string $color, bool $archived): Board {
|
||||
public function update($id, $title, $color, $archived) {
|
||||
$this->boardServiceValidator->check(compact('id', 'title', 'color', 'archived'));
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -297,7 +320,7 @@ class BoardService {
|
||||
return $board;
|
||||
}
|
||||
|
||||
private function applyPermissions(int $boardId, bool $edit, bool $share, bool $manage, ?Acl $oldAcl = null): array {
|
||||
private function applyPermissions($boardId, $edit, $share, $manage, $oldAcl = null) {
|
||||
try {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_MANAGE);
|
||||
} catch (NoPermissionException $e) {
|
||||
@@ -309,7 +332,7 @@ class BoardService {
|
||||
return [$edit, $share, $manage];
|
||||
}
|
||||
|
||||
public function enrichWithBoardSettings(Board $board): void {
|
||||
public function enrichWithBoardSettings(Board $board) {
|
||||
$globalCalendarConfig = (bool)$this->config->getUserValue($this->userId, Application::APP_ID, 'calendar', true);
|
||||
$settings = [
|
||||
'notify-due' => $this->config->getUserValue($this->userId, Application::APP_ID, 'board:' . $board->getId() . ':notify-due', ConfigService::SETTING_BOARD_NOTIFICATION_DUE_ASSIGNED),
|
||||
@@ -318,7 +341,7 @@ class BoardService {
|
||||
$board->setSettings($settings);
|
||||
}
|
||||
|
||||
public function enrichWithActiveSessions(Board $board): void {
|
||||
public function enrichWithActiveSessions(Board $board) {
|
||||
$sessions = $this->sessionMapper->findAllActive($board->getId());
|
||||
|
||||
$board->setActiveSessions(array_values(
|
||||
@@ -331,11 +354,17 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Acl::PERMISSION_TYPE_* $type
|
||||
* @param $boardId
|
||||
* @param $type
|
||||
* @param $participant
|
||||
* @param $edit
|
||||
* @param $share
|
||||
* @param $manage
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws BadRequestException
|
||||
* @throws NoPermissionException
|
||||
*/
|
||||
public function addAcl(int $boardId, int $type, $participant, bool $edit, bool $share, bool $manage): Acl {
|
||||
public function addAcl($boardId, $type, $participant, $edit, $share, $manage) {
|
||||
$this->boardServiceValidator->check(compact('boardId', 'type', 'participant', 'edit', 'share', 'manage'));
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_SHARE);
|
||||
@@ -371,12 +400,17 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $edit
|
||||
* @param $share
|
||||
* @param $manage
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function updateAcl(int $id, bool $edit, bool $share, bool $manage): Acl {
|
||||
public function updateAcl($id, $edit, $share, $manage) {
|
||||
$this->boardServiceValidator->check(compact('id', 'edit', 'share', 'manage'));
|
||||
|
||||
$this->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_SHARE);
|
||||
@@ -388,12 +422,12 @@ class BoardService {
|
||||
$acl->setPermissionShare($share);
|
||||
$acl->setPermissionManage($manage);
|
||||
$this->boardMapper->mapAcl($acl);
|
||||
$acl = $this->aclMapper->update($acl);
|
||||
$board = $this->aclMapper->update($acl);
|
||||
$this->changeHelper->boardChanged($acl->getBoardId());
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new AclUpdatedEvent($acl));
|
||||
|
||||
return $acl;
|
||||
return $board;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -545,23 +579,27 @@ class BoardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return Board
|
||||
* @throws DoesNotExistException
|
||||
* @throws NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function export(int $id): Board {
|
||||
public function export($id) : Board {
|
||||
if (is_numeric($id) === false) {
|
||||
throw new BadRequestException('board id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->boardMapper, $id, Acl::PERMISSION_READ);
|
||||
$board = $this->boardMapper->find($id);
|
||||
$board = $this->boardMapper->find((int)$id);
|
||||
$this->enrichWithCards($board);
|
||||
$this->enrichWithLabels($board);
|
||||
|
||||
return $board;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Board[] $boards
|
||||
* @return Board[]
|
||||
*/
|
||||
/** @param Board[] $boards */
|
||||
private function enrichBoards(array $boards, bool $fullDetails = true): array {
|
||||
$result = [];
|
||||
foreach ($boards as $board) {
|
||||
@@ -677,8 +715,8 @@ class BoardService {
|
||||
}
|
||||
}
|
||||
|
||||
private function enrichWithStacks(Board $board): void {
|
||||
$stacks = $this->stackMapper->findAll($board->getId());
|
||||
private function enrichWithStacks($board, $since = -1) {
|
||||
$stacks = $this->stackMapper->findAll($board->getId(), null, null, $since);
|
||||
|
||||
if (\count($stacks) === 0) {
|
||||
return;
|
||||
@@ -687,8 +725,8 @@ class BoardService {
|
||||
$board->setStacks($stacks);
|
||||
}
|
||||
|
||||
private function enrichWithLabels(Board $board): void {
|
||||
$labels = $this->labelMapper->findAll($board->getId());
|
||||
private function enrichWithLabels($board, $since = -1) {
|
||||
$labels = $this->labelMapper->findAll($board->getId(), null, null, $since);
|
||||
|
||||
if (\count($labels) === 0) {
|
||||
return;
|
||||
@@ -697,7 +735,7 @@ class BoardService {
|
||||
$board->setLabels($labels);
|
||||
}
|
||||
|
||||
private function enrichWithUsers(Board $board): void {
|
||||
private function enrichWithUsers($board, $since = -1) {
|
||||
$boardUsers = $this->permissionService->findUsers($board->getId());
|
||||
if ($boardUsers === null || \count($boardUsers) === 0) {
|
||||
return;
|
||||
@@ -708,7 +746,7 @@ class BoardService {
|
||||
/**
|
||||
* Clean a given board data from the Cache
|
||||
*/
|
||||
private function clearBoardFromCache(Board $board): void {
|
||||
private function clearBoardFromCache(Board $board) {
|
||||
$boardId = $board->getId();
|
||||
$boardOwnerId = $board->getOwner();
|
||||
|
||||
@@ -717,15 +755,13 @@ class BoardService {
|
||||
unset($this->boardsCachePartial[$boardId]);
|
||||
}
|
||||
|
||||
private function enrichWithCards(Board $board): void {
|
||||
private function enrichWithCards($board) {
|
||||
$stacks = $this->stackMapper->findAll($board->getId());
|
||||
foreach ($stacks as $stack) {
|
||||
$cards = $this->cardMapper->findAllByStack($stack->getId());
|
||||
$fullCards = [];
|
||||
foreach ($cards as $card) {
|
||||
$fullCard = $this->cardMapper->find($card->getId());
|
||||
$assignedUsers = $this->assignedUsersMapper->findAll($card->getId());
|
||||
$fullCard->setAssignedUsers($assignedUsers);
|
||||
array_push($fullCards, $fullCard);
|
||||
}
|
||||
$stack->setCards($fullCards);
|
||||
|
||||
@@ -64,14 +64,10 @@ class CardService {
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Card[] $cards
|
||||
* @return CardDetails[]
|
||||
*/
|
||||
public function enrichCards(array $cards): array {
|
||||
public function enrichCards($cards) {
|
||||
$user = $this->userManager->get($this->userId);
|
||||
|
||||
$cardIds = array_map(function (Card $card) use ($user): int {
|
||||
$cardIds = array_map(function (Card $card) use ($user) {
|
||||
// Everything done in here might be heavy as it is executed for every card
|
||||
$cardId = $card->getId();
|
||||
$this->cardMapper->mapOwner($card);
|
||||
@@ -124,8 +120,7 @@ class CardService {
|
||||
);
|
||||
}
|
||||
|
||||
/** @return Card[] */
|
||||
public function fetchDeleted($boardId): array {
|
||||
public function fetchDeleted($boardId) {
|
||||
$this->cardServiceValidator->check(compact('boardId'));
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||
$cards = $this->cardMapper->findDeleted($boardId);
|
||||
@@ -134,12 +129,13 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OCA\Deck\Db\RelationalEntity
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function find(int $cardId): Card {
|
||||
public function find(int $cardId) {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
$card = $this->cardMapper->find($cardId);
|
||||
[$card] = $this->enrichCards([$card]);
|
||||
@@ -156,10 +152,7 @@ class CardService {
|
||||
return $card;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Card[]
|
||||
*/
|
||||
public function findCalendarEntries(int $boardId): array {
|
||||
public function findCalendarEntries($boardId) {
|
||||
try {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||
} catch (NoPermissionException $e) {
|
||||
@@ -170,13 +163,20 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $stackId
|
||||
* @param $type
|
||||
* @param integer $order
|
||||
* @param $description
|
||||
* @param $owner
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadrequestException
|
||||
*/
|
||||
public function create(string $title, int $stackId, string $type, int $order, string $owner, string $description = '', $duedate = null): Card {
|
||||
public function create($title, $stackId, $type, $order, $owner, $description = '', $duedate = null) {
|
||||
$this->cardServiceValidator->check(compact('title', 'stackId', 'type', 'order', 'owner'));
|
||||
|
||||
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
|
||||
@@ -203,13 +203,19 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function delete(int $id): Card {
|
||||
public function delete($id) {
|
||||
if (is_numeric($id) === false) {
|
||||
throw new BadRequestException('card id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
if ($this->boardService->isArchived($this->cardMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
@@ -227,13 +233,25 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $stackId
|
||||
* @param $type
|
||||
* @param $owner
|
||||
* @param $description
|
||||
* @param $order
|
||||
* @param $duedate
|
||||
* @param $deletedAt
|
||||
* @param $archived
|
||||
* @param $done
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function update(int $id, string $title, int $stackId, string $type, string $owner, string $description = '', int $order = 0, ?string $duedate = null, ?int $deletedAt = null, ?bool $archived = null, ?OptionalNullableValue $done = null): Card {
|
||||
public function update($id, $title, $stackId, $type, $owner, $description = '', $order = 0, $duedate = null, $deletedAt = null, $archived = null, ?OptionalNullableValue $done = null) {
|
||||
$this->cardServiceValidator->check(compact('id', 'title', 'stackId', 'type', 'owner', 'order'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT, allowDeletedCard: true);
|
||||
@@ -338,7 +356,7 @@ class CardService {
|
||||
if ($resetDuedateNotification) {
|
||||
$this->notificationHelper->markDuedateAsRead($card);
|
||||
}
|
||||
$this->changeHelper->cardChanged($card->getId());
|
||||
$this->changeHelper->cardChanged($card->getId(), true);
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore()));
|
||||
|
||||
@@ -380,13 +398,16 @@ class CardService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function rename(int $id, string $title): Card {
|
||||
public function rename($id, $title) {
|
||||
$this->cardServiceValidator->check(compact('id', 'title'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
@@ -397,27 +418,30 @@ class CardService {
|
||||
if ($card->getArchived()) {
|
||||
throw new StatusException('Operation not allowed. This card is archived.');
|
||||
}
|
||||
$changes = new ChangeSet($card);
|
||||
$card->setTitle($title);
|
||||
$this->changeHelper->cardChanged($card->getId(), false);
|
||||
$update = $this->cardMapper->update($card);
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore()));
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
|
||||
|
||||
return $update;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<Card>
|
||||
* @param $id
|
||||
* @param $stackId
|
||||
* @param $order
|
||||
* @return array
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function reorder(int $id, int $stackId, int $order): array {
|
||||
public function reorder(int $id, int $stackId, int $order) {
|
||||
$this->cardServiceValidator->check(compact('id', 'stackId', 'order'));
|
||||
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
|
||||
|
||||
@@ -435,69 +459,73 @@ class CardService {
|
||||
$changes->setAfter($card);
|
||||
$this->activityManager->triggerUpdateEvents(ActivityManager::DECK_OBJECT_CARD, $changes, ActivityManager::SUBJECT_CARD_UPDATE);
|
||||
|
||||
$cardsToReorder = $this->cardMapper->findAll($stackId);
|
||||
$cards = $this->cardMapper->findAll($stackId);
|
||||
$result = [];
|
||||
$i = 0;
|
||||
foreach ($cardsToReorder as $cardToReorder) {
|
||||
if ($cardToReorder->getArchived()) {
|
||||
foreach ($cards as $card) {
|
||||
if ($card->getArchived()) {
|
||||
throw new StatusException('Operation not allowed. This card is archived.');
|
||||
}
|
||||
if ($cardToReorder->id === $id) {
|
||||
$cardToReorder->setOrder($order);
|
||||
$cardToReorder->setLastModified(time());
|
||||
if ($card->id === $id) {
|
||||
$card->setOrder($order);
|
||||
$card->setLastModified(time());
|
||||
}
|
||||
|
||||
if ($i === $order) {
|
||||
$i++;
|
||||
}
|
||||
|
||||
if ($cardToReorder->id !== $id) {
|
||||
$cardToReorder->setOrder($i++);
|
||||
if ($card->id !== $id) {
|
||||
$card->setOrder($i++);
|
||||
}
|
||||
$this->cardMapper->update($cardToReorder);
|
||||
$result[$cardToReorder->getOrder()] = $cardToReorder;
|
||||
$this->cardMapper->update($card);
|
||||
$result[$card->getOrder()] = $card;
|
||||
}
|
||||
$this->changeHelper->cardChanged($id, false);
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore()));
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
|
||||
|
||||
return array_values($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function archive(int $id): Card {
|
||||
public function archive($id) {
|
||||
$this->cardServiceValidator->check(compact('id'));
|
||||
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
|
||||
if ($this->boardService->isArchived($this->cardMapper, $id)) {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = $this->cardMapper->find($id);
|
||||
$changes = new ChangeSet($card);
|
||||
$card->setArchived(true);
|
||||
$newCard = $this->cardMapper->update($card);
|
||||
$this->notificationHelper->markDuedateAsRead($card);
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_ARCHIVE);
|
||||
$this->changeHelper->cardChanged($id, false);
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore()));
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
|
||||
|
||||
return $newCard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function unarchive(int $id): Card {
|
||||
public function unarchive($id) {
|
||||
$this->cardServiceValidator->check(compact('id'));
|
||||
|
||||
|
||||
@@ -506,18 +534,19 @@ class CardService {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = $this->cardMapper->find($id);
|
||||
$changes = new ChangeSet($card);
|
||||
$card->setArchived(false);
|
||||
$newCard = $this->cardMapper->update($card);
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_UNARCHIVE);
|
||||
$this->changeHelper->cardChanged($id, false);
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore()));
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
|
||||
|
||||
return $newCard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCA\Deck\Db\Card
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
@@ -530,14 +559,13 @@ class CardService {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = $this->cardMapper->find($id);
|
||||
$changes = new ChangeSet($card);
|
||||
$card->setDone(new \DateTime());
|
||||
$newCard = $this->cardMapper->update($card);
|
||||
$this->notificationHelper->markDuedateAsRead($card);
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_DONE);
|
||||
$this->changeHelper->cardChanged($id, false);
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore()));
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
|
||||
|
||||
return $newCard;
|
||||
}
|
||||
@@ -557,25 +585,26 @@ class CardService {
|
||||
throw new StatusException('Operation not allowed. This board is archived.');
|
||||
}
|
||||
$card = $this->cardMapper->find($id);
|
||||
$changes = new ChangeSet($card);
|
||||
$card->setDone(null);
|
||||
$newCard = $this->cardMapper->update($card);
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_UNDONE);
|
||||
$this->changeHelper->cardChanged($id, false);
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore()));
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
|
||||
|
||||
return $newCard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $labelId
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function assignLabel(int $cardId, int $labelId): Card {
|
||||
public function assignLabel($cardId, $labelId) {
|
||||
$this->cardServiceValidator->check(compact('cardId', 'labelId'));
|
||||
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_EDIT);
|
||||
@@ -597,16 +626,18 @@ class CardService {
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_LABEL_ASSIGN, ['label' => $label]);
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
|
||||
return $card;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cardId
|
||||
* @param $labelId
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function removeLabel(int $cardId, int $labelId): Card {
|
||||
public function removeLabel($cardId, $labelId) {
|
||||
$this->cardServiceValidator->check(compact('cardId', 'labelId'));
|
||||
|
||||
|
||||
@@ -626,7 +657,6 @@ class CardService {
|
||||
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_LABEL_UNASSING, ['label' => $label]);
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
|
||||
return $card;
|
||||
}
|
||||
|
||||
public function getCardUrl(int $cardId): string {
|
||||
|
||||
@@ -66,7 +66,7 @@ class CirclesService {
|
||||
$circlesManager->startSession($federatedUser);
|
||||
$circle = $circlesManager->getCircle($circleId);
|
||||
$member = $circle->getInitiator();
|
||||
$isUserInCircle = $member->getLevel() >= Member::LEVEL_MEMBER;
|
||||
$isUserInCircle = $member !== null && $member->getLevel() >= Member::LEVEL_MEMBER;
|
||||
|
||||
if (!isset($this->userCircleCache[$circleId])) {
|
||||
$this->userCircleCache[$circleId] = [];
|
||||
|
||||
@@ -22,6 +22,8 @@ use OCP\IUserManager;
|
||||
use OutOfBoundsException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
use function is_numeric;
|
||||
|
||||
class CommentService {
|
||||
|
||||
public function __construct(
|
||||
@@ -34,9 +36,12 @@ class CommentService {
|
||||
) {
|
||||
}
|
||||
|
||||
public function list(int $cardId, int $limit = 20, int $offset = 0): DataResponse {
|
||||
public function list(string $cardId, int $limit = 20, int $offset = 0): DataResponse {
|
||||
if (!is_numeric($cardId)) {
|
||||
throw new BadRequestException('A valid card id must be provided');
|
||||
}
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
$comments = $this->commentsManager->getForObject(Application::COMMENT_ENTITY_TYPE, (string)$cardId, $limit, $offset);
|
||||
$comments = $this->commentsManager->getForObject(Application::COMMENT_ENTITY_TYPE, $cardId, $limit, $offset);
|
||||
$result = [];
|
||||
foreach ($comments as $comment) {
|
||||
$formattedComment = $this->formatComment($comment);
|
||||
@@ -91,13 +96,13 @@ class CommentService {
|
||||
* @throws BadRequestException
|
||||
* @throws NotFoundException|NoPermissionException
|
||||
*/
|
||||
public function create(int $cardId, string $message, int $replyTo = 0): DataResponse {
|
||||
public function create(int $cardId, string $message, string $replyTo = '0'): DataResponse {
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
|
||||
// Check if parent is a comment on the same card
|
||||
if ($replyTo !== 0) {
|
||||
if ($replyTo !== '0') {
|
||||
try {
|
||||
$comment = $this->commentsManager->get((string)$replyTo);
|
||||
$comment = $this->commentsManager->get($replyTo);
|
||||
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || (int)$comment->getObjectId() !== $cardId) {
|
||||
throw new CommentNotFoundException();
|
||||
}
|
||||
@@ -110,7 +115,7 @@ class CommentService {
|
||||
$comment = $this->commentsManager->create('users', $this->userId, Application::COMMENT_ENTITY_TYPE, (string)$cardId);
|
||||
$comment->setMessage($message);
|
||||
$comment->setVerb('comment');
|
||||
$comment->setParentId((string)$replyTo);
|
||||
$comment->setParentId($replyTo);
|
||||
$this->commentsManager->save($comment);
|
||||
return new DataResponse($this->formatComment($comment, true));
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
@@ -123,8 +128,14 @@ class CommentService {
|
||||
}
|
||||
}
|
||||
|
||||
public function update(int $cardId, int $commentId, string $message): DataResponse {
|
||||
$comment = $this->get($cardId, $commentId);
|
||||
public function update(string $cardId, string $commentId, string $message): DataResponse {
|
||||
if (!is_numeric($cardId)) {
|
||||
throw new BadRequestException('A valid card id must be provided');
|
||||
}
|
||||
if (!is_numeric($commentId)) {
|
||||
throw new BadRequestException('A valid comment id must be provided');
|
||||
}
|
||||
$comment = $this->get((int)$cardId, (int)$commentId);
|
||||
if ($comment->getActorType() !== 'users' || $comment->getActorId() !== $this->userId) {
|
||||
throw new NoPermissionException('Only authors are allowed to edit their comment.');
|
||||
}
|
||||
@@ -134,12 +145,18 @@ class CommentService {
|
||||
return new DataResponse($this->formatComment($comment));
|
||||
}
|
||||
|
||||
public function delete(int $cardId, int $commentId): DataResponse {
|
||||
public function delete(string $cardId, string $commentId): DataResponse {
|
||||
if (!is_numeric($cardId)) {
|
||||
throw new BadRequestException('A valid card id must be provided');
|
||||
}
|
||||
if (!is_numeric($commentId)) {
|
||||
throw new BadRequestException('A valid comment id must be provided');
|
||||
}
|
||||
$this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ);
|
||||
|
||||
try {
|
||||
$comment = $this->commentsManager->get((string)$commentId);
|
||||
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || (int)$comment->getObjectId() !== $cardId) {
|
||||
$comment = $this->commentsManager->get($commentId);
|
||||
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) {
|
||||
throw new CommentNotFoundException();
|
||||
}
|
||||
} catch (CommentNotFoundException $e) {
|
||||
@@ -148,11 +165,11 @@ class CommentService {
|
||||
if ($comment->getActorType() !== 'users' || $comment->getActorId() !== $this->userId) {
|
||||
throw new NoPermissionException('Only authors are allowed to edit their comment.');
|
||||
}
|
||||
$this->commentsManager->delete((string)$commentId);
|
||||
$this->commentsManager->delete($commentId);
|
||||
return new DataResponse([]);
|
||||
}
|
||||
|
||||
private function formatComment(IComment $comment, bool $addReplyTo = false): array {
|
||||
private function formatComment(IComment $comment, $addReplyTo = false): array {
|
||||
$actorDisplayName = $this->userManager->getDisplayName($comment->getActorId()) ?? $comment->getActorId();
|
||||
|
||||
$formattedComment = [
|
||||
|
||||
@@ -48,8 +48,7 @@ class ConfigService {
|
||||
}
|
||||
|
||||
public function getAll(): array {
|
||||
$userId = $this->getUserId();
|
||||
if ($userId === null) {
|
||||
if ($this->getUserId() === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -58,7 +57,7 @@ class ConfigService {
|
||||
'cardDetailsInModal' => $this->isCardDetailsInModal(),
|
||||
'cardIdBadge' => $this->isCardIdBadgeEnabled()
|
||||
];
|
||||
if ($this->groupManager->isAdmin($userId)) {
|
||||
if ($this->groupManager->isAdmin($this->getUserId())) {
|
||||
$data['groupLimit'] = $this->get('groupLimit');
|
||||
}
|
||||
return $data;
|
||||
@@ -96,48 +95,44 @@ class ConfigService {
|
||||
}
|
||||
|
||||
public function isCalendarEnabled(?int $boardId = null): bool {
|
||||
$userId = $this->getUserId();
|
||||
if ($userId === null) {
|
||||
if ($this->getUserId() === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$appConfigState = $this->config->getAppValue(Application::APP_ID, 'calendar', 'yes') === 'yes';
|
||||
$defaultState = (bool)$this->config->getUserValue($userId, Application::APP_ID, 'calendar', $appConfigState);
|
||||
$defaultState = (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'calendar', $appConfigState);
|
||||
if ($boardId === null) {
|
||||
return $defaultState;
|
||||
}
|
||||
|
||||
return (bool)$this->config->getUserValue($userId, Application::APP_ID, 'board:' . $boardId . ':calendar', $defaultState);
|
||||
return (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'board:' . $boardId . ':calendar', $defaultState);
|
||||
}
|
||||
|
||||
public function isCardDetailsInModal(?int $boardId = null): bool {
|
||||
$userId = $this->getUserId();
|
||||
if ($userId === null) {
|
||||
if ($this->getUserId() === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$defaultState = (bool)$this->config->getUserValue($userId, Application::APP_ID, 'cardDetailsInModal', true);
|
||||
$defaultState = (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'cardDetailsInModal', true);
|
||||
if ($boardId === null) {
|
||||
return $defaultState;
|
||||
}
|
||||
|
||||
return (bool)$this->config->getUserValue($userId, Application::APP_ID, 'board:' . $boardId . ':cardDetailsInModal', $defaultState);
|
||||
return (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'board:' . $boardId . ':cardDetailsInModal', $defaultState);
|
||||
}
|
||||
|
||||
public function isCardIdBadgeEnabled(): bool {
|
||||
$userId = $this->getUserId();
|
||||
if ($userId === null) {
|
||||
if ($this->getUserId() === null) {
|
||||
return false;
|
||||
}
|
||||
$appConfigState = $this->config->getAppValue(Application::APP_ID, 'cardIdBadge', 'yes') === 'no';
|
||||
$defaultState = (bool)$this->config->getUserValue($userId, Application::APP_ID, 'cardIdBadge', $appConfigState);
|
||||
$defaultState = (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'cardIdBadge', $appConfigState);
|
||||
|
||||
return (bool)$this->config->getUserValue($userId, Application::APP_ID, 'cardIdBadge', $defaultState);
|
||||
return (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'cardIdBadge', $defaultState);
|
||||
}
|
||||
|
||||
public function set($key, $value) {
|
||||
$userId = $this->getUserId();
|
||||
if ($userId === null) {
|
||||
if ($this->getUserId() === null) {
|
||||
throw new NoPermissionException('Must be logged in to set user config');
|
||||
}
|
||||
|
||||
@@ -145,21 +140,21 @@ class ConfigService {
|
||||
[$scope] = explode(':', $key, 2);
|
||||
switch ($scope) {
|
||||
case 'groupLimit':
|
||||
if (!$this->groupManager->isAdmin($userId)) {
|
||||
if (!$this->groupManager->isAdmin($this->getUserId())) {
|
||||
throw new NoPermissionException('You must be admin to set the group limit');
|
||||
}
|
||||
$result = $this->setGroupLimit($value);
|
||||
break;
|
||||
case 'calendar':
|
||||
$this->config->setUserValue($userId, Application::APP_ID, 'calendar', (string)$value);
|
||||
$this->config->setUserValue($this->getUserId(), Application::APP_ID, 'calendar', (string)$value);
|
||||
$result = $value;
|
||||
break;
|
||||
case 'cardDetailsInModal':
|
||||
$this->config->setUserValue($userId, Application::APP_ID, 'cardDetailsInModal', (string)$value);
|
||||
$this->config->setUserValue($this->getUserId(), Application::APP_ID, 'cardDetailsInModal', (string)$value);
|
||||
$result = $value;
|
||||
break;
|
||||
case 'cardIdBadge':
|
||||
$this->config->setUserValue($userId, Application::APP_ID, 'cardIdBadge', (string)$value);
|
||||
$this->config->setUserValue($this->getUserId(), Application::APP_ID, 'cardIdBadge', (string)$value);
|
||||
$result = $value;
|
||||
break;
|
||||
case 'board':
|
||||
@@ -167,7 +162,7 @@ class ConfigService {
|
||||
if ($boardConfigKey === 'notify-due' && !in_array($value, [self::SETTING_BOARD_NOTIFICATION_DUE_ALL, self::SETTING_BOARD_NOTIFICATION_DUE_ASSIGNED, self::SETTING_BOARD_NOTIFICATION_DUE_OFF], true)) {
|
||||
throw new BadRequestException('Board notification option must be one of: off, assigned, all');
|
||||
}
|
||||
$this->config->setUserValue($userId, Application::APP_ID, $key, (string)$value);
|
||||
$this->config->setUserValue($this->getUserId(), Application::APP_ID, $key, (string)$value);
|
||||
$result = $value;
|
||||
}
|
||||
return $result;
|
||||
|
||||
@@ -9,7 +9,6 @@ namespace OCA\Deck\Service;
|
||||
|
||||
use OCA\Deck\AppInfo\Application;
|
||||
use OCA\Deck\BadRequestException;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
@@ -22,8 +21,6 @@ class DefaultBoardService {
|
||||
private $cardService;
|
||||
private $config;
|
||||
private $l10n;
|
||||
private LabelService $labelService;
|
||||
private AttachmentService $attachmentService;
|
||||
|
||||
public function __construct(
|
||||
IL10N $l10n,
|
||||
@@ -32,8 +29,6 @@ class DefaultBoardService {
|
||||
StackService $stackService,
|
||||
CardService $cardService,
|
||||
IConfig $config,
|
||||
LabelService $labelService,
|
||||
AttachmentService $attachmentService,
|
||||
) {
|
||||
$this->boardService = $boardService;
|
||||
$this->stackService = $stackService;
|
||||
@@ -41,8 +36,6 @@ class DefaultBoardService {
|
||||
$this->config = $config;
|
||||
$this->boardMapper = $boardMapper;
|
||||
$this->l10n = $l10n;
|
||||
$this->labelService = $labelService;
|
||||
$this->attachmentService = $attachmentService;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,13 +59,10 @@ class DefaultBoardService {
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getDefaultBoardData(): array {
|
||||
$defaultBoardDataJson = file_get_contents(__DIR__ . '/fixtures/default-board.json');
|
||||
return json_decode($defaultBoardDataJson, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $userId
|
||||
* @param $color
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCA\Deck\StatusException
|
||||
@@ -81,71 +71,19 @@ class DefaultBoardService {
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function createDefaultBoard(string $title, string $userId, string $color) {
|
||||
$boardData = $this->getDefaultBoardData();
|
||||
$defaultBoard = $this->boardService->create($title, $userId, $color);
|
||||
$defaultStacks = [];
|
||||
$defaultCards = [];
|
||||
|
||||
/** @var Board $defaultBoard */
|
||||
$defaultBoard = $this->boardService->create(
|
||||
$boardData['title'] ?? $title,
|
||||
$userId,
|
||||
$boardData['color'] ?? $color,
|
||||
);
|
||||
$boardId = $defaultBoard->getId();
|
||||
$additionLabels = [];
|
||||
$translatedLabelTitles = [
|
||||
'Read more inside' => $this->l10n->t('Read more inside'),
|
||||
];
|
||||
$translatedStackTitles = [
|
||||
'Custom lists - click to rename!' => $this->l10n->t('Custom lists - click to rename!'),
|
||||
'To Do' => $this->l10n->t('To Do'),
|
||||
'In Progress' => $this->l10n->t('In Progress'),
|
||||
'Done' => $this->l10n->t('Done'),
|
||||
];
|
||||
$translatedCardTitles = [
|
||||
'1. Open to learn more about boards and cards' => $this->l10n->t('1. Open to learn more about boards and cards'),
|
||||
'2. Drag cards left and right, up and down' => $this->l10n->t('2. Drag cards left and right, up and down'),
|
||||
'3. Apply rich formatting and link content' => $this->l10n->t('3. Apply rich formatting and link content'),
|
||||
'4. Share, comment and collaborate!' => $this->l10n->t('4. Share, comment and collaborate!'),
|
||||
'Create your first card!' => $this->l10n->t('Create your first card!'),
|
||||
];
|
||||
|
||||
foreach ($boardData['addition_labels'] as $labelData) {
|
||||
$additionLabels[] = $this->labelService->create(
|
||||
$translatedLabelTitles[$labelData['title']] ?? $labelData['title'],
|
||||
$labelData['color'],
|
||||
$boardId
|
||||
);
|
||||
}
|
||||
$defaultStacks[] = $this->stackService->create($this->l10n->t('To do'), $boardId, 1);
|
||||
$defaultStacks[] = $this->stackService->create($this->l10n->t('Doing'), $boardId, 1);
|
||||
$defaultStacks[] = $this->stackService->create($this->l10n->t('Done'), $boardId, 1);
|
||||
|
||||
$defaultLabels = array_merge($defaultBoard->getLabels() ?? [], $additionLabels);
|
||||
|
||||
foreach ($boardData['stacks'] as $stackData) {
|
||||
$stack = $this->stackService->create(
|
||||
$translatedStackTitles[$stackData['title']] ?? $stackData['title'],
|
||||
$boardId,
|
||||
$stackData['order']
|
||||
);
|
||||
|
||||
foreach ($stackData['cards'] as $cardData) {
|
||||
$card = $this->cardService->create(
|
||||
$translatedCardTitles[$cardData['title']] ?? $cardData['title'],
|
||||
$stack->getId(),
|
||||
$cardData['type'],
|
||||
$cardData['order'],
|
||||
$userId,
|
||||
$cardData['description'],
|
||||
);
|
||||
|
||||
foreach ($defaultLabels as $defaultLabel) {
|
||||
if ($defaultLabel && in_array($defaultLabel->getTitle(), $cardData['labels'])) {
|
||||
$this->cardService->assignLabel($card->getId(), $defaultLabel->getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($cardData['has_example_attachment'])) {
|
||||
$this->attachmentService->create($card->getId(), 'file', 'DEFAULT_SAMPLE_FILE');
|
||||
}
|
||||
}
|
||||
}
|
||||
$defaultCards[] = $this->cardService->create($this->l10n->t('Example Task 3'), $defaultStacks[0]->getId(), 'text', 0, $userId);
|
||||
$defaultCards[] = $this->cardService->create($this->l10n->t('Example Task 2'), $defaultStacks[1]->getId(), 'text', 0, $userId);
|
||||
$defaultCards[] = $this->cardService->create($this->l10n->t('Example Task 1'), $defaultStacks[2]->getId(), 'text', 0, $userId);
|
||||
|
||||
return $defaultBoard;
|
||||
}
|
||||
|
||||
@@ -162,15 +162,7 @@ class FilesAppService implements IAttachmentService, ICustomAttachmentService {
|
||||
}
|
||||
|
||||
public function create(Attachment $attachment) {
|
||||
if ($attachment->getData() === 'DEFAULT_SAMPLE_FILE' && !$this->request->getUploadedFile('file')) {
|
||||
$file = [
|
||||
'name' => 'Nextcloud sample image - add your image here!.jpg',
|
||||
'tmp_name' => __DIR__ . '/../../img/sample-image.jpg',
|
||||
];
|
||||
} else {
|
||||
$file = $this->getUploadedFile();
|
||||
}
|
||||
|
||||
$file = $this->getUploadedFile();
|
||||
$fileName = $file['name'];
|
||||
|
||||
// get shares for current card
|
||||
|
||||
@@ -124,15 +124,18 @@ class FullTextSearchService {
|
||||
|
||||
|
||||
/**
|
||||
* @param int $cardId
|
||||
*
|
||||
* @return Board
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function getBoardFromCardId(int $cardId): Board {
|
||||
$boardId = $this->cardMapper->findBoardId($cardId);
|
||||
if ($boardId === null) {
|
||||
throw new DoesNotExistException("Board '$cardId' does not exist");
|
||||
}
|
||||
return $this->boardMapper->find($boardId);
|
||||
$boardId = (int)$this->cardMapper->findBoardId($cardId);
|
||||
/** @var Board $board */
|
||||
$board = $this->boardMapper->find($boardId);
|
||||
|
||||
return $board;
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +145,7 @@ class FullTextSearchService {
|
||||
* @return Card[]
|
||||
*/
|
||||
private function getCardsFromStack(int $stackId): array {
|
||||
return $this->cardMapper->findAll($stackId);
|
||||
return $this->cardMapper->findAll($stackId, null, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +155,7 @@ class FullTextSearchService {
|
||||
* @return Stack[]
|
||||
*/
|
||||
private function getStacksFromBoard(int $boardId): array {
|
||||
return $this->stackMapper->findAll($boardId);
|
||||
return $this->stackMapper->findAll($boardId, null, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +165,6 @@ class FullTextSearchService {
|
||||
* @return Board[]
|
||||
*/
|
||||
private function getBoardsFromUser(string $userId): array {
|
||||
return $this->boardMapper->findAllByUser($userId);
|
||||
return $this->boardMapper->findAllByUser($userId, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,25 +19,29 @@ use OCP\Comments\IComment;
|
||||
abstract class ABoardImportService {
|
||||
/** @var string */
|
||||
public static $name = '';
|
||||
private BoardImportService $boardImportService;
|
||||
protected bool $needValidateData = true;
|
||||
/** @var BoardImportService */
|
||||
private $boardImportService;
|
||||
/** @var bool */
|
||||
protected $needValidateData = true;
|
||||
/** @var Stack[] */
|
||||
protected array $stacks = [];
|
||||
protected $stacks = [];
|
||||
/** @var Label[] */
|
||||
protected array $labels = [];
|
||||
protected $labels = [];
|
||||
/** @var Card[] */
|
||||
protected array $cards = [];
|
||||
protected $cards = [];
|
||||
/** @var Acl[] */
|
||||
protected array $acls = [];
|
||||
protected $acls = [];
|
||||
/** @var IComment[][] */
|
||||
protected array $comments = [];
|
||||
protected $comments = [];
|
||||
/** @var Assignment[] */
|
||||
protected array $assignments = [];
|
||||
/** @var int[][] */
|
||||
protected array $labelCardAssignments = [];
|
||||
protected $assignments = [];
|
||||
/** @var string[][] */
|
||||
protected $labelCardAssignments = [];
|
||||
|
||||
/**
|
||||
* Configure import service
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function bootstrap(): void;
|
||||
|
||||
@@ -64,13 +68,10 @@ abstract class ABoardImportService {
|
||||
|
||||
abstract public function getCardAssignments(): array;
|
||||
|
||||
/**
|
||||
* @return array<int, array<int, int>>
|
||||
*/
|
||||
abstract public function getCardLabelAssignment(): array;
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, IComment>>
|
||||
* @return IComment[][]|array
|
||||
*/
|
||||
abstract public function getComments(): array;
|
||||
|
||||
@@ -97,16 +98,16 @@ abstract class ABoardImportService {
|
||||
$this->acls[$code] = $acl;
|
||||
}
|
||||
|
||||
public function updateComment(int $cardId, string $commentId, IComment $comment): void {
|
||||
public function updateComment(string $cardId, string $commentId, IComment $comment): void {
|
||||
$this->comments[$cardId][$commentId] = $comment;
|
||||
}
|
||||
|
||||
public function updateCardAssignment(int $cardId, int $assignmentId, Entity $assignment): void {
|
||||
public function updateCardAssignment(string $cardId, string $assignmentId, Entity $assignment): void {
|
||||
$this->assignments[$cardId][$assignmentId] = $assignment;
|
||||
}
|
||||
|
||||
public function updateCardLabelsAssignment(int $cardId, int $assignmentId, int $labelId): void {
|
||||
$this->labelCardAssignments[$cardId][$assignmentId] = $labelId;
|
||||
public function updateCardLabelsAssignment(string $cardId, string $assignmentId, string $assignment): void {
|
||||
$this->labelCardAssignments[$cardId][$assignmentId] = $assignment;
|
||||
}
|
||||
|
||||
public function setImportService(BoardImportService $service): void {
|
||||
|
||||
@@ -209,15 +209,14 @@ class BoardImportService {
|
||||
|
||||
public function importBoard(): void {
|
||||
$board = $this->getImportSystem()->getBoard();
|
||||
if ($board === null) {
|
||||
throw new \LogicException('Import board not found');
|
||||
}
|
||||
if (!$this->userManager->userExists($board->getOwner())) {
|
||||
throw new \Exception('Target owner ' . $board->getOwner() . ' not found. Please provide a mapping through the import config.');
|
||||
}
|
||||
|
||||
$this->boardMapper->insert($board);
|
||||
$this->board = $board;
|
||||
if ($board) {
|
||||
$this->boardMapper->insert($board);
|
||||
$this->board = $board;
|
||||
}
|
||||
}
|
||||
|
||||
public function getBoard(bool $reset = false): Board {
|
||||
@@ -293,7 +292,12 @@ class BoardImportService {
|
||||
}
|
||||
}
|
||||
|
||||
public function assignCardToLabel(int $cardId, int $labelId): self {
|
||||
/**
|
||||
* @param mixed $cardId
|
||||
* @param mixed $labelId
|
||||
* @return self
|
||||
*/
|
||||
public function assignCardToLabel($cardId, $labelId): self {
|
||||
$this->cardMapper->assignLabel(
|
||||
$cardId,
|
||||
$labelId
|
||||
@@ -303,14 +307,14 @@ class BoardImportService {
|
||||
|
||||
public function assignCardsToLabels(): void {
|
||||
$data = $this->getImportSystem()->getCardLabelAssignment();
|
||||
foreach ($data as $cardId => $assignment) {
|
||||
foreach ($assignment as $assignmentId => $labelId) {
|
||||
foreach ($data as $cardId => $assignemnt) {
|
||||
foreach ($assignemnt as $assignmentId => $labelId) {
|
||||
try {
|
||||
$this->assignCardToLabel(
|
||||
(int)$cardId,
|
||||
$cardId,
|
||||
$labelId
|
||||
);
|
||||
$this->getImportSystem()->updateCardLabelsAssignment((int)$cardId, (int)$assignmentId, $labelId);
|
||||
$this->getImportSystem()->updateCardLabelsAssignment($cardId, $assignmentId, $labelId);
|
||||
} catch (\Exception $e) {
|
||||
$this->addError('Failed to assign label ' . $labelId . ' to ' . $cardId, $e);
|
||||
}
|
||||
@@ -322,20 +326,20 @@ class BoardImportService {
|
||||
$allComments = $this->getImportSystem()->getComments();
|
||||
foreach ($allComments as $cardId => $comments) {
|
||||
foreach ($comments as $commentId => $comment) {
|
||||
$this->insertComment((int)$cardId, $comment);
|
||||
$this->getImportSystem()->updateComment((int)$cardId, $commentId, $comment);
|
||||
$this->insertComment($cardId, $comment);
|
||||
$this->getImportSystem()->updateComment($cardId, $commentId, $comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function insertComment(int $cardId, IComment $comment): void {
|
||||
$comment->setObject('deckCard', (string)$cardId);
|
||||
private function insertComment(string $cardId, IComment $comment): void {
|
||||
$comment->setObject('deckCard', $cardId);
|
||||
$comment->setVerb('comment');
|
||||
// Check if parent is a comment on the same card
|
||||
if ($comment->getParentId() !== '0') {
|
||||
try {
|
||||
$parent = $this->commentsManager->get($comment->getParentId());
|
||||
if ($parent->getObjectType() !== Application::COMMENT_ENTITY_TYPE || (int)$parent->getObjectId() !== $cardId) {
|
||||
if ($parent->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $parent->getObjectId() !== $cardId) {
|
||||
throw new CommentNotFoundException();
|
||||
}
|
||||
} catch (CommentNotFoundException $e) {
|
||||
@@ -358,7 +362,7 @@ class BoardImportService {
|
||||
foreach ($assignments as $assignment) {
|
||||
try {
|
||||
$assignment = $this->assignmentMapper->insert($assignment);
|
||||
$this->getImportSystem()->updateCardAssignment((int)$cardId, $assignment->getId(), $assignment);
|
||||
$this->getImportSystem()->updateCardAssignment($cardId, (string)$assignment->getId(), $assignment);
|
||||
$this->addOutput('Assignment ' . $assignment->getParticipant() . ' added');
|
||||
} catch (NotFoundException $e) {
|
||||
$this->addError('No origin or mapping found for card "' . $cardId . '" and ' . $assignment->getTypeString() . ' assignment "' . $assignment->getParticipant(), $e);
|
||||
|
||||
@@ -16,7 +16,6 @@ use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Db\Stack;
|
||||
use OCA\Deck\Service\Importer\ABoardImportService;
|
||||
use OCP\Comments\IComment;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
|
||||
@@ -119,7 +118,6 @@ class DeckJsonService extends ABoardImportService {
|
||||
$comments[$this->cards[$sourceCard->id]->getId()][$commentOriginal->id] = $comment;
|
||||
}
|
||||
}
|
||||
/** @var array<int, array<string, IComment>> */
|
||||
return $comments;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ use Psr\Log\LoggerInterface;
|
||||
class TrelloApiService extends TrelloJsonService {
|
||||
/** @var string */
|
||||
public static $name = 'Trello API';
|
||||
protected bool $needValidateData = false;
|
||||
protected $needValidateData = false;
|
||||
/** @var IClient */
|
||||
private $httpClient;
|
||||
/** @var LoggerInterface */
|
||||
@@ -176,7 +176,7 @@ class TrelloApiService extends TrelloJsonService {
|
||||
if (empty($queryString['limit'])) {
|
||||
return [];
|
||||
}
|
||||
if ((count($data) < $queryString['limit']) || (count($data) === 0)) {
|
||||
if (count($data) < $queryString['limit']) {
|
||||
return [];
|
||||
}
|
||||
$queryString['before'] = end($data)->id;
|
||||
|
||||
@@ -159,7 +159,6 @@ class TrelloJsonService extends ABoardImportService {
|
||||
$comments[$cardId][$commentId] = $comment;
|
||||
}
|
||||
}
|
||||
/** @var array<int, array<string, IComment>> */
|
||||
return $comments;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,24 +43,33 @@ class LabelService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $labelId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function find(int $labelId): Label {
|
||||
public function find($labelId) {
|
||||
if (is_numeric($labelId) === false) {
|
||||
throw new BadRequestException('label id must be a number');
|
||||
}
|
||||
$this->permissionService->checkPermission($this->labelMapper, $labelId, Acl::PERMISSION_READ);
|
||||
return $this->labelMapper->find($labelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @param $boardId
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function create(string $title, string $color, int $boardId): Label {
|
||||
public function create($title, $color, $boardId) {
|
||||
$this->labelServiceValidator->check(compact('title', 'color', 'boardId'));
|
||||
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
|
||||
@@ -97,13 +106,15 @@ class LabelService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function delete(int $id): Label {
|
||||
public function delete($id) {
|
||||
$this->labelServiceValidator->check(compact('id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -116,13 +127,17 @@ class LabelService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $color
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function update(int $id, string $title, string $color): Label {
|
||||
public function update($id, $title, $color) {
|
||||
$this->labelServiceValidator->check(compact('title', 'color', 'id'));
|
||||
|
||||
$this->permissionService->checkPermission($this->labelMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
|
||||
@@ -9,28 +9,53 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\Deck\Service;
|
||||
|
||||
use OCA\Deck\Db\AssignmentMapper;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Db\LabelMapper;
|
||||
use OCA\Deck\Model\CardDetails;
|
||||
use OCP\Comments\ICommentsManager;
|
||||
use OCP\IUserManager;
|
||||
|
||||
class OverviewService {
|
||||
private CardService $cardService;
|
||||
private BoardMapper $boardMapper;
|
||||
private LabelMapper $labelMapper;
|
||||
private CardMapper $cardMapper;
|
||||
private AssignmentMapper $assignedUsersMapper;
|
||||
private IUserManager $userManager;
|
||||
private ICommentsManager $commentsManager;
|
||||
private AttachmentService $attachmentService;
|
||||
|
||||
public function __construct(
|
||||
private readonly CardService $cardService,
|
||||
private readonly BoardMapper $boardMapper,
|
||||
private readonly CardMapper $cardMapper,
|
||||
CardService $cardService,
|
||||
BoardMapper $boardMapper,
|
||||
LabelMapper $labelMapper,
|
||||
CardMapper $cardMapper,
|
||||
AssignmentMapper $assignedUsersMapper,
|
||||
IUserManager $userManager,
|
||||
ICommentsManager $commentsManager,
|
||||
AttachmentService $attachmentService,
|
||||
) {
|
||||
$this->cardService = $cardService;
|
||||
$this->boardMapper = $boardMapper;
|
||||
$this->labelMapper = $labelMapper;
|
||||
$this->cardMapper = $cardMapper;
|
||||
$this->assignedUsersMapper = $assignedUsersMapper;
|
||||
$this->userManager = $userManager;
|
||||
$this->commentsManager = $commentsManager;
|
||||
$this->attachmentService = $attachmentService;
|
||||
}
|
||||
|
||||
public function findUpcomingCards(string $userId): array {
|
||||
$userBoards = $this->boardMapper->findAllForUser($userId);
|
||||
|
||||
$boardOwnerIds = array_filter(array_map(function (Board $board) {
|
||||
return count($board->getAcl() ?? []) === 0 ? $board->getId() : null;
|
||||
return count($board->getAcl()) === 0 ? $board->getId() : null;
|
||||
}, $userBoards));
|
||||
$boardSharedIds = array_filter(array_map(function (Board $board) {
|
||||
return count($board->getAcl() ?? []) > 0 ? $board->getId() : null;
|
||||
return count($board->getAcl()) > 0 ? $board->getId() : null;
|
||||
}, $userBoards));
|
||||
|
||||
$foundCards = array_merge(
|
||||
|
||||
@@ -29,7 +29,6 @@ class PermissionService {
|
||||
private array $users = [];
|
||||
|
||||
private CappedMemoryCache $boardCache;
|
||||
/** @var CappedMemoryCache<array<Acl::PERMISSION_*, bool>> */
|
||||
private CappedMemoryCache $permissionCache;
|
||||
|
||||
public function __construct(
|
||||
@@ -50,16 +49,15 @@ class PermissionService {
|
||||
/**
|
||||
* Get current user permissions for a board by id
|
||||
*
|
||||
* @return array<Acl::PERMISSION_*, bool>
|
||||
* @return bool|array
|
||||
*/
|
||||
public function getPermissions(int $boardId, ?string $userId = null): array {
|
||||
public function getPermissions(int $boardId, ?string $userId = null) {
|
||||
if ($userId === null) {
|
||||
$userId = $this->userId;
|
||||
}
|
||||
|
||||
$cacheKey = $boardId . '-' . $userId;
|
||||
if ($cached = $this->permissionCache->get($cacheKey)) {
|
||||
/** @var array<Acl::PERMISSION_*, bool> $cached */
|
||||
return $cached;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,31 +75,35 @@ class StackService {
|
||||
$this->stackServiceValidator = $stackServiceValidator;
|
||||
}
|
||||
|
||||
/** @param Stack[] $stacks */
|
||||
private function enrichStacksWithCards(array $stacks, $since = -1): void {
|
||||
$cardsByStackId = $this->cardMapper->findAllForStacks(array_map(fn (Stack $stack) => $stack->getId(), $stacks), null, 0, $since);
|
||||
private function enrichStackWithCards($stack, $since = -1) {
|
||||
$cards = $this->cardMapper->findAll($stack->getId(), null, null, $since);
|
||||
|
||||
foreach ($cardsByStackId as $stackId => $cards) {
|
||||
if (!$cards) {
|
||||
continue;
|
||||
}
|
||||
if (\count($cards) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$stack->setCards($this->cardService->enrichCards($cards));
|
||||
}
|
||||
|
||||
foreach ($stacks as $stack) {
|
||||
if ($stack->getId() === $stackId) {
|
||||
$stack->setCards($this->cardService->enrichCards($cards));
|
||||
break;
|
||||
}
|
||||
}
|
||||
private function enrichStacksWithCards($stacks, $since = -1) {
|
||||
foreach ($stacks as $stack) {
|
||||
$this->enrichStackWithCards($stack, $since);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $stackId
|
||||
*
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function find(int $stackId): Stack {
|
||||
public function find($stackId) {
|
||||
if (is_numeric($stackId) === false) {
|
||||
throw new BadRequestException('stack id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_READ);
|
||||
$stack = $this->stackMapper->find($stackId);
|
||||
|
||||
@@ -120,11 +124,17 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @param $boardId
|
||||
*
|
||||
* @return array
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function findAll(int $boardId, int $since = -1): array {
|
||||
public function findAll($boardId, $since = -1) {
|
||||
if (is_numeric($boardId) === false) {
|
||||
throw new BadRequestException('boardId must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_READ);
|
||||
$stacks = $this->stackMapper->findAll($boardId);
|
||||
$this->enrichStacksWithCards($stacks, $since);
|
||||
@@ -132,11 +142,7 @@ class StackService {
|
||||
return $stacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findCalendarEntries(int $boardId): array {
|
||||
public function findCalendarEntries($boardId) {
|
||||
try {
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_READ);
|
||||
} catch (NoPermissionException $e) {
|
||||
@@ -146,11 +152,7 @@ class StackService {
|
||||
return $this->stackMapper->findAll($boardId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function fetchDeleted(int $boardId): array {
|
||||
public function fetchDeleted($boardId) {
|
||||
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ);
|
||||
$stacks = $this->stackMapper->findDeleted($boardId);
|
||||
$this->enrichStacksWithCards($stacks);
|
||||
@@ -159,11 +161,17 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack[]
|
||||
* @param $boardId
|
||||
*
|
||||
* @return array
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function findAllArchived(int $boardId): array {
|
||||
public function findAllArchived($boardId) {
|
||||
if (is_numeric($boardId) === false) {
|
||||
throw new BadRequestException('board id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_READ);
|
||||
$stacks = $this->stackMapper->findAll($boardId);
|
||||
$labels = $this->labelMapper->getAssignedLabelsForBoard($boardId);
|
||||
@@ -178,18 +186,22 @@ class StackService {
|
||||
$stacks[$stackIndex]->setCards($cards);
|
||||
}
|
||||
|
||||
/** @var Stack[] $stacks */
|
||||
return $stacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param $boardId
|
||||
* @param integer $order
|
||||
*
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function create(string $title, int $boardId, int $order): Stack {
|
||||
public function create($title, $boardId, $order) {
|
||||
$this->stackServiceValidator->check(compact('title', 'boardId', 'order'));
|
||||
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE);
|
||||
@@ -211,13 +223,19 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stack The deleted stack.
|
||||
* @param $id
|
||||
*
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function delete(int $id): Stack {
|
||||
public function delete($id) {
|
||||
if (is_numeric($id) === false) {
|
||||
throw new BadRequestException('stack id must be a number');
|
||||
}
|
||||
|
||||
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
|
||||
$stack = $this->stackMapper->find($id);
|
||||
@@ -229,19 +247,26 @@ class StackService {
|
||||
);
|
||||
$this->changeHelper->boardChanged($stack->getBoardId());
|
||||
$this->eventDispatcher->dispatchTyped(new BoardUpdatedEvent($stack->getBoardId()));
|
||||
$this->enrichStacksWithCards([$stack]);
|
||||
$this->enrichStackWithCards($stack);
|
||||
|
||||
return $stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @param $title
|
||||
* @param $boardId
|
||||
* @param $order
|
||||
* @param $deletedAt
|
||||
*
|
||||
* @return \OCP\AppFramework\Db\Entity
|
||||
* @throws StatusException
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function update(int $id, string $title, int $boardId, int $order, ?int $deletedAt): Stack {
|
||||
public function update($id, $title, $boardId, $order, $deletedAt) {
|
||||
$this->stackServiceValidator->check(compact('id', 'title', 'boardId', 'order'));
|
||||
|
||||
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -269,13 +294,16 @@ class StackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, Stack> The stacks in the correct order.
|
||||
* @param $id
|
||||
* @param $order
|
||||
*
|
||||
* @return array
|
||||
* @throws \OCA\Deck\NoPermissionException
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
* @throws BadRequestException
|
||||
*/
|
||||
public function reorder(int $id, int $order): array {
|
||||
public function reorder($id, $order) {
|
||||
$this->stackServiceValidator->check(compact('id', 'order'));
|
||||
|
||||
$this->permissionService->checkPermission($this->stackMapper, $id, Acl::PERMISSION_MANAGE);
|
||||
@@ -296,7 +324,7 @@ class StackService {
|
||||
if ($stack->id !== $id) {
|
||||
$stack->setOrder($i++);
|
||||
}
|
||||
$stack = $this->stackMapper->update($stack);
|
||||
$this->stackMapper->update($stack);
|
||||
$result[$stack->getOrder()] = $stack;
|
||||
}
|
||||
$this->changeHelper->boardChanged($stackToSort->getBoardId());
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
{
|
||||
"color": "bf678b",
|
||||
"addition_labels": [
|
||||
{
|
||||
"title": "Read more inside",
|
||||
"color": "CC317C"
|
||||
}
|
||||
],
|
||||
"stacks": [
|
||||
{
|
||||
"title": "Custom lists - click to rename!",
|
||||
"order": 0,
|
||||
"cards": [
|
||||
{
|
||||
"title": "1. Open to learn more about boards and cards",
|
||||
"description": "## Welcome to Nextcloud Deck!\n\nNextcloud Deck is a kanban style project management app that integrates seamlessly with the Nextcloud ecosystem. Here, you can create and manage boards to streamline your projects and organize project tasks visually using cards. A versatile tool, Nextcloud Deck will help you stay efficient in both personal and collaborative settings!\n\n### \ud83d\udccc How to set up a new board?\n\nAdd a new board via the \u201c+\u201d button or \u201cAdd board\u201d. Name your board and add a description to clarify its purpose if you wish.\n\nAdd task lists to your board via \u201cAdd List\u201d (e.g., \"To Do\"). Add cards to these lists to represent individual tasks or items. Organize your cards visually by assigning labels or colors.\n\nManage your board list: In the board menu next to the board name, you can edit, clone, archive and export your boards.\n\n### \ud83d\uddc2\ufe0f How to create and edit task cards?\n\nAdd cards via the \u201c+\u201d button on top of the list of your choice. Name your card and add a description using the available rich text formatting instruments.\n\nSet a due date to track deadlines and add responsible team members. Label your cards with tags for better navigation. You can create and manage tags in the sidebar, which is accessible via the toolbar button.\n\n### \ud83d\udca1Useful tips for Nextcloud Deck\n\n- Integrate Nextcloud Deck with Nextcloud Calendar and track the upcoming card deadlines.\n- Use comments to keep discussions around a task within its dedicated card.\n- Enable Nextcloud Deck notifications to always stay updated on changes to your boards.",
|
||||
"labels": [
|
||||
"Read more inside"
|
||||
],
|
||||
"type": "text",
|
||||
"order": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "To Do",
|
||||
"order": 1,
|
||||
"cards": [
|
||||
{
|
||||
"title": "2. Drag cards left and right, up and down",
|
||||
"description": "## \ud83d\udea6 Manage your boards and cards\n\nDrag your cards around the board to change position in the list or move them to other lists.\n\nArchive cards to remove them from the board without losing your content. You can always access archived cards and put them back by going to \"Show archived cards\" in the board menu.\n\nUse tags to assign types, statuses and other special attributes to your cards to aid visual navigation. Open the \"Tags\" tab in the sidebar of Nextcloud Deck to manage tags you can add to your cards.\n\n## \ud83d\udc53 Change how you view your boards\n\nTo navigate large boards easily, you can filter your cards by tags, team members, statuses and due dates. Open filter menu via Nextcloud Deck toolbar.\n\nEnable compact display mode in the Deck Board menu via the three dots menu in the toolbar. In the same menu, you can disable and enable cover images.",
|
||||
"labels": [
|
||||
"Read more inside"
|
||||
],
|
||||
"type": "text",
|
||||
"order": 0
|
||||
},
|
||||
{
|
||||
"title": "Create your first card!",
|
||||
"description": "",
|
||||
"labels": [
|
||||
"Action needed"
|
||||
],
|
||||
"type": "text",
|
||||
"order": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "In Progress",
|
||||
"order": 2,
|
||||
"cards": [
|
||||
{
|
||||
"title": "3. Apply rich formatting and link content",
|
||||
"description": "## \ud83c\udfa8 Make use of rich formatting in card descriptions\n\nYou can use various instruments to make your content more structured and informative. Try all the instruments yourself - use this checklist!\n\n- [ ] Apply headings of different hierarchy (H1-H6).\n- [ ] Use **bold** *italic* __underline__ and ~~strikethrough~~ text formatting.\n- [ ] Create unordered, ordered and to-do lists.\n- [ ] Highlight code and blockquotes, add various illustrated callouts.\n- [ ] Create and format tables\n- [ ] Add details\n- [ ] Add links, for example to [the Nextcloud website](https:\/\/nextcloud.com\/)\n- [ ] Insert attachments\n- [ ] Add emojis \ud83d\udd76\ufe0f \n\n## \ud83d\udd17 Attach files to cards\n\nYou can upload any files from your machine or pick from your Nextcloud Files, such as documents, presentations, images, video clips and anything else. Add files via \"Attachments\" tab.\n\n## \ud83c\udf04 Illustrate cards with images\n\nAttach images to your cards - they will automatically work as card covers.",
|
||||
"labels": [
|
||||
"Read more inside"
|
||||
],
|
||||
"type": "text",
|
||||
"order": 0,
|
||||
"has_example_attachment": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Done",
|
||||
"order": 3,
|
||||
"cards": [
|
||||
{
|
||||
"title": "4. Share, comment and collaborate!",
|
||||
"description": "## \ud83e\udd1d How to collaborate in your board?\n\nShare your cards and boards with others. In many Nextcloud apps, linked Nextcloud Deck items will appear as rich, interactive widgets. Once you assign someone to a card, they will receive a notification.\n\nEdit cards together, leave notes for your teammates, share task-related files by adding attachments and discuss your tasks using card comments.\n\n### ",
|
||||
"labels": [
|
||||
"Read more inside"
|
||||
],
|
||||
"type": "text",
|
||||
"order": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace OCA\Deck\Sharing;
|
||||
use OC\Files\Cache\Cache;
|
||||
use OCA\Deck\Cache\AttachmentCacheHelper;
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Db\User;
|
||||
@@ -98,13 +99,9 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function create(IShare $share) {
|
||||
$cardId = (int)$share->getSharedWith();
|
||||
$cardId = $share->getSharedWith();
|
||||
$boardId = $this->cardMapper->findBoardId($cardId);
|
||||
$valid = $boardId !== null;
|
||||
if (!$valid) {
|
||||
throw new GenericShareException('Card not found', $this->l->t('Card not found'), 404);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_EDIT);
|
||||
} catch (NoPermissionException $e) {
|
||||
@@ -150,7 +147,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
);
|
||||
$data = $this->getRawShare($shareId);
|
||||
|
||||
$this->attachmentCacheHelper->clearAttachmentCount($cardId);
|
||||
$this->attachmentCacheHelper->clearAttachmentCount((int)$cardId);
|
||||
|
||||
return $this->createShareObject($data);
|
||||
}
|
||||
@@ -216,7 +213,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->from('share')
|
||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
|
||||
@@ -300,7 +297,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
|
||||
->executeStatement();
|
||||
->execute();
|
||||
|
||||
/*
|
||||
* Update all user defined group shares
|
||||
@@ -313,7 +310,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||
->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
|
||||
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
|
||||
->executeStatement();
|
||||
->execute();
|
||||
|
||||
/*
|
||||
* Now update the permissions for all children that have not set it to 0
|
||||
@@ -323,7 +320,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
|
||||
->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0)))
|
||||
->set('permissions', $qb->createNamedParameter($share->getPermissions()))
|
||||
->executeStatement();
|
||||
->execute();
|
||||
|
||||
return $share;
|
||||
}
|
||||
@@ -338,7 +335,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
|
||||
$qb->orWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())));
|
||||
|
||||
$qb->executeStatement();
|
||||
$qb->execute();
|
||||
|
||||
$this->attachmentCacheHelper->clearAttachmentCount((int)$share->getSharedWith());
|
||||
}
|
||||
@@ -358,7 +355,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
|
||||
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
|
||||
))
|
||||
->executeQuery();
|
||||
->execute();
|
||||
|
||||
$data = $stmt->fetch();
|
||||
$stmt->closeCursor();
|
||||
@@ -379,14 +376,14 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
'file_target' => $qb->createNamedParameter($share->getTarget()),
|
||||
'permissions' => $qb->createNamedParameter(0),
|
||||
'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
|
||||
])->executeStatement();
|
||||
])->execute();
|
||||
} elseif ($data['permissions'] !== 0) {
|
||||
// Already a userroom share. Update it.
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->update('share')
|
||||
->set('permissions', $qb->createNamedParameter(0))
|
||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
|
||||
->executeStatement();
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,7 +397,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->where(
|
||||
$qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))
|
||||
);
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
|
||||
@@ -417,7 +414,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
$qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))
|
||||
);
|
||||
|
||||
$qb->executeStatement();
|
||||
$qb->execute();
|
||||
|
||||
return $this->getShareById((int)$share->getId(), $recipient);
|
||||
}
|
||||
@@ -438,7 +435,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
|
||||
))
|
||||
->setMaxResults(1)
|
||||
->executeQuery();
|
||||
->execute();
|
||||
|
||||
$data = $stmt->fetch();
|
||||
$stmt->closeCursor();
|
||||
@@ -512,7 +509,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
|
||||
$qb->orderBy('s.id');
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$shares = [];
|
||||
while ($data = $cursor->fetch()) {
|
||||
$shares[$data['fileid']][] = $this->createShareObject($data);
|
||||
@@ -557,7 +554,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
$qb->setFirstResult($offset);
|
||||
$qb->orderBy('id');
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$shares = [];
|
||||
while ($data = $cursor->fetch()) {
|
||||
$shares[] = $this->createShareObject($data);
|
||||
@@ -585,7 +582,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->where($qb->expr()->eq('s.id', $qb->createNamedParameter($id)))
|
||||
->andWhere($qb->expr()->eq('s.share_type', $qb->createNamedParameter(IShare::TYPE_DECK)));
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
|
||||
@@ -650,7 +647,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
|
||||
));
|
||||
|
||||
$stmt = $query->executeQuery();
|
||||
$stmt = $query->execute();
|
||||
|
||||
while ($data = $stmt->fetch()) {
|
||||
$this->applyBoardPermission($shareMap[$data['parent']], (int)$data['permissions'], $userId);
|
||||
@@ -680,7 +677,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->from('share')
|
||||
->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
|
||||
->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_DECK)))
|
||||
->executeQuery();
|
||||
->execute();
|
||||
|
||||
$shares = [];
|
||||
while ($data = $cursor->fetch()) {
|
||||
@@ -752,7 +749,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
|
||||
$qb->andWhere($qb->expr()->eq('dc.deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
if (!$this->isAccessibleResult($data)) {
|
||||
continue;
|
||||
@@ -845,7 +842,6 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @psalm-suppress InvalidReturnType Not returning anything
|
||||
*/
|
||||
public function getShareByToken($token) {
|
||||
throw new ShareNotFound();
|
||||
@@ -855,7 +851,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->from('share')
|
||||
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_ROOM)))
|
||||
->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
|
||||
->executeQuery();
|
||||
->execute();
|
||||
|
||||
$data = $cursor->fetch();
|
||||
|
||||
@@ -1019,7 +1015,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_DECK)))
|
||||
->orderBy('id');
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
$children[] = $this->createShareObject($data);
|
||||
}
|
||||
@@ -1042,7 +1038,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
)
|
||||
);
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
$share = $this->createShareObject($data);
|
||||
|
||||
@@ -1059,7 +1055,7 @@ class DeckShareProvider implements \OCP\Share\IShareProvider {
|
||||
->where($qb->expr()->eq('s.share_type', $qb->createNamedParameter(IShare::TYPE_DECK)))
|
||||
->andWhere($qb->expr()->notIn('s.share_with', $qb->createNamedParameter($allCardIds, IQueryBuilder::PARAM_STR_ARRAY)));
|
||||
|
||||
$cursor = $qb->executeQuery();
|
||||
$cursor = $qb->execute();
|
||||
$shares = [];
|
||||
while ($data = $cursor->fetch()) {
|
||||
$shares[] = $this->createShareObject($data);
|
||||
|
||||
583
package-lock.json
generated
583
package-lock.json
generated
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"name": "deck",
|
||||
"version": "2.0.0-dev.0",
|
||||
"version": "1.15.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "deck",
|
||||
"version": "2.0.0-dev.0",
|
||||
"version": "1.15.3",
|
||||
"license": "agpl",
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/runtime": "^7.27.1",
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@nextcloud/auth": "^2.4.0",
|
||||
"@nextcloud/axios": "^2.5.1",
|
||||
"@nextcloud/capabilities": "^1.2.0",
|
||||
"@nextcloud/dialogs": "^6.3.1",
|
||||
"@nextcloud/event-bus": "^3.3.2",
|
||||
"@nextcloud/dialogs": "^6.0.1",
|
||||
"@nextcloud/event-bus": "^3.3.1",
|
||||
"@nextcloud/files": "^3.10.1",
|
||||
"@nextcloud/initial-state": "^2.2.0",
|
||||
"@nextcloud/l10n": "^3.4.0",
|
||||
@@ -25,7 +25,7 @@
|
||||
"@nextcloud/vue": "^8.31.0",
|
||||
"blueimp-md5": "^2.19.0",
|
||||
"chroma-js": "^3.1.2",
|
||||
"dompurify": "^3.2.5",
|
||||
"dompurify": "^3.2.3",
|
||||
"lodash": "^4.17.21",
|
||||
"markdown-it": "^14.1.0",
|
||||
"markdown-it-link-attributes": "^4.0.1",
|
||||
@@ -48,16 +48,16 @@
|
||||
"devDependencies": {
|
||||
"@nextcloud/babel-config": "^1.2.0",
|
||||
"@nextcloud/browserslist-config": "^3.0.1",
|
||||
"@nextcloud/cypress": "^1.0.0-beta.15",
|
||||
"@nextcloud/eslint-config": "^8.4.2",
|
||||
"@nextcloud/cypress": "^1.0.0-beta.12",
|
||||
"@nextcloud/eslint-config": "^8.4.1",
|
||||
"@nextcloud/stylelint-config": "^3.0.1",
|
||||
"@nextcloud/webpack-vue-config": "^6.3.0",
|
||||
"@relative-ci/agent": "^4.3.1",
|
||||
"@nextcloud/webpack-vue-config": "^6.2.0",
|
||||
"@relative-ci/agent": "^4.2.14",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"@vue/vue2-jest": "^29.2.6",
|
||||
"cypress": "^13.17.0",
|
||||
"eslint-plugin-cypress": "^3.6.0",
|
||||
"eslint-webpack-plugin": "^5.0.1",
|
||||
"eslint-webpack-plugin": "^4.2.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-serializer-vue": "^3.1.0",
|
||||
"stylelint-webpack-plugin": "^5.0.1",
|
||||
@@ -105,15 +105,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.26.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
|
||||
"integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
|
||||
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.25.9",
|
||||
"@babel/helper-validator-identifier": "^7.27.1",
|
||||
"js-tokens": "^4.0.0",
|
||||
"picocolors": "^1.0.0"
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -536,18 +536,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
|
||||
"integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
|
||||
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-validator-identifier": {
|
||||
"version": "7.25.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
|
||||
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
|
||||
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -579,26 +579,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helpers": {
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz",
|
||||
"integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==",
|
||||
"version": "7.27.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz",
|
||||
"integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/template": "^7.27.0",
|
||||
"@babel/types": "^7.27.0"
|
||||
"@babel/template": "^7.27.2",
|
||||
"@babel/types": "^7.27.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/parser": {
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
|
||||
"integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
|
||||
"version": "7.27.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz",
|
||||
"integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/types": "^7.27.0"
|
||||
"@babel/types": "^7.27.3"
|
||||
},
|
||||
"bin": {
|
||||
"parser": "bin/babel-parser.js"
|
||||
@@ -1919,24 +1919,24 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz",
|
||||
"integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
|
||||
"version": "7.27.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz",
|
||||
"integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
|
||||
"integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
|
||||
"version": "7.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
|
||||
"integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.26.2",
|
||||
"@babel/parser": "^7.27.0",
|
||||
"@babel/types": "^7.27.0"
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/parser": "^7.27.2",
|
||||
"@babel/types": "^7.27.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -1962,13 +1962,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.27.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
|
||||
"integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
|
||||
"version": "7.27.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz",
|
||||
"integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-string-parser": "^7.25.9",
|
||||
"@babel/helper-validator-identifier": "^7.25.9"
|
||||
"@babel/helper-string-parser": "^7.27.1",
|
||||
"@babel/helper-validator-identifier": "^7.27.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@@ -2377,9 +2377,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@grpc/grpc-js": {
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.2.tgz",
|
||||
"integrity": "sha512-nnR5nmL6lxF8YBqb6gWvEgLdLh/Fn+kvAdX5hUOnt48sNSb0riz/93ASd2E5gvanPA41X6Yp25bIfGRp1SMb2g==",
|
||||
"version": "1.13.4",
|
||||
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.4.tgz",
|
||||
"integrity": "sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -2391,9 +2391,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@grpc/proto-loader": {
|
||||
"version": "0.7.13",
|
||||
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz",
|
||||
"integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==",
|
||||
"version": "0.7.15",
|
||||
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz",
|
||||
"integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -4886,11 +4886,10 @@
|
||||
"integrity": "sha512-qZ72SFTgUAZ5a7Tj6kf2SHLetiH5S6f8G5frB2SPQ3EyF02kxdyBFf4Tz4banE3xCgGnKgWLt//a6VuYHKYJTg=="
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "9.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
|
||||
"integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
|
||||
"version": "8.56.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz",
|
||||
"integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "*",
|
||||
"@types/json-schema": "*"
|
||||
@@ -4965,10 +4964,11 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/http-proxy": {
|
||||
"version": "1.17.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz",
|
||||
"integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==",
|
||||
"version": "1.17.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz",
|
||||
"integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
@@ -5107,9 +5107,9 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
|
||||
"integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
|
||||
"version": "7.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz",
|
||||
"integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/send": {
|
||||
@@ -5402,10 +5402,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
@@ -6408,15 +6409,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/available-typed-arrays": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
|
||||
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"possible-typed-array-names": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@@ -6440,9 +6437,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz",
|
||||
"integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==",
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz",
|
||||
"integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
@@ -6899,7 +6896,9 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -7262,48 +7261,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
|
||||
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
||||
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.0",
|
||||
"es-define-property": "^1.0.0",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"set-function-length": "^1.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bound": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
|
||||
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"get-intrinsic": "^1.3.0"
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"set-function-length": "^1.2.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -8873,9 +8840,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dockerode": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/dockerode/-/dockerode-4.0.5.tgz",
|
||||
"integrity": "sha512-ZPmKSr1k1571Mrh7oIBS/j0AqAccoecY2yH420ni5j1KyNMgnoTh4Nu4FWunh0HZIJmRSmSysJjBIpa/zyWUEA==",
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/dockerode/-/dockerode-4.0.7.tgz",
|
||||
"integrity": "sha512-R+rgrSRTRdU5mH14PZTCPZtW/zw3HDWNTS/1ZAQpL/5Upe/ye5K9WQkIysu4wBoiMwKynsz0a8qWuGsHgEvSAA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -9011,21 +8978,6 @@
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
@@ -9084,10 +9036,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/editorconfig/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
@@ -9360,11 +9313,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
@@ -9384,19 +9339,6 @@
|
||||
"integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
|
||||
@@ -9927,20 +9869,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-webpack-plugin": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-5.0.1.tgz",
|
||||
"integrity": "sha512-Ur100Vi+z0uP7j4Z8Ccah0pXmNHhl3f7P2hCYZj3mZCOSc33G5c1R/vZ4KCapwWikPgRyD4dkangx6JW3KaVFQ==",
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-4.2.0.tgz",
|
||||
"integrity": "sha512-rsfpFQ01AWQbqtjgPRr2usVRxhWDuG0YDYcG8DJOteD3EFnpeuYuOwk0PQiN7PRBTqS6ElNdtPZPggj8If9WnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@types/eslint": "^8.56.10",
|
||||
"jest-worker": "^29.7.0",
|
||||
"micromatch": "^4.0.8",
|
||||
"micromatch": "^4.0.5",
|
||||
"normalize-path": "^3.0.0",
|
||||
"schema-utils": "^4.3.0"
|
||||
"schema-utils": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18.12.0"
|
||||
"node": ">= 14.15.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -9952,16 +9893,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-webpack-plugin/node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"version": "8.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
||||
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2"
|
||||
"require-from-string": "^2.0.2",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
@@ -9973,7 +9913,6 @@
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
||||
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3"
|
||||
},
|
||||
@@ -10009,15 +9948,13 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/eslint-webpack-plugin/node_modules/schema-utils": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
|
||||
"integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
|
||||
"integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.9",
|
||||
"ajv": "^8.9.0",
|
||||
@@ -10025,7 +9962,7 @@
|
||||
"ajv-keywords": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
"node": ">= 12.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -10366,6 +10303,7 @@
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/events": {
|
||||
@@ -10617,7 +10555,8 @@
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz",
|
||||
"integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/fast-xml-parser": {
|
||||
"version": "4.5.3",
|
||||
@@ -10872,20 +10811,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/for-each": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
|
||||
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
||||
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"is-callable": "^1.2.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
"is-callable": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child": {
|
||||
@@ -11086,22 +11018,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
"has-proto": "^1.0.1",
|
||||
"has-symbols": "^1.0.3",
|
||||
"hasown": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -11119,20 +11045,6 @@
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
|
||||
@@ -11343,13 +11255,12 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.1.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
@@ -11420,7 +11331,6 @@
|
||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@@ -11429,11 +11339,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@@ -11442,14 +11351,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
|
||||
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
"has-symbols": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -11725,6 +11633,7 @@
|
||||
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
|
||||
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"eventemitter3": "^4.0.0",
|
||||
@@ -11766,6 +11675,7 @@
|
||||
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
|
||||
"integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
@@ -12459,14 +12369,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/is-typed-array": {
|
||||
"version": "1.1.15",
|
||||
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
|
||||
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
|
||||
"integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"which-typed-array": "^1.1.16"
|
||||
"which-typed-array": "^1.1.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -14387,10 +14296,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/js-beautify/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
@@ -14950,9 +14860,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/long": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.3.1.tgz",
|
||||
"integrity": "sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng==",
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
|
||||
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
@@ -15057,16 +14967,6 @@
|
||||
"version": "1.2.6",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/mathml-tag-names": {
|
||||
"version": "2.1.3",
|
||||
"dev": true,
|
||||
@@ -16687,83 +16587,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/pbkdf2": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz",
|
||||
"integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
|
||||
"integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"create-hash": "~1.1.3",
|
||||
"create-hmac": "^1.1.7",
|
||||
"ripemd160": "=2.0.1",
|
||||
"safe-buffer": "^5.2.1",
|
||||
"sha.js": "^2.4.11",
|
||||
"to-buffer": "^1.2.0"
|
||||
"create-hash": "^1.1.2",
|
||||
"create-hmac": "^1.1.4",
|
||||
"ripemd160": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1",
|
||||
"sha.js": "^2.4.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/pbkdf2/node_modules/create-hash": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
|
||||
"integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cipher-base": "^1.0.1",
|
||||
"inherits": "^2.0.1",
|
||||
"ripemd160": "^2.0.0",
|
||||
"sha.js": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pbkdf2/node_modules/hash-base": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
|
||||
"integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/pbkdf2/node_modules/ripemd160": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
|
||||
"integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"hash-base": "^2.0.0",
|
||||
"inherits": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/pbkdf2/node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/pend": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||
@@ -16879,17 +16718,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/possible-typed-array-names": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
||||
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.38",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
|
||||
@@ -17206,9 +17034,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/protobufjs": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
|
||||
"integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
|
||||
"version": "7.5.3",
|
||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz",
|
||||
"integrity": "sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "BSD-3-Clause",
|
||||
@@ -19900,52 +19728,6 @@
|
||||
"integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/to-buffer": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
|
||||
"integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"isarray": "^2.0.5",
|
||||
"safe-buffer": "^5.2.1",
|
||||
"typed-array-buffer": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/to-buffer/node_modules/isarray": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/to-buffer/node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
@@ -20268,16 +20050,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typed-array-buffer": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
|
||||
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
|
||||
"integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"call-bound": "^1.0.3",
|
||||
"es-errors": "^1.3.0",
|
||||
"is-typed-array": "^1.1.14"
|
||||
"call-bind": "^1.0.2",
|
||||
"get-intrinsic": "^1.2.1",
|
||||
"is-typed-array": "^1.1.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@@ -21174,17 +20955,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webdav/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webdav/node_modules/entities": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
||||
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
|
||||
"integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
@@ -21678,20 +21460,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/which-typed-array": {
|
||||
"version": "1.1.19",
|
||||
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
|
||||
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
|
||||
"integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"available-typed-arrays": "^1.0.7",
|
||||
"call-bind": "^1.0.8",
|
||||
"call-bound": "^1.0.4",
|
||||
"for-each": "^0.3.5",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-tostringtag": "^1.0.2"
|
||||
"available-typed-arrays": "^1.0.5",
|
||||
"call-bind": "^1.0.2",
|
||||
"for-each": "^0.3.3",
|
||||
"gopd": "^1.0.1",
|
||||
"has-tostringtag": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
||||
20
package.json
20
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "deck",
|
||||
"description": "",
|
||||
"version": "2.0.0-dev.0",
|
||||
"version": "1.15.3",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Julius Härtl",
|
||||
@@ -31,12 +31,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/runtime": "^7.27.1",
|
||||
"@babel/runtime": "^7.26.0",
|
||||
"@nextcloud/auth": "^2.4.0",
|
||||
"@nextcloud/axios": "^2.5.1",
|
||||
"@nextcloud/capabilities": "^1.2.0",
|
||||
"@nextcloud/dialogs": "^6.3.1",
|
||||
"@nextcloud/event-bus": "^3.3.2",
|
||||
"@nextcloud/dialogs": "^6.0.1",
|
||||
"@nextcloud/event-bus": "^3.3.1",
|
||||
"@nextcloud/files": "^3.10.1",
|
||||
"@nextcloud/initial-state": "^2.2.0",
|
||||
"@nextcloud/l10n": "^3.4.0",
|
||||
@@ -46,7 +46,7 @@
|
||||
"@nextcloud/vue": "^8.31.0",
|
||||
"blueimp-md5": "^2.19.0",
|
||||
"chroma-js": "^3.1.2",
|
||||
"dompurify": "^3.2.5",
|
||||
"dompurify": "^3.2.3",
|
||||
"lodash": "^4.17.21",
|
||||
"markdown-it": "^14.1.0",
|
||||
"markdown-it-link-attributes": "^4.0.1",
|
||||
@@ -76,16 +76,16 @@
|
||||
"devDependencies": {
|
||||
"@nextcloud/babel-config": "^1.2.0",
|
||||
"@nextcloud/browserslist-config": "^3.0.1",
|
||||
"@nextcloud/cypress": "^1.0.0-beta.15",
|
||||
"@nextcloud/eslint-config": "^8.4.2",
|
||||
"@nextcloud/cypress": "^1.0.0-beta.12",
|
||||
"@nextcloud/eslint-config": "^8.4.1",
|
||||
"@nextcloud/stylelint-config": "^3.0.1",
|
||||
"@nextcloud/webpack-vue-config": "^6.3.0",
|
||||
"@relative-ci/agent": "^4.3.1",
|
||||
"@nextcloud/webpack-vue-config": "^6.2.0",
|
||||
"@relative-ci/agent": "^4.2.14",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"@vue/vue2-jest": "^29.2.6",
|
||||
"cypress": "^13.17.0",
|
||||
"eslint-plugin-cypress": "^3.6.0",
|
||||
"eslint-webpack-plugin": "^5.0.1",
|
||||
"eslint-webpack-plugin": "^4.2.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-serializer-vue": "^3.1.0",
|
||||
"stylelint-webpack-plugin": "^5.0.1",
|
||||
|
||||
10
psalm.xml
10
psalm.xml
@@ -6,8 +6,6 @@
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config"
|
||||
errorBaseline="tests/psalm-baseline.xml"
|
||||
findUnusedBaselineEntry="true"
|
||||
findUnusedCode="false"
|
||||
phpVersion="8.1"
|
||||
>
|
||||
<stubs>
|
||||
@@ -17,7 +15,6 @@
|
||||
<directory name="lib" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
<directory name="vendor-bin" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
<extraFiles>
|
||||
@@ -29,6 +26,13 @@
|
||||
<referencedMethod name="/Db\\.*::.*/" />
|
||||
</errorLevel>
|
||||
</UndefinedMagicMethod>
|
||||
<UndefinedInterfaceMethod>
|
||||
<errorLevel type="suppress">
|
||||
<!-- FIXME Deprecated event handling -->
|
||||
<referencedMethod name="OCP\IUserManager::listen" />
|
||||
<referencedMethod name="OCP\IGroupManager::listen" />
|
||||
</errorLevel>
|
||||
</UndefinedInterfaceMethod>
|
||||
<UndefinedClass>
|
||||
<errorLevel type="suppress">
|
||||
<referencedClass name="OC\*" />
|
||||
|
||||
@@ -263,10 +263,10 @@ import { mapState, mapGetters } from 'vuex'
|
||||
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
|
||||
import { NcActions, NcActionButton, NcAvatar, NcButton, NcPopover, NcModal } from '@nextcloud/vue'
|
||||
import labelStyle from '../mixins/labelStyle.js'
|
||||
import ArchiveIcon from 'vue-material-design-icons/ArchiveOutline.vue'
|
||||
import ImageIcon from 'vue-material-design-icons/ImageMultipleOutline.vue'
|
||||
import FilterIcon from 'vue-material-design-icons/FilterOutline.vue'
|
||||
import FilterOffIcon from 'vue-material-design-icons/FilterOffOutline.vue'
|
||||
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
|
||||
import ImageIcon from 'vue-material-design-icons/ImageMultiple.vue'
|
||||
import FilterIcon from 'vue-material-design-icons/Filter.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 ArrowExpandVerticalIcon from 'vue-material-design-icons/ArrowExpandVertical.vue'
|
||||
|
||||
@@ -276,15 +276,18 @@ export default {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: calc(100vh - 50px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.board {
|
||||
padding-left: $board-spacing;
|
||||
position: relative;
|
||||
max-height: calc(100% - var(--default-clickable-area));
|
||||
overflow: hidden;
|
||||
overflow-x: auto;
|
||||
flex-grow: 1;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,15 +297,11 @@ export default {
|
||||
.smooth-dnd-container.horizontal {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: $board-gap;
|
||||
padding: 0 $board-gap;
|
||||
height: 100%;
|
||||
|
||||
&:deep(.stack-draggable-wrapper.smooth-dnd-draggable-wrapper) {
|
||||
display: flex;
|
||||
height: auto;
|
||||
flex: 0 1 $card-max-width;
|
||||
min-width: $card-min-width;
|
||||
|
||||
.stack {
|
||||
display: flex;
|
||||
@@ -310,13 +309,16 @@ export default {
|
||||
position: relative;
|
||||
|
||||
.smooth-dnd-container.vertical {
|
||||
$margin-x: calc($stack-gap * -1);
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $stack-gap;
|
||||
padding: $stack-gap;
|
||||
margin: 0 $margin-x;
|
||||
// Margin left instead of padidng to avoid jumps on dropping a card
|
||||
margin-left: $stack-spacing;
|
||||
padding-right: $stack-spacing;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding-top: 15px;
|
||||
margin-top: -10px;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user