Compare commits
280 Commits
bug/use-di
...
v1.6.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9e55f8091 | ||
|
|
aff4cb6ac0 | ||
|
|
69e8fe23b4 | ||
|
|
ec9c4220b5 | ||
|
|
babf767286 | ||
|
|
5e3eca1e29 | ||
|
|
983365830c | ||
|
|
139e901af6 | ||
|
|
f98ab9ed8e | ||
|
|
d34562b7bd | ||
|
|
512b0d7664 | ||
|
|
d2c81dde9c | ||
|
|
2dff9d5a09 | ||
|
|
76e08f2a21 | ||
|
|
d83fdfcb0a | ||
|
|
9d498ca84c | ||
|
|
2d05e84de9 | ||
|
|
3bf57dd6d7 | ||
|
|
27110581fd | ||
|
|
c735e4b017 | ||
|
|
c20da909a5 | ||
|
|
2d64c52079 | ||
|
|
53dc650e51 | ||
|
|
ff77c45a50 | ||
|
|
357f30464d | ||
|
|
561d081a95 | ||
|
|
34541cab03 | ||
|
|
0dfbcd4631 | ||
|
|
2742334cf9 | ||
|
|
1a1cb058d3 | ||
|
|
03dd572d0c | ||
|
|
59efdf8964 | ||
|
|
631e688a03 | ||
|
|
1db5d7cf47 | ||
|
|
6f6d2df9de | ||
|
|
a5eecd9d19 | ||
|
|
7e949052dc | ||
|
|
4cc32a1e8b | ||
|
|
bf9f9da3b0 | ||
|
|
f70595ea2a | ||
|
|
e6f9c136e9 | ||
|
|
632cd3079f | ||
|
|
578fd46765 | ||
|
|
3dec4b7f2c | ||
|
|
3f7a2b31b3 | ||
|
|
c072d713cb | ||
|
|
9fe5ec7fab | ||
|
|
3ec0579256 | ||
|
|
ebc4ad45ff | ||
|
|
a4d89a5b3d | ||
|
|
bf504624f4 | ||
|
|
4e7ce3e061 | ||
|
|
96da8d8b06 | ||
|
|
8d51826169 | ||
|
|
188e60c7d0 | ||
|
|
fc47f8b719 | ||
|
|
44b744017d | ||
|
|
693acfa8df | ||
|
|
655f82e1cf | ||
|
|
4e54a77075 | ||
|
|
ce123d10e5 | ||
|
|
82c9e7d174 | ||
|
|
f8cf9a1856 | ||
|
|
6219004c51 | ||
|
|
28a65a2e98 | ||
|
|
edcb5c4eca | ||
|
|
05109c351f | ||
|
|
c3a5898271 | ||
|
|
5befacc95e | ||
|
|
3e0a0e0a0e | ||
|
|
5f4bd548fe | ||
|
|
ae7e4e04ad | ||
|
|
89173f4ef7 | ||
|
|
ff09639924 | ||
|
|
811e19db0e | ||
|
|
1cf0930f2a | ||
|
|
8154741d6d | ||
|
|
e4a9482979 | ||
|
|
b23d53e541 | ||
|
|
65e4e65bd6 | ||
|
|
2ebcda8ca9 | ||
|
|
e686c6b32b | ||
|
|
f3526cc996 | ||
|
|
673addc6ba | ||
|
|
7a5c745bdf | ||
|
|
c46ca8a03a | ||
|
|
b686cae095 | ||
|
|
4c7f64e427 | ||
|
|
699b089655 | ||
|
|
3cc1db09d1 | ||
|
|
912dd4778e | ||
|
|
cd3ff3e8bc | ||
|
|
28c39ae6b4 | ||
|
|
efa7838993 | ||
|
|
04c131d58f | ||
|
|
da8e2886ae | ||
|
|
57c7ac6ebf | ||
|
|
cfc5bb266d | ||
|
|
04619d16dd | ||
|
|
9f709a851f | ||
|
|
0b1accc395 | ||
|
|
db1167a05f | ||
|
|
1f4d1a7ea2 | ||
|
|
0f83e606a5 | ||
|
|
6edb957849 | ||
|
|
1151f907f5 | ||
|
|
c330cff60b | ||
|
|
809383702a | ||
|
|
a341206ff0 | ||
|
|
b33fe37499 | ||
|
|
05f764bc17 | ||
|
|
f5307362ee | ||
|
|
ce40630b2f | ||
|
|
afbc1c263c | ||
|
|
24a2ee5bd4 | ||
|
|
8542dfc7e1 | ||
|
|
165604cbac | ||
|
|
841f66e854 | ||
|
|
c4a3eec533 | ||
|
|
9fb6db4c31 | ||
|
|
47b71f93c8 | ||
|
|
42c01d7c3b | ||
|
|
c3b610bc38 | ||
|
|
2d7edbf2f2 | ||
|
|
26f1288440 | ||
|
|
55f52d5d68 | ||
|
|
e8ed6fb89e | ||
|
|
36e8a88588 | ||
|
|
aa7dfbd749 | ||
|
|
cec655c1fa | ||
|
|
228457e387 | ||
|
|
66f985a9fb | ||
|
|
54706cfe8d | ||
|
|
48bf117339 | ||
|
|
d585e14240 | ||
|
|
6a790154c2 | ||
|
|
33913be41f | ||
|
|
393e08519d | ||
|
|
dfcf096caa | ||
|
|
4859456588 | ||
|
|
366df500e6 | ||
|
|
7c6cdfd498 | ||
|
|
29fb2e63ad | ||
|
|
e021d400f3 | ||
|
|
139a8a0fb7 | ||
|
|
43e91b9082 | ||
|
|
316f5fb25a | ||
|
|
008b41a2ad | ||
|
|
e5e836101c | ||
|
|
dd261fec6c | ||
|
|
5214377341 | ||
|
|
ad4174f6bd | ||
|
|
976e68e40c | ||
|
|
9c33cdf3d3 | ||
|
|
d5eea830a5 | ||
|
|
c8e94c2de4 | ||
|
|
f838d91304 | ||
|
|
f4c615252b | ||
|
|
f084193daf | ||
|
|
20b9b1e1e9 | ||
|
|
eae7fd88d8 | ||
|
|
983247b9e8 | ||
|
|
afbd6ce1b0 | ||
|
|
31311f1123 | ||
|
|
7a3fb009d6 | ||
|
|
a7974d32ee | ||
|
|
558ac704f5 | ||
|
|
0c98a04699 | ||
|
|
4f9b71dcad | ||
|
|
b2367314fc | ||
|
|
c04e5c1681 | ||
|
|
541eeb0b06 | ||
|
|
1bd62d7fa2 | ||
|
|
03a9915dd5 | ||
|
|
b6cce55325 | ||
|
|
47345e10f1 | ||
|
|
39784dc940 | ||
|
|
1cdea9dba0 | ||
|
|
49591d6699 | ||
|
|
101e15c1b7 | ||
|
|
4d9743f8d3 | ||
|
|
51433ac4a9 | ||
|
|
2cde9ac16c | ||
|
|
fb2a38e684 | ||
|
|
ff4f33264b | ||
|
|
879e936728 | ||
|
|
c47bfd21eb | ||
|
|
c59b6f8882 | ||
|
|
4dabc22f27 | ||
|
|
490cfb2396 | ||
|
|
f840bbba11 | ||
|
|
cffcd4fd66 | ||
|
|
a3336cb0a0 | ||
|
|
379f1144b3 | ||
|
|
eb69512b5f | ||
|
|
f46c31f120 | ||
|
|
b75fb76c08 | ||
|
|
3d925fb145 | ||
|
|
7786c86f47 | ||
|
|
7f3a318fc5 | ||
|
|
525a14c428 | ||
|
|
48ec97386c | ||
|
|
26c76fbb46 | ||
|
|
c95c96fb40 | ||
|
|
981fc8e16f | ||
|
|
b7f3c2d140 | ||
|
|
b01d472745 | ||
|
|
05dbf67531 | ||
|
|
a8c22482f6 | ||
|
|
c0886cfc7a | ||
|
|
7c68414435 | ||
|
|
da745f9306 | ||
|
|
16413735d2 | ||
|
|
e70e7128c0 | ||
|
|
36a9d2e95c | ||
|
|
ce85b4378f | ||
|
|
d52697823d | ||
|
|
53d462b3da | ||
|
|
fc9fa5dc25 | ||
|
|
eb8a321637 | ||
|
|
ce77725ef0 | ||
|
|
a88e028793 | ||
|
|
0655ab8d59 | ||
|
|
2c5b8c5fba | ||
|
|
1057dc7039 | ||
|
|
8274d090c3 | ||
|
|
c213727180 | ||
|
|
a5565d192d | ||
|
|
d25c8f6945 | ||
|
|
e31ff9f247 | ||
|
|
2d8bb1e654 | ||
|
|
18babccfe1 | ||
|
|
4646499917 | ||
|
|
da9c18b4cb | ||
|
|
94134fc7d6 | ||
|
|
113cc5c578 | ||
|
|
0d12c2a4ec | ||
|
|
3d1ed51ea9 | ||
|
|
31152d9763 | ||
|
|
044afef32d | ||
|
|
1e35c7b836 | ||
|
|
0a43156a91 | ||
|
|
fd9ad30e3e | ||
|
|
c5fc9f6833 | ||
|
|
298d72c651 | ||
|
|
64e231630f | ||
|
|
314fdc43ad | ||
|
|
6962187497 | ||
|
|
0f9fdbd82a | ||
|
|
c6f8b22837 | ||
|
|
a3cdd5e19d | ||
|
|
239bb5e4cb | ||
|
|
2a121536de | ||
|
|
1f645a3059 | ||
|
|
92efa7f5ec | ||
|
|
70664c1853 | ||
|
|
8ac2bbbbbc | ||
|
|
7560619939 | ||
|
|
7ce68f74c4 | ||
|
|
fa493ddd9a | ||
|
|
d4c9147419 | ||
|
|
21b81ff56c | ||
|
|
4645c5077d | ||
|
|
9a7bcafa6c | ||
|
|
53ebe480cf | ||
|
|
e4db5e4d28 | ||
|
|
2b8dee5081 | ||
|
|
a8d41797ef | ||
|
|
bc9fe51036 | ||
|
|
d16799948f | ||
|
|
764dd947d4 | ||
|
|
ea35f64d2a | ||
|
|
a2205db748 | ||
|
|
a80d87a3e9 | ||
|
|
12ed617a56 | ||
|
|
ffccbf73fd | ||
|
|
8514e91edc | ||
|
|
8926363092 | ||
|
|
2be4fff781 | ||
|
|
8f52667d2c |
@@ -3,10 +3,7 @@ root = true
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = tab
|
||||
indent_style = tab
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{js,vue}]
|
||||
indent_style = tab
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: [
|
||||
'@nextcloud',
|
||||
],
|
||||
@@ -8,7 +7,6 @@ module.exports = {
|
||||
'jsdoc/require-param-type': ['off'],
|
||||
'jsdoc/check-param-names': ['off'],
|
||||
'jsdoc/no-undefined-types': ['off'],
|
||||
'jsdoc/require-property-description': ['off'],
|
||||
'import/no-named-as-default-member': ['off']
|
||||
'jsdoc/require-property-description' : ['off']
|
||||
},
|
||||
}
|
||||
|
||||
80
.github/dependabot.yml
vendored
@@ -11,58 +11,19 @@ updates:
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- juliushaertl
|
||||
|
||||
- package-ecosystem: npm
|
||||
target-branch: stable25
|
||||
versioning-strategy: lockfile-only
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
open-pull-requests-limit: 30
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
|
||||
- package-ecosystem: npm
|
||||
target-branch: stable24
|
||||
versioning-strategy: lockfile-only
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types: ["version-update:semver-major"]
|
||||
open-pull-requests-limit: 30
|
||||
labels:
|
||||
- 3. to review
|
||||
- dependencies
|
||||
|
||||
- package-ecosystem: npm
|
||||
target-branch: stable23
|
||||
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
|
||||
|
||||
- jakobroehrl
|
||||
#- package-ecosystem: npm
|
||||
# directory: "/"
|
||||
# target-branch: "stable1.1"
|
||||
# schedule:
|
||||
# interval: weekly
|
||||
# day: saturday
|
||||
# time: "03:00"
|
||||
# timezone: Europe/Paris
|
||||
# open-pull-requests-limit: 10
|
||||
# reviewers:
|
||||
# - juliushaertl
|
||||
# - jakobroehrl
|
||||
- package-ecosystem: composer
|
||||
directory: "/"
|
||||
schedule:
|
||||
@@ -73,16 +34,11 @@ updates:
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- juliushaertl
|
||||
- package-ecosystem: composer
|
||||
directory: "/tests/integration"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: saturday
|
||||
time: "03:00"
|
||||
timezone: Europe/Paris
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- juliushaertl
|
||||
ignore:
|
||||
- dependency-name: christophwurst/nextcloud
|
||||
versions:
|
||||
- "< 16"
|
||||
- ">= 15.a"
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
|
||||
14
.github/workflows/appbuild.yml
vendored
@@ -1,11 +1,7 @@
|
||||
name: Package build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
- stable*
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -16,15 +12,15 @@ jobs:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v2.4.1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Set up npm7
|
||||
run: npm i -g npm@7
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@2.15.0
|
||||
with:
|
||||
php-version: '7.4'
|
||||
tools: composer
|
||||
@@ -37,7 +33,7 @@ jobs:
|
||||
uname -a
|
||||
RUST_BACKTRACE=1 krankerl --version
|
||||
RUST_BACKTRACE=1 krankerl package
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Deck app tarball
|
||||
path: build/artifacts/deck.tar.gz
|
||||
|
||||
6
.github/workflows/appstore-build-publish.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
expression: "//info//dependencies//nextcloud/@min-version"
|
||||
|
||||
- name: Read package.json node and npm engines version
|
||||
uses: skjnldsv/read-package-engines-version-actions@v2.0
|
||||
uses: skjnldsv/read-package-engines-version-actions@v1.2
|
||||
id: versions
|
||||
# Continue if no package.json
|
||||
continue-on-error: true
|
||||
@@ -66,14 +66,14 @@ jobs:
|
||||
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
|
||||
|
||||
- name: Set up php ${{ env.PHP_VERSION }}
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ env.PHP_VERSION }}
|
||||
coverage: none
|
||||
|
||||
- name: Check composer.json
|
||||
id: check_composer
|
||||
uses: andstor/file-existence-action@v2
|
||||
uses: andstor/file-existence-action@v1
|
||||
with:
|
||||
files: "${{ env.APP_NAME }}/composer.json"
|
||||
|
||||
|
||||
13
.github/workflows/command-rebase.yml
vendored
@@ -9,21 +9,16 @@ on:
|
||||
issue_comment:
|
||||
types: created
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
rebase:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: none
|
||||
|
||||
# On pull requests and if the comment starts with `/rebase`
|
||||
if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/rebase')
|
||||
|
||||
steps:
|
||||
- name: Add reaction on start
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
repository: ${{ github.event.repository.full_name }}
|
||||
@@ -31,18 +26,18 @@ jobs:
|
||||
reaction-type: "+1"
|
||||
|
||||
- name: Checkout the latest code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2.4.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
|
||||
- name: Automatic Rebase
|
||||
uses: cirrus-actions/rebase@1.8
|
||||
uses: cirrus-actions/rebase@1.5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
|
||||
- name: Add reaction on failure
|
||||
uses: peter-evans/create-or-update-comment@v2
|
||||
uses: peter-evans/create-or-update-comment@v1
|
||||
if: failure()
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
|
||||
112
.github/workflows/cypress.yml
vendored
@@ -1,112 +0,0 @@
|
||||
name: Cypress
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- stable*
|
||||
|
||||
env:
|
||||
APP_NAME: deck
|
||||
CYPRESS_baseUrl: http://localhost:8081/index.php
|
||||
|
||||
jobs:
|
||||
cypress:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
# containers: [1, 2, 3]
|
||||
php-versions: [ '7.4' ]
|
||||
databases: [ 'sqlite' ]
|
||||
server-versions: [ 'master' ]
|
||||
|
||||
steps:
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Set up npm7
|
||||
run: npm i -g npm@7
|
||||
|
||||
- name: Checkout server
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: nextcloud/server
|
||||
ref: ${{ matrix.server-versions }}
|
||||
|
||||
- name: Checkout submodules
|
||||
shell: bash
|
||||
run: |
|
||||
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
||||
git submodule sync --recursive
|
||||
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||
|
||||
- name: Checkout ${{ env.APP_NAME }}
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
extensions: mbstring, iconv, fileinfo, intl, sqlite, pdo_sqlite, zip, gd, apcu
|
||||
ini-values:
|
||||
apc.enable_cli=on
|
||||
coverage: none
|
||||
|
||||
- name: Set up Nextcloud
|
||||
env:
|
||||
DB_PORT: 4444
|
||||
PHP_CLI_SERVER_WORKERS: 10
|
||||
run: |
|
||||
mkdir data
|
||||
php occ maintenance:install --verbose --database=${{ matrix.databases }} --database-name=nextcloud --database-host=127.0.0.1 --database-port=$DB_PORT --database-user=root --database-pass=rootpassword --admin-user admin --admin-pass admin
|
||||
php occ config:system:set memcache.local --value="\\OC\\Memcache\\APCu"
|
||||
php occ config:system:set debug --value=true --type=boolean
|
||||
php -f index.php
|
||||
php -S 0.0.0.0:8081 &
|
||||
export OC_PASS=1234561
|
||||
php occ user:add --password-from-env user1
|
||||
php occ user:add --password-from-env user2
|
||||
php occ app:enable deck
|
||||
php occ app:list
|
||||
cd apps/deck
|
||||
composer install --no-dev
|
||||
npm ci
|
||||
npm run build
|
||||
cd ../../
|
||||
curl -v http://localhost:8081/index.php/login
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v5
|
||||
with:
|
||||
record: true
|
||||
parallel: false
|
||||
wait-on: '${{ env.CYPRESS_baseUrl }}'
|
||||
working-directory: 'apps/${{ env.APP_NAME }}'
|
||||
config: defaultCommandTimeout=10000,video=false
|
||||
env:
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
npm_package_name: ${{ env.APP_NAME }}
|
||||
|
||||
- name: Upload test failure screenshots
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: Upload screenshots
|
||||
path: apps/${{ env.APP_NAME }}/cypress/screenshots/
|
||||
retention-days: 5
|
||||
|
||||
- name: Upload nextcloud logs
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: Upload nextcloud log
|
||||
path: data/nextcloud.log
|
||||
retention-days: 5
|
||||
11
.github/workflows/dependabot-approve-merge.yml
vendored
@@ -8,29 +8,22 @@ name: Dependabot
|
||||
on:
|
||||
pull_request_target:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
- stable*
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
auto-approve-merge:
|
||||
if: github.actor == 'dependabot[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# for hmarr/auto-approve-action to approve PRs
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
# Github actions bot approve
|
||||
- uses: hmarr/auto-approve-action@v3
|
||||
- uses: hmarr/auto-approve-action@v2
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Nextcloud bot approve and merge request
|
||||
- uses: ahmadnassri/action-dependabot-auto-merge@v2
|
||||
with:
|
||||
target: minor
|
||||
target: patch
|
||||
github-token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN }}
|
||||
|
||||
19
.github/workflows/integration.yml
vendored
@@ -2,14 +2,6 @@ name: Integration tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/integration.yml'
|
||||
- 'appinfo/**'
|
||||
- 'lib/**'
|
||||
- 'templates/**'
|
||||
- 'tests/**'
|
||||
- 'composer.json'
|
||||
- 'composer.lock'
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
@@ -27,7 +19,7 @@ jobs:
|
||||
matrix:
|
||||
php-versions: ['7.4']
|
||||
databases: ['sqlite', 'mysql', 'pgsql']
|
||||
server-versions: ['master']
|
||||
server-versions: ['stable23']
|
||||
|
||||
name: php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }}
|
||||
|
||||
@@ -51,7 +43,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout server
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2.4.0
|
||||
with:
|
||||
repository: nextcloud/server
|
||||
ref: ${{ matrix.server-versions }}
|
||||
@@ -62,15 +54,14 @@ jobs:
|
||||
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
||||
git submodule sync --recursive
|
||||
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||
cd build/integration && composer require --dev phpunit/phpunit:~9
|
||||
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2.4.0
|
||||
with:
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@2.15.0
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
tools: phpunit
|
||||
@@ -79,7 +70,7 @@ jobs:
|
||||
|
||||
- name: Set up PHPUnit
|
||||
working-directory: apps/${{ env.APP_NAME }}
|
||||
run: composer i --no-dev
|
||||
run: composer i
|
||||
|
||||
- name: Set up Nextcloud
|
||||
run: |
|
||||
|
||||
18
.github/workflows/lint.yml
vendored
@@ -13,13 +13,13 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php-versions: ['7.4', '8.0', '8.1']
|
||||
php-versions: ['7.3', '7.4']
|
||||
|
||||
name: php${{ matrix.php-versions }} lint
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- name: Set up php${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@2.15.0
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
coverage: none
|
||||
@@ -31,9 +31,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2.4.0
|
||||
- name: Set up php
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@2.15.0
|
||||
with:
|
||||
php-version: 7.4
|
||||
coverage: none
|
||||
@@ -50,9 +50,9 @@ jobs:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- name: Use node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v2.4.1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Set up npm7
|
||||
@@ -71,10 +71,10 @@ jobs:
|
||||
|
||||
name: stylelint node${{ matrix.node-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.4.0
|
||||
|
||||
- name: Set up node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v2.4.1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
|
||||
6
.github/workflows/nightly.yml
vendored
@@ -17,15 +17,15 @@ jobs:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v2.4.1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Set up npm7
|
||||
run: npm i -g npm@7
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@2.15.0
|
||||
with:
|
||||
php-version: '7.4'
|
||||
tools: composer
|
||||
|
||||
4
.github/workflows/nodejs.yml
vendored
@@ -12,9 +12,9 @@ jobs:
|
||||
node-version: [14.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2.4.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v2.4.1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Set up npm7
|
||||
|
||||
18
.github/workflows/phpunit.yml
vendored
@@ -2,14 +2,6 @@ name: PHPUnit
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/phpunit.yml'
|
||||
- 'appinfo/**'
|
||||
- 'lib/**'
|
||||
- 'templates/**'
|
||||
- 'tests/**'
|
||||
- 'composer.json'
|
||||
- 'composer.lock'
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
@@ -26,9 +18,9 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-versions: ['7.4', '8.0', '8.1']
|
||||
php-versions: ['7.3', '7.4']
|
||||
databases: ['sqlite', 'mysql', 'pgsql']
|
||||
server-versions: ['master']
|
||||
server-versions: ['stable23']
|
||||
|
||||
name: php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }}
|
||||
|
||||
@@ -52,7 +44,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout server
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2.4.0
|
||||
with:
|
||||
repository: nextcloud/server
|
||||
ref: ${{ matrix.server-versions }}
|
||||
@@ -65,12 +57,12 @@ jobs:
|
||||
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||
|
||||
- name: Checkout app
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v2.4.0
|
||||
with:
|
||||
path: apps/${{ env.APP_NAME }}
|
||||
|
||||
- name: Set up php ${{ matrix.php-versions }}
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@2.15.0
|
||||
with:
|
||||
php-version: ${{ matrix.php-versions }}
|
||||
tools: phpunit
|
||||
|
||||
2
.github/workflows/psalm.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up php
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 7.4
|
||||
coverage: none
|
||||
|
||||
4
.github/workflows/update-nextcloud-ocp.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
submodules: true
|
||||
|
||||
- name: Set up php7.4
|
||||
uses: shivammathur/setup-php@2.22.0
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 7.4
|
||||
extensions: ctype,curl,dom,fileinfo,gd,intl,json,mbstring,openssl,pdo_sqlite,posix,sqlite,xml,zip
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
continue-on-error: true
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
commit-message: Update psalm baseline
|
||||
|
||||
1
.gitignore
vendored
@@ -9,4 +9,3 @@ tests/.phpunit.result.cache
|
||||
vendor/
|
||||
.php_cs.cache
|
||||
\.idea/
|
||||
settings.json
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
lang_map = hu_HU: hu, nb_NO: nb, sk_SK: sk, th_TH: th, ja_JP: ja, bg_BG: bg, cs_CZ: cs, fi_FI: fi
|
||||
lang_map = sk_SK: sk, th_TH: th, ja_JP: ja, bg_BG: bg, cs_CZ: cs, fi_FI: fi, hu_HU: hu, nb_NO: nb
|
||||
|
||||
[o:nextcloud:p:nextcloud:r:deck]
|
||||
file_filter = translationfiles/<lang>/deck.po
|
||||
|
||||
150
CHANGELOG.md
@@ -1,102 +1,83 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 1.8.0-beta.1
|
||||
### Enhancements
|
||||
|
||||
- Nextcloud 25 compatibility
|
||||
- Performance improvements
|
||||
- Use capped memory cache for board permissions @juliushaertl [#3980](https://github.com/nextcloud/deck/pull/3980)
|
||||
- Improve CalDAV integration performance @juliushaertl [#3982](https://github.com/nextcloud/deck/pull/3982)
|
||||
- Simpify query for getting shared files @juliushaertl [#3983](https://github.com/nextcloud/deck/pull/3983)
|
||||
- Accessibility improvements
|
||||
- Add a11y label for sidebar button @marcelklehr [#3986](https://github.com/nextcloud/deck/pull/3986)
|
||||
- Improve filter popover accessibility @juliushaertl [#3820](https://github.com/nextcloud/deck/pull/3820)
|
||||
- Set ids to skip to content/navigation @juliushaertl [#3924](https://github.com/nextcloud/deck/pull/3924)
|
||||
- Invert icons properly in dark mode @juliushaertl [#3939](https://github.com/nextcloud/deck/pull/3939)
|
||||
- Bump dependencies
|
||||
## 1.6.5
|
||||
|
||||
### Fixed
|
||||
|
||||
- set last modified when the card was found. Fixes #3763 @ylebre [#3796](https://github.com/nextcloud/deck/pull/3796)
|
||||
- Increase file count after sharing @luka-nextcloud [#3682](https://github.com/nextcloud/deck/pull/3682)
|
||||
- Align Duedate-delete icon properly - fixes nextcloud/deck#3791 @Ben-Ro [#3811](https://github.com/nextcloud/deck/pull/3811)
|
||||
- Fix for issue #3637 @flummer [#3833](https://github.com/nextcloud/deck/pull/3833)
|
||||
- Switch to 'markdown-it-task-checkbox' for rendering of task lists @q-wertz [#3898](https://github.com/nextcloud/deck/pull/3898)
|
||||
- Make rename functions accessibly by keyboard navigation @juliushaertl [#3813](https://github.com/nextcloud/deck/pull/3813)
|
||||
- Prevent opening card and applyLabelFilter on card drag end @eneiluj [#3916](https://github.com/nextcloud/deck/pull/3916)
|
||||
- Inserted required property in the rename list field, to prevent the l… @mstolf [#3862](https://github.com/nextcloud/deck/pull/3862)
|
||||
- Fix share provider for master changes @nickvergessen [#3942](https://github.com/nextcloud/deck/pull/3942)
|
||||
- Fetch attachment folder for the correct user during cron job @juliushaertl [#3952](https://github.com/nextcloud/deck/pull/3952)
|
||||
- Fix z-index for deck sidebar @Raudius [#3884](https://github.com/nextcloud/deck/pull/3884)
|
||||
- minor style fixes [#4203](https://github.com/nextcloud/deck/pull/4203)
|
||||
- Add integration test for attachment handling on cards [#4177](https://github.com/nextcloud/deck/pull/4177)
|
||||
- feat: add validators to check values in services @juliushaertl [#4175](https://github.com/nextcloud/deck/pull/4175)
|
||||
- disables autocomplete on card creation @juliushaertl [#4183](https://github.com/nextcloud/deck/pull/4183)
|
||||
|
||||
## 1.6.4
|
||||
|
||||
### Fixed
|
||||
|
||||
- Cache user membership for circles [#4133](https://github.com/nextcloud/deck/pull/4133)
|
||||
- Set event link also for notifications that get emitted from activities [#4119](https://github.com/nextcloud/deck/pull/4119)
|
||||
- disable Create card button while no stack is chosen [#4020](https://github.com/nextcloud/deck/pull/4020)
|
||||
- to nextcloud/OCP package in stable23 [#4094](https://github.com/nextcloud/deck/pull/4094)
|
||||
- Use capped memory cache for board permissions [#3998](https://github.com/nextcloud/deck/pull/3998)
|
||||
- Improve CalDAV integration performance [#3996](https://github.com/nextcloud/deck/pull/3996)
|
||||
- Fetch attachment folder for the correct user during cron job [#3960](https://github.com/nextcloud/deck/pull/3960)
|
||||
- Switch to 'markdown-it-task-checkbox' for rendering of task lists [#3926](https://github.com/nextcloud/deck/pull/3926)
|
||||
- Prevent opening card and applyLabelFilter on card drag end [#3918](https://github.com/nextcloud/deck/pull/3918)
|
||||
- Fix z-index for deck sidebar [#3886](https://github.com/nextcloud/deck/pull/3886)
|
||||
|
||||
|
||||
## 1.6.3
|
||||
|
||||
### Fixed
|
||||
|
||||
- Align Duedate-delete icon properly - fixes nextcloud/deck#3791 [#3816](https://github.com/nextcloud/deck/pull/3816)
|
||||
- Increase file count after sharing [#3805](https://github.com/nextcloud/deck/pull/3805)
|
||||
- Show cards after moving into another list [#3795](https://github.com/nextcloud/deck/pull/3795)
|
||||
- Fetch full board data after cloning [#3780](https://github.com/nextcloud/deck/pull/3780)
|
||||
- Handle qb mapper exception messages properly [#3770](https://github.com/nextcloud/deck/pull/3770)
|
||||
|
||||
## 1.6.2
|
||||
|
||||
### Added
|
||||
|
||||
- Transfer ownership @juliushaertl [#3664](https://github.com/nextcloud/deck/pull/3664)
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛 Fix missing files sidebar [#3641](https://github.com/nextcloud/deck/pull/3641)
|
||||
- Add a missing translation - not found in transifex [#3706](https://github.com/nextcloud/deck/pull/3706)
|
||||
- Fix: Check all circle shares for permissions [#3717](https://github.com/nextcloud/deck/pull/3717)
|
||||
- Sort boards non case sensitive [#3663](https://github.com/nextcloud/deck/pull/3663)
|
||||
- Use explicit cast to make use of index @juliushaertl [#3497](https://github.com/nextcloud/deck/pull/3497)
|
||||
- Fix paramter replacements when creating deck cards from talk messages @juliushaertl [#3741](https://github.com/nextcloud/deck/pull/3741)
|
||||
- Fix hidden attachment icon on archived cards [#3734](https://github.com/nextcloud/deck/pull/3734)
|
||||
- Fix text selection in dark mode and modal view [#3766](https://github.com/nextcloud/deck/pull/3766)
|
||||
|
||||
### Other
|
||||
|
||||
- Switch from OC::$server->get to OCP\Server::get @CarlSchwan [#3801](https://github.com/nextcloud/deck/pull/3801)
|
||||
- Add performance section in README @eneiluj [#3830](https://github.com/nextcloud/deck/pull/3830)
|
||||
- Fix static analysis by stubbing more circle methods @juliushaertl [#3900](https://github.com/nextcloud/deck/pull/3900)
|
||||
- fix(docs): fix links to JSON schemas for Trello @wiktor2200 [#3872](https://github.com/nextcloud/deck/pull/3872)
|
||||
- Move to OCP\Collaboration\Resources\LoadAdditionalScriptsEvent @juliushaertl [#3818](https://github.com/nextcloud/deck/pull/3818)
|
||||
- Rename settings to deck settings @PVince81 [#3928](https://github.com/nextcloud/deck/pull/3928)
|
||||
- SCSS cleanup @juliushaertl [#3803](https://github.com/nextcloud/deck/pull/3803)
|
||||
- Hide deprecated projects in sidebar and card details by default @Pytal [#3984](https://github.com/nextcloud/deck/pull/3984)
|
||||
- Properly check for the stack AND setting board permissions [#3713](https://github.com/nextcloud/deck/pull/3713)
|
||||
- Add missing indices [#3755](https://github.com/nextcloud/deck/pull/3755)
|
||||
|
||||
## 1.7.0
|
||||
|
||||
### Added
|
||||
|
||||
- Transfer ownership @matchish @luka-nextcloud @juliushaertl [#2496](https://github.com/nextcloud/deck/pull/2496)
|
||||
- Import from trello via CLI @vitormattos [#3182](https://github.com/nextcloud/deck/pull/3182)
|
||||
- Add app config to toggle the default calendar setting as an admin @juliushaertl [#3528](https://github.com/nextcloud/deck/pull/3528)
|
||||
- Show board name in browser title @luka-nextcloud [#3499](https://github.com/nextcloud/deck/pull/3499)
|
||||
- Move DeleteCron to be time insensitive @juliushaertl [#3599](https://github.com/nextcloud/deck/pull/3599)
|
||||
- 🚸 Shows error on board fetchData @vinicius73 [#3653](https://github.com/nextcloud/deck/pull/3653)
|
||||
- Add support for PHP 8.1 @juliushaertl [#3601](https://github.com/nextcloud/deck/pull/3601)
|
||||
- Nextcloud 24 compatibility
|
||||
## 1.6.1
|
||||
|
||||
### Fixed
|
||||
|
||||
- CardApiController: Fix order of optional parameters @simonspa [#3512](https://github.com/nextcloud/deck/pull/3512)
|
||||
- Exclude deleted boards in the selection for target @luka-nextcloud [#3502](https://github.com/nextcloud/deck/pull/3502)
|
||||
- Fix CalDAV blocking and modernize circles API usage @juliushaertl [#3500](https://github.com/nextcloud/deck/pull/3500)
|
||||
- Timestamps on created and modified at values @luka-nextcloud [#3532](https://github.com/nextcloud/deck/pull/3532)
|
||||
- return the selector for collections @dartcafe [#3552](https://github.com/nextcloud/deck/pull/3552)
|
||||
- Generate fixed link for activity emails @luka-nextcloud [#3611](https://github.com/nextcloud/deck/pull/3611)
|
||||
- 🐛 Fix missing files sidebar @vinicius73 [#3635](https://github.com/nextcloud/deck/pull/3635)
|
||||
- Handle description shortening more gracefully @juliushaertl [#3650](https://github.com/nextcloud/deck/pull/3650)
|
||||
- Sort boards non case sensitive @Ben-Ro [#3560](https://github.com/nextcloud/deck/pull/3560)
|
||||
- Remove unused argument from transfer ownership @juliushaertl [#3712](https://github.com/nextcloud/deck/pull/3712)
|
||||
- Fix: Check all circle shares for permissions @bink [#3625](https://github.com/nextcloud/deck/pull/3625)
|
||||
- Extend API changelog @juliushaertl [#3522](https://github.com/nextcloud/deck/pull/3522)
|
||||
- Fix talk integration @nickvergessen [#3529](https://github.com/nextcloud/deck/pull/3529)
|
||||
- Fix confusion between stackId and boardId in StackService @eneiluj [#3541](https://github.com/nextcloud/deck/pull/3541)
|
||||
- Add horizontal scrollbar into the large table inside description @luka-nextcloud [#3531](https://github.com/nextcloud/deck/pull/3531)
|
||||
- Make links in markdown note bolder @luka-nextcloud [#3530](https://github.com/nextcloud/deck/pull/3530)
|
||||
- Update master php testing versions @nickvergessen [#3561](https://github.com/nextcloud/deck/pull/3561)
|
||||
- Update master php enviroment @nickvergessen [#3582](https://github.com/nextcloud/deck/pull/3582)
|
||||
- Make insert attachment buttom easy to click @luka-nextcloud [#3612](https://github.com/nextcloud/deck/pull/3612)
|
||||
- Remove extra bullet @elitejake [#3613](https://github.com/nextcloud/deck/pull/3613)
|
||||
- l10n: Delete space @Valdnet [#3666](https://github.com/nextcloud/deck/pull/3666)
|
||||
- Update master php testing versions @nickvergessen [#3688](https://github.com/nextcloud/deck/pull/3688)
|
||||
- Fix wording to represent the code behavior @q-wertz [#3685](https://github.com/nextcloud/deck/pull/3685)
|
||||
- Fix cron jobs @nickvergessen [#3689](https://github.com/nextcloud/deck/pull/3689)
|
||||
- Update master php testing versions @nickvergessen [#3695](https://github.com/nextcloud/deck/pull/3695)
|
||||
- Optimise queries when preparing card related notifications @Raudius [#3690](https://github.com/nextcloud/deck/pull/3690)
|
||||
- Properly check for the stack AND setting board permissions @juliushaertl [#3670](https://github.com/nextcloud/deck/pull/3670)
|
||||
- Replace deprecated String.prototype.substr() @CommanderRoot [#3669](https://github.com/nextcloud/deck/pull/3669)
|
||||
- Dependency updates
|
||||
- Show cards after moving into another list [#3736](https://github.com/nextcloud/deck/pull/3736)
|
||||
- Fix paramter replacements when creating deck cards from talk messages @nickvergessen [#3683](https://github.com/nextcloud/deck/pull/3683)
|
||||
- Fix hidden attachment icon on archived cards [#3733](https://github.com/nextcloud/deck/pull/3733)
|
||||
- Adapt the card modal to upstream changes [#3764](https://github.com/nextcloud/deck/pull/3764)
|
||||
- Fix text selection in dark mode and modal view [#3765](https://github.com/nextcloud/deck/pull/3765)
|
||||
- Add missing indices [#3754](https://github.com/nextcloud/deck/pull/3754)
|
||||
- Exclude deleted boards in the selection for target [#3523](https://api.github.com/repos/nextcloud/deck/pulls/3523)
|
||||
- CardApiController: Fix order of optional parameters [#3520](https://api.github.com/repos/nextcloud/deck/pulls/3520)
|
||||
- Fix cursor generation if no results are found [#3462](https://api.github.com/repos/nextcloud/deck/pulls/3462)
|
||||
- Fix CalDAV blocking and modernize circles API usage [#3526](https://api.github.com/repos/nextcloud/deck/pulls/3526)
|
||||
- Fix overview card listing [#3463](https://api.github.com/repos/nextcloud/deck/pulls/3463)
|
||||
- Generate fixed link for activity emails [#3626](https://api.github.com/repos/nextcloud/deck/pulls/3626)
|
||||
- return the selector for collections [#3618](https://api.github.com/repos/nextcloud/deck/pulls/3618)
|
||||
- Fix confusion between stackId and boardId in StackService [#3543](https://api.github.com/repos/nextcloud/deck/pulls/3543)
|
||||
- Fix talk integration [#3537](https://api.github.com/repos/nextcloud/deck/pulls/3537)
|
||||
- Make insert attachment buttom easy to click [#3614](https://api.github.com/repos/nextcloud/deck/pulls/3614)
|
||||
|
||||
|
||||
## 1.6.0-beta1
|
||||
## 1.6.0
|
||||
|
||||
### Added
|
||||
|
||||
- #3449 Cache most frequent queries
|
||||
- #3177 Use async import for vue component on collections entrypoint @juliushaertl
|
||||
- #2791 Open description links in new tab @fm-sys
|
||||
- #3344 Improve combined search @eneiluj
|
||||
@@ -105,6 +86,11 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
### Fixed
|
||||
|
||||
- #3446 Switch to QBMapper in BoardMapper
|
||||
- #3433 Fix event name for updating the description
|
||||
- #3463 Fix overview card listing
|
||||
- #3440 Allow to download an attachment without navigating to the files app
|
||||
- #3462 Fix cursor generation if no results are found
|
||||
- #3161 Reduce duplicate queries when fetching user boards an permissions @juliushaertl
|
||||
- #3151 Always log generic exceptions @juliushaertl
|
||||
- #3217 Move circle checks to a unified service and improve member checks @juliushaertl
|
||||
|
||||
10
Makefile
@@ -30,16 +30,6 @@ build: clean-dist install-deps build-js
|
||||
|
||||
release: clean-dist install-deps-nodev build-js
|
||||
|
||||
lint: lint-js lint-php
|
||||
|
||||
lint-js:
|
||||
npm run lint
|
||||
npm run stylelint
|
||||
|
||||
lint-php:
|
||||
composer run lint 1>/dev/null
|
||||
composer run cs:check
|
||||
|
||||
build-js: install-deps-js
|
||||
npm run build
|
||||
|
||||
|
||||
23
README.md
@@ -20,14 +20,13 @@ Deck is a kanban style organization tool aimed at personal planning and project
|
||||
### Mobile apps
|
||||
|
||||
- [Nextcloud Deck app for Android](https://github.com/stefan-niedermann/nextcloud-deck) - It is available in [F-Droid](https://f-droid.org/de/packages/it.niedermann.nextcloud.deck/) and the [Google Play Store](https://play.google.com/store/apps/details?id=it.niedermann.nextcloud.deck.play)
|
||||
- [deck NG for Android and iOS](https://github.com/meltzow/deck-ng) - It is available in [Google Play Store](https://play.google.com/store/apps/details?id=net.meltzow.deckng) and [Apple App Store](https://apps.apple.com/us/app/deck-ng/id6443334702)
|
||||
|
||||
### 3rd-Party Integrations
|
||||
|
||||
- [trello-to-deck](https://github.com/maxammann/trello-to-deck) - Migrates cards from Trello
|
||||
- [mail2deck](https://github.com/newroco/mail2deck) - Provides an "email in" solution
|
||||
- [mail2deck](https://github.com/newroco/mail2deck) - Provides an "email in" solution
|
||||
- [A-deck](https://github.com/leoossa/A-deck) - Chrome Extension that allows to create new card in selected stack based on current tab
|
||||
|
||||
-
|
||||
## Installation/Update
|
||||
|
||||
This app is supposed to work on the two latest Nextcloud versions.
|
||||
@@ -53,32 +52,14 @@ Please make sure you have installed the following dependencies: `make, which, ta
|
||||
|
||||
Instead of setting everything up manually, you can just [download the nightly build](https://github.com/nextcloud/deck/releases/tag/nightly) instead. These builds are updated every 24 hours, and are pre-configured with all the needed dependencies.
|
||||
|
||||
## Performance limitations
|
||||
|
||||
Deck is not yet ready for intensive usage.
|
||||
A lot of database queries are generated when the number of boards, cards and attachments is high.
|
||||
For example, a user having access to 13 boards, with each board having on average 100 cards,
|
||||
and each card having on average 5 attachments,
|
||||
would generate 6500 database queries when doing the file related queries
|
||||
which would increase the page loading time significantly.
|
||||
|
||||
Improvements on Nextcloud server and Deck itself will improve the situation.
|
||||
|
||||
## Developing
|
||||
|
||||
### Nextcloud environment
|
||||
|
||||
You need to setup a [development environment](https://docs.nextcloud.com/server/latest/developer_manual//getting_started/devenv.html) of the current nextcloud version. You can also alternatively install & run the [nextcloud docker container](https://github.com/juliushaertl/nextcloud-docker-dev).
|
||||
After the finished installation, you can clone the deck project directly in the `/[nextcloud-docker-dev-dir]/workspace/server/apps/` folder.
|
||||
|
||||
### PHP
|
||||
|
||||
Nothing to prepare, just dig into the code.
|
||||
|
||||
### JavaScript
|
||||
|
||||
This requires at least Node 16 and npm 7 to be installed.
|
||||
|
||||
Deck requires running a `make build-js` to install npm dependencies and build the JavaScript code using webpack. While developing you can also use `make watch` to rebuild everytime the code changes.
|
||||
|
||||
#### Hot reloading
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
|
||||
|
||||
- 📥 Add your tasks to cards and put them in order
|
||||
- 📄 Write down additional notes in Markdown
|
||||
- 📄 Write down additional notes in markdown
|
||||
- 🔖 Assign labels for even better organization
|
||||
- 👥 Share with your team, friends or family
|
||||
- 📎 Attach files and embed them in your Markdown description
|
||||
- 📎 Attach files and embed them in your markdown description
|
||||
- 💬 Discuss with your team using comments
|
||||
- ⚡ Keep track of changes in the activity stream
|
||||
- 🚀 Get your project organized
|
||||
|
||||
</description>
|
||||
<version>1.9.0-beta.1</version>
|
||||
<version>1.6.5</version>
|
||||
<licence>agpl</licence>
|
||||
<author>Julius Härtl</author>
|
||||
<namespace>Deck</namespace>
|
||||
@@ -31,24 +31,19 @@
|
||||
<screenshot>https://download.bitgrid.net/nextcloud/deck/screenshots/1.0/Deck-1.png</screenshot>
|
||||
<screenshot>https://download.bitgrid.net/nextcloud/deck/screenshots/1.0/Deck-2.png</screenshot>
|
||||
<dependencies>
|
||||
<php min-version="7.3"/>
|
||||
<database min-version="9.4">pgsql</database>
|
||||
<database>sqlite</database>
|
||||
<database min-version="8.0">mysql</database>
|
||||
<nextcloud min-version="26" max-version="26"/>
|
||||
<database min-version="5.5">mysql</database>
|
||||
<nextcloud min-version="23" max-version="23"/>
|
||||
</dependencies>
|
||||
<background-jobs>
|
||||
<job>OCA\Deck\Cron\DeleteCron</job>
|
||||
<job>OCA\Deck\Cron\ScheduledNotifications</job>
|
||||
<job>OCA\Deck\Cron\CardDescriptionActivity</job>
|
||||
</background-jobs>
|
||||
<repair-steps>
|
||||
<live-migration>
|
||||
<step>OCA\Deck\Migration\DeletedCircleCleanup</step>
|
||||
</live-migration>
|
||||
</repair-steps>
|
||||
<commands>
|
||||
<command>OCA\Deck\Command\UserExport</command>
|
||||
<command>OCA\Deck\Command\BoardImport</command>
|
||||
<command>OCA\Deck\Command\TransferOwnership</command>
|
||||
</commands>
|
||||
<activity>
|
||||
|
||||
@@ -92,10 +92,6 @@ return [
|
||||
['name' => 'board_api#deleteAcl', 'url' => '/api/v{apiVersion}/boards/{boardId}/acl/{aclId}', 'verb' => 'DELETE'],
|
||||
['name' => 'board_api#updateAcl', 'url' => '/api/v{apiVersion}/boards/{boardId}/acl/{aclId}', 'verb' => 'PUT'],
|
||||
|
||||
['name' => 'board_import_api#getAllowedSystems', 'url' => '/api/v{apiVersion}/boards/import/getSystems','verb' => 'GET'],
|
||||
['name' => 'board_import_api#getConfigSchema', 'url' => '/api/v{apiVersion}/boards/import/config/schema/{name}','verb' => 'GET'],
|
||||
['name' => 'board_import_api#import', 'url' => '/api/v{apiVersion}/boards/import','verb' => 'POST'],
|
||||
|
||||
|
||||
['name' => 'stack_api#index', 'url' => '/api/v{apiVersion}/boards/{boardId}/stacks', 'verb' => 'GET'],
|
||||
['name' => 'stack_api#getArchived', 'url' => '/api/v{apiVersion}/boards/{boardId}/stacks/archived', 'verb' => 'GET'],
|
||||
|
||||
@@ -9,34 +9,29 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"cogpowered/finediff": "0.3.*",
|
||||
"justinrainbow/json-schema": "^5.2"
|
||||
"cogpowered/finediff": "0.3.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"roave/security-advisories": "dev-master",
|
||||
"phpunit/phpunit": "^9",
|
||||
"nextcloud/coding-standard": "^1.0.0",
|
||||
"phpunit/phpunit": "^8",
|
||||
"nextcloud/coding-standard": "^0.5.0",
|
||||
"symfony/event-dispatcher": "^4.0",
|
||||
"vimeo/psalm": "^4.3",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"nextcloud/ocp": "dev-master"
|
||||
"nextcloud/ocp": "dev-stable23"
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"classmap-authoritative": true,
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true
|
||||
},
|
||||
"platform": {
|
||||
"php": "7.4"
|
||||
}
|
||||
"php": "7.3"
|
||||
},
|
||||
"optimize-autoloader": true,
|
||||
"classmap-authoritative": true
|
||||
},
|
||||
"scripts": {
|
||||
"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 --update-baseline",
|
||||
"psalm:fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType",
|
||||
"test": [
|
||||
"@test:unit",
|
||||
|
||||
1744
composer.lock
generated
@@ -1,9 +0,0 @@
|
||||
.icon-deck {
|
||||
background-image: url(../img/deck-dark.svg);
|
||||
filter: var(--background-invert-if-dark);
|
||||
}
|
||||
|
||||
.icon-deck-white, .icon-deck.icon-white {
|
||||
background-image: url(../img/deck.svg);
|
||||
filter: var(--background-invert-if-dark);
|
||||
}
|
||||
1
css/deck.scss
Normal file
@@ -0,0 +1 @@
|
||||
@include icon-black-white('deck', 'deck', 1);
|
||||
@@ -1,8 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 Raul Ferreira Fuentes <raul@nextcloud.com>
|
||||
/*
|
||||
* @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
|
||||
*
|
||||
* @author Raul Ferreira Fuentes <raul@nextcloud.com>
|
||||
* @author Julius Härtl <jus@bitgrid.net>
|
||||
* @author Artem Anufrij <artem.anufrij@live.de>
|
||||
* @author Marin Treselj <marin@pixelipo.com>
|
||||
* @author Oskar Kurz <oskar.kurz@gmail.com>
|
||||
* @author Ryan Fletcher <ryan.fletcher@codepassion.ca>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
@@ -20,26 +23,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OCA\Deck\Model;
|
||||
|
||||
use OCA\Deck\Db\Board;
|
||||
|
||||
class BoardSummary extends Board {
|
||||
private Board $board;
|
||||
|
||||
public function __construct(Board $board) {
|
||||
parent::__construct();
|
||||
$this->board = $board;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array {
|
||||
return [
|
||||
'id' => $this->getId(),
|
||||
'title' => $this->getTitle()
|
||||
];
|
||||
}
|
||||
|
||||
public function __call($name, $arguments) {
|
||||
return $this->board->__call($name, $arguments);
|
||||
}
|
||||
}
|
||||
@import 'icons';
|
||||
@import 'print';
|
||||
41
css/icons.scss
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Custom icons
|
||||
*/
|
||||
@include icon-black-white('deck', 'deck', 1);
|
||||
@include icon-black-white('archive', 'deck', 1);
|
||||
@include icon-black-white('circles', 'deck', 1);
|
||||
@include icon-black-white('clone', 'deck', 1);
|
||||
@include icon-black-white('filter', 'deck', 1);
|
||||
@include icon-black-white('filter_set', 'deck', 1);
|
||||
@include icon-black-white('attach', 'deck', 1);
|
||||
@include icon-black-white('reply', 'deck', 1);
|
||||
@include icon-black-white('notifications-dark', 'deck', 1);
|
||||
@include icon-black-white('description', 'deck', 1);
|
||||
|
||||
.icon-toggle-compact-collapsed {
|
||||
@include icon-color('toggle-view-expand', 'deck', $color-black);
|
||||
}
|
||||
|
||||
.icon-toggle-compact-expanded {
|
||||
@include icon-color('toggle-view-collapse', 'deck', $color-black);
|
||||
}
|
||||
.icon-activity {
|
||||
@include icon-color('activity-dark', 'activity', $color-black);
|
||||
}
|
||||
.icon-comment--unread {
|
||||
@include icon-color('comment', 'actions', $color-primary, 1, true);
|
||||
}
|
||||
|
||||
.avatardiv.circles {
|
||||
background: var(--color-primary);
|
||||
}
|
||||
|
||||
.icon-circles {
|
||||
opacity: 1;
|
||||
background-size: 20px;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.icon-colorpicker {
|
||||
background-image: url('../img/color_picker.svg');
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
const { defineConfig } = require('cypress')
|
||||
|
||||
module.exports = defineConfig({
|
||||
projectId: '1s7wkc',
|
||||
viewportWidth: 1280,
|
||||
viewportHeight: 720,
|
||||
e2e: {
|
||||
// We've imported your old cypress plugins here.
|
||||
// You may want to clean this up later by importing these.
|
||||
setupNodeEvents(on, config) {
|
||||
return require('./cypress/plugins/index.js')(on, config)
|
||||
},
|
||||
baseUrl: 'http://nextcloud.local/index.php',
|
||||
experimentalSessionAndOrigin: true,
|
||||
specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
|
||||
},
|
||||
})
|
||||
@@ -1,41 +0,0 @@
|
||||
import { randHash } from '../utils'
|
||||
const randUser = randHash()
|
||||
|
||||
describe('Board', function() {
|
||||
const password = 'pass123'
|
||||
|
||||
before(function() {
|
||||
cy.nextcloudCreateUser(randUser, password)
|
||||
})
|
||||
|
||||
beforeEach(function() {
|
||||
cy.login(randUser, password)
|
||||
})
|
||||
|
||||
it('Can create a board', function() {
|
||||
const board = 'TestBoard'
|
||||
|
||||
cy.intercept({
|
||||
method: 'POST',
|
||||
url: '/index.php/apps/deck/boards',
|
||||
}).as('createBoardRequest')
|
||||
|
||||
// Click "Add board"
|
||||
cy.openLeftSidebar()
|
||||
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry')
|
||||
.eq(3).find('a').first().click({ force: true })
|
||||
|
||||
// Type the board title
|
||||
cy.get('.board-create form input[type=text]')
|
||||
.type(board, { force: true })
|
||||
|
||||
// Submit
|
||||
cy.get('.board-create form input[type=submit]')
|
||||
.first().click({ force: true })
|
||||
|
||||
cy.wait('@createBoardRequest').its('response.statusCode').should('equal', 200)
|
||||
|
||||
cy.get('.app-navigation__list .app-navigation-entry__children .app-navigation-entry')
|
||||
.contains(board).should('be.visible')
|
||||
})
|
||||
})
|
||||
@@ -1,67 +0,0 @@
|
||||
import { randHash } from '../utils'
|
||||
const randUser = randHash()
|
||||
|
||||
const testBoardData = {
|
||||
title: 'MyBoardTest',
|
||||
color: '00ff00',
|
||||
stacks: [
|
||||
{
|
||||
title: 'TestList',
|
||||
cards: [
|
||||
{
|
||||
title: 'Hello world',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
describe('Card', function() {
|
||||
before(function() {
|
||||
cy.nextcloudCreateUser(randUser, randUser)
|
||||
cy.createExampleBoard({
|
||||
user: randUser,
|
||||
password: randUser,
|
||||
board: testBoardData,
|
||||
})
|
||||
})
|
||||
|
||||
beforeEach(function() {
|
||||
cy.login(randUser, randUser)
|
||||
})
|
||||
|
||||
it('Can show card details modal', function() {
|
||||
cy.openLeftSidebar()
|
||||
cy.getNavigationEntry(testBoardData.title)
|
||||
.first().click({ force: true })
|
||||
|
||||
cy.get('.board .stack').eq(0).within(() => {
|
||||
cy.get('.card:contains("Hello world")').should('be.visible').click()
|
||||
})
|
||||
|
||||
cy.get('.modal__card').should('be.visible')
|
||||
cy.get('.app-sidebar-header__maintitle').contains('Hello world')
|
||||
})
|
||||
|
||||
it('Can add a card', function() {
|
||||
const newCardTitle = 'Write some cypress tests'
|
||||
|
||||
cy.openLeftSidebar()
|
||||
cy.getNavigationEntry(testBoardData.title)
|
||||
.first().click({ force: true })
|
||||
|
||||
cy.get('.board .stack').eq(0).within(() => {
|
||||
cy.get('.card:contains("Hello world")').should('be.visible')
|
||||
|
||||
cy.get('.button-vue[aria-label*="Add card"]')
|
||||
.first().click()
|
||||
|
||||
cy.get('.stack__card-add form input#new-stack-input-main')
|
||||
.type(newCardTitle)
|
||||
cy.get('.stack__card-add form input[type=submit]')
|
||||
.first().click()
|
||||
cy.get(`.card:contains("${newCardTitle}")`).should('be.visible')
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
@@ -1,31 +0,0 @@
|
||||
import { randHash } from '../utils'
|
||||
const randUser = randHash()
|
||||
|
||||
describe('Deck dashboard', function() {
|
||||
const password = 'pass123'
|
||||
|
||||
before(function() {
|
||||
cy.nextcloudCreateUser(randUser, password)
|
||||
})
|
||||
|
||||
beforeEach(function() {
|
||||
cy.login(randUser, password)
|
||||
})
|
||||
|
||||
it('Can show the right title on the dashboard', function() {
|
||||
cy.get('.board-title h2')
|
||||
.should('have.length', 1).first()
|
||||
.should('have.text', 'Upcoming cards')
|
||||
})
|
||||
|
||||
it('Can see the default "Personal Board" created for user by default', function() {
|
||||
const defaultBoard = 'Personal'
|
||||
|
||||
cy.openLeftSidebar()
|
||||
cy.get('.app-navigation-entry-wrapper[icon=icon-deck]')
|
||||
.find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + defaultBoard + ')')
|
||||
.first()
|
||||
.contains(defaultBoard)
|
||||
.should('be.visible')
|
||||
})
|
||||
})
|
||||
@@ -1,30 +0,0 @@
|
||||
import { randHash } from '../utils'
|
||||
const randUser = randHash()
|
||||
|
||||
describe('Stack', function() {
|
||||
const board = 'TestBoard'
|
||||
const password = 'pass123'
|
||||
const stack = 'List 1'
|
||||
|
||||
before(function() {
|
||||
cy.nextcloudCreateUser(randUser, password)
|
||||
cy.deckCreateBoard({ user: randUser, password }, board)
|
||||
})
|
||||
|
||||
beforeEach(function() {
|
||||
cy.logout()
|
||||
cy.login(randUser, password)
|
||||
})
|
||||
|
||||
it('Can create a stack', function() {
|
||||
cy.openLeftSidebar()
|
||||
cy.getNavigationEntry(board)
|
||||
.click({ force: true })
|
||||
|
||||
cy.get('#stack-add button').first().click()
|
||||
cy.get('#stack-add form input#new-stack-input-main').type(stack)
|
||||
cy.get('#stack-add form input[type=submit]').first().click()
|
||||
|
||||
cy.get('.board .stack').eq(0).contains(stack).should('be.visible')
|
||||
})
|
||||
})
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
/**
|
||||
* @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
const url = Cypress.config('baseUrl').replace(/\/index.php\/?$/g, '')
|
||||
Cypress.env('baseUrl', url)
|
||||
|
||||
Cypress.Commands.add('login', (user, password, route = '/apps/deck/') => {
|
||||
const session = `${user}-${Date.now()}`
|
||||
cy.session(session, function() {
|
||||
cy.visit(route)
|
||||
cy.get('input[name=user]').type(user)
|
||||
cy.get('input[name=password]').type(password)
|
||||
cy.get('form[name=login] [type=submit]').click()
|
||||
cy.url().should('include', route)
|
||||
})
|
||||
cy.visit(route)
|
||||
})
|
||||
|
||||
Cypress.Commands.add('logout', (route = '/') => {
|
||||
cy.session('_guest', function() {})
|
||||
})
|
||||
|
||||
Cypress.Commands.add('nextcloudCreateUser', (user, password) => {
|
||||
cy.clearCookies()
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: `${Cypress.env('baseUrl')}/ocs/v1.php/cloud/users?format=json`,
|
||||
form: true,
|
||||
body: {
|
||||
userid: user,
|
||||
password,
|
||||
},
|
||||
auth: { user: 'admin', pass: 'admin' },
|
||||
headers: {
|
||||
'OCS-ApiRequest': 'true',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
}).then((response) => {
|
||||
cy.log(`Created user ${user}`, response.status)
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add('nextcloudUpdateUser', (user, password, key, value) => {
|
||||
cy.request({
|
||||
method: 'PUT',
|
||||
url: `${Cypress.env('baseUrl')}/ocs/v2.php/cloud/users/${user}`,
|
||||
form: true,
|
||||
body: { key, value },
|
||||
auth: { user, pass: password },
|
||||
headers: {
|
||||
'OCS-ApiRequest': 'true',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
}).then((response) => {
|
||||
cy.log(`Updated user ${user} ${key} to ${value}`, response.status)
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add('openLeftSidebar', () => {
|
||||
cy.get('.app-navigation button.app-navigation-toggle').click()
|
||||
})
|
||||
|
||||
Cypress.Commands.add('deckCreateBoard', ({ user, password }, title) => {
|
||||
cy.login(user, password)
|
||||
|
||||
cy.get('.app-navigation button.app-navigation-toggle').click()
|
||||
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry')
|
||||
.eq(3)
|
||||
.find('a')
|
||||
.first()
|
||||
.click({ force: true })
|
||||
|
||||
cy.get('.board-create form input[type=text]').type(title, { force: true })
|
||||
|
||||
cy.get('.board-create form input[type=submit]')
|
||||
.first()
|
||||
.click({ force: true })
|
||||
})
|
||||
|
||||
Cypress.Commands.add('deckCreateList', ({ user, password }, title) => {
|
||||
cy.login(user, password)
|
||||
|
||||
cy.get('.app-navigation button.app-navigation-toggle').click()
|
||||
cy.get('#app-navigation-vue .app-navigation__list .app-navigation-entry')
|
||||
.eq(3)
|
||||
.find('a.app-navigation-entry-link')
|
||||
.first()
|
||||
.click({ force: true })
|
||||
|
||||
cy.get('#stack-add button').first().click()
|
||||
cy.get('#stack-add form input#new-stack-input-main').type(title)
|
||||
cy.get('#stack-add form input[type=submit]').first().click()
|
||||
})
|
||||
|
||||
Cypress.Commands.add('createExampleBoard', ({ user, password, board }) => {
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: `${Cypress.env('baseUrl')}/index.php/apps/deck/api/v1.0/boards`,
|
||||
auth: {
|
||||
user,
|
||||
password,
|
||||
},
|
||||
body: { title: board.title, color: board.color ?? 'ff0000' },
|
||||
}).then((boardResponse) => {
|
||||
expect(boardResponse.status).to.eq(200)
|
||||
const boardData = boardResponse.body
|
||||
for (const stackIndex in board.stacks) {
|
||||
const stack = board.stacks[stackIndex]
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: `${Cypress.env('baseUrl')}/index.php/apps/deck/api/v1.0/boards/${boardData.id}/stacks`,
|
||||
auth: {
|
||||
user,
|
||||
password,
|
||||
},
|
||||
body: { title: stack.title, order: 0 },
|
||||
}).then((stackResponse) => {
|
||||
const stackData = stackResponse.body
|
||||
for (const cardIndex in stack.cards) {
|
||||
const card = stack.cards[cardIndex]
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: `${Cypress.env('baseUrl')}/index.php/apps/deck/api/v1.0/boards/${boardData.id}/stacks/${stackData.id}/cards`,
|
||||
auth: {
|
||||
user,
|
||||
password,
|
||||
},
|
||||
body: { title: card.title },
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.Commands.add('getNavigationEntry', (boardTitle) => {
|
||||
return cy.get('.app-navigation-entry-wrapper[icon=icon-deck]')
|
||||
.find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + boardTitle + ')')
|
||||
.find('a.app-navigation-entry-link')
|
||||
})
|
||||
@@ -1,20 +0,0 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
@@ -1 +0,0 @@
|
||||
export const randHash = () => Math.random().toString(36).replace(/[^a-z]+/g, '').slice(0, 10)
|
||||
75
docs/API.md
@@ -1,7 +1,7 @@
|
||||
|
||||
The REST API provides access for authenticated users to their data inside the Deck app. To get a better understanding of Decks data models and their relations, please have a look at the [data structure](structure.md) documentation.
|
||||
|
||||
# Prerequisites
|
||||
# Prequisited
|
||||
|
||||
- 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
|
||||
@@ -9,7 +9,7 @@ The REST API provides access for authenticated users to their data inside the De
|
||||
|
||||
## Naming
|
||||
|
||||
- Board is the project like grouping of tasks that can be shared to different users and groups
|
||||
- Board is the the project like grouping of tasks that can be shared to different users and groups
|
||||
|
||||
- Stack is the grouping of cards which is rendered in vertical columns in the UI
|
||||
|
||||
@@ -96,27 +96,10 @@ If available the ETag will also be part of JSON response objects as shown below
|
||||
|
||||
# Changelog
|
||||
|
||||
## API version 1.0
|
||||
|
||||
- Deck >=1.0.0: The maximum length of the card title has been extended from 100 to 255 characters
|
||||
- Deck >=1.0.0: The API will now return a 400 Bad request response if the length limitation of a board, stack or card title is exceeded
|
||||
|
||||
## API version 1.1
|
||||
|
||||
This API version has become available with **Deck 1.3.0**.
|
||||
## 1.0.0 (unreleased)
|
||||
|
||||
- The maximum length of the card title has been extended from 100 to 255 characters
|
||||
- The API will now return a 400 Bad request response if the length limitation of a board, stack or card title is exceeded
|
||||
- The attachments API endpoints will return other attachment types than deck_file
|
||||
- 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
|
||||
|
||||
## API version 1.2 (unreleased)
|
||||
|
||||
- Endpoints for the new import functionality have been added:
|
||||
- [GET /boards/import/getSystems - Import a board](#get-boardsimportgetsystems-import-a-board)
|
||||
- [GET /boards/import/config/system/{schema} - Import a board](#get-boardsimportconfigsystemschema-import-a-board)
|
||||
- [POST /boards/import - Import a board](#post-boardsimport-import-a-board)
|
||||
|
||||
# Endpoints
|
||||
|
||||
@@ -944,8 +927,7 @@ The request can fail with a bad request response for the following reasons:
|
||||
| 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
|
||||
For now only `deck_file` is supported as an attachment type.
|
||||
|
||||
#### Response
|
||||
|
||||
@@ -1006,49 +988,6 @@ For now only `deck_file` is supported as an attachment type.
|
||||
|
||||
##### 200 Success
|
||||
|
||||
### GET /boards/import/getSystems - Import a board
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| ------------ | ------- | --------------------------------------------- |
|
||||
| system | Integer | The system name. Example: trello |
|
||||
|
||||
#### Response
|
||||
|
||||
Make a request to see the json schema of system
|
||||
|
||||
```json
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
### GET /boards/import/config/system/{schema} - Import a board
|
||||
|
||||
#### Request parameters
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
[
|
||||
"trello"
|
||||
]
|
||||
```
|
||||
|
||||
### POST /boards/import - Import a board
|
||||
|
||||
#### Request parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| ------------ | ------- | --------------------------------------------- |
|
||||
| system | string | The allowed name of system to import from |
|
||||
| config | Object | The config object (JSON) |
|
||||
| data | Object | The data object to import (JSON) |
|
||||
|
||||
#### Response
|
||||
|
||||
##### 200 Success
|
||||
|
||||
# OCS API
|
||||
|
||||
The following endpoints are available through the Nextcloud OCS endpoint, which is available at `/ocs/v2.php/apps/deck/api/v1.0/`.
|
||||
@@ -1065,8 +1004,6 @@ Deck stores user and app configuration values globally and per board. The GET en
|
||||
| Config key | Description |
|
||||
| --- | --- |
|
||||
| calendar | Determines if the calendar/tasks integration through the CalDAV backend is enabled for the user (boolean) |
|
||||
| cardDetailsInModal | Determines if the bigger view is used (boolean) |
|
||||
| cardIdBadge | Determines if the ID badges are displayed on cards (boolean) |
|
||||
| groupLimit | Determines if creating new boards is limited to certain groups of the instance. The resulting output is an array of group objects with the id and the displayname (Admin only)|
|
||||
|
||||
```
|
||||
@@ -1079,8 +1016,6 @@ Deck stores user and app configuration values globally and per board. The GET en
|
||||
},
|
||||
"data": {
|
||||
"calendar": true,
|
||||
"cardDetailsInModal": true,
|
||||
"cardIdBadge": true,
|
||||
"groupLimit": [
|
||||
{
|
||||
"id": "admin",
|
||||
@@ -1110,8 +1045,6 @@ Deck stores user and app configuration values globally and per board. The GET en
|
||||
| --- | ----- |
|
||||
| notify-due | `off`, `assigned` or `all` |
|
||||
| calendar | Boolean |
|
||||
| cardDetailsInModal | Boolean |
|
||||
| cardIdBadge | Boolean |
|
||||
|
||||
#### Example request
|
||||
|
||||
|
||||
@@ -14,9 +14,7 @@ Overall, Deck is easy to use. You can create boards, add users, share the Deck,
|
||||
3. [Handle cards options](#3-handle-cards-options)
|
||||
4. [Archive old tasks](#4-archive-old-tasks)
|
||||
5. [Manage your board](#5-manage-your-board)
|
||||
6. [Import boards](#6-import-boards)
|
||||
7. [Search](#7-search)
|
||||
8. [New owner for the deck entities](#8-new-owner-for-the-deck-entities)
|
||||
6. [New owner for the deck entities](#8-new-owner-for-the-deck-entities)
|
||||
|
||||
### 1. Create my first board
|
||||
In this example, we're going to create a board and share it with an other nextcloud user.
|
||||
@@ -72,80 +70,14 @@ The **sharing tab** allows you to add users or even groups to your boards.
|
||||
**Deleted objects** allows you to return previously deleted stacks or cards.
|
||||
The **Timeline** allows you to see everything that happened in your boards. Everything!
|
||||
|
||||
### 6. Import boards
|
||||
|
||||
Importing can be done using the API or the `occ` `deck:import` command.
|
||||
|
||||
Comments with more than 1000 characters are placed as attached files to the card.
|
||||
|
||||
It is possible to import from the following sources:
|
||||
|
||||
#### Trello JSON
|
||||
|
||||
Steps:
|
||||
* Create the data file
|
||||
* Access Trello
|
||||
* go to the board you want to export
|
||||
* Follow the steps in [Trello documentation](https://help.trello.com/article/747-exporting-data-from-trello-1) and export as JSON
|
||||
* Create the configuration file
|
||||
* Execute the import informing the import file path, data file and source as `Trello JSON`
|
||||
|
||||
Create the configuration file respecting the [JSON Schema](https://github.com/nextcloud/deck/blob/master/lib/Service/Importer/fixtures/config-trelloJson-schema.json) for import `Trello JSON`
|
||||
|
||||
Example configuration file:
|
||||
```json
|
||||
{
|
||||
"owner": "admin",
|
||||
"color": "0800fd",
|
||||
"uidRelation": {
|
||||
"johndoe": "johndoe"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Limitations**:
|
||||
|
||||
Importing from a JSON file imports up to 1000 actions. To find out how many actions the board to be imported has, identify how many actions the JSON has.
|
||||
|
||||
#### Trello API
|
||||
|
||||
Import using API is recommended for boards with more than 1000 actions.
|
||||
|
||||
Trello makes it possible to attach links to a card. Deck does not have this feature. Attachments and attachment links are added in a markdown table at the end of the description for every imported card that has attachments in Trello.
|
||||
|
||||
* Get the API Key and API Token [here](https://developer.atlassian.com/cloud/trello/guides/rest-api/api-introduction/#authentication-and-authorization)
|
||||
* Get the ID of the board you want to import by making a request to:
|
||||
https://api.trello.com/1/members/me/boards?key={yourKey}&token={yourToken}&fields=id,name
|
||||
|
||||
This ID you will use in the configuration file in the `board` property
|
||||
* Create the configuration file
|
||||
|
||||
Create the configuration file respecting the [JSON Schema](https://github.com/nextcloud/deck/blob/master/lib/Service/Importer/fixtures/config-trelloApi-schema.json) for import `Trello JSON`
|
||||
|
||||
Example configuration file:
|
||||
```json
|
||||
{
|
||||
"owner": "admin",
|
||||
"color": "0800fd",
|
||||
"api": {
|
||||
"key": "0cc175b9c0f1b6a831c399e269772661",
|
||||
"token": "92eb5ffee6ae2fec3ad71c777531578f4a8a08f09d37b73795649038408b5f33"
|
||||
},
|
||||
"board": "8277e0910d750195b4487976",
|
||||
"uidRelation": {
|
||||
"johndoe": "johndoe"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Search
|
||||
## Search
|
||||
|
||||
Deck provides a global search either through the unified search in the Nextcloud header or with the inline search next to the board controls.
|
||||
This search allows advanced filtering of cards across all board of the logged in user.
|
||||
|
||||
For example the search `project tag:ToDo assigned:alice assigned:bob` will return all cards where the card title or description contains project **and** the tag ToDo is set **and** the user alice is assigned **and** the user bob is assigned.
|
||||
|
||||
#### Supported search filters
|
||||
### Supported search filters
|
||||
|
||||
| Filter | Operators | Query |
|
||||
| ----------- | ----------------- | ------------------------------------------------------------ |
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
## Implement import
|
||||
|
||||
* Create a new importer class extending `ABoardImportService`
|
||||
* Create a listener for event `BoardImportGetAllowedEvent` to enable your importer.
|
||||
> You can read more about listeners on [Nextcloud](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html?highlight=event#writing-a-listener) doc.
|
||||
|
||||
Example:
|
||||
|
||||
```php
|
||||
class YourCustomImporterListener {
|
||||
public function handle(Event $event): void {
|
||||
if (!($event instanceof BoardImportGetAllowedEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$event->getService()->addAllowedImportSystem([
|
||||
'name' => YourCustomImporterService::$name,
|
||||
'class' => YourCustomImporterService::class,
|
||||
'internalName' => 'YourCustomImporter'
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
* Register your listener on your `Application` class like this:
|
||||
```php
|
||||
$dispatcher = $this->getContainer()->query(IEventDispatcher::class);
|
||||
$dispatcher->registerEventListener(
|
||||
BoardImportGetAllowedEvent::class,
|
||||
YourCustomImporterListener::class
|
||||
);
|
||||
```
|
||||
* Use the `lib/Service/Importer/Systems/TrelloJsonService.php` class as inspiration
|
||||
@@ -1,7 +0,0 @@
|
||||
## Import class diagram
|
||||
|
||||
Importing boards to the Deck implements the class diagram below.
|
||||
|
||||
> **NOTE**: When making any changes to the structure of the classes or implementing import from other sources, edit the `BoardImport.yuml` file
|
||||
|
||||

|
||||
@@ -1,214 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.40.1 (20161225.0304)
|
||||
-->
|
||||
<!-- Title: G Pages: 1 -->
|
||||
<svg width="417pt" height="830pt"
|
||||
viewBox="0.00 0.00 417.01 830.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 826)">
|
||||
<title>G</title>
|
||||
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-826 413.012,-826 413.012,4 -4,4"/>
|
||||
<!-- A0 -->
|
||||
<g id="node1" class="node">
|
||||
<title>A0</title>
|
||||
<polygon fill="#fff8dc" stroke="#000000" points="165.909,-822 70.091,-822 70.091,-766 171.909,-766 171.909,-816 165.909,-822"/>
|
||||
<polyline fill="none" stroke="#000000" points="165.909,-822 165.909,-816 "/>
|
||||
<polyline fill="none" stroke="#000000" points="171.909,-816 165.909,-816 "/>
|
||||
<text text-anchor="middle" x="121" y="-809" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Classes used on</text>
|
||||
<text text-anchor="middle" x="121" y="-797" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">board import.</text>
|
||||
<text text-anchor="middle" x="121" y="-785" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Methods just to</text>
|
||||
<text text-anchor="middle" x="121" y="-773" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">illustrate.</text>
|
||||
</g>
|
||||
<!-- A1 -->
|
||||
<g id="node2" class="node">
|
||||
<title>A1</title>
|
||||
<polygon fill="none" stroke="#000000" points="108.7773,-680 23.2227,-680 23.2227,-644 108.7773,-644 108.7773,-680"/>
|
||||
<text text-anchor="middle" x="66" y="-659" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ApiController</text>
|
||||
</g>
|
||||
<!-- A2 -->
|
||||
<g id="node3" class="node">
|
||||
<title>A2</title>
|
||||
<polygon fill="none" stroke="#000000" points="0,-514 0,-546 132,-546 132,-514 0,-514"/>
|
||||
<text text-anchor="start" x="9.607" y="-527" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">BoardImportApiController</text>
|
||||
<polygon fill="none" stroke="#000000" points="0,-458 0,-514 132,-514 132,-458 0,-458"/>
|
||||
<text text-anchor="start" x="45.8645" y="-495" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+import()</text>
|
||||
<text text-anchor="start" x="16.1335" y="-483" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+getAllowedSystems()</text>
|
||||
<text text-anchor="start" x="20.0185" y="-471" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+getConfigSchema()</text>
|
||||
</g>
|
||||
<!-- A1->A2 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>A1->A2</title>
|
||||
<path fill="none" stroke="#000000" d="M66,-633.6693C66,-609.4424 66,-574.1663 66,-546.2238"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="66,-643.957 61.5001,-633.9569 66,-638.957 66.0001,-633.957 66.0001,-633.957 66.0001,-633.957 66,-638.957 70.5001,-633.957 66,-643.957 66,-643.957"/>
|
||||
</g>
|
||||
<!-- A3 -->
|
||||
<g id="node4" class="node">
|
||||
<title>A3</title>
|
||||
<polygon fill="none" stroke="#000000" points="92,-364 92,-396 200,-396 200,-364 92,-364"/>
|
||||
<text text-anchor="start" x="101.828" y="-377" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">BoardImportService</text>
|
||||
<polygon fill="none" stroke="#000000" points="92,-284 92,-364 200,-364 200,-284 92,-284"/>
|
||||
<text text-anchor="start" x="125.8645" y="-345" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+import()</text>
|
||||
<text text-anchor="start" x="118.9105" y="-333" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+bootstrap()</text>
|
||||
<text text-anchor="start" x="105.857" y="-321" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+validateSystem()</text>
|
||||
<text text-anchor="start" x="108.218" y="-309" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">#validateConfig()</text>
|
||||
<text text-anchor="start" x="112.107" y="-297" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">#validateData()</text>
|
||||
</g>
|
||||
<!-- A2->A3 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>A2->A3</title>
|
||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M87.8604,-457.7328C95.8577,-441.5382 105.0823,-422.8583 113.7939,-405.2174"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="118.2935,-396.1057 117.9004,-407.0646 116.0795,-400.5889 113.8656,-405.072 113.8656,-405.072 113.8656,-405.072 116.0795,-400.5889 109.8308,-403.0795 118.2935,-396.1057 118.2935,-396.1057"/>
|
||||
<text text-anchor="middle" x="88.3076" y="-434.7378" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">uses</text>
|
||||
</g>
|
||||
<!-- A7 -->
|
||||
<g id="node8" class="node">
|
||||
<title>A7</title>
|
||||
<polygon fill="none" stroke="#000000" points="37,-196 37,-228 129,-228 129,-196 37,-196"/>
|
||||
<text text-anchor="start" x="46.612" y="-209" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">TrelloApiService</text>
|
||||
<polygon fill="none" stroke="#000000" points="37,-164 37,-196 129,-196 129,-164 37,-164"/>
|
||||
<text text-anchor="start" x="53.9655" y="-177" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+name:string</text>
|
||||
</g>
|
||||
<!-- A3->A7 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>A3->A7</title>
|
||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M114.8609,-283.9135C107.8316,-268.5143 100.7854,-252.0928 95.0404,-237.6613"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="91.2872,-228.0253 99.1098,-235.7102 93.1019,-232.6844 94.9167,-237.3434 94.9167,-237.3434 94.9167,-237.3434 93.1019,-232.6844 90.7235,-238.9767 91.2872,-228.0253 91.2872,-228.0253"/>
|
||||
<text text-anchor="middle" x="99.6759" y="-267.8975" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">uses</text>
|
||||
</g>
|
||||
<!-- A9 -->
|
||||
<g id="node10" class="node">
|
||||
<title>A9</title>
|
||||
<polygon fill="none" stroke="#000000" points="148,-202 148,-234 273,-234 273,-202 148,-202"/>
|
||||
<text text-anchor="start" x="170.7765" y="-215" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">TrelloJsonService</text>
|
||||
<polygon fill="none" stroke="#000000" points="148,-158 148,-202 273,-202 273,-158 148,-158"/>
|
||||
<text text-anchor="start" x="181.4655" y="-183" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+name:string</text>
|
||||
<text text-anchor="start" x="157.981" y="-171" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">#needValidateData:true</text>
|
||||
</g>
|
||||
<!-- A3->A9 -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>A3->A9</title>
|
||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M164.3261,-283.9135C170.0039,-270.5688 176.3462,-256.4563 182.4816,-243.5365"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="186.9002,-234.3677 186.6126,-245.3298 184.7295,-238.872 182.5588,-243.3762 182.5588,-243.3762 182.5588,-243.3762 184.7295,-238.872 178.505,-241.4226 186.9002,-234.3677 186.9002,-234.3677"/>
|
||||
<text text-anchor="middle" x="163.6874" y="-260.9237" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">uses</text>
|
||||
</g>
|
||||
<!-- A10 -->
|
||||
<g id="node11" class="node">
|
||||
<title>A10</title>
|
||||
<polygon fill="#fff8dc" stroke="#000000" points="317.7872,-362 218.2128,-362 218.2128,-318 323.7872,-318 323.7872,-356 317.7872,-362"/>
|
||||
<polyline fill="none" stroke="#000000" points="317.7872,-362 317.7872,-356 "/>
|
||||
<polyline fill="none" stroke="#000000" points="323.7872,-356 317.7872,-356 "/>
|
||||
<text text-anchor="middle" x="271" y="-349" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">validateSystem is</text>
|
||||
<text text-anchor="middle" x="271" y="-337" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">public because is</text>
|
||||
<text text-anchor="middle" x="271" y="-325" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">used on Api.</text>
|
||||
</g>
|
||||
<!-- A3->A10 -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>A3->A10</title>
|
||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M200.1992,-340C206.1915,-340 212.1837,-340 218.176,-340"/>
|
||||
</g>
|
||||
<!-- A4 -->
|
||||
<g id="node5" class="node">
|
||||
<title>A4</title>
|
||||
<polygon fill="none" stroke="#000000" points="264.1131,-812 189.8869,-812 189.8869,-776 264.1131,-776 264.1131,-812"/>
|
||||
<text text-anchor="middle" x="227" y="-791" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">Command</text>
|
||||
</g>
|
||||
<!-- A5 -->
|
||||
<g id="node6" class="node">
|
||||
<title>A5</title>
|
||||
<polygon fill="none" stroke="#000000" points="148,-684 148,-716 307,-716 307,-684 148,-684"/>
|
||||
<text text-anchor="start" x="199.9955" y="-697" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">BoardImport</text>
|
||||
<polygon fill="none" stroke="#000000" points="148,-652 148,-684 307,-684 307,-652 148,-652"/>
|
||||
<text text-anchor="start" x="157.907" y="-665" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+boardImportCommandService</text>
|
||||
<polygon fill="none" stroke="#000000" points="148,-608 148,-652 307,-652 307,-608 148,-608"/>
|
||||
<text text-anchor="start" x="200.8305" y="-633" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">#configure()</text>
|
||||
<text text-anchor="start" x="177.76" y="-621" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">#execute(input,output)</text>
|
||||
</g>
|
||||
<!-- A4->A5 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>A4->A5</title>
|
||||
<path fill="none" stroke="#000000" d="M227,-765.6356C227,-751.1554 227,-733.0451 227,-716.0324"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="227,-775.9227 222.5001,-765.9227 227,-770.9227 227.0001,-765.9227 227.0001,-765.9227 227.0001,-765.9227 227,-770.9227 231.5001,-765.9228 227,-775.9227 227,-775.9227"/>
|
||||
</g>
|
||||
<!-- A6 -->
|
||||
<g id="node7" class="node">
|
||||
<title>A6</title>
|
||||
<polygon fill="none" stroke="#000000" points="150,-526 150,-558 304,-558 304,-526 150,-526"/>
|
||||
<text text-anchor="start" x="159.7715" y="-539" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">BoardImportCommandService</text>
|
||||
<polygon fill="none" stroke="#000000" points="150,-446 150,-526 304,-526 304,-446 150,-446"/>
|
||||
<text text-anchor="start" x="199.9105" y="-507" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+bootstrap()</text>
|
||||
<text text-anchor="start" x="206.8645" y="-495" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+import()</text>
|
||||
<text text-anchor="start" x="186.857" y="-483" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+validateSystem()</text>
|
||||
<text text-anchor="start" x="189.218" y="-471" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">#validateConfig()</text>
|
||||
<text text-anchor="start" x="193.107" y="-459" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">#validateData()</text>
|
||||
</g>
|
||||
<!-- A5->A6 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>A5->A6</title>
|
||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M227,-607.8313C227,-595.0442 227,-581.2707 227,-568.0248"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="227,-558.0234 231.5001,-568.0234 227,-563.0234 227.0001,-568.0234 227.0001,-568.0234 227.0001,-568.0234 227,-563.0234 222.5001,-568.0235 227,-558.0234 227,-558.0234"/>
|
||||
<text text-anchor="middle" x="218.5476" y="-586.7051" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">uses</text>
|
||||
</g>
|
||||
<!-- A6->A3 -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>A6->A3</title>
|
||||
<path fill="none" stroke="#000000" d="M198.8975,-445.7949C192.3634,-432.7268 185.3528,-418.7057 178.6417,-405.2834"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="174.0529,-396.1057 182.55,-403.0375 176.289,-400.5779 178.5251,-405.05 178.5251,-405.05 178.5251,-405.05 176.289,-400.5779 174.5001,-407.0625 174.0529,-396.1057 174.0529,-396.1057"/>
|
||||
</g>
|
||||
<!-- A7->A3 -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>A7->A3</title>
|
||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M102.735,-228.0253C109.5347,-241.763 117.1224,-258.3431 124.0627,-274.4849"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="128.0634,-283.9135 120.0148,-276.4657 126.1104,-279.3107 124.1573,-274.7079 124.1573,-274.7079 124.1573,-274.7079 126.1104,-279.3107 128.2998,-272.9502 128.0634,-283.9135 128.0634,-283.9135"/>
|
||||
<text text-anchor="middle" x="118.307" y="-237.5757" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">uses</text>
|
||||
</g>
|
||||
<!-- A8 -->
|
||||
<g id="node9" class="node">
|
||||
<title>A8</title>
|
||||
<polygon fill="none" stroke="#000000" points="80,-64 80,-108 213,-108 213,-64 80,-64"/>
|
||||
<text text-anchor="start" x="117.04" y="-89" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"><<abstract>></text>
|
||||
<text text-anchor="start" x="98.9935" y="-77" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">ABoardImportService</text>
|
||||
<polygon fill="none" stroke="#000000" points="80,-32 80,-64 213,-64 213,-32 80,-32"/>
|
||||
<text text-anchor="start" x="92.036" y="-45" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">#needValidateData:false</text>
|
||||
<polygon fill="none" stroke="#000000" points="80,0 80,-32 213,-32 213,0 80,0"/>
|
||||
<text text-anchor="start" x="89.677" y="-13" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">+needValidateData():bool</text>
|
||||
</g>
|
||||
<!-- A7->A8 -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>A7->A8</title>
|
||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M97.2957,-163.778C103.3956,-150.029 110.7371,-133.4813 117.8485,-117.4527"/>
|
||||
<polygon fill="none" stroke="#000000" points="121.1416,-118.6605 121.9978,-108.1003 114.743,-115.8216 121.1416,-118.6605"/>
|
||||
<text text-anchor="middle" x="96.9205" y="-140.7815" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">implements</text>
|
||||
</g>
|
||||
<!-- A9->A3 -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>A9->A3</title>
|
||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M198.9952,-234.3677C194.0646,-246.7117 188.0483,-260.7568 181.8434,-274.4849"/>
|
||||
<polygon fill="#000000" stroke="#000000" points="177.5286,-283.9135 177.598,-272.9478 179.6093,-279.367 181.6899,-274.8204 181.6899,-274.8204 181.6899,-274.8204 179.6093,-279.367 185.7818,-276.693 177.5286,-283.9135 177.5286,-283.9135"/>
|
||||
<text text-anchor="middle" x="200.0654" y="-251.3391" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">uses</text>
|
||||
</g>
|
||||
<!-- A9->A8 -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>A9->A8</title>
|
||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M192.8492,-157.9466C187.2535,-145.5313 180.8796,-131.389 174.6742,-117.6209"/>
|
||||
<polygon fill="none" stroke="#000000" points="177.7167,-115.8534 170.4168,-108.1747 171.3349,-118.7297 177.7167,-115.8534"/>
|
||||
<text text-anchor="middle" x="177.6953" y="-141.8944" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">implements</text>
|
||||
</g>
|
||||
<!-- A11 -->
|
||||
<g id="node12" class="node">
|
||||
<title>A11</title>
|
||||
<polygon fill="#fff8dc" stroke="#000000" points="403.024,-224 290.976,-224 290.976,-168 409.024,-168 409.024,-218 403.024,-224"/>
|
||||
<polyline fill="none" stroke="#000000" points="403.024,-224 403.024,-218 "/>
|
||||
<polyline fill="none" stroke="#000000" points="409.024,-218 403.024,-218 "/>
|
||||
<text text-anchor="middle" x="350" y="-211" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">To create an import</text>
|
||||
<text text-anchor="middle" x="350" y="-199" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">to another system,</text>
|
||||
<text text-anchor="middle" x="350" y="-187" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">create another class</text>
|
||||
<text text-anchor="middle" x="350" y="-175" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000">similar to this.</text>
|
||||
</g>
|
||||
<!-- A9->A11 -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>A9->A11</title>
|
||||
<path fill="none" stroke="#000000" stroke-dasharray="5,2" d="M272.6172,-196C278.6627,-196 284.7083,-196 290.7538,-196"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,24 +0,0 @@
|
||||
// Created using [yUML](https://github.com/jaime-olivares/vscode-yuml)
|
||||
|
||||
// {type:class}
|
||||
// {direction:topDown}
|
||||
// {generate:true}
|
||||
|
||||
[note: Classes used on board import. Methods just to illustrate. {bg:cornsilk}]
|
||||
|
||||
[ApiController]<-[BoardImportApiController|+import();+getAllowedSystems();+getConfigSchema()]
|
||||
[BoardImportApiController]uses-.->[BoardImportService|+import();+bootstrap();+validateSystem();#validateConfig();#validateData();]
|
||||
|
||||
[Command]<-[BoardImport|+boardImportCommandService|#configure();#execute(input,output)]
|
||||
[BoardImport]uses-.->[BoardImportCommandService|+bootstrap();+import();+validateSystem();#validateConfig();#validateData()]
|
||||
[BoardImportCommandService]->[BoardImportService]
|
||||
|
||||
[BoardImportService]uses-.->[TrelloApiService|+name:string]
|
||||
[TrelloApiService]uses-.->[BoardImportService]
|
||||
[TrelloApiService]implements-.-^[<<abstract>> ABoardImportService|#needValidateData:false|+needValidateData():bool]
|
||||
|
||||
[BoardImportService]uses-.->[TrelloJsonService|+name:string;#needValidateData:true]
|
||||
[TrelloJsonService]uses-.->[BoardImportService]
|
||||
[BoardImportService]-[note: validateSystem is public because is used on Api. {bg:cornsilk}]
|
||||
[TrelloJsonService]-[note: To create an import to another system, create another class similar to this. {bg:cornsilk}]
|
||||
[TrelloJsonService]implements-.-^[<<abstract>> ABoardImportService]
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" version="1.0" viewbox="0 0 32 32">
|
||||
<path d="m16 1-10 18h11l-1 12 10-18h-11z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 205 B |
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" version="1.0" viewBox="0 0 32 32">
|
||||
<path d="m16 1-10 18h11l-1 12 10-18h-11z" fill="#FFF"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 217 B |
1
img/archive-white.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><g transform="translate(0 -1036.362)" fill="#fff"><path d="M1.93 1041.296c-.185 0-.336.138-.336.31v9.842c0 .172.15.313.336.313h12.517c.185 0 .333-.14.333-.313v-9.842c0-.172-.148-.31-.333-.31H1.93zm4.124 1.507h4.223c.39 0 .705.314.705.704v.43c0 .39-.315.705-.705.705H6.054a.703.703 0 0 1-.705-.705v-.43c0-.39.314-.704.705-.704z"/><rect width="15.742" height="2.296" x=".136" y="1037.543" ry="0"/></g></svg>
|
||||
|
After Width: | Height: | Size: 488 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 58 58" width="512" height="512"><g fill="#000"><path d="M54.319 37.839C54.762 35.918 55 33.96 55 32c0-9.095-4.631-17.377-12.389-22.153a1 1 0 1 0-1.049 1.703C48.724 15.96 53 23.604 53 32c0 1.726-.2 3.451-.573 5.147A6.992 6.992 0 0 0 51 37c-3.86 0-7 3.141-7 7s3.14 7 7 7 7-3.141 7-7a7.006 7.006 0 0 0-3.681-6.161zM38.171 54.182A23.867 23.867 0 0 1 29 56a24.047 24.047 0 0 1-17.017-7.092A6.974 6.974 0 0 0 14 44c0-3.859-3.14-7-7-7s-7 3.141-7 7 3.14 7 7 7a6.952 6.952 0 0 0 3.381-.875C15.26 55.136 21.994 58 29 58c3.435 0 6.778-.663 9.936-1.971.51-.211.753-.796.542-1.307a1.001 1.001 0 0 0-1.307-.54zM4 31.213a1 1 0 0 0 1.068-.927c.712-10.089 7.586-18.52 17.22-21.314C23.142 11.874 25.825 14 29 14c3.86 0 7-3.141 7-7s-3.14-7-7-7c-3.851 0-6.985 3.127-6.999 6.975C11.42 9.922 3.851 19.12 3.073 30.146A.999.999 0 0 0 4 31.213z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 885 B |
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 58 58" width="512" height="512"><g fill="#fff"><path d="M54.319 37.839C54.762 35.918 55 33.96 55 32c0-9.095-4.631-17.377-12.389-22.153a1 1 0 1 0-1.049 1.703C48.724 15.96 53 23.604 53 32c0 1.726-.2 3.451-.573 5.147A6.992 6.992 0 0 0 51 37c-3.86 0-7 3.141-7 7s3.14 7 7 7 7-3.141 7-7a7.006 7.006 0 0 0-3.681-6.161zM38.171 54.182A23.867 23.867 0 0 1 29 56a24.047 24.047 0 0 1-17.017-7.092A6.974 6.974 0 0 0 14 44c0-3.859-3.14-7-7-7s-7 3.141-7 7 3.14 7 7 7a6.952 6.952 0 0 0 3.381-.875C15.26 55.136 21.994 58 29 58c3.435 0 6.778-.663 9.936-1.971.51-.211.753-.796.542-1.307a1.001 1.001 0 0 0-1.307-.54zM4 31.213a1 1 0 0 0 1.068-.927c.712-10.089 7.586-18.52 17.22-21.314C23.142 11.874 25.825 14 29 14c3.86 0 7-3.141 7-7s-3.14-7-7-7c-3.851 0-6.985 3.127-6.999 6.975C11.42 9.922 3.851 19.12 3.073 30.146A.999.999 0 0 0 4 31.213z"/></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 58 58" width="512" height="512"><g fill="#000"><path d="M54.319 37.839C54.762 35.918 55 33.96 55 32c0-9.095-4.631-17.377-12.389-22.153a1 1 0 1 0-1.049 1.703C48.724 15.96 53 23.604 53 32c0 1.726-.2 3.451-.573 5.147A6.992 6.992 0 0 0 51 37c-3.86 0-7 3.141-7 7s3.14 7 7 7 7-3.141 7-7a7.006 7.006 0 0 0-3.681-6.161zM38.171 54.182A23.867 23.867 0 0 1 29 56a24.047 24.047 0 0 1-17.017-7.092A6.974 6.974 0 0 0 14 44c0-3.859-3.14-7-7-7s-7 3.141-7 7 3.14 7 7 7a6.952 6.952 0 0 0 3.381-.875C15.26 55.136 21.994 58 29 58c3.435 0 6.778-.663 9.936-1.971.51-.211.753-.796.542-1.307a1.001 1.001 0 0 0-1.307-.54zM4 31.213a1 1 0 0 0 1.068-.927c.712-10.089 7.586-18.52 17.22-21.314C23.142 11.874 25.825 14 29 14c3.86 0 7-3.141 7-7s-3.14-7-7-7c-3.851 0-6.985 3.127-6.999 6.975C11.42 9.922 3.851 19.12 3.073 30.146A.999.999 0 0 0 4 31.213z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 885 B After Width: | Height: | Size: 885 B |
1
img/clone.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M11.8 13.8H2.2V4.2h9.6m1.2 0c0-.67-.53-1.2-1.2-1.2H2.2C1.53 3 1 3.53 1 4.2v9.6c0 .67.53 1.2 1.2 1.2h9.6c.67 0 1.2-.53 1.2-1.2"/><path d="m4.2 1c-0.67 0-1.2 0.54-1.2 1.2h10.8v10.8c0.67 0 1.2-0.53 1.2-1.2v-9.6c0-0.67-0.53-1.2-1.2-1.2z"/></svg>
|
||||
|
After Width: | Height: | Size: 327 B |
1
img/reply.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16"><path d="M15 15s-.4-7.8-7-10V1L1 8l7 7v-4c5.1 0 7 4 7 4z"/></svg>
|
||||
|
After Width: | Height: | Size: 128 B |
65
l10n/ca.js
@@ -29,7 +29,7 @@ OC.L10N.register(
|
||||
"{user} has deleted card {card} in list {stack} on board {board}" : "{user} ha suprimit la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"You have renamed the card {before} to {card}" : "Heu reanomenat la targeta {before} a {card}",
|
||||
"{user} has renamed the card {before} to {card}" : "{user} ha reanomenat la targeta {before} a {card}",
|
||||
"You have added a description to card {card} in list {stack} on board {board}" : "Heu afegit una descripció a la targeta {card} a la llista {stack} del tauler {board}",
|
||||
"You have added a description to card {card} in list {stack} on board {board}" : "Heu afegit una descripció a la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"{user} has added a description to card {card} in list {stack} on board {board}" : "{user} ha afegit una descripció a la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"You have updated the description of card {card} in list {stack} on board {board}" : "Heu actualitzat la descripció de la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"{user} has updated the description of the card {card} in list {stack} on board {board}" : "{user} ha actualitzat la descripció de la targeta {card} a la llista {stack} al tauler {board}",
|
||||
@@ -37,12 +37,12 @@ OC.L10N.register(
|
||||
"{user} has archived card {card} in list {stack} on board {board}" : "{user} té la targeta arxivada {card} a la llista {stack} al tauler {board}",
|
||||
"You have unarchived card {card} in list {stack} on board {board}" : "Teniu una targeta no-arxchivada {card} a la llista {stack} al tauler {board}",
|
||||
"{user} has unarchived card {card} in list {stack} on board {board}" : "{user} té una targeta no-arxivada {card} a la llista {stack} al tauler {board}",
|
||||
"You have removed the due date of card {card}" : "Heu suprimit la data de caducitat de la targeta {targeta}",
|
||||
"{user} has removed the due date of card {card}" : "{user} ha suprimit la data de caducitat de la targeta {targeta}",
|
||||
"You have set the due date of card {card} to {after}" : "Heu establert la data de caducitat de la targeta {card} a {after}",
|
||||
"{user} has set the due date of card {card} to {after}" : "{user} ha establert la data de caducitat de la targeta {card} a {after}",
|
||||
"You have updated the due date of card {card} to {after}" : "Heu actualitzat la data de caducitat de la targeta {card} a {after}",
|
||||
"{user} has updated the due date of card {card} to {after}" : "{user} ha actualitzat la data de caducitat de la targeta {card} a {after}",
|
||||
"You have removed the due date of card {card}" : "Heu suprimit la data de venciment de la targeta {targeta}",
|
||||
"{user} has removed the due date of card {card}" : "{user} ha suprimit la data de venciment de la targeta {targeta}",
|
||||
"You have set the due date of card {card} to {after}" : "Heu establert la data de venciment de la targeta {card} a {after}",
|
||||
"{user} has set the due date of card {card} to {after}" : "{user} ha establert la data de venciment de la targeta {card} a {after}",
|
||||
"You have updated the due date of card {card} to {after}" : "Heu actualitzat la data de venciment de la targeta {card} a {after}",
|
||||
"{user} has updated the due date of card {card} to {after}" : "{user} ha actualitzat la data de venciment de la targeta {card} a {after}",
|
||||
"You have added the tag {label} to card {card} in list {stack} on board {board}" : "Heu afegit l'etiqueta {label} a la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"{user} has added the tag {label} to card {card} in list {stack} on board {board}" : "{user} ha afegit l'etiqueta {label} a la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"You have removed the tag {label} from card {card} in list {stack} on board {board}" : "Heu eliminat l'etiqueta {label} de la targeta {card} a la llista {stack} al tauler {board}",
|
||||
@@ -66,13 +66,13 @@ OC.L10N.register(
|
||||
"A <strong>card description</strong> inside the Deck app has been changed" : "S'ha canviat una <strong>descripció de targeta</strong> a l'aplicació Tauler",
|
||||
"Deck" : "Targetes",
|
||||
"Changes in the <strong>Deck app</strong>" : "Canvis a l'<strong>aplicació Targetes</strong>",
|
||||
"A <strong>comment</strong> was created on a card" : "S'ha creat un <strong>comentari</strong> a una targeta",
|
||||
"A <strong>comment</strong> was created on a card" : "S'ha afegit un <strong>comentari</strong> a una targeta",
|
||||
"Upcoming cards" : "Pròximes targetes",
|
||||
"Load more" : "Carrega'n més",
|
||||
"Personal" : "Personal",
|
||||
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "La targeta \"%s\" sobre \"%s\" se us ha assignat per %s.",
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} us ha assignat la targeta {deck-card} a {deck-board}.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "La targeta \"%s\" sobre \"%s\" ha assolit la seva data de caducitat.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "La targeta \"%s\" sobre \"%s\" ha assolit la seva data de venciment.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "La targeta {deck-card} a {deck-board} ha assolit la seva data de caducitat.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : "%s us ha anomenat en un comentari sobre \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} us ha mencionat en un comentari a {deck-card}.",
|
||||
@@ -88,7 +88,7 @@ OC.L10N.register(
|
||||
"copy" : "còpia",
|
||||
"To do" : "Pendent",
|
||||
"Doing" : "En procés",
|
||||
"Done" : "Fet",
|
||||
"Done" : "Finalitzat",
|
||||
"Example Task 3" : "Tasca d'exemple 3",
|
||||
"Example Task 2" : "Tasca d'exemple 2",
|
||||
"Example Task 1" : "Tasca d'exemple 1",
|
||||
@@ -99,7 +99,7 @@ OC.L10N.register(
|
||||
"No file was uploaded" : "No s'ha pujat cap fitxer",
|
||||
"Missing a temporary folder" : "Falta una carpeta temporal",
|
||||
"Could not write file to disk" : "No s’ha pogut escriure el fitxer al disc",
|
||||
"A PHP extension stopped the file upload" : "Una extensió del PHP ha aturat la pujada del fitxer",
|
||||
"A PHP extension stopped the file upload" : "Una extensió del PHP ha aturat la carregada del fitxer",
|
||||
"No file uploaded or file size exceeds maximum of %s" : "No s'ha carregat cap fitxer o la mida del fitxer sobrepassa el màxim de %s",
|
||||
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Aquest comentari té més de %s caràcters.\nS'ha afegit com a fitxer adjunt a la targeta amb el nom %s.\nAccessible a l'URL: %s.",
|
||||
"Card not found" : "No s'ha trobat la targeta",
|
||||
@@ -131,7 +131,7 @@ OC.L10N.register(
|
||||
"Overwrite file" : "Sobreescriu el fitxer",
|
||||
"Keep existing file" : "Mantén el fitxer existent",
|
||||
"This board is read only" : "Aquest tauler és només de lectura",
|
||||
"Drop your files to upload" : "Deixeu anar els fitxers per pujar-los",
|
||||
"Drop your files to upload" : "Deixeu anar els fitxers per penjar-los",
|
||||
"Add card" : "Afegeix una targeta",
|
||||
"Archived cards" : "Targetes arxivades",
|
||||
"Add list" : "Afegeix una llista",
|
||||
@@ -174,38 +174,36 @@ OC.L10N.register(
|
||||
"Can share" : "Pot compartir",
|
||||
"Can manage" : "Pot gestionar",
|
||||
"Owner" : "Propietari",
|
||||
"Delete" : "Suprimeix",
|
||||
"Delete" : "Eliminar",
|
||||
"Failed to create share with {displayName}" : "Ha fallat la creació de la compartició amb {displayName}",
|
||||
"Are you sure you want to transfer the board {title} to {user}?" : "Esteu segur que voleu transferir el tauler {title} a {user}?",
|
||||
"Transfer the board." : "Transfereix el tauler.",
|
||||
"Transfer" : "Transferència",
|
||||
"The board has been transferred to {user}" : "El tauler s'ha transferit a {user}",
|
||||
"Failed to transfer the board to {user}" : "No s'ha pogut transferir el tauler a {user}",
|
||||
"Add a new list" : "Afegeix una llista nova",
|
||||
"Add a new list" : "Afegir una llista nova",
|
||||
"Archive all cards" : "Arxiva totes les targetes",
|
||||
"Unarchive all cards" : "Desarxivar totes les targetes",
|
||||
"Delete list" : "Suprimeix la llista",
|
||||
"Archive all cards in this list" : "Arxiva totes les targetes d'aquesta llista",
|
||||
"Unarchive all cards in this list" : "Desarxivar totes les targetes d'aquesta llista",
|
||||
"Add a new card" : "Afegeix una nova targeta",
|
||||
"Add a new card" : "Afegir una nova targeta",
|
||||
"Card name" : "Nom de la targeta",
|
||||
"List deleted" : "Llista suprimida",
|
||||
"Edit" : "Edició",
|
||||
"Add a new tag" : "Afegeix una etiqueta nova",
|
||||
"Edit" : "Edita",
|
||||
"Add a new tag" : "Afegir una etiqueta nova",
|
||||
"title and color value must be provided" : "s’ha de proporcionar el valor del títol i del color",
|
||||
"Board name" : "Nom del taulell",
|
||||
"Members" : "Membres",
|
||||
"Upload new files" : "Pujada de nous fitxers",
|
||||
"Upload new files" : "Puja nous fitxers",
|
||||
"Share from Files" : "Comparteix des de Fitxers",
|
||||
"Pending share" : "Compartició pendent",
|
||||
"Add this attachment" : "Afegeix aquest adjunt",
|
||||
"Show in Files" : "Mostra a Fitxers",
|
||||
"Download" : "Baixada",
|
||||
"Download" : "Baixa",
|
||||
"Remove attachment" : "Treu l'adjunt",
|
||||
"Delete Attachment" : "Suprimeix l’adjunt",
|
||||
"Restore Attachment" : "Restaura l'adjunt",
|
||||
"File to share" : "Fitxer a compartir",
|
||||
"Invalid path selected" : "S'ha seleccionat un camí no vàlid",
|
||||
"Invalid path selected" : "S'ha seleccionat una ruta invàlida",
|
||||
"Open in sidebar view" : "Obre a la vista de la barra lateral",
|
||||
"Open in bigger view" : "Obre a la vista més gran",
|
||||
"Attachments" : "Adjunts",
|
||||
@@ -215,13 +213,13 @@ OC.L10N.register(
|
||||
"The title cannot be empty." : "El títol no pot estar buit.",
|
||||
"No comments yet. Begin the discussion!" : "No hi ha comentaris encara. Començar la discussió!",
|
||||
"Failed to load comments" : "No s'han pogut carregar els comentaris",
|
||||
"Assign a tag to this card…" : "Assignació d'una etiqueta a aquesta targeta…",
|
||||
"Assign to users" : "Assignació als usuaris",
|
||||
"Assign to users/groups/circles" : "Assignació a usuaris/grups/cercles",
|
||||
"Assign a user to this card…" : "Assignació d'un usuari a aquesta targeta…",
|
||||
"Due date" : "Data de caducitat",
|
||||
"Set a due date" : "Definir una data de caducitat",
|
||||
"Remove due date" : "Suprimeix la data de caducitat",
|
||||
"Assign a tag to this card…" : "Assigna una etiqueta a aquesta targeta…",
|
||||
"Assign to users" : "Assigna als usuaris",
|
||||
"Assign to users/groups/circles" : "Assigna a usuaris/grups/cercles",
|
||||
"Assign a user to this card…" : "Assigneu un usuari a aquesta targeta…",
|
||||
"Due date" : "Per la data",
|
||||
"Set a due date" : "Definir una data de venciment",
|
||||
"Remove due date" : "Elimina la data de venciment",
|
||||
"Select Date" : "Selecciona la data",
|
||||
"Today" : "Avui",
|
||||
"Tomorrow" : "Demà",
|
||||
@@ -238,15 +236,15 @@ OC.L10N.register(
|
||||
"(Unsaved)" : "(No desat)",
|
||||
"(Saving…)" : "(Desant…)",
|
||||
"Formatting help" : "Format d'ajuda",
|
||||
"Edit description" : "Edició descripció",
|
||||
"Edit description" : "Edita descripció",
|
||||
"View description" : "Veure descripció",
|
||||
"Add Attachment" : "Afegeix un adjunt",
|
||||
"Write a description …" : "Escriviu una descripció …",
|
||||
"Choose attachment" : "Triar adjunt",
|
||||
"(group)" : "(grup)",
|
||||
"Todo items" : "Tasques pendents",
|
||||
"Todo items" : "Elements pendents",
|
||||
"{count} comments, {unread} unread" : "{count} comentaris, {unread} no llegits",
|
||||
"Edit card title" : "Edició del títol de la targeta",
|
||||
"Edit card title" : "Edita el títol de la targeta",
|
||||
"Assign to me" : "Assigna'm a mi",
|
||||
"Unassign myself" : "Desasignar a mi mateix",
|
||||
"Move card" : "Mou la targeta",
|
||||
@@ -260,9 +258,8 @@ OC.L10N.register(
|
||||
"All boards" : "Tots els taulers",
|
||||
"Archived boards" : "Taulers arxivats",
|
||||
"Shared with you" : "Us han compartit",
|
||||
"Deck settings" : "Paràmetres del Tauler",
|
||||
"Deck settings" : "Configuració del Tauler",
|
||||
"Use bigger card view" : "Utilitza la visualització de targetes més gran",
|
||||
"Show card ID badge" : "Mostra el distintiu d’ID de la targeta",
|
||||
"Show boards in calendar/tasks" : "Mostra els taulers al calendari/tasques",
|
||||
"Limit deck usage of groups" : "Limitar l'ús del tauler de grups",
|
||||
"Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them." : "Limitant el Tauler bloquejarà la creació de taulers als usuaris que no són part d'aquests grups. Els usuaris podran seguir treballant en els taulers que hagin estat compartits amb ells.",
|
||||
|
||||
65
l10n/ca.json
@@ -27,7 +27,7 @@
|
||||
"{user} has deleted card {card} in list {stack} on board {board}" : "{user} ha suprimit la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"You have renamed the card {before} to {card}" : "Heu reanomenat la targeta {before} a {card}",
|
||||
"{user} has renamed the card {before} to {card}" : "{user} ha reanomenat la targeta {before} a {card}",
|
||||
"You have added a description to card {card} in list {stack} on board {board}" : "Heu afegit una descripció a la targeta {card} a la llista {stack} del tauler {board}",
|
||||
"You have added a description to card {card} in list {stack} on board {board}" : "Heu afegit una descripció a la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"{user} has added a description to card {card} in list {stack} on board {board}" : "{user} ha afegit una descripció a la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"You have updated the description of card {card} in list {stack} on board {board}" : "Heu actualitzat la descripció de la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"{user} has updated the description of the card {card} in list {stack} on board {board}" : "{user} ha actualitzat la descripció de la targeta {card} a la llista {stack} al tauler {board}",
|
||||
@@ -35,12 +35,12 @@
|
||||
"{user} has archived card {card} in list {stack} on board {board}" : "{user} té la targeta arxivada {card} a la llista {stack} al tauler {board}",
|
||||
"You have unarchived card {card} in list {stack} on board {board}" : "Teniu una targeta no-arxchivada {card} a la llista {stack} al tauler {board}",
|
||||
"{user} has unarchived card {card} in list {stack} on board {board}" : "{user} té una targeta no-arxivada {card} a la llista {stack} al tauler {board}",
|
||||
"You have removed the due date of card {card}" : "Heu suprimit la data de caducitat de la targeta {targeta}",
|
||||
"{user} has removed the due date of card {card}" : "{user} ha suprimit la data de caducitat de la targeta {targeta}",
|
||||
"You have set the due date of card {card} to {after}" : "Heu establert la data de caducitat de la targeta {card} a {after}",
|
||||
"{user} has set the due date of card {card} to {after}" : "{user} ha establert la data de caducitat de la targeta {card} a {after}",
|
||||
"You have updated the due date of card {card} to {after}" : "Heu actualitzat la data de caducitat de la targeta {card} a {after}",
|
||||
"{user} has updated the due date of card {card} to {after}" : "{user} ha actualitzat la data de caducitat de la targeta {card} a {after}",
|
||||
"You have removed the due date of card {card}" : "Heu suprimit la data de venciment de la targeta {targeta}",
|
||||
"{user} has removed the due date of card {card}" : "{user} ha suprimit la data de venciment de la targeta {targeta}",
|
||||
"You have set the due date of card {card} to {after}" : "Heu establert la data de venciment de la targeta {card} a {after}",
|
||||
"{user} has set the due date of card {card} to {after}" : "{user} ha establert la data de venciment de la targeta {card} a {after}",
|
||||
"You have updated the due date of card {card} to {after}" : "Heu actualitzat la data de venciment de la targeta {card} a {after}",
|
||||
"{user} has updated the due date of card {card} to {after}" : "{user} ha actualitzat la data de venciment de la targeta {card} a {after}",
|
||||
"You have added the tag {label} to card {card} in list {stack} on board {board}" : "Heu afegit l'etiqueta {label} a la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"{user} has added the tag {label} to card {card} in list {stack} on board {board}" : "{user} ha afegit l'etiqueta {label} a la targeta {card} a la llista {stack} al tauler {board}",
|
||||
"You have removed the tag {label} from card {card} in list {stack} on board {board}" : "Heu eliminat l'etiqueta {label} de la targeta {card} a la llista {stack} al tauler {board}",
|
||||
@@ -64,13 +64,13 @@
|
||||
"A <strong>card description</strong> inside the Deck app has been changed" : "S'ha canviat una <strong>descripció de targeta</strong> a l'aplicació Tauler",
|
||||
"Deck" : "Targetes",
|
||||
"Changes in the <strong>Deck app</strong>" : "Canvis a l'<strong>aplicació Targetes</strong>",
|
||||
"A <strong>comment</strong> was created on a card" : "S'ha creat un <strong>comentari</strong> a una targeta",
|
||||
"A <strong>comment</strong> was created on a card" : "S'ha afegit un <strong>comentari</strong> a una targeta",
|
||||
"Upcoming cards" : "Pròximes targetes",
|
||||
"Load more" : "Carrega'n més",
|
||||
"Personal" : "Personal",
|
||||
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "La targeta \"%s\" sobre \"%s\" se us ha assignat per %s.",
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} us ha assignat la targeta {deck-card} a {deck-board}.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "La targeta \"%s\" sobre \"%s\" ha assolit la seva data de caducitat.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "La targeta \"%s\" sobre \"%s\" ha assolit la seva data de venciment.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "La targeta {deck-card} a {deck-board} ha assolit la seva data de caducitat.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : "%s us ha anomenat en un comentari sobre \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} us ha mencionat en un comentari a {deck-card}.",
|
||||
@@ -86,7 +86,7 @@
|
||||
"copy" : "còpia",
|
||||
"To do" : "Pendent",
|
||||
"Doing" : "En procés",
|
||||
"Done" : "Fet",
|
||||
"Done" : "Finalitzat",
|
||||
"Example Task 3" : "Tasca d'exemple 3",
|
||||
"Example Task 2" : "Tasca d'exemple 2",
|
||||
"Example Task 1" : "Tasca d'exemple 1",
|
||||
@@ -97,7 +97,7 @@
|
||||
"No file was uploaded" : "No s'ha pujat cap fitxer",
|
||||
"Missing a temporary folder" : "Falta una carpeta temporal",
|
||||
"Could not write file to disk" : "No s’ha pogut escriure el fitxer al disc",
|
||||
"A PHP extension stopped the file upload" : "Una extensió del PHP ha aturat la pujada del fitxer",
|
||||
"A PHP extension stopped the file upload" : "Una extensió del PHP ha aturat la carregada del fitxer",
|
||||
"No file uploaded or file size exceeds maximum of %s" : "No s'ha carregat cap fitxer o la mida del fitxer sobrepassa el màxim de %s",
|
||||
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Aquest comentari té més de %s caràcters.\nS'ha afegit com a fitxer adjunt a la targeta amb el nom %s.\nAccessible a l'URL: %s.",
|
||||
"Card not found" : "No s'ha trobat la targeta",
|
||||
@@ -129,7 +129,7 @@
|
||||
"Overwrite file" : "Sobreescriu el fitxer",
|
||||
"Keep existing file" : "Mantén el fitxer existent",
|
||||
"This board is read only" : "Aquest tauler és només de lectura",
|
||||
"Drop your files to upload" : "Deixeu anar els fitxers per pujar-los",
|
||||
"Drop your files to upload" : "Deixeu anar els fitxers per penjar-los",
|
||||
"Add card" : "Afegeix una targeta",
|
||||
"Archived cards" : "Targetes arxivades",
|
||||
"Add list" : "Afegeix una llista",
|
||||
@@ -172,38 +172,36 @@
|
||||
"Can share" : "Pot compartir",
|
||||
"Can manage" : "Pot gestionar",
|
||||
"Owner" : "Propietari",
|
||||
"Delete" : "Suprimeix",
|
||||
"Delete" : "Eliminar",
|
||||
"Failed to create share with {displayName}" : "Ha fallat la creació de la compartició amb {displayName}",
|
||||
"Are you sure you want to transfer the board {title} to {user}?" : "Esteu segur que voleu transferir el tauler {title} a {user}?",
|
||||
"Transfer the board." : "Transfereix el tauler.",
|
||||
"Transfer" : "Transferència",
|
||||
"The board has been transferred to {user}" : "El tauler s'ha transferit a {user}",
|
||||
"Failed to transfer the board to {user}" : "No s'ha pogut transferir el tauler a {user}",
|
||||
"Add a new list" : "Afegeix una llista nova",
|
||||
"Add a new list" : "Afegir una llista nova",
|
||||
"Archive all cards" : "Arxiva totes les targetes",
|
||||
"Unarchive all cards" : "Desarxivar totes les targetes",
|
||||
"Delete list" : "Suprimeix la llista",
|
||||
"Archive all cards in this list" : "Arxiva totes les targetes d'aquesta llista",
|
||||
"Unarchive all cards in this list" : "Desarxivar totes les targetes d'aquesta llista",
|
||||
"Add a new card" : "Afegeix una nova targeta",
|
||||
"Add a new card" : "Afegir una nova targeta",
|
||||
"Card name" : "Nom de la targeta",
|
||||
"List deleted" : "Llista suprimida",
|
||||
"Edit" : "Edició",
|
||||
"Add a new tag" : "Afegeix una etiqueta nova",
|
||||
"Edit" : "Edita",
|
||||
"Add a new tag" : "Afegir una etiqueta nova",
|
||||
"title and color value must be provided" : "s’ha de proporcionar el valor del títol i del color",
|
||||
"Board name" : "Nom del taulell",
|
||||
"Members" : "Membres",
|
||||
"Upload new files" : "Pujada de nous fitxers",
|
||||
"Upload new files" : "Puja nous fitxers",
|
||||
"Share from Files" : "Comparteix des de Fitxers",
|
||||
"Pending share" : "Compartició pendent",
|
||||
"Add this attachment" : "Afegeix aquest adjunt",
|
||||
"Show in Files" : "Mostra a Fitxers",
|
||||
"Download" : "Baixada",
|
||||
"Download" : "Baixa",
|
||||
"Remove attachment" : "Treu l'adjunt",
|
||||
"Delete Attachment" : "Suprimeix l’adjunt",
|
||||
"Restore Attachment" : "Restaura l'adjunt",
|
||||
"File to share" : "Fitxer a compartir",
|
||||
"Invalid path selected" : "S'ha seleccionat un camí no vàlid",
|
||||
"Invalid path selected" : "S'ha seleccionat una ruta invàlida",
|
||||
"Open in sidebar view" : "Obre a la vista de la barra lateral",
|
||||
"Open in bigger view" : "Obre a la vista més gran",
|
||||
"Attachments" : "Adjunts",
|
||||
@@ -213,13 +211,13 @@
|
||||
"The title cannot be empty." : "El títol no pot estar buit.",
|
||||
"No comments yet. Begin the discussion!" : "No hi ha comentaris encara. Començar la discussió!",
|
||||
"Failed to load comments" : "No s'han pogut carregar els comentaris",
|
||||
"Assign a tag to this card…" : "Assignació d'una etiqueta a aquesta targeta…",
|
||||
"Assign to users" : "Assignació als usuaris",
|
||||
"Assign to users/groups/circles" : "Assignació a usuaris/grups/cercles",
|
||||
"Assign a user to this card…" : "Assignació d'un usuari a aquesta targeta…",
|
||||
"Due date" : "Data de caducitat",
|
||||
"Set a due date" : "Definir una data de caducitat",
|
||||
"Remove due date" : "Suprimeix la data de caducitat",
|
||||
"Assign a tag to this card…" : "Assigna una etiqueta a aquesta targeta…",
|
||||
"Assign to users" : "Assigna als usuaris",
|
||||
"Assign to users/groups/circles" : "Assigna a usuaris/grups/cercles",
|
||||
"Assign a user to this card…" : "Assigneu un usuari a aquesta targeta…",
|
||||
"Due date" : "Per la data",
|
||||
"Set a due date" : "Definir una data de venciment",
|
||||
"Remove due date" : "Elimina la data de venciment",
|
||||
"Select Date" : "Selecciona la data",
|
||||
"Today" : "Avui",
|
||||
"Tomorrow" : "Demà",
|
||||
@@ -236,15 +234,15 @@
|
||||
"(Unsaved)" : "(No desat)",
|
||||
"(Saving…)" : "(Desant…)",
|
||||
"Formatting help" : "Format d'ajuda",
|
||||
"Edit description" : "Edició descripció",
|
||||
"Edit description" : "Edita descripció",
|
||||
"View description" : "Veure descripció",
|
||||
"Add Attachment" : "Afegeix un adjunt",
|
||||
"Write a description …" : "Escriviu una descripció …",
|
||||
"Choose attachment" : "Triar adjunt",
|
||||
"(group)" : "(grup)",
|
||||
"Todo items" : "Tasques pendents",
|
||||
"Todo items" : "Elements pendents",
|
||||
"{count} comments, {unread} unread" : "{count} comentaris, {unread} no llegits",
|
||||
"Edit card title" : "Edició del títol de la targeta",
|
||||
"Edit card title" : "Edita el títol de la targeta",
|
||||
"Assign to me" : "Assigna'm a mi",
|
||||
"Unassign myself" : "Desasignar a mi mateix",
|
||||
"Move card" : "Mou la targeta",
|
||||
@@ -258,9 +256,8 @@
|
||||
"All boards" : "Tots els taulers",
|
||||
"Archived boards" : "Taulers arxivats",
|
||||
"Shared with you" : "Us han compartit",
|
||||
"Deck settings" : "Paràmetres del Tauler",
|
||||
"Deck settings" : "Configuració del Tauler",
|
||||
"Use bigger card view" : "Utilitza la visualització de targetes més gran",
|
||||
"Show card ID badge" : "Mostra el distintiu d’ID de la targeta",
|
||||
"Show boards in calendar/tasks" : "Mostra els taulers al calendari/tasques",
|
||||
"Limit deck usage of groups" : "Limitar l'ús del tauler de grups",
|
||||
"Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them." : "Limitant el Tauler bloquejarà la creació de taulers als usuaris que no són part d'aquests grups. Els usuaris podran seguir treballant en els taulers que hagin estat compartits amb ells.",
|
||||
|
||||
@@ -37,7 +37,6 @@ OC.L10N.register(
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "Kortet \"%s\" på \"%s\" har nået sin forfaldsdato.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : " %s har nævnt dig i en kommentar på \"%s\".",
|
||||
"The board \"%s\" has been shared with you by %s." : "Tavlen \"%s\" er blevet delt med dig af %s.",
|
||||
"%s on %s" : "%s på %s",
|
||||
"No data was provided to create an attachment." : "Ingen data blev givet som kunne vedhæftes",
|
||||
"Finished" : "Færdiggjort",
|
||||
"To review" : "Til gennemgang",
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "Kortet \"%s\" på \"%s\" har nået sin forfaldsdato.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : " %s har nævnt dig i en kommentar på \"%s\".",
|
||||
"The board \"%s\" has been shared with you by %s." : "Tavlen \"%s\" er blevet delt med dig af %s.",
|
||||
"%s on %s" : "%s på %s",
|
||||
"No data was provided to create an attachment." : "Ingen data blev givet som kunne vedhæftes",
|
||||
"Finished" : "Færdiggjort",
|
||||
"To review" : "Til gennemgang",
|
||||
|
||||
@@ -245,7 +245,7 @@ OC.L10N.register(
|
||||
"Archive card" : "Αρχειοθέτηση καρτέλας",
|
||||
"Delete card" : "Διαγραφή καρτέλας",
|
||||
"Move card to another board" : "Μετακίνηση καρτέλας σε άλλο πίνακα",
|
||||
"List is empty" : "Η λίστα είναι κενή",
|
||||
"List is empty" : "Η λίστα είναι άδεια.",
|
||||
"Card deleted" : "Η καρτέλα διαγράφηκε",
|
||||
"seconds ago" : " δευτερόλεπτα πριν ",
|
||||
"All boards" : "Όλοι οι πίνακες",
|
||||
|
||||
@@ -243,7 +243,7 @@
|
||||
"Archive card" : "Αρχειοθέτηση καρτέλας",
|
||||
"Delete card" : "Διαγραφή καρτέλας",
|
||||
"Move card to another board" : "Μετακίνηση καρτέλας σε άλλο πίνακα",
|
||||
"List is empty" : "Η λίστα είναι κενή",
|
||||
"List is empty" : "Η λίστα είναι άδεια.",
|
||||
"Card deleted" : "Η καρτέλα διαγράφηκε",
|
||||
"seconds ago" : " δευτερόλεπτα πριν ",
|
||||
"All boards" : "Όλοι οι πίνακες",
|
||||
|
||||
237
l10n/en_GB.js
@@ -1,97 +1,17 @@
|
||||
OC.L10N.register(
|
||||
"deck",
|
||||
{
|
||||
"You have created a new board {board}" : "You have created a new board {board}",
|
||||
"{user} has created a new board {board}" : "{user} has created a new board {board}",
|
||||
"You have deleted the board {board}" : "You have deleted the board {board}",
|
||||
"{user} has deleted the board {board}" : "{user} has deleted the board {board}",
|
||||
"You have restored the board {board}" : "You have restored the board {board}",
|
||||
"{user} has restored the board {board}" : "{user} has restored the board {board}",
|
||||
"You have shared the board {board} with {acl}" : "You have shared the board {board} with {acl}",
|
||||
"{user} has shared the board {board} with {acl}" : "{user} has shared the board {board} with {acl}",
|
||||
"You have removed {acl} from the board {board}" : "You have removed {acl} from the board {board}",
|
||||
"{user} has removed {acl} from the board {board}" : "{user} has removed {acl} from the board {board}",
|
||||
"You have renamed the board {before} to {board}" : "You have renamed the board {before} to {board}",
|
||||
"{user} has renamed the board {before} to {board}" : "{user} has renamed the board {before} to {board}",
|
||||
"You have archived the board {board}" : "You have archived the board {board}",
|
||||
"{user} has archived the board {before}" : "{user} has archived the board {before}",
|
||||
"You have unarchived the board {board}" : "You have unarchived the board {board}",
|
||||
"{user} has unarchived the board {before}" : "{user} has unarchived the board {before}",
|
||||
"You have created a new list {stack} on board {board}" : "You have created a new list {stack} on board {board}",
|
||||
"{user} has created a new list {stack} on board {board}" : "{user} has created a new list {stack} on board {board}",
|
||||
"You have renamed list {before} to {stack} on board {board}" : "You have renamed list {before} to {stack} on board {board}",
|
||||
"{user} has renamed list {before} to {stack} on board {board}" : "{user} has renamed list {before} to {stack} on board {board}",
|
||||
"You have deleted list {stack} on board {board}" : "You have deleted list {stack} on board {board}",
|
||||
"{user} has deleted list {stack} on board {board}" : "{user} has deleted list {stack} on board {board}",
|
||||
"You have created card {card} in list {stack} on board {board}" : "You have created card {card} in list {stack} on board {board}",
|
||||
"{user} has created card {card} in list {stack} on board {board}" : "{user} has created card {card} in list {stack} on board {board}",
|
||||
"You have deleted card {card} in list {stack} on board {board}" : "You have deleted card {card} in list {stack} on board {board}",
|
||||
"{user} has deleted card {card} in list {stack} on board {board}" : "{user} has deleted card {card} in list {stack} on board {board}",
|
||||
"You have renamed the card {before} to {card}" : "You have renamed the card {before} to {card}",
|
||||
"{user} has renamed the card {before} to {card}" : "{user} has renamed the card {before} to {card}",
|
||||
"You have added a description to card {card} in list {stack} on board {board}" : "You have added a description to card {card} in list {stack} on board {board}",
|
||||
"{user} has added a description to card {card} in list {stack} on board {board}" : "{user} has added a description to card {card} in list {stack} on board {board}",
|
||||
"You have updated the description of card {card} in list {stack} on board {board}" : "You have updated the description of card {card} in list {stack} on board {board}",
|
||||
"{user} has updated the description of the card {card} in list {stack} on board {board}" : "{user} has updated the description of the card {card} in list {stack} on board {board}",
|
||||
"You have archived card {card} in list {stack} on board {board}" : "You have archived card {card} in list {stack} on board {board}",
|
||||
"{user} has archived card {card} in list {stack} on board {board}" : "{user} has archived card {card} in list {stack} on board {board}",
|
||||
"You have unarchived card {card} in list {stack} on board {board}" : "You have unarchived card {card} in list {stack} on board {board}",
|
||||
"{user} has unarchived card {card} in list {stack} on board {board}" : "{user} has unarchived card {card} in list {stack} on board {board}",
|
||||
"You have removed the due date of card {card}" : "You have removed the due date of card {card}",
|
||||
"{user} has removed the due date of card {card}" : "{user} has removed the due date of card {card}",
|
||||
"You have set the due date of card {card} to {after}" : "You have set the due date of card {card} to {after}",
|
||||
"{user} has set the due date of card {card} to {after}" : "{user} has set the due date of card {card} to {after}",
|
||||
"You have updated the due date of card {card} to {after}" : "You have updated the due date of card {card} to {after}",
|
||||
"{user} has updated the due date of card {card} to {after}" : "{user} has updated the due date of card {card} to {after}",
|
||||
"You have added the tag {label} to card {card} in list {stack} on board {board}" : "You have added the tag {label} to card {card} in list {stack} on board {board}",
|
||||
"{user} has added the tag {label} to card {card} in list {stack} on board {board}" : "{user} has added the tag {label} to card {card} in list {stack} on board {board}",
|
||||
"You have removed the tag {label} from card {card} in list {stack} on board {board}" : "You have removed the tag {label} from card {card} in list {stack} on board {board}",
|
||||
"{user} has removed the tag {label} from card {card} in list {stack} on board {board}" : "{user} has removed the tag {label} from card {card} in list {stack} on board {board}",
|
||||
"You have assigned {assigneduser} to card {card} on board {board}" : "You have assigned {assigneduser} to card {card} on board {board}",
|
||||
"{user} has assigned {assigneduser} to card {card} on board {board}" : "{user} has assigned {assigneduser} to card {card} on board {board}",
|
||||
"You have unassigned {assigneduser} from card {card} on board {board}" : "You have unassigned {assigneduser} from card {card} on board {board}",
|
||||
"{user} has unassigned {assigneduser} from card {card} on board {board}" : "{user} has unassigned {assigneduser} from card {card} on board {board}",
|
||||
"You have moved the card {card} from list {stackBefore} to {stack}" : "You have moved the card {card} from list {stackBefore} to {stack}",
|
||||
"{user} has moved the card {card} from list {stackBefore} to {stack}" : "{user} has moved the card {card} from list {stackBefore} to {stack}",
|
||||
"You have added the attachment {attachment} to card {card}" : "You have added the attachment {attachment} to card {card}",
|
||||
"{user} has added the attachment {attachment} to card {card}" : "{user} has added the attachment {attachment} to card {card}",
|
||||
"You have updated the attachment {attachment} on card {card}" : "You have updated the attachment {attachment} on card {card}",
|
||||
"{user} has updated the attachment {attachment} on card {card}" : "{user} has updated the attachment {attachment} on card {card}",
|
||||
"You have deleted the attachment {attachment} from card {card}" : "You have deleted the attachment {attachment} from card {card}",
|
||||
"{user} has deleted the attachment {attachment} from card {card}" : "{user} has deleted the attachment {attachment} from card {card}",
|
||||
"You have restored the attachment {attachment} to card {card}" : "You have restored the attachment {attachment} to card {card}",
|
||||
"{user} has restored the attachment {attachment} to card {card}" : "{user} has restored the attachment {attachment} to card {card}",
|
||||
"You have commented on card {card}" : "You have commented on card {card}",
|
||||
"{user} has commented on card {card}" : "{user} has commented on card {card}",
|
||||
"A <strong>card description</strong> inside the Deck app has been changed" : "A <strong>card description</strong> inside the Deck app has been changed",
|
||||
"Deck" : "Deck",
|
||||
"Changes in the <strong>Deck app</strong>" : "Changes in the <strong>Deck app</strong>",
|
||||
"A <strong>comment</strong> was created on a card" : "A <strong>comment</strong> was created on a card",
|
||||
"Upcoming cards" : "Upcoming cards",
|
||||
"Load more" : "Load more",
|
||||
"Personal" : "Personal",
|
||||
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "The card \"%s\" on \"%s\" has been assigned to you by %s.",
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} has assigned the card {deck-card} on {deck-board} to you.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "The card \"%s\" on \"%s\" has reached its due date.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "The card {deck-card} on {deck-board} has reached its due date.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : "%s has mentioned you in a comment on \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} has mentioned you in a comment on {deck-card}.",
|
||||
"The board \"%s\" has been shared with you by %s." : "The board \"%s\" has been shared with you by %s.",
|
||||
"{user} has shared {deck-board} with you." : "{user} has shared {deck-board} with you.",
|
||||
"Card comments" : "Card comments",
|
||||
"%s on %s" : "%s on %s",
|
||||
"No data was provided to create an attachment." : "No data was provided to create an attachment.",
|
||||
"Finished" : "Finished",
|
||||
"To review" : "To review",
|
||||
"Action needed" : "Action needed",
|
||||
"Later" : "Later",
|
||||
"copy" : "copy",
|
||||
"To do" : "To do",
|
||||
"Doing" : "Doing",
|
||||
"Done" : "Done",
|
||||
"Example Task 3" : "Example Task 3",
|
||||
"Example Task 2" : "Example Task 2",
|
||||
"Example Task 1" : "Example Task 1",
|
||||
"The file was uploaded" : "The file was uploaded",
|
||||
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "The uploaded file exceeds the upload_max_filesize directive in php.ini",
|
||||
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
|
||||
@@ -100,218 +20,63 @@ OC.L10N.register(
|
||||
"Missing a temporary folder" : "Missing a temporary folder",
|
||||
"Could not write file to disk" : "Could not write file to disk",
|
||||
"A PHP extension stopped the file upload" : "A PHP extension stopped the file upload",
|
||||
"No file uploaded or file size exceeds maximum of %s" : "No file uploaded or file size exceeds maximum of %s",
|
||||
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s.",
|
||||
"Card not found" : "Card not found",
|
||||
"Path is already shared with this card" : "Path is already shared with this card",
|
||||
"Invalid date, date format must be YYYY-MM-DD" : "Invalid date, date format must be YYYY-MM-DD",
|
||||
"Personal planning and team project organization" : "Personal planning and team project organization",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized",
|
||||
"Card details" : "Card details",
|
||||
"Add board" : "Add board",
|
||||
"Select the board to link to a project" : "Select the board to link to a project",
|
||||
"Search by board title" : "Search by board title",
|
||||
"Select board" : "Select board",
|
||||
"Create a new card" : "Create a new card",
|
||||
"Select a board" : "Select a board",
|
||||
"Select a list" : "Select a list",
|
||||
"Card title" : "Card title",
|
||||
"Cancel" : "Cancel",
|
||||
"Creating the new card …" : "Creating the new card …",
|
||||
"Card \"{card}\" was added to \"{board}\"" : "Card \"{card}\" was added to \"{board}\"",
|
||||
"Open card" : "Open card",
|
||||
"Close" : "Close",
|
||||
"Create card" : "Create card",
|
||||
"Select a card" : "Select a card",
|
||||
"Select the card to link to a project" : "Select the card to link to a project",
|
||||
"Link to card" : "Link to card",
|
||||
"File already exists" : "File already exists",
|
||||
"A file with the name {filename} already exists." : "A file with the name {filename} already exists.",
|
||||
"Do you want to overwrite it?" : "Do you want to overwrite it?",
|
||||
"Overwrite file" : "Overwrite file",
|
||||
"Keep existing file" : "Keep existing file",
|
||||
"This board is read only" : "This board is read only",
|
||||
"Drop your files to upload" : "Drop your files to upload",
|
||||
"Add card" : "Add card",
|
||||
"Archived cards" : "Archived cards",
|
||||
"Add list" : "Add list",
|
||||
"List name" : "List name",
|
||||
"Active filters" : "Active filters",
|
||||
"Apply filter" : "Apply filter",
|
||||
"Filter by tag" : "Filter by tag",
|
||||
"Filter by assigned user" : "Filter by assigned user",
|
||||
"Unassigned" : "Unassigned",
|
||||
"Filter by due date" : "Filter by due date",
|
||||
"Overdue" : "Overdue",
|
||||
"Next 24 hours" : "Next 24 hours",
|
||||
"Next 7 days" : "Next 7 days",
|
||||
"Next 30 days" : "Next 30 days",
|
||||
"No due date" : "No due date",
|
||||
"Clear filter" : "Clear filter",
|
||||
"Hide archived cards" : "Hide archived cards",
|
||||
"Show archived cards" : "Show archived cards",
|
||||
"Toggle compact mode" : "Toggle compact mode",
|
||||
"Open details" : "Open details",
|
||||
"Details" : "Details",
|
||||
"Loading board" : "Loading board",
|
||||
"No lists available" : "No lists available",
|
||||
"Create a new list to add cards to this board" : "Create a new list to add cards to this board",
|
||||
"Board not found" : "Board not found",
|
||||
"Sharing" : "Sharing",
|
||||
"Tags" : "Tags",
|
||||
"Deleted items" : "Deleted items",
|
||||
"Timeline" : "Timeline",
|
||||
"Deleted lists" : "Deleted lists",
|
||||
"Undo" : "Undo",
|
||||
"Deleted cards" : "Deleted cards",
|
||||
"Share board with a user, group or circle …" : "Share board with a user, group or circle …",
|
||||
"Searching for users, groups and circles …" : "Searching for users, groups and circles …",
|
||||
"No participants found" : "No participants found",
|
||||
"Board owner" : "Board owner",
|
||||
"(Group)" : "(Group)",
|
||||
"(Circle)" : "(Circle)",
|
||||
"Can edit" : "Can edit",
|
||||
"Can share" : "Can share",
|
||||
"Can manage" : "Can manage",
|
||||
"Owner" : "Owner",
|
||||
"Delete" : "Delete",
|
||||
"Failed to create share with {displayName}" : "Failed to create share with {displayName}",
|
||||
"Are you sure you want to transfer the board {title} to {user}?" : "Are you sure you want to transfer the board {title} to {user}?",
|
||||
"Transfer the board." : "Transfer the board.",
|
||||
"Transfer" : "Transfer",
|
||||
"The board has been transferred to {user}" : "The board has been transferred to {user}",
|
||||
"Failed to transfer the board to {user}" : "Failed to transfer the board to {user}",
|
||||
"Add a new list" : "Add a new list",
|
||||
"Archive all cards" : "Archive all cards",
|
||||
"Unarchive all cards" : "Unarchive all cards",
|
||||
"Delete list" : "Delete list",
|
||||
"Archive all cards in this list" : "Archive all cards in this list",
|
||||
"Unarchive all cards in this list" : "Unarchive all cards in this list",
|
||||
"Add a new card" : "Add a new card",
|
||||
"Card name" : "Card name",
|
||||
"List deleted" : "List deleted",
|
||||
"Edit" : "Edit",
|
||||
"Add a new tag" : "Add a new tag",
|
||||
"title and color value must be provided" : "title and colour value must be provided",
|
||||
"Board name" : "Board name",
|
||||
"Members" : "Members",
|
||||
"Upload new files" : "Upload new files",
|
||||
"Share from Files" : "Share from Files",
|
||||
"Pending share" : "Pending share",
|
||||
"Add this attachment" : "Add this attachment",
|
||||
"Show in Files" : "Show in Files",
|
||||
"Download" : "Download",
|
||||
"Remove attachment" : "Remove attachment",
|
||||
"Delete Attachment" : "Delete Attachment",
|
||||
"Restore Attachment" : "Restore Attachment",
|
||||
"File to share" : "File to share",
|
||||
"Invalid path selected" : "Invalid path selected",
|
||||
"Open in sidebar view" : "Open in sidebar view",
|
||||
"Open in bigger view" : "Open in bigger view",
|
||||
"Attachments" : "Attachments",
|
||||
"Comments" : "Comments",
|
||||
"Modified" : "Modified",
|
||||
"Created" : "Created",
|
||||
"The title cannot be empty." : "The title cannot be empty.",
|
||||
"No comments yet. Begin the discussion!" : "No comments yet. Begin the discussion!",
|
||||
"Failed to load comments" : "Failed to load comments",
|
||||
"Assign a tag to this card…" : "Assign a tag to this card…",
|
||||
"Assign to users" : "Assign to users",
|
||||
"Assign to users/groups/circles" : "Assign to users/groups/circles",
|
||||
"Assign a user to this card…" : "Assign a user to this card…",
|
||||
"Due date" : "Due date",
|
||||
"Set a due date" : "Set a due date",
|
||||
"Remove due date" : "Remove due date",
|
||||
"Select Date" : "Select Date",
|
||||
"Today" : "Today",
|
||||
"Tomorrow" : "Tomorrow",
|
||||
"Next week" : "Next week",
|
||||
"Next month" : "Next month",
|
||||
"Save" : "Save",
|
||||
"The comment cannot be empty." : "The comment cannot be empty.",
|
||||
"The comment cannot be longer than 1000 characters." : "The comment cannot be longer than 1000 characters.",
|
||||
"In reply to" : "In reply to",
|
||||
"Cancel reply" : "Cancel reply",
|
||||
"Reply" : "Reply",
|
||||
"Update" : "Update",
|
||||
"Description" : "Description",
|
||||
"(Unsaved)" : "(Unsaved)",
|
||||
"(Saving…)" : "(Saving…)",
|
||||
"Formatting help" : "Formatting help",
|
||||
"Edit description" : "Edit description",
|
||||
"View description" : "View description",
|
||||
"Add Attachment" : "Add Attachment",
|
||||
"Write a description …" : "Write a description …",
|
||||
"Choose attachment" : "Choose attachment",
|
||||
"(group)" : "(group)",
|
||||
"Todo items" : "Todo items",
|
||||
"{count} comments, {unread} unread" : "{count} comments, {unread} unread",
|
||||
"Edit card title" : "Edit card title",
|
||||
"Assign to me" : "Assign to me",
|
||||
"Unassign myself" : "Unassign myself",
|
||||
"Move card" : "Move card",
|
||||
"Unarchive card" : "Unarchive card",
|
||||
"Archive card" : "Archive card",
|
||||
"Delete card" : "Delete card",
|
||||
"Move card to another board" : "Move card to another board",
|
||||
"List is empty" : "List is empty",
|
||||
"Card deleted" : "Card deleted",
|
||||
"seconds ago" : "seconds ago",
|
||||
"All boards" : "All boards",
|
||||
"Archived boards" : "Archived boards",
|
||||
"Shared with you" : "Shared with you",
|
||||
"Deck settings" : "Deck settings",
|
||||
"Use bigger card view" : "Use bigger card view",
|
||||
"Show card ID badge" : "Show card ID badge",
|
||||
"Show boards in calendar/tasks" : "Show boards in calendar/tasks",
|
||||
"Limit deck usage of groups" : "Limit deck usage of groups",
|
||||
"Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them." : "Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them.",
|
||||
"Board details" : "Board details",
|
||||
"Edit board" : "Edit board",
|
||||
"Clone board" : "Clone board",
|
||||
"Unarchive board" : "Unarchive board",
|
||||
"Archive board" : "Archive board",
|
||||
"Turn on due date reminders" : "Turn on due date reminders",
|
||||
"Turn off due date reminders" : "Turn off due date reminders",
|
||||
"Due date reminders" : "Due date reminders",
|
||||
"All cards" : "All cards",
|
||||
"Assigned cards" : "Assigned cards",
|
||||
"No notifications" : "No notifications",
|
||||
"Delete board" : "Delete board",
|
||||
"Board {0} deleted" : "Board {0} deleted",
|
||||
"Only assigned cards" : "Only assigned cards",
|
||||
"No reminder" : "No reminder",
|
||||
"An error occurred" : "An error occurred",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards.",
|
||||
"Delete the board?" : "Delete the board?",
|
||||
"Loading filtered view" : "Loading filtered view",
|
||||
"No due" : "No due",
|
||||
"Search for {searchQuery} in all boards" : "Search for {searchQuery} in all boards",
|
||||
"No results found" : "No results found",
|
||||
"{stack} in {board}" : "{stack} in {board}",
|
||||
"Click to expand description" : "Click to expand description",
|
||||
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments",
|
||||
"{nbCards} cards" : "{nbCards} cards",
|
||||
"No upcoming cards" : "No upcoming cards",
|
||||
"upcoming cards" : "upcoming cards",
|
||||
"Due on {date}" : "Due on {date}",
|
||||
"Link to a board" : "Link to a board",
|
||||
"Link to a card" : "Link to a card",
|
||||
"Create a card" : "Create a card",
|
||||
"Message from {author} in {conversationName}" : "Message from {author} in {conversationName}",
|
||||
"Something went wrong" : "Something went wrong",
|
||||
"Failed to upload {name}" : "Failed to upload {name}",
|
||||
"Maximum file size of {size} exceeded" : "Maximum file size of {size} exceeded",
|
||||
"Error creating the share" : "Error creating the share",
|
||||
"Share with a Deck card" : "Share with a Deck card",
|
||||
"Share {file} with a Deck card" : "Share {file} with a Deck card",
|
||||
"Share" : "Share",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized",
|
||||
"Are you sure you want to transfer the board {title} for {user} ?" : "Are you sure you want to transfer the board {title} for {user} ?",
|
||||
"Transfer the board for {user} successfully" : "Transfer the board for {user} successfully",
|
||||
"Failed to transfer the board for {user}" : "Failed to transfer the board for {user}",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board." : "Are you sure you want to delete the board {title}? This will delete all the data of this board.",
|
||||
"This week" : "This week",
|
||||
"Are you sure you want to transfer the board {title} for {user}?" : "Are you sure you want to transfer the board {title} for {user}?"
|
||||
"This week" : "This week"
|
||||
},
|
||||
"nplurals=2; plural=(n != 1);");
|
||||
|
||||
237
l10n/en_GB.json
@@ -1,95 +1,15 @@
|
||||
{ "translations": {
|
||||
"You have created a new board {board}" : "You have created a new board {board}",
|
||||
"{user} has created a new board {board}" : "{user} has created a new board {board}",
|
||||
"You have deleted the board {board}" : "You have deleted the board {board}",
|
||||
"{user} has deleted the board {board}" : "{user} has deleted the board {board}",
|
||||
"You have restored the board {board}" : "You have restored the board {board}",
|
||||
"{user} has restored the board {board}" : "{user} has restored the board {board}",
|
||||
"You have shared the board {board} with {acl}" : "You have shared the board {board} with {acl}",
|
||||
"{user} has shared the board {board} with {acl}" : "{user} has shared the board {board} with {acl}",
|
||||
"You have removed {acl} from the board {board}" : "You have removed {acl} from the board {board}",
|
||||
"{user} has removed {acl} from the board {board}" : "{user} has removed {acl} from the board {board}",
|
||||
"You have renamed the board {before} to {board}" : "You have renamed the board {before} to {board}",
|
||||
"{user} has renamed the board {before} to {board}" : "{user} has renamed the board {before} to {board}",
|
||||
"You have archived the board {board}" : "You have archived the board {board}",
|
||||
"{user} has archived the board {before}" : "{user} has archived the board {before}",
|
||||
"You have unarchived the board {board}" : "You have unarchived the board {board}",
|
||||
"{user} has unarchived the board {before}" : "{user} has unarchived the board {before}",
|
||||
"You have created a new list {stack} on board {board}" : "You have created a new list {stack} on board {board}",
|
||||
"{user} has created a new list {stack} on board {board}" : "{user} has created a new list {stack} on board {board}",
|
||||
"You have renamed list {before} to {stack} on board {board}" : "You have renamed list {before} to {stack} on board {board}",
|
||||
"{user} has renamed list {before} to {stack} on board {board}" : "{user} has renamed list {before} to {stack} on board {board}",
|
||||
"You have deleted list {stack} on board {board}" : "You have deleted list {stack} on board {board}",
|
||||
"{user} has deleted list {stack} on board {board}" : "{user} has deleted list {stack} on board {board}",
|
||||
"You have created card {card} in list {stack} on board {board}" : "You have created card {card} in list {stack} on board {board}",
|
||||
"{user} has created card {card} in list {stack} on board {board}" : "{user} has created card {card} in list {stack} on board {board}",
|
||||
"You have deleted card {card} in list {stack} on board {board}" : "You have deleted card {card} in list {stack} on board {board}",
|
||||
"{user} has deleted card {card} in list {stack} on board {board}" : "{user} has deleted card {card} in list {stack} on board {board}",
|
||||
"You have renamed the card {before} to {card}" : "You have renamed the card {before} to {card}",
|
||||
"{user} has renamed the card {before} to {card}" : "{user} has renamed the card {before} to {card}",
|
||||
"You have added a description to card {card} in list {stack} on board {board}" : "You have added a description to card {card} in list {stack} on board {board}",
|
||||
"{user} has added a description to card {card} in list {stack} on board {board}" : "{user} has added a description to card {card} in list {stack} on board {board}",
|
||||
"You have updated the description of card {card} in list {stack} on board {board}" : "You have updated the description of card {card} in list {stack} on board {board}",
|
||||
"{user} has updated the description of the card {card} in list {stack} on board {board}" : "{user} has updated the description of the card {card} in list {stack} on board {board}",
|
||||
"You have archived card {card} in list {stack} on board {board}" : "You have archived card {card} in list {stack} on board {board}",
|
||||
"{user} has archived card {card} in list {stack} on board {board}" : "{user} has archived card {card} in list {stack} on board {board}",
|
||||
"You have unarchived card {card} in list {stack} on board {board}" : "You have unarchived card {card} in list {stack} on board {board}",
|
||||
"{user} has unarchived card {card} in list {stack} on board {board}" : "{user} has unarchived card {card} in list {stack} on board {board}",
|
||||
"You have removed the due date of card {card}" : "You have removed the due date of card {card}",
|
||||
"{user} has removed the due date of card {card}" : "{user} has removed the due date of card {card}",
|
||||
"You have set the due date of card {card} to {after}" : "You have set the due date of card {card} to {after}",
|
||||
"{user} has set the due date of card {card} to {after}" : "{user} has set the due date of card {card} to {after}",
|
||||
"You have updated the due date of card {card} to {after}" : "You have updated the due date of card {card} to {after}",
|
||||
"{user} has updated the due date of card {card} to {after}" : "{user} has updated the due date of card {card} to {after}",
|
||||
"You have added the tag {label} to card {card} in list {stack} on board {board}" : "You have added the tag {label} to card {card} in list {stack} on board {board}",
|
||||
"{user} has added the tag {label} to card {card} in list {stack} on board {board}" : "{user} has added the tag {label} to card {card} in list {stack} on board {board}",
|
||||
"You have removed the tag {label} from card {card} in list {stack} on board {board}" : "You have removed the tag {label} from card {card} in list {stack} on board {board}",
|
||||
"{user} has removed the tag {label} from card {card} in list {stack} on board {board}" : "{user} has removed the tag {label} from card {card} in list {stack} on board {board}",
|
||||
"You have assigned {assigneduser} to card {card} on board {board}" : "You have assigned {assigneduser} to card {card} on board {board}",
|
||||
"{user} has assigned {assigneduser} to card {card} on board {board}" : "{user} has assigned {assigneduser} to card {card} on board {board}",
|
||||
"You have unassigned {assigneduser} from card {card} on board {board}" : "You have unassigned {assigneduser} from card {card} on board {board}",
|
||||
"{user} has unassigned {assigneduser} from card {card} on board {board}" : "{user} has unassigned {assigneduser} from card {card} on board {board}",
|
||||
"You have moved the card {card} from list {stackBefore} to {stack}" : "You have moved the card {card} from list {stackBefore} to {stack}",
|
||||
"{user} has moved the card {card} from list {stackBefore} to {stack}" : "{user} has moved the card {card} from list {stackBefore} to {stack}",
|
||||
"You have added the attachment {attachment} to card {card}" : "You have added the attachment {attachment} to card {card}",
|
||||
"{user} has added the attachment {attachment} to card {card}" : "{user} has added the attachment {attachment} to card {card}",
|
||||
"You have updated the attachment {attachment} on card {card}" : "You have updated the attachment {attachment} on card {card}",
|
||||
"{user} has updated the attachment {attachment} on card {card}" : "{user} has updated the attachment {attachment} on card {card}",
|
||||
"You have deleted the attachment {attachment} from card {card}" : "You have deleted the attachment {attachment} from card {card}",
|
||||
"{user} has deleted the attachment {attachment} from card {card}" : "{user} has deleted the attachment {attachment} from card {card}",
|
||||
"You have restored the attachment {attachment} to card {card}" : "You have restored the attachment {attachment} to card {card}",
|
||||
"{user} has restored the attachment {attachment} to card {card}" : "{user} has restored the attachment {attachment} to card {card}",
|
||||
"You have commented on card {card}" : "You have commented on card {card}",
|
||||
"{user} has commented on card {card}" : "{user} has commented on card {card}",
|
||||
"A <strong>card description</strong> inside the Deck app has been changed" : "A <strong>card description</strong> inside the Deck app has been changed",
|
||||
"Deck" : "Deck",
|
||||
"Changes in the <strong>Deck app</strong>" : "Changes in the <strong>Deck app</strong>",
|
||||
"A <strong>comment</strong> was created on a card" : "A <strong>comment</strong> was created on a card",
|
||||
"Upcoming cards" : "Upcoming cards",
|
||||
"Load more" : "Load more",
|
||||
"Personal" : "Personal",
|
||||
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "The card \"%s\" on \"%s\" has been assigned to you by %s.",
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} has assigned the card {deck-card} on {deck-board} to you.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "The card \"%s\" on \"%s\" has reached its due date.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "The card {deck-card} on {deck-board} has reached its due date.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : "%s has mentioned you in a comment on \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} has mentioned you in a comment on {deck-card}.",
|
||||
"The board \"%s\" has been shared with you by %s." : "The board \"%s\" has been shared with you by %s.",
|
||||
"{user} has shared {deck-board} with you." : "{user} has shared {deck-board} with you.",
|
||||
"Card comments" : "Card comments",
|
||||
"%s on %s" : "%s on %s",
|
||||
"No data was provided to create an attachment." : "No data was provided to create an attachment.",
|
||||
"Finished" : "Finished",
|
||||
"To review" : "To review",
|
||||
"Action needed" : "Action needed",
|
||||
"Later" : "Later",
|
||||
"copy" : "copy",
|
||||
"To do" : "To do",
|
||||
"Doing" : "Doing",
|
||||
"Done" : "Done",
|
||||
"Example Task 3" : "Example Task 3",
|
||||
"Example Task 2" : "Example Task 2",
|
||||
"Example Task 1" : "Example Task 1",
|
||||
"The file was uploaded" : "The file was uploaded",
|
||||
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "The uploaded file exceeds the upload_max_filesize directive in php.ini",
|
||||
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
|
||||
@@ -98,218 +18,63 @@
|
||||
"Missing a temporary folder" : "Missing a temporary folder",
|
||||
"Could not write file to disk" : "Could not write file to disk",
|
||||
"A PHP extension stopped the file upload" : "A PHP extension stopped the file upload",
|
||||
"No file uploaded or file size exceeds maximum of %s" : "No file uploaded or file size exceeds maximum of %s",
|
||||
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s.",
|
||||
"Card not found" : "Card not found",
|
||||
"Path is already shared with this card" : "Path is already shared with this card",
|
||||
"Invalid date, date format must be YYYY-MM-DD" : "Invalid date, date format must be YYYY-MM-DD",
|
||||
"Personal planning and team project organization" : "Personal planning and team project organization",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized",
|
||||
"Card details" : "Card details",
|
||||
"Add board" : "Add board",
|
||||
"Select the board to link to a project" : "Select the board to link to a project",
|
||||
"Search by board title" : "Search by board title",
|
||||
"Select board" : "Select board",
|
||||
"Create a new card" : "Create a new card",
|
||||
"Select a board" : "Select a board",
|
||||
"Select a list" : "Select a list",
|
||||
"Card title" : "Card title",
|
||||
"Cancel" : "Cancel",
|
||||
"Creating the new card …" : "Creating the new card …",
|
||||
"Card \"{card}\" was added to \"{board}\"" : "Card \"{card}\" was added to \"{board}\"",
|
||||
"Open card" : "Open card",
|
||||
"Close" : "Close",
|
||||
"Create card" : "Create card",
|
||||
"Select a card" : "Select a card",
|
||||
"Select the card to link to a project" : "Select the card to link to a project",
|
||||
"Link to card" : "Link to card",
|
||||
"File already exists" : "File already exists",
|
||||
"A file with the name {filename} already exists." : "A file with the name {filename} already exists.",
|
||||
"Do you want to overwrite it?" : "Do you want to overwrite it?",
|
||||
"Overwrite file" : "Overwrite file",
|
||||
"Keep existing file" : "Keep existing file",
|
||||
"This board is read only" : "This board is read only",
|
||||
"Drop your files to upload" : "Drop your files to upload",
|
||||
"Add card" : "Add card",
|
||||
"Archived cards" : "Archived cards",
|
||||
"Add list" : "Add list",
|
||||
"List name" : "List name",
|
||||
"Active filters" : "Active filters",
|
||||
"Apply filter" : "Apply filter",
|
||||
"Filter by tag" : "Filter by tag",
|
||||
"Filter by assigned user" : "Filter by assigned user",
|
||||
"Unassigned" : "Unassigned",
|
||||
"Filter by due date" : "Filter by due date",
|
||||
"Overdue" : "Overdue",
|
||||
"Next 24 hours" : "Next 24 hours",
|
||||
"Next 7 days" : "Next 7 days",
|
||||
"Next 30 days" : "Next 30 days",
|
||||
"No due date" : "No due date",
|
||||
"Clear filter" : "Clear filter",
|
||||
"Hide archived cards" : "Hide archived cards",
|
||||
"Show archived cards" : "Show archived cards",
|
||||
"Toggle compact mode" : "Toggle compact mode",
|
||||
"Open details" : "Open details",
|
||||
"Details" : "Details",
|
||||
"Loading board" : "Loading board",
|
||||
"No lists available" : "No lists available",
|
||||
"Create a new list to add cards to this board" : "Create a new list to add cards to this board",
|
||||
"Board not found" : "Board not found",
|
||||
"Sharing" : "Sharing",
|
||||
"Tags" : "Tags",
|
||||
"Deleted items" : "Deleted items",
|
||||
"Timeline" : "Timeline",
|
||||
"Deleted lists" : "Deleted lists",
|
||||
"Undo" : "Undo",
|
||||
"Deleted cards" : "Deleted cards",
|
||||
"Share board with a user, group or circle …" : "Share board with a user, group or circle …",
|
||||
"Searching for users, groups and circles …" : "Searching for users, groups and circles …",
|
||||
"No participants found" : "No participants found",
|
||||
"Board owner" : "Board owner",
|
||||
"(Group)" : "(Group)",
|
||||
"(Circle)" : "(Circle)",
|
||||
"Can edit" : "Can edit",
|
||||
"Can share" : "Can share",
|
||||
"Can manage" : "Can manage",
|
||||
"Owner" : "Owner",
|
||||
"Delete" : "Delete",
|
||||
"Failed to create share with {displayName}" : "Failed to create share with {displayName}",
|
||||
"Are you sure you want to transfer the board {title} to {user}?" : "Are you sure you want to transfer the board {title} to {user}?",
|
||||
"Transfer the board." : "Transfer the board.",
|
||||
"Transfer" : "Transfer",
|
||||
"The board has been transferred to {user}" : "The board has been transferred to {user}",
|
||||
"Failed to transfer the board to {user}" : "Failed to transfer the board to {user}",
|
||||
"Add a new list" : "Add a new list",
|
||||
"Archive all cards" : "Archive all cards",
|
||||
"Unarchive all cards" : "Unarchive all cards",
|
||||
"Delete list" : "Delete list",
|
||||
"Archive all cards in this list" : "Archive all cards in this list",
|
||||
"Unarchive all cards in this list" : "Unarchive all cards in this list",
|
||||
"Add a new card" : "Add a new card",
|
||||
"Card name" : "Card name",
|
||||
"List deleted" : "List deleted",
|
||||
"Edit" : "Edit",
|
||||
"Add a new tag" : "Add a new tag",
|
||||
"title and color value must be provided" : "title and colour value must be provided",
|
||||
"Board name" : "Board name",
|
||||
"Members" : "Members",
|
||||
"Upload new files" : "Upload new files",
|
||||
"Share from Files" : "Share from Files",
|
||||
"Pending share" : "Pending share",
|
||||
"Add this attachment" : "Add this attachment",
|
||||
"Show in Files" : "Show in Files",
|
||||
"Download" : "Download",
|
||||
"Remove attachment" : "Remove attachment",
|
||||
"Delete Attachment" : "Delete Attachment",
|
||||
"Restore Attachment" : "Restore Attachment",
|
||||
"File to share" : "File to share",
|
||||
"Invalid path selected" : "Invalid path selected",
|
||||
"Open in sidebar view" : "Open in sidebar view",
|
||||
"Open in bigger view" : "Open in bigger view",
|
||||
"Attachments" : "Attachments",
|
||||
"Comments" : "Comments",
|
||||
"Modified" : "Modified",
|
||||
"Created" : "Created",
|
||||
"The title cannot be empty." : "The title cannot be empty.",
|
||||
"No comments yet. Begin the discussion!" : "No comments yet. Begin the discussion!",
|
||||
"Failed to load comments" : "Failed to load comments",
|
||||
"Assign a tag to this card…" : "Assign a tag to this card…",
|
||||
"Assign to users" : "Assign to users",
|
||||
"Assign to users/groups/circles" : "Assign to users/groups/circles",
|
||||
"Assign a user to this card…" : "Assign a user to this card…",
|
||||
"Due date" : "Due date",
|
||||
"Set a due date" : "Set a due date",
|
||||
"Remove due date" : "Remove due date",
|
||||
"Select Date" : "Select Date",
|
||||
"Today" : "Today",
|
||||
"Tomorrow" : "Tomorrow",
|
||||
"Next week" : "Next week",
|
||||
"Next month" : "Next month",
|
||||
"Save" : "Save",
|
||||
"The comment cannot be empty." : "The comment cannot be empty.",
|
||||
"The comment cannot be longer than 1000 characters." : "The comment cannot be longer than 1000 characters.",
|
||||
"In reply to" : "In reply to",
|
||||
"Cancel reply" : "Cancel reply",
|
||||
"Reply" : "Reply",
|
||||
"Update" : "Update",
|
||||
"Description" : "Description",
|
||||
"(Unsaved)" : "(Unsaved)",
|
||||
"(Saving…)" : "(Saving…)",
|
||||
"Formatting help" : "Formatting help",
|
||||
"Edit description" : "Edit description",
|
||||
"View description" : "View description",
|
||||
"Add Attachment" : "Add Attachment",
|
||||
"Write a description …" : "Write a description …",
|
||||
"Choose attachment" : "Choose attachment",
|
||||
"(group)" : "(group)",
|
||||
"Todo items" : "Todo items",
|
||||
"{count} comments, {unread} unread" : "{count} comments, {unread} unread",
|
||||
"Edit card title" : "Edit card title",
|
||||
"Assign to me" : "Assign to me",
|
||||
"Unassign myself" : "Unassign myself",
|
||||
"Move card" : "Move card",
|
||||
"Unarchive card" : "Unarchive card",
|
||||
"Archive card" : "Archive card",
|
||||
"Delete card" : "Delete card",
|
||||
"Move card to another board" : "Move card to another board",
|
||||
"List is empty" : "List is empty",
|
||||
"Card deleted" : "Card deleted",
|
||||
"seconds ago" : "seconds ago",
|
||||
"All boards" : "All boards",
|
||||
"Archived boards" : "Archived boards",
|
||||
"Shared with you" : "Shared with you",
|
||||
"Deck settings" : "Deck settings",
|
||||
"Use bigger card view" : "Use bigger card view",
|
||||
"Show card ID badge" : "Show card ID badge",
|
||||
"Show boards in calendar/tasks" : "Show boards in calendar/tasks",
|
||||
"Limit deck usage of groups" : "Limit deck usage of groups",
|
||||
"Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them." : "Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them.",
|
||||
"Board details" : "Board details",
|
||||
"Edit board" : "Edit board",
|
||||
"Clone board" : "Clone board",
|
||||
"Unarchive board" : "Unarchive board",
|
||||
"Archive board" : "Archive board",
|
||||
"Turn on due date reminders" : "Turn on due date reminders",
|
||||
"Turn off due date reminders" : "Turn off due date reminders",
|
||||
"Due date reminders" : "Due date reminders",
|
||||
"All cards" : "All cards",
|
||||
"Assigned cards" : "Assigned cards",
|
||||
"No notifications" : "No notifications",
|
||||
"Delete board" : "Delete board",
|
||||
"Board {0} deleted" : "Board {0} deleted",
|
||||
"Only assigned cards" : "Only assigned cards",
|
||||
"No reminder" : "No reminder",
|
||||
"An error occurred" : "An error occurred",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards.",
|
||||
"Delete the board?" : "Delete the board?",
|
||||
"Loading filtered view" : "Loading filtered view",
|
||||
"No due" : "No due",
|
||||
"Search for {searchQuery} in all boards" : "Search for {searchQuery} in all boards",
|
||||
"No results found" : "No results found",
|
||||
"{stack} in {board}" : "{stack} in {board}",
|
||||
"Click to expand description" : "Click to expand description",
|
||||
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments",
|
||||
"{nbCards} cards" : "{nbCards} cards",
|
||||
"No upcoming cards" : "No upcoming cards",
|
||||
"upcoming cards" : "upcoming cards",
|
||||
"Due on {date}" : "Due on {date}",
|
||||
"Link to a board" : "Link to a board",
|
||||
"Link to a card" : "Link to a card",
|
||||
"Create a card" : "Create a card",
|
||||
"Message from {author} in {conversationName}" : "Message from {author} in {conversationName}",
|
||||
"Something went wrong" : "Something went wrong",
|
||||
"Failed to upload {name}" : "Failed to upload {name}",
|
||||
"Maximum file size of {size} exceeded" : "Maximum file size of {size} exceeded",
|
||||
"Error creating the share" : "Error creating the share",
|
||||
"Share with a Deck card" : "Share with a Deck card",
|
||||
"Share {file} with a Deck card" : "Share {file} with a Deck card",
|
||||
"Share" : "Share",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized",
|
||||
"Are you sure you want to transfer the board {title} for {user} ?" : "Are you sure you want to transfer the board {title} for {user} ?",
|
||||
"Transfer the board for {user} successfully" : "Transfer the board for {user} successfully",
|
||||
"Failed to transfer the board for {user}" : "Failed to transfer the board for {user}",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board." : "Are you sure you want to delete the board {title}? This will delete all the data of this board.",
|
||||
"This week" : "This week",
|
||||
"Are you sure you want to transfer the board {title} for {user}?" : "Are you sure you want to transfer the board {title} for {user}?"
|
||||
"This week" : "This week"
|
||||
},"pluralForm" :"nplurals=2; plural=(n != 1);"
|
||||
}
|
||||
@@ -18,7 +18,6 @@ OC.L10N.register(
|
||||
"Details" : "Üksikasjad",
|
||||
"Sharing" : "Jagamine",
|
||||
"Tags" : "Sildid",
|
||||
"Undo" : "Tühista",
|
||||
"Can edit" : "Võib redigeerida",
|
||||
"Can share" : "Can share",
|
||||
"Owner" : "Omanik",
|
||||
@@ -43,7 +42,6 @@ OC.L10N.register(
|
||||
"Shared with you" : "Sinuga jagatud",
|
||||
"No notifications" : "Märguandeid pole",
|
||||
"An error occurred" : "Tekkis tõrge",
|
||||
"Share" : "Jaga",
|
||||
"This week" : "Käesolev nädal"
|
||||
"Share" : "Jaga"
|
||||
},
|
||||
"nplurals=2; plural=(n != 1);");
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
"Details" : "Üksikasjad",
|
||||
"Sharing" : "Jagamine",
|
||||
"Tags" : "Sildid",
|
||||
"Undo" : "Tühista",
|
||||
"Can edit" : "Võib redigeerida",
|
||||
"Can share" : "Can share",
|
||||
"Owner" : "Omanik",
|
||||
@@ -41,7 +40,6 @@
|
||||
"Shared with you" : "Sinuga jagatud",
|
||||
"No notifications" : "Märguandeid pole",
|
||||
"An error occurred" : "Tekkis tõrge",
|
||||
"Share" : "Jaga",
|
||||
"This week" : "Käesolev nädal"
|
||||
"Share" : "Jaga"
|
||||
},"pluralForm" :"nplurals=2; plural=(n != 1);"
|
||||
}
|
||||
@@ -131,7 +131,7 @@ OC.L10N.register(
|
||||
"Overwrite file" : "Remplacer le fichier",
|
||||
"Keep existing file" : "Conserver le fichier existant",
|
||||
"This board is read only" : "Ce tableau est en lecture seule",
|
||||
"Drop your files to upload" : "Glissez vos fichiers pour les téléverser",
|
||||
"Drop your files to upload" : "Glissez vos fichiers pour les envoyer",
|
||||
"Add card" : "Ajouter une carte",
|
||||
"Archived cards" : "Cartes archivées",
|
||||
"Add list" : "Ajouter une liste",
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
"Overwrite file" : "Remplacer le fichier",
|
||||
"Keep existing file" : "Conserver le fichier existant",
|
||||
"This board is read only" : "Ce tableau est en lecture seule",
|
||||
"Drop your files to upload" : "Glissez vos fichiers pour les téléverser",
|
||||
"Drop your files to upload" : "Glissez vos fichiers pour les envoyer",
|
||||
"Add card" : "Ajouter une carte",
|
||||
"Archived cards" : "Cartes archivées",
|
||||
"Add list" : "Ajouter une liste",
|
||||
|
||||
@@ -71,14 +71,14 @@ OC.L10N.register(
|
||||
"Load more" : "Carregar mais",
|
||||
"Personal" : "Pessoal",
|
||||
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "O cartão \"%s\" em \"%s\" foi vinculado com você por %s.",
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} atribuiu o cartão {deck-card} no {deck-board} a você.",
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{usuário} atribuiu a carta {deck-card} no {deck-board} para você.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "O cartão \"%s\" em \"%s\" atingiu sua data de vencimento.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "O cartão {deck-card} em {deck-board} atingiu sua data de vencimento.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "A carta {deck-card} em {deck-board} atingiu sua data de vencimento.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : "%s citou você num comentário em \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} mencionou você em um comentário em {deck-card}.",
|
||||
"The board \"%s\" has been shared with you by %s." : "O painel \"%s\" foi compartilhado com você por %s.",
|
||||
"{user} has shared {deck-board} with you." : "{user} compartilhou o {deck-board} com você.",
|
||||
"Card comments" : "Comentários do cartão",
|
||||
"{user} has shared {deck-board} with you." : "{user} compartilhou {deck-board} com você.",
|
||||
"Card comments" : "Comentários nos Cards",
|
||||
"%s on %s" : "%s em %s",
|
||||
"No data was provided to create an attachment." : "Nenhum dado foi fornecido para criar um anexo.",
|
||||
"Finished" : "Terminado",
|
||||
@@ -101,12 +101,12 @@ OC.L10N.register(
|
||||
"Could not write file to disk" : "Não foi possível escrever no disco",
|
||||
"A PHP extension stopped the file upload" : "Uma extensão PHP parou o envio do arquivo",
|
||||
"No file uploaded or file size exceeds maximum of %s" : "Nenhum arquivo enviado ou o tamanho excede o máximo de %s",
|
||||
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Este comentário tem mais de %s caracteres.\nEle foi adicionado como um anexo ao cartão de nome %s.\nAcessível na URL: %s.",
|
||||
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Este comentário tem mais de %s caracteres.\nAdicionado como um anexo ao cartão com o nome %s.\nAcessível no URL: %s.",
|
||||
"Card not found" : "Cartão não encontrado",
|
||||
"Path is already shared with this card" : "O caminho já é compartilhado com este cartão",
|
||||
"Invalid date, date format must be YYYY-MM-DD" : "Data inválida, o formato da data deve ser AAAA-MM-DD",
|
||||
"Personal planning and team project organization" : "Planejamento pessoal e organização de projetos em equipe",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "O Deck é uma ferramenta de organização ao estilo kanban voltada para o planejamento pessoal e para a organização de projetos para equipes, integrada ao Nextcloud.\n\n\n- 📥Adicione suas tarefas aos cartões e coloque-os em ordem\n- 📄 Escreva notas adicionais formatadas em Markdown \n- 🔖 Atribua rótulos para uma organização ainda melhor\n- 👥 Compartilhe com sua equipe, seus amigos ou sua família\n- 📎 Anexe arquivos e incorpore-os à sua descrição em Markdown\n- 💬 Discuta com sua equipe usando comentários\n- ⚡ Acompanhe as alterações no fluxo de atividades \n- 🚀 Organize seu projeto ",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck é uma ferramenta de organização do estilo kanban voltada para o planejamento pessoal e organização de projetos para equipes integradas ao Nextcloud.\n\n\n- 📥Adicione suas tarefas aos cartões e coloque-as em ordem\n- 📄 Escreva notas adicionais em Anotar \n- 🔖 Atribua rótulos para uma organização ainda melhor\n- 👥 Compartilhe com sua equipe, amigos ou família\n- 📎 Anexar arquivos e incorporá-los à descrição da Nota\n- 💬 Discuta com sua equipe usando comentários\n- ⚡ Acompanhe as mudanças no fluxo de atividades \n- 🚀 Organize seu projeto ",
|
||||
"Card details" : "Detalhes do cartão",
|
||||
"Add board" : "Adicionar painel",
|
||||
"Select the board to link to a project" : "Selecione o painel para vincular a um projeto",
|
||||
@@ -117,7 +117,7 @@ OC.L10N.register(
|
||||
"Select a list" : "Selecione uma lista",
|
||||
"Card title" : "Título do cartão",
|
||||
"Cancel" : "Cancelar",
|
||||
"Creating the new card …" : "Criando o novo cartão…",
|
||||
"Creating the new card …" : "Criando o novo cartão …",
|
||||
"Card \"{card}\" was added to \"{board}\"" : "O cartão \"{card}\" foi adicionado a \"{board}\" ",
|
||||
"Open card" : "Abrir o cartão",
|
||||
"Close" : "Fechar",
|
||||
@@ -150,7 +150,7 @@ OC.L10N.register(
|
||||
"Clear filter" : "Limpar filtro",
|
||||
"Hide archived cards" : "Ocultar cartões arquivados",
|
||||
"Show archived cards" : "Exibir cartões arquivados",
|
||||
"Toggle compact mode" : "Alternar modo compacto",
|
||||
"Toggle compact mode" : "Alternar para modo compacto",
|
||||
"Open details" : "Abrir detalhes",
|
||||
"Details" : "Detalhes",
|
||||
"Loading board" : "Carregando painel",
|
||||
@@ -176,17 +176,15 @@ OC.L10N.register(
|
||||
"Owner" : "Proprietário",
|
||||
"Delete" : "Excluir",
|
||||
"Failed to create share with {displayName}" : "Falha ao criar compartilhamento com {displayName}",
|
||||
"Are you sure you want to transfer the board {title} to {user}?" : "Deseja realmente transferir o painel {title} para {user}?",
|
||||
"Transfer the board." : "Transferir o painel.",
|
||||
"Are you sure you want to transfer the board {title} to {user}?" : "Tem certeza de que deseja transferir o quadro {title} para {user}?",
|
||||
"Transfer the board." : "Transfira a reunião.",
|
||||
"Transfer" : "Transferir",
|
||||
"The board has been transferred to {user}" : "A painel foi transferida para {user}",
|
||||
"Failed to transfer the board to {user}" : "Não foi possível transferir o painel para {user}",
|
||||
"The board has been transferred to {user}" : "A quadro foi transferida para {user}",
|
||||
"Failed to transfer the board to {user}" : "Falha ao transferir o quadro para {user}",
|
||||
"Add a new list" : "Adicionar nova lista",
|
||||
"Archive all cards" : "Arquivar todos os cartões",
|
||||
"Unarchive all cards" : "Desarquivar todos os cartões",
|
||||
"Delete list" : "Excluir lista",
|
||||
"Archive all cards in this list" : "Arquivar todos os cartões desta lista",
|
||||
"Unarchive all cards in this list" : "Desarquivar todos os cartões desta lista",
|
||||
"Add a new card" : "Adicionar um novo cartão",
|
||||
"Card name" : "Nome do cartão",
|
||||
"List deleted" : "Lista excluída",
|
||||
@@ -199,7 +197,7 @@ OC.L10N.register(
|
||||
"Share from Files" : "Compartilhar de Arquivos",
|
||||
"Pending share" : "Compartilhamento pendente",
|
||||
"Add this attachment" : "Adicionar este anexo",
|
||||
"Show in Files" : "Exibir em Arquivos",
|
||||
"Show in Files" : "Mostrar em Arquivos",
|
||||
"Download" : "Baixar",
|
||||
"Remove attachment" : "Remover anexo",
|
||||
"Delete Attachment" : "Excluir Anexo",
|
||||
@@ -214,13 +212,13 @@ OC.L10N.register(
|
||||
"Created" : "Criado",
|
||||
"The title cannot be empty." : "O título não pode ficar em branco.",
|
||||
"No comments yet. Begin the discussion!" : "Nenhum comentário ainda. Inicie a conversa!",
|
||||
"Failed to load comments" : "Não foi possível carregar os comentários",
|
||||
"Failed to load comments" : "Falha ao carregar comentários",
|
||||
"Assign a tag to this card…" : "Atribuir uma etiqueta a este cartão...",
|
||||
"Assign to users" : "Atribuir a usuários",
|
||||
"Assign to users/groups/circles" : "Atribuir a usuários/grupos/círculos",
|
||||
"Assign a user to this card…" : "Atribuir um usuário a este cartão...",
|
||||
"Due date" : "Data de vencimento",
|
||||
"Set a due date" : "Definir uma data de vencimento",
|
||||
"Set a due date" : "Definir uma data de finalização",
|
||||
"Remove due date" : "Remover data de vencimento",
|
||||
"Select Date" : "Selecionar Data",
|
||||
"Today" : "Hoje",
|
||||
@@ -244,7 +242,7 @@ OC.L10N.register(
|
||||
"Write a description …" : "Escreva uma descrição...",
|
||||
"Choose attachment" : "Escolher anexo",
|
||||
"(group)" : "(grupo)",
|
||||
"Todo items" : "Itens a fazer",
|
||||
"Todo items" : "Itens para fazer",
|
||||
"{count} comments, {unread} unread" : "{count} comentários, {unread} não lidos",
|
||||
"Edit card title" : "Editar título do cartão",
|
||||
"Assign to me" : "Atribuir a mim",
|
||||
@@ -254,7 +252,7 @@ OC.L10N.register(
|
||||
"Archive card" : "Arquivar cartão",
|
||||
"Delete card" : "Excluir cartão",
|
||||
"Move card to another board" : "Mover o cartão para outro painel",
|
||||
"List is empty" : "A lista está vazia",
|
||||
"List is empty" : "A Lista está vazia",
|
||||
"Card deleted" : "Cartão excluído",
|
||||
"seconds ago" : "segundos atrás",
|
||||
"All boards" : "Todos os painéis",
|
||||
@@ -262,8 +260,7 @@ OC.L10N.register(
|
||||
"Shared with you" : "Compartilhado com você",
|
||||
"Deck settings" : "Configurações do Deck",
|
||||
"Use bigger card view" : "Use uma exibição de cartão maior",
|
||||
"Show card ID badge" : "Exibir o distintivo de identificação do cartão",
|
||||
"Show boards in calendar/tasks" : "Exibir os painéis em calendários/tarefas",
|
||||
"Show boards in calendar/tasks" : "Mostrar painéis em calendários/tarefas",
|
||||
"Limit deck usage of groups" : "Limitar o uso de grupos no deck",
|
||||
"Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them." : "Limitar o Deck impedirá que usuários que não fazem parte desses grupos criem seus próprios painéis. Os usuários ainda poderão trabalhar em pastas que foram compartilhadas com eles.",
|
||||
"Board details" : "Detalhes do painel",
|
||||
@@ -282,20 +279,20 @@ OC.L10N.register(
|
||||
"Only assigned cards" : "Apenas cartões atribuídos",
|
||||
"No reminder" : "Nenhum lembrete",
|
||||
"An error occurred" : "Ocorreu um erro",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Deseja realmente excluir o painel {title}? Isso excluirá todos os dados deste painel, inclusive os cartões arquivados.",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Tem certeza de que deseja excluir o quadro {title}? Isso excluirá todos os dados deste quadro, incluindo cartões arquivados.",
|
||||
"Delete the board?" : "Excluir o painel?",
|
||||
"Loading filtered view" : "Carregando exibição filtrada",
|
||||
"No due" : "Sem vencimento",
|
||||
"Search for {searchQuery} in all boards" : "Pesquisar por {searchQuery} em todos os painéis",
|
||||
"No results found" : "Nenhum resultado encontrado",
|
||||
"{stack} in {board}" : "{stack} em {board}",
|
||||
"{stack} in {board}" : "{stack} de {board}",
|
||||
"Click to expand description" : "Clique para expandir a descrição",
|
||||
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Criado em {created}\n* Última modificação em {lastMod}\n* {nbAttachments} anexos\n* {nbComments} comentários",
|
||||
"{nbCards} cards" : "{nbCards} cartões",
|
||||
"No upcoming cards" : "Não há mais cartões",
|
||||
"upcoming cards" : "próximos cartões",
|
||||
"Due on {date}" : "Vencimento em {date}",
|
||||
"Link to a board" : "Vincular a um painel",
|
||||
"Link to a board" : "Linkar a um painel",
|
||||
"Link to a card" : "Vincular a um cartão",
|
||||
"Create a card" : "Criar um cartão",
|
||||
"Message from {author} in {conversationName}" : "Mensagem de {author} em {conversationName}",
|
||||
@@ -307,11 +304,11 @@ OC.L10N.register(
|
||||
"Share {file} with a Deck card" : "Compartilhar {file} com um cartão Deck",
|
||||
"Share" : "Compartilhar",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck é uma ferramenta de organização de estilo kanban destinada ao planejamento pessoal e organização para equipes integradas com o Nextcloud.\n\n\n- 📥 Adicione suas tarefas aos cartões e coloque-os em ordem\n- 📄 Insira notas adicionais em markdown\n- 🔖 Atribua etiquetas para melhorar a organização\n- 👥 Compartilhe com sua equipe, amigos ou familiares\n- 📎 Anexe arquivos e incorpore-os em sua descrição no markdown\n- 💬 Discuta com sua equipe usando os comentários\n- ⚡ Acompanhe as alterações no fluxo de atividades\n- 🚀 Mantenha seu projeto organizado",
|
||||
"Are you sure you want to transfer the board {title} for {user} ?" : "Deseja realmente transferir o painel {title} para {user}?",
|
||||
"Transfer the board for {user} successfully" : "O painel foi transferido para {user} com sucesso",
|
||||
"Failed to transfer the board for {user}" : "Não foi possível transferir o painel para {user}",
|
||||
"Are you sure you want to transfer the board {title} for {user} ?" : "Tem certeza de que deseja transferir o quadro {title} para {user}?",
|
||||
"Transfer the board for {user} successfully" : "Transferida a reunião para {user} com sucesso",
|
||||
"Failed to transfer the board for {user}" : "Falha ao transferir a reunião para {user}",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board." : "Deseja realmente excluir o painel {title}? Isto excluirá todos os dados deste painel.",
|
||||
"This week" : "Esta semana",
|
||||
"Are you sure you want to transfer the board {title} for {user}?" : "Deseja realmente transferir o painel {title} para {user}?"
|
||||
"Are you sure you want to transfer the board {title} for {user}?" : "Tem certeza de que deseja transferir o quadro {title} para {user}?"
|
||||
},
|
||||
"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");
|
||||
|
||||
@@ -69,14 +69,14 @@
|
||||
"Load more" : "Carregar mais",
|
||||
"Personal" : "Pessoal",
|
||||
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "O cartão \"%s\" em \"%s\" foi vinculado com você por %s.",
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} atribuiu o cartão {deck-card} no {deck-board} a você.",
|
||||
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{usuário} atribuiu a carta {deck-card} no {deck-board} para você.",
|
||||
"The card \"%s\" on \"%s\" has reached its due date." : "O cartão \"%s\" em \"%s\" atingiu sua data de vencimento.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "O cartão {deck-card} em {deck-board} atingiu sua data de vencimento.",
|
||||
"The card {deck-card} on {deck-board} has reached its due date." : "A carta {deck-card} em {deck-board} atingiu sua data de vencimento.",
|
||||
"%s has mentioned you in a comment on \"%s\"." : "%s citou você num comentário em \"%s\".",
|
||||
"{user} has mentioned you in a comment on {deck-card}." : "{user} mencionou você em um comentário em {deck-card}.",
|
||||
"The board \"%s\" has been shared with you by %s." : "O painel \"%s\" foi compartilhado com você por %s.",
|
||||
"{user} has shared {deck-board} with you." : "{user} compartilhou o {deck-board} com você.",
|
||||
"Card comments" : "Comentários do cartão",
|
||||
"{user} has shared {deck-board} with you." : "{user} compartilhou {deck-board} com você.",
|
||||
"Card comments" : "Comentários nos Cards",
|
||||
"%s on %s" : "%s em %s",
|
||||
"No data was provided to create an attachment." : "Nenhum dado foi fornecido para criar um anexo.",
|
||||
"Finished" : "Terminado",
|
||||
@@ -99,12 +99,12 @@
|
||||
"Could not write file to disk" : "Não foi possível escrever no disco",
|
||||
"A PHP extension stopped the file upload" : "Uma extensão PHP parou o envio do arquivo",
|
||||
"No file uploaded or file size exceeds maximum of %s" : "Nenhum arquivo enviado ou o tamanho excede o máximo de %s",
|
||||
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Este comentário tem mais de %s caracteres.\nEle foi adicionado como um anexo ao cartão de nome %s.\nAcessível na URL: %s.",
|
||||
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Este comentário tem mais de %s caracteres.\nAdicionado como um anexo ao cartão com o nome %s.\nAcessível no URL: %s.",
|
||||
"Card not found" : "Cartão não encontrado",
|
||||
"Path is already shared with this card" : "O caminho já é compartilhado com este cartão",
|
||||
"Invalid date, date format must be YYYY-MM-DD" : "Data inválida, o formato da data deve ser AAAA-MM-DD",
|
||||
"Personal planning and team project organization" : "Planejamento pessoal e organização de projetos em equipe",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "O Deck é uma ferramenta de organização ao estilo kanban voltada para o planejamento pessoal e para a organização de projetos para equipes, integrada ao Nextcloud.\n\n\n- 📥Adicione suas tarefas aos cartões e coloque-os em ordem\n- 📄 Escreva notas adicionais formatadas em Markdown \n- 🔖 Atribua rótulos para uma organização ainda melhor\n- 👥 Compartilhe com sua equipe, seus amigos ou sua família\n- 📎 Anexe arquivos e incorpore-os à sua descrição em Markdown\n- 💬 Discuta com sua equipe usando comentários\n- ⚡ Acompanhe as alterações no fluxo de atividades \n- 🚀 Organize seu projeto ",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck é uma ferramenta de organização do estilo kanban voltada para o planejamento pessoal e organização de projetos para equipes integradas ao Nextcloud.\n\n\n- 📥Adicione suas tarefas aos cartões e coloque-as em ordem\n- 📄 Escreva notas adicionais em Anotar \n- 🔖 Atribua rótulos para uma organização ainda melhor\n- 👥 Compartilhe com sua equipe, amigos ou família\n- 📎 Anexar arquivos e incorporá-los à descrição da Nota\n- 💬 Discuta com sua equipe usando comentários\n- ⚡ Acompanhe as mudanças no fluxo de atividades \n- 🚀 Organize seu projeto ",
|
||||
"Card details" : "Detalhes do cartão",
|
||||
"Add board" : "Adicionar painel",
|
||||
"Select the board to link to a project" : "Selecione o painel para vincular a um projeto",
|
||||
@@ -115,7 +115,7 @@
|
||||
"Select a list" : "Selecione uma lista",
|
||||
"Card title" : "Título do cartão",
|
||||
"Cancel" : "Cancelar",
|
||||
"Creating the new card …" : "Criando o novo cartão…",
|
||||
"Creating the new card …" : "Criando o novo cartão …",
|
||||
"Card \"{card}\" was added to \"{board}\"" : "O cartão \"{card}\" foi adicionado a \"{board}\" ",
|
||||
"Open card" : "Abrir o cartão",
|
||||
"Close" : "Fechar",
|
||||
@@ -148,7 +148,7 @@
|
||||
"Clear filter" : "Limpar filtro",
|
||||
"Hide archived cards" : "Ocultar cartões arquivados",
|
||||
"Show archived cards" : "Exibir cartões arquivados",
|
||||
"Toggle compact mode" : "Alternar modo compacto",
|
||||
"Toggle compact mode" : "Alternar para modo compacto",
|
||||
"Open details" : "Abrir detalhes",
|
||||
"Details" : "Detalhes",
|
||||
"Loading board" : "Carregando painel",
|
||||
@@ -174,17 +174,15 @@
|
||||
"Owner" : "Proprietário",
|
||||
"Delete" : "Excluir",
|
||||
"Failed to create share with {displayName}" : "Falha ao criar compartilhamento com {displayName}",
|
||||
"Are you sure you want to transfer the board {title} to {user}?" : "Deseja realmente transferir o painel {title} para {user}?",
|
||||
"Transfer the board." : "Transferir o painel.",
|
||||
"Are you sure you want to transfer the board {title} to {user}?" : "Tem certeza de que deseja transferir o quadro {title} para {user}?",
|
||||
"Transfer the board." : "Transfira a reunião.",
|
||||
"Transfer" : "Transferir",
|
||||
"The board has been transferred to {user}" : "A painel foi transferida para {user}",
|
||||
"Failed to transfer the board to {user}" : "Não foi possível transferir o painel para {user}",
|
||||
"The board has been transferred to {user}" : "A quadro foi transferida para {user}",
|
||||
"Failed to transfer the board to {user}" : "Falha ao transferir o quadro para {user}",
|
||||
"Add a new list" : "Adicionar nova lista",
|
||||
"Archive all cards" : "Arquivar todos os cartões",
|
||||
"Unarchive all cards" : "Desarquivar todos os cartões",
|
||||
"Delete list" : "Excluir lista",
|
||||
"Archive all cards in this list" : "Arquivar todos os cartões desta lista",
|
||||
"Unarchive all cards in this list" : "Desarquivar todos os cartões desta lista",
|
||||
"Add a new card" : "Adicionar um novo cartão",
|
||||
"Card name" : "Nome do cartão",
|
||||
"List deleted" : "Lista excluída",
|
||||
@@ -197,7 +195,7 @@
|
||||
"Share from Files" : "Compartilhar de Arquivos",
|
||||
"Pending share" : "Compartilhamento pendente",
|
||||
"Add this attachment" : "Adicionar este anexo",
|
||||
"Show in Files" : "Exibir em Arquivos",
|
||||
"Show in Files" : "Mostrar em Arquivos",
|
||||
"Download" : "Baixar",
|
||||
"Remove attachment" : "Remover anexo",
|
||||
"Delete Attachment" : "Excluir Anexo",
|
||||
@@ -212,13 +210,13 @@
|
||||
"Created" : "Criado",
|
||||
"The title cannot be empty." : "O título não pode ficar em branco.",
|
||||
"No comments yet. Begin the discussion!" : "Nenhum comentário ainda. Inicie a conversa!",
|
||||
"Failed to load comments" : "Não foi possível carregar os comentários",
|
||||
"Failed to load comments" : "Falha ao carregar comentários",
|
||||
"Assign a tag to this card…" : "Atribuir uma etiqueta a este cartão...",
|
||||
"Assign to users" : "Atribuir a usuários",
|
||||
"Assign to users/groups/circles" : "Atribuir a usuários/grupos/círculos",
|
||||
"Assign a user to this card…" : "Atribuir um usuário a este cartão...",
|
||||
"Due date" : "Data de vencimento",
|
||||
"Set a due date" : "Definir uma data de vencimento",
|
||||
"Set a due date" : "Definir uma data de finalização",
|
||||
"Remove due date" : "Remover data de vencimento",
|
||||
"Select Date" : "Selecionar Data",
|
||||
"Today" : "Hoje",
|
||||
@@ -242,7 +240,7 @@
|
||||
"Write a description …" : "Escreva uma descrição...",
|
||||
"Choose attachment" : "Escolher anexo",
|
||||
"(group)" : "(grupo)",
|
||||
"Todo items" : "Itens a fazer",
|
||||
"Todo items" : "Itens para fazer",
|
||||
"{count} comments, {unread} unread" : "{count} comentários, {unread} não lidos",
|
||||
"Edit card title" : "Editar título do cartão",
|
||||
"Assign to me" : "Atribuir a mim",
|
||||
@@ -252,7 +250,7 @@
|
||||
"Archive card" : "Arquivar cartão",
|
||||
"Delete card" : "Excluir cartão",
|
||||
"Move card to another board" : "Mover o cartão para outro painel",
|
||||
"List is empty" : "A lista está vazia",
|
||||
"List is empty" : "A Lista está vazia",
|
||||
"Card deleted" : "Cartão excluído",
|
||||
"seconds ago" : "segundos atrás",
|
||||
"All boards" : "Todos os painéis",
|
||||
@@ -260,8 +258,7 @@
|
||||
"Shared with you" : "Compartilhado com você",
|
||||
"Deck settings" : "Configurações do Deck",
|
||||
"Use bigger card view" : "Use uma exibição de cartão maior",
|
||||
"Show card ID badge" : "Exibir o distintivo de identificação do cartão",
|
||||
"Show boards in calendar/tasks" : "Exibir os painéis em calendários/tarefas",
|
||||
"Show boards in calendar/tasks" : "Mostrar painéis em calendários/tarefas",
|
||||
"Limit deck usage of groups" : "Limitar o uso de grupos no deck",
|
||||
"Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them." : "Limitar o Deck impedirá que usuários que não fazem parte desses grupos criem seus próprios painéis. Os usuários ainda poderão trabalhar em pastas que foram compartilhadas com eles.",
|
||||
"Board details" : "Detalhes do painel",
|
||||
@@ -280,20 +277,20 @@
|
||||
"Only assigned cards" : "Apenas cartões atribuídos",
|
||||
"No reminder" : "Nenhum lembrete",
|
||||
"An error occurred" : "Ocorreu um erro",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Deseja realmente excluir o painel {title}? Isso excluirá todos os dados deste painel, inclusive os cartões arquivados.",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Tem certeza de que deseja excluir o quadro {title}? Isso excluirá todos os dados deste quadro, incluindo cartões arquivados.",
|
||||
"Delete the board?" : "Excluir o painel?",
|
||||
"Loading filtered view" : "Carregando exibição filtrada",
|
||||
"No due" : "Sem vencimento",
|
||||
"Search for {searchQuery} in all boards" : "Pesquisar por {searchQuery} em todos os painéis",
|
||||
"No results found" : "Nenhum resultado encontrado",
|
||||
"{stack} in {board}" : "{stack} em {board}",
|
||||
"{stack} in {board}" : "{stack} de {board}",
|
||||
"Click to expand description" : "Clique para expandir a descrição",
|
||||
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Criado em {created}\n* Última modificação em {lastMod}\n* {nbAttachments} anexos\n* {nbComments} comentários",
|
||||
"{nbCards} cards" : "{nbCards} cartões",
|
||||
"No upcoming cards" : "Não há mais cartões",
|
||||
"upcoming cards" : "próximos cartões",
|
||||
"Due on {date}" : "Vencimento em {date}",
|
||||
"Link to a board" : "Vincular a um painel",
|
||||
"Link to a board" : "Linkar a um painel",
|
||||
"Link to a card" : "Vincular a um cartão",
|
||||
"Create a card" : "Criar um cartão",
|
||||
"Message from {author} in {conversationName}" : "Mensagem de {author} em {conversationName}",
|
||||
@@ -305,11 +302,11 @@
|
||||
"Share {file} with a Deck card" : "Compartilhar {file} com um cartão Deck",
|
||||
"Share" : "Compartilhar",
|
||||
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck é uma ferramenta de organização de estilo kanban destinada ao planejamento pessoal e organização para equipes integradas com o Nextcloud.\n\n\n- 📥 Adicione suas tarefas aos cartões e coloque-os em ordem\n- 📄 Insira notas adicionais em markdown\n- 🔖 Atribua etiquetas para melhorar a organização\n- 👥 Compartilhe com sua equipe, amigos ou familiares\n- 📎 Anexe arquivos e incorpore-os em sua descrição no markdown\n- 💬 Discuta com sua equipe usando os comentários\n- ⚡ Acompanhe as alterações no fluxo de atividades\n- 🚀 Mantenha seu projeto organizado",
|
||||
"Are you sure you want to transfer the board {title} for {user} ?" : "Deseja realmente transferir o painel {title} para {user}?",
|
||||
"Transfer the board for {user} successfully" : "O painel foi transferido para {user} com sucesso",
|
||||
"Failed to transfer the board for {user}" : "Não foi possível transferir o painel para {user}",
|
||||
"Are you sure you want to transfer the board {title} for {user} ?" : "Tem certeza de que deseja transferir o quadro {title} para {user}?",
|
||||
"Transfer the board for {user} successfully" : "Transferida a reunião para {user} com sucesso",
|
||||
"Failed to transfer the board for {user}" : "Falha ao transferir a reunião para {user}",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board." : "Deseja realmente excluir o painel {title}? Isto excluirá todos os dados deste painel.",
|
||||
"This week" : "Esta semana",
|
||||
"Are you sure you want to transfer the board {title} for {user}?" : "Deseja realmente transferir o painel {title} para {user}?"
|
||||
"Are you sure you want to transfer the board {title} for {user}?" : "Tem certeza de que deseja transferir o quadro {title} para {user}?"
|
||||
},"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
|
||||
}
|
||||
@@ -183,10 +183,8 @@ OC.L10N.register(
|
||||
"Failed to transfer the board to {user}" : "Не удалось передать доску пользователю {user}",
|
||||
"Add a new list" : "Создать список",
|
||||
"Archive all cards" : "Переместить все карточки в архив",
|
||||
"Unarchive all cards" : "Восстановить все карточки из архива",
|
||||
"Delete list" : "Удалить список",
|
||||
"Archive all cards in this list" : "Переместить в архив все карточки текущего списка",
|
||||
"Unarchive all cards in this list" : "Восстановить из архива все карточки списка",
|
||||
"Add a new card" : "Создать карточку",
|
||||
"Card name" : "Название карточки",
|
||||
"List deleted" : "Список удалён",
|
||||
@@ -244,9 +242,7 @@ OC.L10N.register(
|
||||
"Write a description …" : "Добавьте описание...",
|
||||
"Choose attachment" : "Выберите вложение",
|
||||
"(group)" : "(группа)",
|
||||
"Todo items" : "Элементы списка задач",
|
||||
"{count} comments, {unread} unread" : "{count} комментариев, {unread} непрочитано",
|
||||
"Edit card title" : "Изменить заголовок карточки",
|
||||
"Assign to me" : "Назначить себе",
|
||||
"Unassign myself" : "Отказаться от назначения",
|
||||
"Move card" : "Переместить карточку",
|
||||
@@ -260,9 +256,7 @@ OC.L10N.register(
|
||||
"All boards" : "Все доски",
|
||||
"Archived boards" : "Архив досок",
|
||||
"Shared with you" : "Предоставленные вам",
|
||||
"Deck settings" : "Параметры карточек",
|
||||
"Use bigger card view" : "Режим просмотра с увеличенными карточками",
|
||||
"Show card ID badge" : "Показывать идентификатор карточки",
|
||||
"Show boards in calendar/tasks" : "Показывать карточки в календаре и задачах",
|
||||
"Limit deck usage of groups" : "Разрешить использовать приложение Карточки только участникам заданных групп",
|
||||
"Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them." : "Создание собственных рабочих досок пользователям, не входящим в заданные группы, будет заблокировано. Тем не менее, такие пользователи смогут продолжить работать с общими досками, к которым у них есть доступ. ",
|
||||
@@ -282,15 +276,12 @@ OC.L10N.register(
|
||||
"Only assigned cards" : "Только для назначенных карточек",
|
||||
"No reminder" : "Не напоминать",
|
||||
"An error occurred" : "Произошла ошибка",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Подтвердите удаление доски «{title}»; это действие приведёт к удалению также все данных, принадлежащих этой доске, включая карточки в архиве.",
|
||||
"Delete the board?" : "Удалить доску?",
|
||||
"Loading filtered view" : "Выполняется отбор",
|
||||
"No due" : "Без назначенной даты",
|
||||
"Search for {searchQuery} in all boards" : "Искать {searchQuery} на всех досках",
|
||||
"No results found" : "Результаты отсутствуют",
|
||||
"{stack} in {board}" : "«{stack}» с доски «{board}»",
|
||||
"Click to expand description" : "Нажмите, чтобы развернуть поле описания",
|
||||
"{nbCards} cards" : "карточек: {nbCards}",
|
||||
"No upcoming cards" : "Отсутствуют карточки, ожидающие выполнения",
|
||||
"upcoming cards" : "карточки, ожидающие выполнения",
|
||||
"Link to a board" : "Ссылка на доску",
|
||||
|
||||
@@ -181,10 +181,8 @@
|
||||
"Failed to transfer the board to {user}" : "Не удалось передать доску пользователю {user}",
|
||||
"Add a new list" : "Создать список",
|
||||
"Archive all cards" : "Переместить все карточки в архив",
|
||||
"Unarchive all cards" : "Восстановить все карточки из архива",
|
||||
"Delete list" : "Удалить список",
|
||||
"Archive all cards in this list" : "Переместить в архив все карточки текущего списка",
|
||||
"Unarchive all cards in this list" : "Восстановить из архива все карточки списка",
|
||||
"Add a new card" : "Создать карточку",
|
||||
"Card name" : "Название карточки",
|
||||
"List deleted" : "Список удалён",
|
||||
@@ -242,9 +240,7 @@
|
||||
"Write a description …" : "Добавьте описание...",
|
||||
"Choose attachment" : "Выберите вложение",
|
||||
"(group)" : "(группа)",
|
||||
"Todo items" : "Элементы списка задач",
|
||||
"{count} comments, {unread} unread" : "{count} комментариев, {unread} непрочитано",
|
||||
"Edit card title" : "Изменить заголовок карточки",
|
||||
"Assign to me" : "Назначить себе",
|
||||
"Unassign myself" : "Отказаться от назначения",
|
||||
"Move card" : "Переместить карточку",
|
||||
@@ -258,9 +254,7 @@
|
||||
"All boards" : "Все доски",
|
||||
"Archived boards" : "Архив досок",
|
||||
"Shared with you" : "Предоставленные вам",
|
||||
"Deck settings" : "Параметры карточек",
|
||||
"Use bigger card view" : "Режим просмотра с увеличенными карточками",
|
||||
"Show card ID badge" : "Показывать идентификатор карточки",
|
||||
"Show boards in calendar/tasks" : "Показывать карточки в календаре и задачах",
|
||||
"Limit deck usage of groups" : "Разрешить использовать приложение Карточки только участникам заданных групп",
|
||||
"Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them." : "Создание собственных рабочих досок пользователям, не входящим в заданные группы, будет заблокировано. Тем не менее, такие пользователи смогут продолжить работать с общими досками, к которым у них есть доступ. ",
|
||||
@@ -280,15 +274,12 @@
|
||||
"Only assigned cards" : "Только для назначенных карточек",
|
||||
"No reminder" : "Не напоминать",
|
||||
"An error occurred" : "Произошла ошибка",
|
||||
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Подтвердите удаление доски «{title}»; это действие приведёт к удалению также все данных, принадлежащих этой доске, включая карточки в архиве.",
|
||||
"Delete the board?" : "Удалить доску?",
|
||||
"Loading filtered view" : "Выполняется отбор",
|
||||
"No due" : "Без назначенной даты",
|
||||
"Search for {searchQuery} in all boards" : "Искать {searchQuery} на всех досках",
|
||||
"No results found" : "Результаты отсутствуют",
|
||||
"{stack} in {board}" : "«{stack}» с доски «{board}»",
|
||||
"Click to expand description" : "Нажмите, чтобы развернуть поле описания",
|
||||
"{nbCards} cards" : "карточек: {nbCards}",
|
||||
"No upcoming cards" : "Отсутствуют карточки, ожидающие выполнения",
|
||||
"upcoming cards" : "карточки, ожидающие выполнения",
|
||||
"Link to a board" : "Ссылка на доску",
|
||||
|
||||
@@ -125,7 +125,7 @@ OC.L10N.register(
|
||||
"Upload new files" : "Додати файл",
|
||||
"Share from Files" : "Відкрити Файли",
|
||||
"Add this attachment" : "Долучити вкладення",
|
||||
"Download" : "Звантажити",
|
||||
"Download" : "Завантажити",
|
||||
"Delete Attachment" : "Забрати вкладення",
|
||||
"Restore Attachment" : "Відновити вкладення",
|
||||
"File to share" : "Виберіть файл для надання доступу",
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
"Upload new files" : "Додати файл",
|
||||
"Share from Files" : "Відкрити Файли",
|
||||
"Add this attachment" : "Долучити вкладення",
|
||||
"Download" : "Звантажити",
|
||||
"Download" : "Завантажити",
|
||||
"Delete Attachment" : "Забрати вкладення",
|
||||
"Restore Attachment" : "Відновити вкладення",
|
||||
"File to share" : "Виберіть файл для надання доступу",
|
||||
|
||||
@@ -134,7 +134,6 @@ OC.L10N.register(
|
||||
"Archived cards" : "已归档卡片",
|
||||
"Add list" : "添加列表",
|
||||
"List name" : "列表名称",
|
||||
"Active filters" : "已开启的过滤器",
|
||||
"Apply filter" : "应用筛选",
|
||||
"Filter by tag" : "按标签筛选",
|
||||
"Filter by assigned user" : "按指派的用户筛选",
|
||||
@@ -236,9 +235,7 @@ OC.L10N.register(
|
||||
"Write a description …" : "写一段描述",
|
||||
"Choose attachment" : "选择附件",
|
||||
"(group)" : "(组)",
|
||||
"Todo items" : "待办事项",
|
||||
"{count} comments, {unread} unread" : "{count} 条评论,{unread} 未读",
|
||||
"Edit card title" : "编辑卡片标题",
|
||||
"Assign to me" : "指派给我",
|
||||
"Unassign myself" : "不再指派给我",
|
||||
"Move card" : "移动卡片",
|
||||
|
||||
@@ -132,7 +132,6 @@
|
||||
"Archived cards" : "已归档卡片",
|
||||
"Add list" : "添加列表",
|
||||
"List name" : "列表名称",
|
||||
"Active filters" : "已开启的过滤器",
|
||||
"Apply filter" : "应用筛选",
|
||||
"Filter by tag" : "按标签筛选",
|
||||
"Filter by assigned user" : "按指派的用户筛选",
|
||||
@@ -234,9 +233,7 @@
|
||||
"Write a description …" : "写一段描述",
|
||||
"Choose attachment" : "选择附件",
|
||||
"(group)" : "(组)",
|
||||
"Todo items" : "待办事项",
|
||||
"{count} comments, {unread} unread" : "{count} 条评论,{unread} 未读",
|
||||
"Edit card title" : "编辑卡片标题",
|
||||
"Assign to me" : "指派给我",
|
||||
"Unassign myself" : "不再指派给我",
|
||||
"Move card" : "移动卡片",
|
||||
|
||||
@@ -31,6 +31,7 @@ use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\AclMapper;
|
||||
use OCA\Deck\Db\Assignment;
|
||||
use OCA\Deck\Db\Attachment;
|
||||
use OCA\Deck\Db\AttachmentMapper;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\Card;
|
||||
@@ -45,24 +46,19 @@ use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\Comments\IComment;
|
||||
use OCP\IUser;
|
||||
use OCP\Server;
|
||||
use OCP\L10N\IFactory;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class ActivityManager {
|
||||
public const DECK_NOAUTHOR_COMMENT_SYSTEM_ENFORCED = 'DECK_NOAUTHOR_COMMENT_SYSTEM_ENFORCED';
|
||||
|
||||
public const SUBJECT_PARAMS_MAX_LENGTH = 4000;
|
||||
public const SHORTENED_DESCRIPTION_MAX_LENGTH = 2000;
|
||||
|
||||
private IManager $manager;
|
||||
private ?string $userId;
|
||||
private PermissionService $permissionService;
|
||||
private BoardMapper $boardMapper;
|
||||
private CardMapper $cardMapper;
|
||||
private AclMapper $aclMapper;
|
||||
private StackMapper $stackMapper;
|
||||
private IFactory $l10nFactory;
|
||||
private $manager;
|
||||
private $userId;
|
||||
private $permissionService;
|
||||
private $boardMapper;
|
||||
private $cardMapper;
|
||||
private $attachmentMapper;
|
||||
private $aclMapper;
|
||||
private $stackMapper;
|
||||
private $l10nFactory;
|
||||
|
||||
public const DECK_OBJECT_BOARD = 'deck_board';
|
||||
public const DECK_OBJECT_CARD = 'deck_card';
|
||||
@@ -114,15 +110,17 @@ class ActivityManager {
|
||||
BoardMapper $boardMapper,
|
||||
CardMapper $cardMapper,
|
||||
StackMapper $stackMapper,
|
||||
AttachmentMapper $attachmentMapper,
|
||||
AclMapper $aclMapper,
|
||||
IFactory $l10nFactory,
|
||||
?string $userId
|
||||
$userId
|
||||
) {
|
||||
$this->manager = $manager;
|
||||
$this->permissionService = $permissionsService;
|
||||
$this->boardMapper = $boardMapper;
|
||||
$this->cardMapper = $cardMapper;
|
||||
$this->stackMapper = $stackMapper;
|
||||
$this->attachmentMapper = $attachmentMapper;
|
||||
$this->aclMapper = $aclMapper;
|
||||
$this->l10nFactory = $l10nFactory;
|
||||
$this->userId = $userId;
|
||||
@@ -251,6 +249,19 @@ class ActivityManager {
|
||||
try {
|
||||
$event = $this->createEvent($objectType, $entity, $subject, $additionalParams, $author);
|
||||
if ($event !== null) {
|
||||
$json = json_encode($event->getSubjectParameters());
|
||||
if (mb_strlen($json) > 4000) {
|
||||
$params = json_decode(json_encode($event->getSubjectParameters()), true);
|
||||
|
||||
$newContent = $params['after'];
|
||||
unset($params['before'], $params['after'], $params['card']['description']);
|
||||
|
||||
$params['after'] = mb_substr($newContent, 0, 2000);
|
||||
if (mb_strlen($newContent) > 2000) {
|
||||
$params['after'] .= '...';
|
||||
}
|
||||
$event->setSubject($event->getSubject(), $params);
|
||||
}
|
||||
$this->sendToUsers($event);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
@@ -312,10 +323,10 @@ class ActivityManager {
|
||||
try {
|
||||
$object = $this->findObjectForEntity($objectType, $entity);
|
||||
} catch (DoesNotExistException $e) {
|
||||
Server::get(LoggerInterface::class)->error('Could not create activity entry for ' . $subject . '. Entity not found.', (array)$entity);
|
||||
\OC::$server->getLogger()->error('Could not create activity entry for ' . $subject . '. Entity not found.', (array)$entity);
|
||||
return null;
|
||||
} catch (MultipleObjectsReturnedException $e) {
|
||||
Server::get(LoggerInterface::class)->error('Could not create activity entry for ' . $subject . '. Entity not found.', (array)$entity);
|
||||
\OC::$server->getLogger()->error('Could not create activity entry for ' . $subject . '. Entity not found.', (array)$entity);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -367,15 +378,7 @@ class ActivityManager {
|
||||
case self::SUBJECT_CARD_USER_ASSIGN:
|
||||
case self::SUBJECT_CARD_USER_UNASSIGN:
|
||||
$subjectParams = $this->findDetailsForCard($entity->getId(), $subject);
|
||||
|
||||
if (isset($additionalParams['after']) && $additionalParams['after'] instanceof \DateTimeInterface) {
|
||||
$additionalParams['after'] = $additionalParams['after']->format('c');
|
||||
}
|
||||
if (isset($additionalParams['before']) && $additionalParams['before'] instanceof \DateTimeInterface) {
|
||||
$additionalParams['before'] = $additionalParams['before']->format('c');
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
case self::SUBJECT_ATTACHMENT_CREATE:
|
||||
case self::SUBJECT_ATTACHMENT_UPDATE:
|
||||
case self::SUBJECT_ATTACHMENT_DELETE:
|
||||
@@ -407,31 +410,12 @@ class ActivityManager {
|
||||
|
||||
$subjectParams['author'] = $author === null ? $this->userId : $author;
|
||||
|
||||
$subjectParams = array_merge($subjectParams, $additionalParams);
|
||||
$json = json_encode($subjectParams);
|
||||
if (mb_strlen($json) > self::SUBJECT_PARAMS_MAX_LENGTH) {
|
||||
$params = json_decode(json_encode($subjectParams), true);
|
||||
|
||||
if ($subject === self::SUBJECT_CARD_UPDATE_DESCRIPTION && isset($params['after'])) {
|
||||
$newContent = $params['after'];
|
||||
unset($params['before'], $params['after'], $params['card']['description']);
|
||||
|
||||
$params['after'] = mb_substr($newContent, 0, self::SHORTENED_DESCRIPTION_MAX_LENGTH);
|
||||
if (mb_strlen($newContent) > self::SHORTENED_DESCRIPTION_MAX_LENGTH) {
|
||||
$params['after'] .= '...';
|
||||
}
|
||||
$subjectParams = $params;
|
||||
} else {
|
||||
throw new \Exception('Subject parameters too long');
|
||||
}
|
||||
}
|
||||
|
||||
$event = $this->manager->generateEvent();
|
||||
$event->setApp('deck')
|
||||
->setType($eventType)
|
||||
->setAuthor($subjectParams['author'])
|
||||
->setObject($objectType, (int)$object->getId(), $object->getTitle())
|
||||
->setSubject($subject, $subjectParams)
|
||||
->setSubject($subject, array_merge($subjectParams, $additionalParams))
|
||||
->setTimestamp(time());
|
||||
|
||||
if ($message !== null) {
|
||||
|
||||
@@ -69,7 +69,15 @@ class ChangeSet implements \JsonSerializable {
|
||||
return $this->after;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array {
|
||||
/**
|
||||
* Specify data which should be serialized to JSON
|
||||
*
|
||||
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
|
||||
* @return mixed data which can be serialized by <b>json_encode</b>,
|
||||
* which is a value of any type other than a resource.
|
||||
* @since 5.4.0
|
||||
*/
|
||||
public function jsonSerialize() {
|
||||
return [
|
||||
'before' => $this->getBefore(),
|
||||
'after' => $this->getAfter(),
|
||||
|
||||
@@ -312,19 +312,12 @@ class DeckProvider implements IProvider {
|
||||
$userLanguage = $this->config->getUserValue($event->getAuthor(), 'core', 'lang', $this->l10nFactory->findLanguage());
|
||||
$userLocale = $this->config->getUserValue($event->getAuthor(), 'core', 'locale', $this->l10nFactory->findLocale());
|
||||
$l10n = $this->l10nFactory->get('deck', $userLanguage, $userLocale);
|
||||
if (is_array($subjectParams['after'])) {
|
||||
// Unluckily there was a time when we stored jsonSerialized date objects in the database
|
||||
// Broken in 1.8.0 and fixed again in 1.8.1
|
||||
$date = new \DateTime($subjectParams['after']['date']);
|
||||
$date->setTimezone(new \DateTimeZone(\date_default_timezone_get()));
|
||||
} else {
|
||||
$date = new \DateTime($subjectParams['after']);
|
||||
$date->setTimezone(new \DateTimeZone(\date_default_timezone_get()));
|
||||
}
|
||||
$date = new \DateTime($subjectParams['after']);
|
||||
$date->setTimezone(new \DateTimeZone(\date_default_timezone_get()));
|
||||
$params['after'] = [
|
||||
'type' => 'highlight',
|
||||
'id' => 'dt:' . $subjectParams['after'],
|
||||
'name' => $l10n->l('datetime', $date),
|
||||
'name' => $l10n->l('datetime', $date)
|
||||
];
|
||||
}
|
||||
return $params;
|
||||
|
||||
@@ -26,13 +26,15 @@ namespace OCA\Deck\AppInfo;
|
||||
use Closure;
|
||||
use Exception;
|
||||
use OC\EventDispatcher\SymfonyAdapter;
|
||||
use OCA\Circles\Events\CircleDestroyedEvent;
|
||||
use OCA\Deck\Activity\CommentEventHandler;
|
||||
use OCA\Deck\Capabilities;
|
||||
use OCA\Deck\Collaboration\Resources\ResourceProvider;
|
||||
use OCA\Deck\Collaboration\Resources\ResourceProviderCard;
|
||||
use OCA\Deck\Dashboard\DeckWidget;
|
||||
use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Db\AclMapper;
|
||||
use OCA\Deck\Db\AssignmentMapper;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Event\AclCreatedEvent;
|
||||
use OCA\Deck\Event\AclDeletedEvent;
|
||||
@@ -41,13 +43,10 @@ use OCA\Deck\Event\CardCreatedEvent;
|
||||
use OCA\Deck\Event\CardDeletedEvent;
|
||||
use OCA\Deck\Event\CardUpdatedEvent;
|
||||
use OCA\Deck\Listeners\BeforeTemplateRenderedListener;
|
||||
use OCA\Deck\Listeners\ParticipantCleanupListener;
|
||||
use OCA\Deck\Listeners\FullTextSearchEventListener;
|
||||
use OCA\Deck\Listeners\ResourceListener;
|
||||
use OCA\Deck\Middleware\DefaultBoardMiddleware;
|
||||
use OCA\Deck\Middleware\ExceptionMiddleware;
|
||||
use OCA\Deck\Notification\Notifier;
|
||||
use OCA\Deck\Reference\CardReferenceProvider;
|
||||
use OCA\Deck\Search\CardCommentProvider;
|
||||
use OCA\Deck\Search\DeckProvider;
|
||||
use OCA\Deck\Service\PermissionService;
|
||||
@@ -58,19 +57,20 @@ use OCP\AppFramework\Bootstrap\IBootContext;
|
||||
use OCP\AppFramework\Bootstrap\IBootstrap;
|
||||
use OCP\AppFramework\Bootstrap\IRegistrationContext;
|
||||
use OCP\AppFramework\Http\Events\BeforeTemplateRenderedEvent;
|
||||
use OCP\Collaboration\Reference\RenderReferenceEvent;
|
||||
use OCP\Collaboration\Resources\IProviderManager;
|
||||
use OCP\Comments\CommentsEntityEvent;
|
||||
use OCP\Comments\ICommentsManager;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Group\Events\GroupDeletedEvent;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IRequest;
|
||||
use OCP\Server;
|
||||
use OCP\IGroup;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IServerContainer;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Notification\IManager as NotificationManager;
|
||||
use OCP\Share\IManager;
|
||||
use OCP\User\Events\UserDeletedEvent;
|
||||
use OCP\Util;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
@@ -79,19 +79,17 @@ class Application extends App implements IBootstrap {
|
||||
|
||||
public const COMMENT_ENTITY_TYPE = 'deckCard';
|
||||
|
||||
/** @var IServerContainer */
|
||||
private $server;
|
||||
|
||||
public function __construct(array $urlParams = []) {
|
||||
parent::__construct(self::APP_ID, $urlParams);
|
||||
|
||||
// TODO move this back to ::register after fixing the autoload issue
|
||||
// (and use a listener class)
|
||||
$container = $this->getContainer();
|
||||
$eventDispatcher = $container->get(IEventDispatcher::class);
|
||||
$eventDispatcher->addListener(RenderReferenceEvent::class, function () {
|
||||
Util::addScript(self::APP_ID, self::APP_ID . '-card-reference');
|
||||
});
|
||||
$this->server = \OC::$server;
|
||||
}
|
||||
|
||||
public function boot(IBootContext $context): void {
|
||||
$context->injectFn(Closure::fromCallable([$this, 'registerUserGroupHooks']));
|
||||
$context->injectFn(Closure::fromCallable([$this, 'registerCommentsEntity']));
|
||||
$context->injectFn(Closure::fromCallable([$this, 'registerCommentsEventHandler']));
|
||||
$context->injectFn(Closure::fromCallable([$this, 'registerNotifications']));
|
||||
@@ -126,12 +124,8 @@ class Application extends App implements IBootstrap {
|
||||
$context->registerSearchProvider(CardCommentProvider::class);
|
||||
$context->registerDashboardWidget(DeckWidget::class);
|
||||
|
||||
// reference widget
|
||||
$context->registerReferenceProvider(CardReferenceProvider::class);
|
||||
// $context->registerEventListener(RenderReferenceEvent::class, CardReferenceListener::class);
|
||||
|
||||
$context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class);
|
||||
|
||||
|
||||
// Event listening for full text search indexing
|
||||
$context->registerEventListener(CardCreatedEvent::class, FullTextSearchEventListener::class);
|
||||
$context->registerEventListener(CardUpdatedEvent::class, FullTextSearchEventListener::class);
|
||||
@@ -139,26 +133,54 @@ class Application extends App implements IBootstrap {
|
||||
$context->registerEventListener(AclCreatedEvent::class, FullTextSearchEventListener::class);
|
||||
$context->registerEventListener(AclUpdatedEvent::class, FullTextSearchEventListener::class);
|
||||
$context->registerEventListener(AclDeletedEvent::class, FullTextSearchEventListener::class);
|
||||
|
||||
// Handling cache invalidation for collections
|
||||
$context->registerEventListener(AclCreatedEvent::class, ResourceListener::class);
|
||||
$context->registerEventListener(AclDeletedEvent::class, ResourceListener::class);
|
||||
|
||||
$context->registerEventListener(UserDeletedEvent::class, ParticipantCleanupListener::class);
|
||||
$context->registerEventListener(GroupDeletedEvent::class, ParticipantCleanupListener::class);
|
||||
$context->registerEventListener(CircleDestroyedEvent::class, ParticipantCleanupListener::class);
|
||||
}
|
||||
|
||||
public function registerNotifications(NotificationManager $notificationManager): void {
|
||||
$notificationManager->registerNotifierService(Notifier::class);
|
||||
}
|
||||
|
||||
private function registerUserGroupHooks(IUserManager $userManager, IGroupManager $groupManager): void {
|
||||
$container = $this->getContainer();
|
||||
// Delete user/group acl entries when they get deleted
|
||||
$userManager->listen('\OC\User', 'postDelete', static function (IUser $user) use ($container) {
|
||||
// delete existing acl entries for deleted user
|
||||
/** @var AclMapper $aclMapper */
|
||||
$aclMapper = $container->query(AclMapper::class);
|
||||
$acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_USER, $user->getUID());
|
||||
foreach ($acls as $acl) {
|
||||
$aclMapper->delete($acl);
|
||||
}
|
||||
// delete existing user assignments
|
||||
$assignmentMapper = $container->query(AssignmentMapper::class);
|
||||
$assignments = $assignmentMapper->findByParticipant($user->getUID());
|
||||
foreach ($assignments as $assignment) {
|
||||
$assignmentMapper->delete($assignment);
|
||||
}
|
||||
|
||||
/** @var BoardMapper $boardMapper */
|
||||
$boardMapper = $container->query(BoardMapper::class);
|
||||
$boards = $boardMapper->findAllByOwner($user->getUID());
|
||||
foreach ($boards as $board) {
|
||||
$boardMapper->delete($board);
|
||||
}
|
||||
});
|
||||
|
||||
$groupManager->listen('\OC\Group', 'postDelete', static function (IGroup $group) use ($container) {
|
||||
/** @var AclMapper $aclMapper */
|
||||
$aclMapper = $container->query(AclMapper::class);
|
||||
$aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID());
|
||||
$acls = $aclMapper->findByParticipant(Acl::PERMISSION_TYPE_GROUP, $group->getGID());
|
||||
foreach ($acls as $acl) {
|
||||
$aclMapper->delete($acl);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function registerCommentsEntity(IEventDispatcher $eventDispatcher): void {
|
||||
$eventDispatcher->addListener(CommentsEntityEvent::EVENT_ENTITY, function (CommentsEntityEvent $event) {
|
||||
$event->addEntityCollection(self::COMMENT_ENTITY_TYPE, function ($name) {
|
||||
/** @var CardMapper */
|
||||
$cardMapper = $this->getContainer()->get(CardMapper::class);
|
||||
/** @var PermissionService $permissionService */
|
||||
$permissionService = $this->getContainer()->get(PermissionService::class);
|
||||
|
||||
try {
|
||||
@@ -181,7 +203,7 @@ class Application extends App implements IBootstrap {
|
||||
$resourceManager->registerResourceProvider(ResourceProviderCard::class);
|
||||
|
||||
$symfonyAdapter->addListener('\OCP\Collaboration\Resources::loadAdditionalScripts', static function () {
|
||||
if (strpos(Server::get(IRequest::class)->getPathInfo(), '/call/') === 0) {
|
||||
if (strpos(\OC::$server->getRequest()->getPathInfo(), '/call/') === 0) {
|
||||
// Talk integration has its own entrypoint which already includes collections handling
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -32,23 +32,20 @@ use OCP\AppFramework\QueryException;
|
||||
use OCP\Collaboration\Resources\IManager;
|
||||
use OCP\Collaboration\Resources\IProvider;
|
||||
use OCP\Collaboration\Resources\IResource;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\Server;
|
||||
|
||||
class ResourceProvider implements IProvider {
|
||||
public const RESOURCE_TYPE = 'deck';
|
||||
|
||||
private BoardMapper $boardMapper;
|
||||
private PermissionService $permissionService;
|
||||
private IURLGenerator $urlGenerator;
|
||||
private $boardMapper;
|
||||
private $permissionService;
|
||||
|
||||
protected array $nodes = [];
|
||||
/** @var array */
|
||||
protected $nodes = [];
|
||||
|
||||
public function __construct(BoardMapper $boardMapper, PermissionService $permissionService, IURLGenerator $urlGenerator) {
|
||||
public function __construct(BoardMapper $boardMapper, PermissionService $permissionService) {
|
||||
$this->boardMapper = $boardMapper;
|
||||
$this->permissionService = $permissionService;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,14 +70,14 @@ class ResourceProvider implements IProvider {
|
||||
*/
|
||||
public function getResourceRichObject(IResource $resource): array {
|
||||
$board = $this->getBoard($resource);
|
||||
$link = $this->urlGenerator->linkToRoute('deck.page.index') . '#/board/' . $resource->getId();
|
||||
$link = \OC::$server->getURLGenerator()->linkToRoute('deck.page.index') . '#/board/' . $resource->getId();
|
||||
|
||||
return [
|
||||
'type' => self::RESOURCE_TYPE,
|
||||
'id' => $resource->getId(),
|
||||
'name' => $board->getTitle(),
|
||||
'link' => $link,
|
||||
'iconUrl' => $this->urlGenerator->imagePath('deck', 'deck-dark.svg')
|
||||
'iconUrl' => \OC::$server->getURLGenerator()->imagePath('deck', 'deck-dark.svg')
|
||||
];
|
||||
}
|
||||
|
||||
@@ -121,7 +118,7 @@ class ResourceProvider implements IProvider {
|
||||
public function invalidateAccessCache($boardId = null) {
|
||||
try {
|
||||
/** @var IManager $resourceManager */
|
||||
$resourceManager = Server::get(IManager::class);
|
||||
$resourceManager = \OC::$server->query(IManager::class);
|
||||
} catch (QueryException $e) {
|
||||
}
|
||||
if ($boardId !== null) {
|
||||
|
||||
@@ -37,16 +37,24 @@ use OCP\Collaboration\Resources\IResource;
|
||||
use OCP\Collaboration\Resources\ResourceException;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUser;
|
||||
use OCP\Server;
|
||||
|
||||
class ResourceProviderCard implements IProvider {
|
||||
public const RESOURCE_TYPE = 'deck-card';
|
||||
|
||||
private CardMapper $cardMapper;
|
||||
private BoardMapper $boardMapper;
|
||||
private PermissionService $permissionService;
|
||||
private IURLGenerator $urlGenerator;
|
||||
protected array $nodes = [];
|
||||
/** @var CardMapper */
|
||||
private $cardMapper;
|
||||
|
||||
/** @var BoardMapper */
|
||||
private $boardMapper;
|
||||
|
||||
/** @var PermissionService */
|
||||
private $permissionService;
|
||||
|
||||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
|
||||
/** @var array */
|
||||
protected $nodes = [];
|
||||
|
||||
public function __construct(CardMapper $cardMapper, BoardMapper $boardMapper, PermissionService $permissionService, IURLGenerator $urlGenerator) {
|
||||
$this->cardMapper = $cardMapper;
|
||||
@@ -139,7 +147,7 @@ class ResourceProviderCard implements IProvider {
|
||||
public function invalidateAccessCache($cardId = null) {
|
||||
try {
|
||||
/** @var IManager $resourceManager */
|
||||
$resourceManager = Server::get(IManager::class);
|
||||
$resourceManager = \OC::$server->query(IManager::class);
|
||||
} catch (QueryException $e) {
|
||||
}
|
||||
if ($cardId !== null) {
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 Vitor Mattos <vitor@php.rio>
|
||||
*
|
||||
* @author Vitor Mattos <vitor@php.rio>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Deck\Command;
|
||||
|
||||
use OCA\Deck\Service\Importer\BoardImportCommandService;
|
||||
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 BoardImport extends Command {
|
||||
private BoardImportCommandService $boardImportCommandService;
|
||||
|
||||
public function __construct(
|
||||
BoardImportCommandService $boardImportCommandService
|
||||
) {
|
||||
$this->boardImportCommandService = $boardImportCommandService;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function configure() {
|
||||
$allowedSystems = $this->boardImportCommandService->getAllowedImportSystems();
|
||||
$names = array_column($allowedSystems, 'name');
|
||||
$this
|
||||
->setName('deck:import')
|
||||
->setDescription('Import data')
|
||||
->addOption(
|
||||
'system',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Source system for import. Available options: ' . implode(', ', $names) . '.',
|
||||
null
|
||||
)
|
||||
->addOption(
|
||||
'config',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Configuration json file.',
|
||||
'config.json'
|
||||
)
|
||||
->addOption(
|
||||
'data',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL,
|
||||
'Data file to import.',
|
||||
'data.json'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int {
|
||||
$this
|
||||
->boardImportCommandService
|
||||
->setInput($input)
|
||||
->setOutput($output)
|
||||
->setCommand($this)
|
||||
->import();
|
||||
$output->writeln('Done!');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,6 @@ use OCA\Deck\Db\AssignmentMapper;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Db\StackMapper;
|
||||
use OCA\Deck\Model\CardDetails;
|
||||
use OCA\Deck\Service\BoardService;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
@@ -102,9 +101,7 @@ class UserExport extends Command {
|
||||
$fullCard = $this->cardMapper->find($card->getId());
|
||||
$assignedUsers = $this->assignedUsersMapper->findAll($card->getId());
|
||||
$fullCard->setAssignedUsers($assignedUsers);
|
||||
|
||||
$cardDetails = new CardDetails($fullCard, $fullBoard);
|
||||
$data[$board->getId()]['stacks'][$stack->getId()]['cards'][] = $cardDetails->jsonSerialize();
|
||||
$data[$board->getId()]['stacks'][$stack->getId()]['cards'][] = (array)$fullCard->jsonSerialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 Vitor Mattos <vitor@php.rio>
|
||||
*
|
||||
* @author Vitor Mattos <vitor@php.rio>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Service\Importer\BoardImportService;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
use OCP\IRequest;
|
||||
|
||||
class BoardImportApiController extends OCSController {
|
||||
/** @var BoardImportService */
|
||||
private $boardImportService;
|
||||
/** @var string */
|
||||
private $userId;
|
||||
|
||||
public function __construct(
|
||||
string $appName,
|
||||
IRequest $request,
|
||||
BoardImportService $boardImportService,
|
||||
string $userId
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->boardImportService = $boardImportService;
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function import(string $system, array $config, array $data): DataResponse {
|
||||
$this->boardImportService->setSystem($system);
|
||||
$config = json_decode(json_encode($config));
|
||||
$config->owner = $this->userId;
|
||||
$this->boardImportService->setConfigInstance($config);
|
||||
$this->boardImportService->setData(json_decode(json_encode($data)));
|
||||
$this->boardImportService->import();
|
||||
return new DataResponse($this->boardImportService->getBoard(), Http::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getAllowedSystems(): DataResponse {
|
||||
$allowedSystems = $this->boardImportService->getAllowedImportSystems();
|
||||
return new DataResponse($allowedSystems, Http::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @CORS
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function getConfigSchema(string $name): DataResponse {
|
||||
$this->boardImportService->setSystem($name);
|
||||
$this->boardImportService->validateSystem();
|
||||
$jsonSchemaPath = json_decode(file_get_contents($this->boardImportService->getJsonSchemaPath()));
|
||||
return new DataResponse($jsonSchemaPath, Http::STATUS_OK);
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,7 @@ use OCA\Deck\Service\PermissionService;
|
||||
use OCA\Files\Event\LoadSidebar;
|
||||
use OCA\Viewer\Event\LoadViewer;
|
||||
use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||
use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent as CollaborationResourcesEvent;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\IConfig;
|
||||
use OCP\IInitialStateService;
|
||||
use OCP\IRequest;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
@@ -43,17 +41,16 @@ use OCA\Deck\Db\Acl;
|
||||
use OCA\Deck\Service\CardService;
|
||||
|
||||
class PageController extends Controller {
|
||||
private PermissionService $permissionService;
|
||||
private IInitialStateService $initialState;
|
||||
private ConfigService $configService;
|
||||
private IEventDispatcher $eventDispatcher;
|
||||
private CardMapper $cardMapper;
|
||||
private IURLGenerator $urlGenerator;
|
||||
private CardService $cardService;
|
||||
private IConfig $config;
|
||||
private $permissionService;
|
||||
private $initialState;
|
||||
private $configService;
|
||||
private $eventDispatcher;
|
||||
private $cardMapper;
|
||||
private $urlGenerator;
|
||||
private $cardService;
|
||||
|
||||
public function __construct(
|
||||
string $AppName,
|
||||
$AppName,
|
||||
IRequest $request,
|
||||
PermissionService $permissionService,
|
||||
IInitialStateService $initialStateService,
|
||||
@@ -61,8 +58,7 @@ class PageController extends Controller {
|
||||
IEventDispatcher $eventDispatcher,
|
||||
CardMapper $cardMapper,
|
||||
IURLGenerator $urlGenerator,
|
||||
CardService $cardService,
|
||||
IConfig $config
|
||||
CardService $cardService
|
||||
) {
|
||||
parent::__construct($AppName, $request);
|
||||
|
||||
@@ -73,7 +69,6 @@ class PageController extends Controller {
|
||||
$this->cardMapper = $cardMapper;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->cardService = $cardService;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,17 +84,13 @@ class PageController extends Controller {
|
||||
$this->initialState->provideInitialState(Application::APP_ID, 'config', $this->configService->getAll());
|
||||
|
||||
$this->eventDispatcher->dispatchTyped(new LoadSidebar());
|
||||
$this->eventDispatcher->dispatchTyped(new CollaborationResourcesEvent());
|
||||
if (class_exists(LoadViewer::class)) {
|
||||
$this->eventDispatcher->dispatchTyped(new LoadViewer());
|
||||
}
|
||||
|
||||
$response = new TemplateResponse('deck', 'main', [
|
||||
'id-app-content' => '#app-content-vue',
|
||||
'id-app-navigation' => '#app-navigation-vue',
|
||||
]);
|
||||
$response = new TemplateResponse('deck', 'main');
|
||||
|
||||
if ($this->config->getSystemValueBool('debug', false)) {
|
||||
if (\OC::$server->getConfig()->getSystemValueBool('debug', false)) {
|
||||
$csp = new ContentSecurityPolicy();
|
||||
$csp->addAllowedConnectDomain('*');
|
||||
$csp->addAllowedScriptDomain('*');
|
||||
|
||||
@@ -27,7 +27,6 @@ declare(strict_types=1);
|
||||
namespace OCA\Deck\Controller;
|
||||
|
||||
use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Model\CardDetails;
|
||||
use OCA\Deck\Service\SearchService;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\OCSController;
|
||||
@@ -51,12 +50,9 @@ class SearchController extends OCSController {
|
||||
public function search(string $term, ?int $limit = null, ?int $cursor = null): DataResponse {
|
||||
$cards = $this->searchService->searchCards($term, $limit, $cursor);
|
||||
return new DataResponse(array_map(function (Card $card) {
|
||||
$board = $card->getRelatedBoard();
|
||||
$json = (new CardDetails($card, $board))->jsonSerialize();
|
||||
|
||||
$json['relatedBoard'] = $board;
|
||||
$json = $card->jsonSerialize();
|
||||
$json['relatedStack'] = $card->getRelatedStack();
|
||||
|
||||
$json['relatedBoard'] = $card->getRelatedBoard();
|
||||
return $json;
|
||||
}, $cards));
|
||||
}
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
|
||||
namespace OCA\Deck\Cron;
|
||||
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\BackgroundJob\Job;
|
||||
use OC\BackgroundJob\Job;
|
||||
use OCA\Deck\Activity\ActivityManager;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
|
||||
@@ -36,8 +35,7 @@ class CardDescriptionActivity extends Job {
|
||||
/** @var CardMapper */
|
||||
private $cardMapper;
|
||||
|
||||
public function __construct(ITimeFactory $time, ActivityManager $activityManager, CardMapper $cardMapper) {
|
||||
parent::__construct($time);
|
||||
public function __construct(ActivityManager $activityManager, CardMapper $cardMapper) {
|
||||
$this->activityManager = $activityManager;
|
||||
$this->cardMapper = $cardMapper;
|
||||
}
|
||||
|
||||
@@ -24,35 +24,25 @@
|
||||
|
||||
namespace OCA\Deck\Cron;
|
||||
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\BackgroundJob\TimedJob;
|
||||
use OC\BackgroundJob\Job;
|
||||
use OCA\Deck\Db\AttachmentMapper;
|
||||
use OCA\Deck\Db\BoardMapper;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\InvalidAttachmentType;
|
||||
use OCA\Deck\Service\AttachmentService;
|
||||
use OCP\BackgroundJob\IJob;
|
||||
|
||||
class DeleteCron extends TimedJob {
|
||||
class DeleteCron extends Job {
|
||||
|
||||
/** @var BoardMapper */
|
||||
private $boardMapper;
|
||||
/** @var CardMapper */
|
||||
private $cardMapper;
|
||||
/** @var AttachmentService */
|
||||
private $attachmentService;
|
||||
/** @var AttachmentMapper */
|
||||
private $attachmentMapper;
|
||||
|
||||
public function __construct(ITimeFactory $time, BoardMapper $boardMapper, CardMapper $cardMapper, AttachmentService $attachmentService, AttachmentMapper $attachmentMapper) {
|
||||
parent::__construct($time);
|
||||
public function __construct(BoardMapper $boardMapper, AttachmentService $attachmentService, AttachmentMapper $attachmentMapper) {
|
||||
$this->boardMapper = $boardMapper;
|
||||
$this->cardMapper = $cardMapper;
|
||||
$this->attachmentService = $attachmentService;
|
||||
$this->attachmentMapper = $attachmentMapper;
|
||||
|
||||
$this->setInterval(60 * 60 * 24);
|
||||
$this->setTimeSensitivity(IJob::TIME_INSENSITIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,12 +55,6 @@ class DeleteCron extends TimedJob {
|
||||
$this->boardMapper->delete($board);
|
||||
}
|
||||
|
||||
$timeLimit = time() - (60 * 5); // 5 min buffer
|
||||
$cards = $this->cardMapper->findToDelete($timeLimit, 500);
|
||||
foreach ($cards as $card) {
|
||||
$this->cardMapper->delete($card);
|
||||
}
|
||||
|
||||
$attachments = $this->attachmentMapper->findToDelete();
|
||||
foreach ($attachments as $attachment) {
|
||||
try {
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
|
||||
namespace OCA\Deck\Cron;
|
||||
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\BackgroundJob\Job;
|
||||
use OC\BackgroundJob\Job;
|
||||
use OCA\Deck\Db\Card;
|
||||
use OCA\Deck\Db\CardMapper;
|
||||
use OCA\Deck\Notification\NotificationHelper;
|
||||
@@ -41,12 +40,10 @@ class ScheduledNotifications extends Job {
|
||||
protected $logger;
|
||||
|
||||
public function __construct(
|
||||
ITimeFactory $time,
|
||||
CardMapper $cardMapper,
|
||||
NotificationHelper $notificationHelper,
|
||||
ILogger $logger
|
||||
) {
|
||||
parent::__construct($time);
|
||||
$this->cardMapper = $cardMapper;
|
||||
$this->notificationHelper = $notificationHelper;
|
||||
$this->logger = $logger;
|
||||
|
||||
@@ -26,34 +26,18 @@ declare(strict_types=1);
|
||||
|
||||
namespace OCA\Deck\Dashboard;
|
||||
|
||||
use DateTime;
|
||||
use OCA\Deck\AppInfo\Application;
|
||||
use OCA\Deck\Db\Label;
|
||||
use OCA\Deck\Service\OverviewService;
|
||||
use OCP\Dashboard\IAPIWidget;
|
||||
use OCP\Dashboard\IButtonWidget;
|
||||
use OCP\Dashboard\IIconWidget;
|
||||
use OCP\Dashboard\Model\WidgetButton;
|
||||
use OCP\Dashboard\Model\WidgetItem;
|
||||
use OCP\IDateTimeFormatter;
|
||||
use OCP\Dashboard\IWidget;
|
||||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\Util;
|
||||
|
||||
class DeckWidget implements IAPIWidget, IButtonWidget, IIconWidget {
|
||||
private IL10N $l10n;
|
||||
private OverviewService $dashboardService;
|
||||
private IURLGenerator $urlGenerator;
|
||||
private IDateTimeFormatter $dateTimeFormatter;
|
||||
class DeckWidget implements IWidget {
|
||||
|
||||
public function __construct(IL10N $l10n,
|
||||
OverviewService $dashboardService,
|
||||
IDateTimeFormatter $dateTimeFormatter,
|
||||
IURLGenerator $urlGenerator) {
|
||||
/**
|
||||
* @var IL10N
|
||||
*/
|
||||
private $l10n;
|
||||
|
||||
public function __construct(IL10N $l10n) {
|
||||
$this->l10n = $l10n;
|
||||
$this->dashboardService = $dashboardService;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->dateTimeFormatter = $dateTimeFormatter;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,88 +68,17 @@ class DeckWidget implements IAPIWidget, IButtonWidget, IIconWidget {
|
||||
return 'icon-deck';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getIconUrl(): string {
|
||||
return $this->urlGenerator->getAbsoluteURL(
|
||||
$this->urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getUrl(): ?string {
|
||||
return $this->urlGenerator->getAbsoluteURL(
|
||||
$this->urlGenerator->linkToRoute(Application::APP_ID . '.page.index')
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function load(): void {
|
||||
Util::addScript('deck', 'deck-dashboard');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getItems(string $userId, ?string $since = null, int $limit = 7): array {
|
||||
$upcomingCards = $this->dashboardService->findUpcomingCards($userId);
|
||||
$nowTimestamp = (new Datetime())->getTimestamp();
|
||||
$sinceTimestamp = $since !== null ? (new Datetime($since))->getTimestamp() : null;
|
||||
$upcomingCards = array_filter($upcomingCards, static function (array $card) use ($nowTimestamp, $sinceTimestamp) {
|
||||
if ($card['duedate']) {
|
||||
$ts = (new Datetime($card['duedate']))->getTimestamp();
|
||||
return $ts > $nowTimestamp && ($sinceTimestamp === null || $ts > $sinceTimestamp);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
usort($upcomingCards, static function ($a, $b) {
|
||||
$a = new Datetime($a['duedate']);
|
||||
$ta = $a->getTimestamp();
|
||||
$b = new Datetime($b['duedate']);
|
||||
$tb = $b->getTimestamp();
|
||||
return ($ta > $tb) ? 1 : -1;
|
||||
});
|
||||
$upcomingCards = array_slice($upcomingCards, 0, $limit);
|
||||
$urlGenerator = $this->urlGenerator;
|
||||
$dateTimeFormatter = $this->dateTimeFormatter;
|
||||
return array_map(static function (array $card) use ($urlGenerator, $dateTimeFormatter) {
|
||||
$formattedDueDate = $dateTimeFormatter->formatDateTime(new DateTime($card['duedate']));
|
||||
return new WidgetItem(
|
||||
$card['title'] . ' (' . $formattedDueDate . ')',
|
||||
implode(
|
||||
', ',
|
||||
array_map(static function (Label $label) {
|
||||
return $label->jsonSerialize()['title'];
|
||||
}, $card['labels'])
|
||||
),
|
||||
$urlGenerator->getAbsoluteURL(
|
||||
$urlGenerator->linkToRoute(Application::APP_ID . '.page.redirectToCard', ['cardId' => $card['id']])
|
||||
),
|
||||
$urlGenerator->getAbsoluteURL(
|
||||
$urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg')
|
||||
),
|
||||
$card['duedate']
|
||||
);
|
||||
}, $upcomingCards);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getWidgetButtons(string $userId): array {
|
||||
return [
|
||||
new WidgetButton(
|
||||
WidgetButton::TYPE_MORE,
|
||||
$this->urlGenerator->getAbsoluteURL(
|
||||
$this->urlGenerator->linkToRoute(Application::APP_ID . '.page.index')
|
||||
),
|
||||
$this->l10n->t('Load more')
|
||||
),
|
||||
];
|
||||
\OCP\Util::addScript('deck', 'deck-dashboard');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,46 +33,18 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
parent::__construct($db, 'deck_board_acl', Acl::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Acl[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll($boardId, $limit = null, $offset = null) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage')
|
||||
->from('deck_board_acl')
|
||||
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
|
||||
->setMaxResults($limit)
|
||||
->setFirstResult($offset);
|
||||
|
||||
return $this->findEntities($qb);
|
||||
$sql = 'SELECT id, board_id, type, participant, permission_edit, permission_share, permission_manage FROM `*PREFIX*deck_board_acl` WHERE `board_id` = ? ';
|
||||
return $this->findEntities($sql, [$boardId], $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $userId
|
||||
* @param numeric $id
|
||||
* @return bool
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function isOwner($userId, $id): bool {
|
||||
$aclId = $id;
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('acl.id')
|
||||
->from($this->getTableName(), 'acl')
|
||||
->innerJoin('acl', 'deck_boards', 'b', 'acl.board_id = b.id')
|
||||
->where($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)))
|
||||
->andWhere($qb->expr()->eq('acl.id', $qb->createNamedParameter($aclId, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
return count($qb->executeQuery()->fetchAll()) > 0;
|
||||
public function isOwner($userId, $aclId): bool {
|
||||
$sql = 'SELECT owner FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_board_acl` WHERE id = ?)';
|
||||
$stmt = $this->execute($sql, [$aclId]);
|
||||
$row = $stmt->fetch();
|
||||
return ($row['owner'] === $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $id
|
||||
* @return int|null
|
||||
*/
|
||||
public function findBoardId($id): ?int {
|
||||
try {
|
||||
$entity = $this->find($id);
|
||||
@@ -82,21 +54,9 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
* @param string $participant
|
||||
* @return Acl[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findByParticipant($type, $participant): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
->where($qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('participant', $qb->createNamedParameter($participant, IQueryBuilder::PARAM_STR)));
|
||||
|
||||
return $this->findEntities($qb);
|
||||
$sql = 'SELECT * from *PREFIX*deck_board_acl WHERE type = ? AND participant = ?';
|
||||
return $this->findEntities($sql, [$type, $participant]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,12 +70,4 @@ class AclMapper extends DeckMapper implements IPermissionMapper {
|
||||
->andWhere($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)));
|
||||
$qb->executeStatement();
|
||||
}
|
||||
|
||||
public function findByType(int $type): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from('deck_board_acl')
|
||||
->where($qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,9 @@ class AssignmentMapper extends QBMapper implements IPermissionMapper {
|
||||
$this->circleService = $circleService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Assignment[]
|
||||
*/
|
||||
public function findAll(int $cardId): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
@@ -77,8 +80,8 @@ class AssignmentMapper extends QBMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
|
||||
public function isOwner($userId, $id): bool {
|
||||
return $this->cardMapper->isOwner($userId, $id);
|
||||
public function isOwner($userId, $cardId): bool {
|
||||
return $this->cardMapper->isOwner($userId, $cardId);
|
||||
}
|
||||
|
||||
public function findBoardId($id): ?int {
|
||||
|
||||
@@ -30,6 +30,7 @@ use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUserManager;
|
||||
use PDO;
|
||||
|
||||
class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
private $cardMapper;
|
||||
@@ -51,53 +52,70 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @return Attachment
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws \OCP\DB\Exception
|
||||
* @param $id
|
||||
* @return Entity|Attachment
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
|
||||
*/
|
||||
public function find($id) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
->from('deck_attachment')
|
||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
return $this->findEntity($qb);
|
||||
$cursor = $qb->execute();
|
||||
$row = $cursor->fetch(PDO::FETCH_ASSOC);
|
||||
if ($row === false) {
|
||||
$cursor->closeCursor();
|
||||
throw new DoesNotExistException('Did expect one result but found none when executing query: ' . $qb->getSQL());
|
||||
}
|
||||
|
||||
$row2 = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
if ($row2 !== false) {
|
||||
throw new MultipleObjectsReturnedException('Did not expect more than one result when executing query: ' . $qb->getSQL());
|
||||
}
|
||||
|
||||
return $this->mapRowToEntity($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $cardId
|
||||
* @param string $data
|
||||
* @return Attachment
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findByData($cardId, $data) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
->from('deck_attachment')
|
||||
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('data', $qb->createNamedParameter($data, IQueryBuilder::PARAM_STR)));
|
||||
|
||||
return $this->findEntity($qb);
|
||||
$cursor = $qb->execute();
|
||||
$row = $cursor->fetch(PDO::FETCH_ASSOC);
|
||||
if ($row === false) {
|
||||
$cursor->closeCursor();
|
||||
throw new DoesNotExistException('Did expect one result but found none when executing query: ' . $qb->getSQL());
|
||||
}
|
||||
$cursor->closeCursor();
|
||||
return $this->mapRowToEntity($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all attachments for a card
|
||||
*
|
||||
* @param $cardId
|
||||
* @return Entity[]
|
||||
* @throws \OCP\DB\Exception
|
||||
* @return array
|
||||
*/
|
||||
public function findAll($cardId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
->from('deck_attachment')
|
||||
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
|
||||
return $this->findEntities($qb);
|
||||
$entities = [];
|
||||
$cursor = $qb->execute();
|
||||
while ($row = $cursor->fetch()) {
|
||||
$entities[] = $this->mapRowToEntity($row);
|
||||
}
|
||||
$cursor->closeCursor();
|
||||
return $entities;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +128,7 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
$timeLimit = time() - (60 * 5);
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
->from('deck_attachment')
|
||||
->where($qb->expr()->gt('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
|
||||
if ($withOffset) {
|
||||
$qb
|
||||
@@ -121,7 +139,13 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper {
|
||||
->andWhere($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)));
|
||||
}
|
||||
|
||||
return $this->findEntities($qb);
|
||||
$entities = [];
|
||||
$cursor = $qb->execute();
|
||||
while ($row = $cursor->fetch()) {
|
||||
$entities[] = $this->mapRowToEntity($row);
|
||||
}
|
||||
$cursor->closeCursor();
|
||||
return $entities;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,14 +23,6 @@
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
/**
|
||||
* @method int getId()
|
||||
* @method string getTitle()
|
||||
* @method int getShared()
|
||||
* @method bool getArchived()
|
||||
* @method int getDeletedAt()
|
||||
* @method int getLastModified()
|
||||
*/
|
||||
class Board extends RelationalEntity {
|
||||
protected $title;
|
||||
protected $owner;
|
||||
@@ -66,7 +58,7 @@ class Board extends RelationalEntity {
|
||||
$this->shared = -1;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array {
|
||||
public function jsonSerialize() {
|
||||
$json = parent::jsonSerialize();
|
||||
if ($this->shared === -1) {
|
||||
unset($json['shared']);
|
||||
|
||||
@@ -42,9 +42,9 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
|
||||
private $circlesService;
|
||||
private $logger;
|
||||
|
||||
/** @var CappedMemoryCache<Board[]> */
|
||||
/** @var CappedMemoryCache */
|
||||
private $userBoardCache;
|
||||
/** @var CappedMemoryCache<Board> */
|
||||
/** @var CappedMemoryCache */
|
||||
private $boardCache;
|
||||
|
||||
public function __construct(
|
||||
@@ -107,47 +107,6 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->boardCache[$id];
|
||||
}
|
||||
|
||||
public function findBoardIds(string $userId): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->selectDistinct('b.id')
|
||||
->from($this->getTableName(), 'b')
|
||||
->leftJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'));
|
||||
|
||||
// Owned by the user
|
||||
$qb->where($qb->expr()->andX(
|
||||
$qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)),
|
||||
));
|
||||
|
||||
// Shared to the user
|
||||
$qb->orWhere($qb->expr()->andX(
|
||||
$qb->expr()->eq('acl.participant', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)),
|
||||
$qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_USER, IQueryBuilder::PARAM_INT)),
|
||||
));
|
||||
|
||||
// Shared to user groups of the user
|
||||
$groupIds = $this->groupManager->getUserGroupIds($this->userManager->get($userId));
|
||||
if (count($groupIds) !== 0) {
|
||||
$qb->orWhere($qb->expr()->andX(
|
||||
$qb->expr()->in('acl.participant', $qb->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)),
|
||||
$qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
|
||||
));
|
||||
}
|
||||
|
||||
// Shared to circles of the user
|
||||
$circles = $this->circlesService->getUserCircles($userId);
|
||||
if (count($circles) !== 0) {
|
||||
$qb->orWhere($qb->expr()->andX(
|
||||
$qb->expr()->in('acl.participant', $qb->createNamedParameter($circles, IQueryBuilder::PARAM_STR_ARRAY)),
|
||||
$qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_CIRCLE, IQueryBuilder::PARAM_INT)),
|
||||
));
|
||||
}
|
||||
|
||||
$result = $qb->executeQuery();
|
||||
return array_map(function (string $id) {
|
||||
return (int)$id;
|
||||
}, $result->fetchAll(\PDO::FETCH_COLUMN));
|
||||
}
|
||||
|
||||
public function findAllForUser(string $userId, ?int $since = null, bool $includeArchived = true, ?int $before = null,
|
||||
?string $term = null): array {
|
||||
$useCache = ($since === -1 && $includeArchived === true && $before === null && $term === null);
|
||||
@@ -172,9 +131,14 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
|
||||
|
||||
/**
|
||||
* Find all boards for a given user
|
||||
*
|
||||
* @param $userId
|
||||
* @param null $limit
|
||||
* @param null $offset
|
||||
* @return array
|
||||
*/
|
||||
public function findAllByUser(string $userId, ?int $limit = null, ?int $offset = null, ?int $since = null,
|
||||
bool $includeArchived = true, ?int $before = null, ?string $term = null): array {
|
||||
bool $includeArchived = true, ?int $before = null, ?string $term = null) {
|
||||
// FIXME this used to be a UNION to get boards owned by $userId and the user shares in one single query
|
||||
// Is it possible with the query builder?
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
@@ -283,9 +247,15 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
|
||||
|
||||
/**
|
||||
* Find all boards for a given user
|
||||
*
|
||||
* @param $userId
|
||||
* @param $groups
|
||||
* @param null $limit
|
||||
* @param null $offset
|
||||
* @return array
|
||||
*/
|
||||
public function findAllByGroups(string $userId, array $groups, ?int $limit = null, ?int $offset = null, ?int $since = null,
|
||||
bool $includeArchived = true, ?int $before = null, ?string $term = null): array {
|
||||
bool $includeArchived = true, ?int $before = null, ?string $term = null) {
|
||||
if (count($groups) <= 0) {
|
||||
return [];
|
||||
}
|
||||
@@ -444,8 +414,8 @@ class BoardMapper extends QBMapper implements IPermissionMapper {
|
||||
return parent::delete($entity);
|
||||
}
|
||||
|
||||
public function isOwner($userId, $id): bool {
|
||||
$board = $this->find($id);
|
||||
public function isOwner($userId, $boardId): bool {
|
||||
$board = $this->find($boardId);
|
||||
return ($board->getOwner() === $userId);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,44 +27,6 @@ use DateTime;
|
||||
use DateTimeZone;
|
||||
use Sabre\VObject\Component\VCalendar;
|
||||
|
||||
/**
|
||||
* @method string getTitle()
|
||||
* @method string getDescription()
|
||||
* @method string getDescriptionPrev()
|
||||
* @method int getStackId()
|
||||
* @method int getOrder()
|
||||
* @method int getLastModified()
|
||||
* @method int getCreatedAt()
|
||||
* @method bool getArchived()
|
||||
* @method bool getNotified()
|
||||
*
|
||||
* @method void setLabels(Label[] $labels)
|
||||
* @method null|Label[] getLabels()
|
||||
*
|
||||
* @method void setAssignedUsers(Assignment[] $users)
|
||||
* @method null|User[] getAssignedUsers()
|
||||
*
|
||||
* @method void setAttachments(Attachment[] $attachments)
|
||||
* @method null|Attachment[] getAttachments()
|
||||
*
|
||||
* @method void setAttachmentCount(int $count)
|
||||
* @method null|int getAttachmentCount()
|
||||
*
|
||||
* @method void setCommentsUnread(int $count)
|
||||
* @method null|int getCommentsUnread()
|
||||
*
|
||||
* @method void setCommentsCount(int $count)
|
||||
* @method null|int getCommentsCount()
|
||||
*
|
||||
* @method void setOwner(string $user)
|
||||
* @method null|string getOwner()
|
||||
*
|
||||
* @method void setRelatedStack(Stack $stack)
|
||||
* @method null|Stack getRelatedStack()
|
||||
*
|
||||
* @method void setRelatedBoard(Board $board)
|
||||
* @method null|Board getRelatedBoard()
|
||||
*/
|
||||
class Card extends RelationalEntity {
|
||||
public const TITLE_MAX_LENGTH = 255;
|
||||
|
||||
@@ -88,7 +50,7 @@ class Card extends RelationalEntity {
|
||||
protected $deletedAt = 0;
|
||||
protected $commentsUnread = 0;
|
||||
protected $commentsCount = 0;
|
||||
|
||||
|
||||
protected $relatedStack = null;
|
||||
protected $relatedBoard = null;
|
||||
|
||||
@@ -108,7 +70,6 @@ class Card extends RelationalEntity {
|
||||
$this->addType('archived', 'boolean');
|
||||
$this->addType('notified', 'boolean');
|
||||
$this->addType('deletedAt', 'integer');
|
||||
$this->addType('duedate', 'datetime');
|
||||
$this->addRelation('labels');
|
||||
$this->addRelation('assignedUsers');
|
||||
$this->addRelation('attachments');
|
||||
@@ -117,7 +78,7 @@ class Card extends RelationalEntity {
|
||||
$this->addRelation('commentsUnread');
|
||||
$this->addRelation('commentsCount');
|
||||
$this->addResolvable('owner');
|
||||
|
||||
|
||||
$this->addRelation('relatedStack');
|
||||
$this->addRelation('relatedBoard');
|
||||
}
|
||||
@@ -126,6 +87,51 @@ class Card extends RelationalEntity {
|
||||
$this->databaseType = $type;
|
||||
}
|
||||
|
||||
public function getDuedate($isoFormat = false) {
|
||||
if ($this->duedate === null) {
|
||||
return null;
|
||||
}
|
||||
$dt = new DateTime($this->duedate);
|
||||
if (!$isoFormat && $this->databaseType === 'mysql') {
|
||||
return $dt->format('Y-m-d H:i:s');
|
||||
}
|
||||
return $dt->format('c');
|
||||
}
|
||||
|
||||
public function jsonSerialize() {
|
||||
$json = parent::jsonSerialize();
|
||||
$json['overdue'] = self::DUEDATE_FUTURE;
|
||||
$due = strtotime($this->duedate);
|
||||
|
||||
$today = new DateTime();
|
||||
$today->setTime(0, 0);
|
||||
|
||||
$match_date = new DateTime($this->duedate);
|
||||
|
||||
$match_date->setTime(0, 0);
|
||||
|
||||
$diff = $today->diff($match_date);
|
||||
$diffDays = (integer) $diff->format('%R%a'); // Extract days count in interval
|
||||
|
||||
if ($due !== false) {
|
||||
if ($diffDays === 1) {
|
||||
$json['overdue'] = self::DUEDATE_NEXT;
|
||||
}
|
||||
if ($diffDays === 0) {
|
||||
$json['overdue'] = self::DUEDATE_NOW;
|
||||
}
|
||||
if ($diffDays < 0) {
|
||||
$json['overdue'] = self::DUEDATE_OVERDUE;
|
||||
}
|
||||
}
|
||||
$json['duedate'] = $this->getDuedate(true);
|
||||
unset($json['notified']);
|
||||
unset($json['descriptionPrev']);
|
||||
unset($json['relatedStack']);
|
||||
unset($json['relatedBoard']);
|
||||
return $json;
|
||||
}
|
||||
|
||||
public function getCalendarObject(): VCalendar {
|
||||
$calendar = new VCalendar();
|
||||
$event = $calendar->createComponent('VTODO');
|
||||
@@ -134,7 +140,7 @@ class Card extends RelationalEntity {
|
||||
$creationDate = new DateTime();
|
||||
$creationDate->setTimestamp($this->createdAt);
|
||||
$event->DTSTAMP = $creationDate;
|
||||
$event->DUE = new DateTime($this->getDuedate()->format('c'), new DateTimeZone('UTC'));
|
||||
$event->DUE = new DateTime($this->getDuedate(true), new DateTimeZone('UTC'));
|
||||
}
|
||||
$event->add('RELATED-TO', 'deck-stack-' . $this->getStackId());
|
||||
|
||||
|
||||
@@ -177,17 +177,6 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $qb;
|
||||
}
|
||||
|
||||
public function findToDelete($timeLimit, $limit = null) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'title', 'owner', 'archived', 'deleted_at', 'last_modified')
|
||||
->from('deck_cards')
|
||||
->where($qb->expr()->gt('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->lt('deleted_at', $qb->createNamedParameter($timeLimit, IQueryBuilder::PARAM_INT)))
|
||||
->orderBy('deleted_at')
|
||||
->setMaxResults($limit);
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
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)))
|
||||
@@ -238,21 +227,6 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
public function findAllByBoardId(int $boardId, ?int $limit = null, ?int $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.*')
|
||||
->from('deck_cards', 'c')
|
||||
->innerJoin('c', 'deck_stacks', 's', 's.id = c.stack_id')
|
||||
->innerJoin('s', 'deck_boards', 'b', 'b.id = s.board_id')
|
||||
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('archived', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
|
||||
->setMaxResults($limit)
|
||||
->setFirstResult($offset)
|
||||
->orderBy('c.lastmodified')
|
||||
->addOrderBy('c.id');
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
public function findAllWithDue($boardId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('c.*')
|
||||
@@ -292,7 +266,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
|
||||
public function findOverdue() {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'title', 'duedate', 'notified')
|
||||
$qb->select('id','title','duedate','notified')
|
||||
->from('deck_cards')
|
||||
->where($qb->expr()->lt('duedate', $qb->createFunction('NOW()')))
|
||||
->andWhere($qb->expr()->eq('notified', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
|
||||
@@ -303,7 +277,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
|
||||
public function findUnexposedDescriptionChances() {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('id', 'title', 'duedate', 'notified', 'description_prev', 'last_editor', 'description')
|
||||
$qb->select('id','title','duedate','notified','description_prev','last_editor','description')
|
||||
->from('deck_cards')
|
||||
->where($qb->expr()->isNotNull('last_editor'))
|
||||
->andWhere($qb->expr()->isNotNull('description_prev'));
|
||||
@@ -575,10 +549,10 @@ class CardMapper extends QBMapper implements IPermissionMapper {
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
public function isOwner($userId, $id): bool {
|
||||
public function isOwner($userId, $cardId): bool {
|
||||
$sql = 'SELECT owner FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_stacks` WHERE id IN (SELECT stack_id FROM `*PREFIX*deck_cards` WHERE id = ?))';
|
||||
$stmt = $this->db->prepare($sql);
|
||||
$stmt->bindParam(1, $id, \PDO::PARAM_INT, 0);
|
||||
$stmt->bindParam(1, $cardId, \PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$row = $stmt->fetch();
|
||||
return ($row['owner'] === $userId);
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
use OCP\ICacheFactory;
|
||||
use OCP\ICache;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IRequest;
|
||||
|
||||
@@ -32,16 +31,13 @@ class ChangeHelper {
|
||||
public const TYPE_BOARD = 'boardChanged';
|
||||
public const TYPE_CARD = 'cardChanged';
|
||||
|
||||
private IDBConnection $db;
|
||||
private ICache $cache;
|
||||
private IRequest $request;
|
||||
private ?string $userId;
|
||||
private $db;
|
||||
|
||||
public function __construct(
|
||||
IDBConnection $db,
|
||||
ICacheFactory $cacheFactory,
|
||||
IRequest $request,
|
||||
?string $userId
|
||||
$userId
|
||||
) {
|
||||
$this->db = $db;
|
||||
$this->cache = $cacheFactory->createDistributed('deck_changes');
|
||||
|
||||
@@ -23,15 +23,17 @@
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
use OCP\AppFramework\Db\QBMapper;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\AppFramework\Db\Mapper;
|
||||
|
||||
/**
|
||||
* Class DeckMapper
|
||||
*
|
||||
* @package OCA\Deck\Db
|
||||
* @deprecated use QBMapper
|
||||
*
|
||||
* TODO: Move to QBMapper once Nextcloud 14 is a minimum requirement
|
||||
*/
|
||||
class DeckMapper extends QBMapper {
|
||||
class DeckMapper extends Mapper {
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
@@ -40,11 +42,11 @@ class DeckMapper extends QBMapper {
|
||||
* @throws \OCP\AppFramework\Db\DoesNotExistException
|
||||
*/
|
||||
public function find($id) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
|
||||
$sql = 'SELECT * FROM `' . $this->tableName . '` ' . 'WHERE `id` = ?';
|
||||
return $this->findEntity($sql, [$id]);
|
||||
}
|
||||
|
||||
return $this->findEntity($qb);
|
||||
protected function execute($sql, array $params = [], $limit = null, $offset = null) {
|
||||
return parent::execute($sql, $params, $limit, $offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace OCA\Deck\Db;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
@@ -34,105 +33,41 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
parent::__construct($db, 'deck_labels', Label::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Label[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAll($boardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from($this->getTableName())
|
||||
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
|
||||
->setMaxResults($limit)
|
||||
->setFirstResult($offset);
|
||||
return $this->findEntities($qb);
|
||||
public function findAll($boardId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT * FROM `*PREFIX*deck_labels` WHERE `board_id` = ? ORDER BY `id`';
|
||||
return $this->findEntities($sql, [$boardId], $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
* @return Entity
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function delete(Entity $entity): Entity {
|
||||
public function delete(\OCP\AppFramework\Db\Entity $entity) {
|
||||
// delete assigned labels
|
||||
$this->deleteLabelAssignments($entity->getId());
|
||||
// delete label
|
||||
return parent::delete($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $cardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Label[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAssignedLabelsForCard($cardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.*', 'card_id')
|
||||
->from($this->getTableName(), 'l')
|
||||
->innerJoin('l', 'deck_assigned_labels', 'al', 'l.id = al.label_id')
|
||||
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)))
|
||||
->orderBy('l.id')
|
||||
->setMaxResults($limit)
|
||||
->setFirstResult($offset);
|
||||
|
||||
return $this->findEntities($qb);
|
||||
public function findAssignedLabelsForCard($cardId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT l.*,card_id FROM `*PREFIX*deck_assigned_labels` as al INNER JOIN *PREFIX*deck_labels as l ON l.id = al.label_id WHERE `card_id` = ? ORDER BY l.id';
|
||||
return $this->findEntities($sql, [$cardId], $limit, $offset);
|
||||
}
|
||||
public function findAssignedLabelsForBoard($boardId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT c.id as card_id, l.id as id, l.title as title, l.color as color FROM `*PREFIX*deck_cards` as c ' .
|
||||
' INNER JOIN `*PREFIX*deck_assigned_labels` as al ON al.card_id = c.id INNER JOIN `*PREFIX*deck_labels` as l ON al.label_id = l.id WHERE board_id=? ORDER BY l.id';
|
||||
return $this->findEntities($sql, [$boardId], $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Label[]
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function findAssignedLabelsForBoard($boardId, $limit = null, $offset = null): array {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.id as id', 'l.title as title', 'l.color as color')
|
||||
->selectAlias('c.id', 'card_id')
|
||||
->from($this->getTableName(), 'l')
|
||||
->innerJoin('l', 'deck_assigned_labels', 'al', 'al.label_id = l.id')
|
||||
->innerJoin('l', 'deck_cards', 'c', 'al.card_id = c.id')
|
||||
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT)))
|
||||
->orderBy('l.id')
|
||||
->setMaxResults($limit)
|
||||
->setFirstResult($offset);
|
||||
|
||||
return $this->findEntities($qb);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
* @return Entity
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function insert(Entity $entity): Entity {
|
||||
public function insert(Entity $entity) {
|
||||
$entity->setLastModified(time());
|
||||
return parent::insert($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
* @param bool $updateModified
|
||||
* @return Entity
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function update(Entity $entity, $updateModified = true): Entity {
|
||||
public function update(Entity $entity, $updateModified = true) {
|
||||
if ($updateModified) {
|
||||
$entity->setLastModified(time());
|
||||
}
|
||||
return parent::update($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $boardId
|
||||
* @return array
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
|
||||
public function getAssignedLabelsForBoard($boardId) {
|
||||
$labels = $this->findAssignedLabelsForBoard($boardId);
|
||||
$result = [];
|
||||
@@ -145,51 +80,27 @@ class LabelMapper extends DeckMapper implements IPermissionMapper {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $labelId
|
||||
* @return void
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function deleteLabelAssignments($labelId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('deck_assigned_labels')
|
||||
->where($qb->expr()->eq('label_id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT)));
|
||||
$qb->executeStatement();
|
||||
$sql = 'DELETE FROM `*PREFIX*deck_assigned_labels` WHERE label_id = ?';
|
||||
$stmt = $this->db->prepare($sql);
|
||||
$stmt->bindParam(1, $labelId, \PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $cardId
|
||||
* @return void
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function deleteLabelAssignmentsForCard($cardId) {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->delete('deck_assigned_labels')
|
||||
->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT)));
|
||||
$qb->executeStatement();
|
||||
$sql = 'DELETE FROM `*PREFIX*deck_assigned_labels` WHERE card_id = ?';
|
||||
$stmt = $this->db->prepare($sql);
|
||||
$stmt->bindParam(1, $cardId, \PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param numeric $labelId
|
||||
* @return bool
|
||||
* @throws \OCP\DB\Exception
|
||||
*/
|
||||
public function isOwner($userId, $labelId): bool {
|
||||
$qb = $this->db->getQueryBuilder();
|
||||
$qb->select('l.id')
|
||||
->from($this->getTableName(), 'l')
|
||||
->innerJoin('l', 'deck_boards', 'b', 'l.board_id = b.id')
|
||||
->where($qb->expr()->eq('l.id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($qb->expr()->eq('b.owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
|
||||
|
||||
return count($qb->executeQuery()->fetchAll()) > 0;
|
||||
$sql = 'SELECT owner FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_labels` WHERE id = ?)';
|
||||
$stmt = $this->execute($sql, [$labelId]);
|
||||
$row = $stmt->fetch();
|
||||
return ($row['owner'] === $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numeric $id
|
||||
* @return int|null
|
||||
*/
|
||||
public function findBoardId($id): ?int {
|
||||
try {
|
||||
$entity = $this->find($id);
|
||||
|
||||
@@ -63,7 +63,7 @@ class RelationalEntity extends Entity implements \JsonSerializable {
|
||||
* @return array serialized data
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public function jsonSerialize(): array {
|
||||
public function jsonSerialize() {
|
||||
$properties = get_object_vars($this);
|
||||
$reflection = new \ReflectionClass($this);
|
||||
$json = [];
|
||||
@@ -72,9 +72,6 @@ class RelationalEntity extends Entity implements \JsonSerializable {
|
||||
$propertyReflection = $reflection->getProperty($property);
|
||||
if (!$propertyReflection->isPrivate() && !in_array($property, $this->_resolvedProperties, true)) {
|
||||
$json[$property] = $this->getter($property);
|
||||
if ($json[$property] instanceof \DateTimeInterface) {
|
||||
$json[$property] = $json[$property]->format('c');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,7 @@
|
||||
|
||||
namespace OCA\Deck\Db;
|
||||
|
||||
use JsonSerializable;
|
||||
|
||||
class RelationalObject implements JsonSerializable {
|
||||
class RelationalObject implements \JsonSerializable {
|
||||
protected $primaryKey;
|
||||
protected $object;
|
||||
|
||||
@@ -40,7 +38,7 @@ class RelationalObject implements JsonSerializable {
|
||||
$this->object = $object;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array {
|
||||
public function jsonSerialize() {
|
||||
return array_merge(
|
||||
['primaryKey' => $this->primaryKey],
|
||||
$this->getObjectSerialization()
|
||||
@@ -53,8 +51,8 @@ class RelationalObject implements JsonSerializable {
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getObjectSerialization() {
|
||||
if ($this->object instanceof JsonSerializable) {
|
||||
return $this->object->jsonSerialize();
|
||||
if ($this->object instanceof \JsonSerializable) {
|
||||
$this->object->jsonSerialize();
|
||||
} else {
|
||||
throw new \Exception('jsonSerialize is not implemented on ' . get_class($this));
|
||||
}
|
||||
|
||||
@@ -25,13 +25,6 @@ namespace OCA\Deck\Db;
|
||||
|
||||
use Sabre\VObject\Component\VCalendar;
|
||||
|
||||
/**
|
||||
* @method int getId()
|
||||
* @method int getBoardId()
|
||||
* @method int getDeletedAt()
|
||||
* @method int getLastModified()
|
||||
* @method int getOrder()
|
||||
*/
|
||||
class Stack extends RelationalEntity {
|
||||
protected $title;
|
||||
protected $boardId;
|
||||
@@ -52,7 +45,7 @@ class Stack extends RelationalEntity {
|
||||
$this->cards = $cards;
|
||||
}
|
||||
|
||||
public function jsonSerialize(): array {
|
||||
public function jsonSerialize() {
|
||||
$json = parent::jsonSerialize();
|
||||
if (empty($this->cards)) {
|
||||
unset($json['cards']);
|
||||
|
||||