Compare commits

...

50 Commits

Author SHA1 Message Date
Julius Härtl
139092d855 Create appstore-build-publish.yml
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2021-12-15 17:20:46 +01:00
Nextcloud bot
82232e8890 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-12-12 02:38:54 +00:00
dependabot[bot]
f5c35729ca Merge pull request #3482 from nextcloud/dependabot/npm_and_yarn/master/dompurify-2.3.4 2021-12-11 05:20:04 +00:00
dependabot[bot]
fc1983869b Bump dompurify from 2.3.3 to 2.3.4
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 2.3.3 to 2.3.4.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/2.3.3...2.3.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-11 04:55:03 +00:00
Nextcloud bot
081b5119f5 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-12-09 02:40:03 +00:00
Nextcloud bot
a22e5f7719 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-12-05 02:43:12 +00:00
dependabot[bot]
8ef118ad0f Merge pull request #3468 from nextcloud/dependabot/npm_and_yarn/master/nextcloud/eslint-config-6.1.1 2021-12-04 03:31:28 +00:00
dependabot[bot]
86945d5030 Bump @nextcloud/eslint-config from 6.1.0 to 6.1.1
Bumps [@nextcloud/eslint-config](https://github.com/nextcloud/eslint-config) from 6.1.0 to 6.1.1.
- [Release notes](https://github.com/nextcloud/eslint-config/releases)
- [Changelog](https://github.com/nextcloud/eslint-config/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/eslint-config/compare/v6.1.0...v6.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-04 02:02:29 +00:00
Nextcloud bot
c63423c25a [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-12-03 02:40:11 +00:00
Nextcloud bot
8db48106b9 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-12-01 17:22:45 +00:00
Julius Härtl
6d201a1f13 Merge pull request #3458 from nextcloud/bugfix/3451 2021-11-30 13:23:40 +01:00
Julius Härtl
5425536fc0 Merge pull request #3459 from nextcloud/bugfix/3457 2021-11-30 13:20:46 +01:00
Julius Härtl
92acaa0011 Properly handle setters now that there is a default value of null with unset acl/labels
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2021-11-30 10:57:24 +01:00
Julius Härtl
a5b76991b8 Fix cursor generation if no results are found
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2021-11-29 20:44:42 +01:00
Julius Härtl
33f5af41c8 Merge pull request #3454 from nextcloud/dependabot/composer/symfony/event-dispatcher-4.4.34 2021-11-29 20:38:44 +01:00
Julius Härtl
f5223d90a0 Merge pull request #3456 from nextcloud/dependabot/github_actions/shivammathur/setup-php-2.16.0 2021-11-29 20:38:29 +01:00
Julius Härtl
4a51335a28 Merge pull request #3455 from nextcloud/dependabot/npm_and_yarn/master/nextcloud/axios-1.8.0 2021-11-29 20:38:18 +01:00
Nextcloud bot
e5ffe95c17 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-11-27 02:37:08 +00:00
dependabot[bot]
3096b701b6 Bump shivammathur/setup-php from 2.15.0 to 2.16.0
Bumps [shivammathur/setup-php](https://github.com/shivammathur/setup-php) from 2.15.0 to 2.16.0.
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/2.15.0...2.16.0)

---
updated-dependencies:
- dependency-name: shivammathur/setup-php
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-27 02:04:50 +00:00
dependabot[bot]
caf2e688f7 Bump @nextcloud/axios from 1.7.0 to 1.8.0
Bumps [@nextcloud/axios](https://github.com/nextcloud/nextcloud-axios) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/nextcloud/nextcloud-axios/releases)
- [Changelog](https://github.com/nextcloud/nextcloud-axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/nextcloud-axios/compare/v1.7.0...v1.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-27 02:02:57 +00:00
dependabot[bot]
3269845cfd Bump symfony/event-dispatcher from 4.4.30 to 4.4.34
Bumps [symfony/event-dispatcher](https://github.com/symfony/event-dispatcher) from 4.4.30 to 4.4.34.
- [Release notes](https://github.com/symfony/event-dispatcher/releases)
- [Changelog](https://github.com/symfony/event-dispatcher/blob/5.3/CHANGELOG.md)
- [Commits](https://github.com/symfony/event-dispatcher/compare/v4.4.30...v4.4.34)

---
updated-dependencies:
- dependency-name: symfony/event-dispatcher
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-27 02:01:03 +00:00
Nextcloud bot
5349fcc707 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-11-26 02:57:38 +00:00
Nextcloud bot
0f095e9b69 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-11-25 02:36:02 +00:00
Julius Härtl
3affa7b5ec Merge pull request #3444 from nextcloud/enh/cache-frequent-queries 2021-11-24 15:06:37 +01:00
Julius Härtl
4ec57d337b Keep API results the same as before
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2021-11-24 10:12:28 +01:00
Julius Härtl
6fd83258a0 Merge pull request #3365 from nextcloud/enh/use-qbmapper-for-boards 2021-11-24 09:40:50 +01:00
Julius Härtl
901b8f2506 Avoid fetching board details multiple times
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2021-11-24 09:40:30 +01:00
Julius Härtl
80388d1a88 Cache card to board id relation
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2021-11-24 09:40:30 +01:00
Nextcloud bot
f90c9602b8 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-11-24 02:36:58 +00:00
Julius Härtl
f861f9e5fc Update psalm baseline
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2021-11-23 23:44:50 +01:00
Julien Veyssier
bbfb155802 switch to QBMapper in BoardMapper
Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
2021-11-23 22:57:50 +01:00
Julius Härtl
10ab8c8688 Merge pull request #3428 from nextcloud/bugfix/download-attachment 2021-11-22 18:39:58 +01:00
Julius Härtl
24a6d088ca Merge pull request #3436 from nextcloud/dependabot/npm_and_yarn/master/vue/test-utils-1.3.0 2021-11-22 16:39:02 +01:00
Julius Härtl
00d386dcaf Allow to download an attachment without navigating to the files app
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2021-11-22 16:38:28 +01:00
Nextcloud bot
b71f91c439 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-11-20 02:53:14 +00:00
dependabot[bot]
7aa35bb728 Bump @vue/test-utils from 1.2.2 to 1.3.0
Bumps [@vue/test-utils](https://github.com/vuejs/vue-test-utils/tree/HEAD/packages/test-utils) from 1.2.2 to 1.3.0.
- [Release notes](https://github.com/vuejs/vue-test-utils/releases)
- [Changelog](https://github.com/vuejs/vue-test-utils/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-test-utils/commits/v1.3.0/packages/test-utils)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-20 02:04:23 +00:00
Julius Härtl
800412237d Merge pull request #3432 from nextcloud/bugfix/noid/description-save 2021-11-19 10:14:25 +01:00
Julius Härtl
ca411c6168 Fix event name for updating the description
Signed-off-by: Julius Härtl <jus@bitgrid.net>
2021-11-19 08:32:40 +01:00
Nextcloud bot
d414ffe937 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-11-19 02:53:33 +00:00
Julius Härtl
ad483f3613 Merge pull request #3425 from nextcloud/dependabot/npm_and_yarn/master/babel/runtime-7.16.3
Bump @babel/runtime from 7.16.0 to 7.16.3
2021-11-15 07:21:51 +01:00
Julius Härtl
8311a13275 Merge pull request #3427 from nextcloud/dependabot/npm_and_yarn/master/nextcloud/webpack-vue-config-4.1.4
Bump @nextcloud/webpack-vue-config from 4.1.2 to 4.1.4
2021-11-15 07:21:38 +01:00
Nextcloud bot
e2a7063772 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-11-15 02:35:06 +00:00
Nextcloud bot
1dbf36ae07 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-11-14 02:36:19 +00:00
Nextcloud bot
29278a51e5 [tx-robot] updated from transifex
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-11-13 02:36:41 +00:00
dependabot[bot]
31e48ce404 Bump @nextcloud/webpack-vue-config from 4.1.2 to 4.1.4
Bumps [@nextcloud/webpack-vue-config](https://github.com/nextcloud/webpack-vue-config) from 4.1.2 to 4.1.4.
- [Release notes](https://github.com/nextcloud/webpack-vue-config/releases)
- [Changelog](https://github.com/nextcloud/webpack-vue-config/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nextcloud/webpack-vue-config/compare/v4.1.2...v4.1.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-13 02:04:54 +00:00
dependabot[bot]
404a7eb412 Bump @babel/runtime from 7.16.0 to 7.16.3
Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.16.0 to 7.16.3.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.16.3/packages/babel-runtime)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-13 02:02:03 +00:00
Julius Härtl
a85a6db368 Merge pull request #3420 from nextcloud/feat/package-node-npm-engines-update 2021-11-11 16:12:42 +01:00
Nextcloud bot
9464337036 Update npm and node engines versions
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2021-11-11 13:36:52 +00:00
Vincent Petry
87676b49dd Merge pull request #3419 from nextcloud/update-master-version
Update version on master
2021-11-11 11:53:23 +01:00
Joas Schilling
6248089d8b Update version on master
Signed-off-by: Joas Schilling <coding@schilljs.com>
2021-11-11 10:51:16 +01:00
70 changed files with 1144 additions and 796 deletions

View File

@@ -20,7 +20,7 @@ jobs:
- name: Set up npm7
run: npm i -g npm@7
- name: Setup PHP
uses: shivammathur/setup-php@2.15.0
uses: shivammathur/setup-php@2.16.0
with:
php-version: '7.4'
tools: composer

View File

@@ -0,0 +1,151 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
name: Build and publish app release
on:
release:
types: [published]
env:
PHP_VERSION: 7.4
jobs:
build_and_publish:
runs-on: ubuntu-latest
# Only allowed to be run on nextcloud-releases repositories
if: ${{ github.repository_owner == 'nextcloud-releases' }}
steps:
- name: Check actor permission
uses: skjnldsv/check-actor-permission@v2
with:
require: admin
- name: Set app env
run: |
# Split and keep last
echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
echo "APP_VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v2
with:
path: ${{ env.APP_NAME }}
- name: Get appinfo data
id: appinfo
uses: skjnldsv/xpath-action@master
with:
filename: ${{ env.APP_NAME }}/appinfo/info.xml
expression: "//info//dependencies//nextcloud/@min-version"
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@v1.1
id: versions
# Continue if no package.json
continue-on-error: true
with:
path: ${{ env.APP_NAME }}
fallbackNode: "^12"
fallbackNpm: "^6"
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
# Skip if no package.json
if: ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@v2
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
# Skip if no package.json
if: ${{ steps.versions.outputs.npmVersion }}
run: npm i -g npm@"${{ steps.versions.outputs.npmVersion }}"
- name: Set up php ${{ env.PHP_VERSION }}
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@v1
with:
files: "${{ env.APP_NAME }}/composer.json"
- name: Install composer dependencies
if: steps.check_composer.outputs.files_exists == 'true'
run: |
cd ${{ env.APP_NAME }}
composer install --no-dev
- name: Build ${{ env.APP_NAME }}
# Skip if no package.json
if: ${{ steps.versions.outputs.nodeVersion }}
run: |
cd ${{ env.APP_NAME }}
npm ci
npm run build
- name: Install Krankerl
run: |
wget https://github.com/ChristophWurst/krankerl/releases/download/v0.13.0/krankerl_0.13.0_amd64.deb
sudo dpkg -i krankerl_0.13.0_amd64.deb
- name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }}
# Try krankerl, fallback to makefile
run: |
cd ${{ env.APP_NAME }}
krankerl package || make appstore
- name: Checkout server ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}
continue-on-error: true
id: server-checkout
run: |
NCVERSION=${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}
wget --quiet https://download.nextcloud.com/server/releases/latest-$NCVERSION.zip
unzip latest-$NCVERSION.zip
- name: Checkout server master fallback
uses: actions/checkout@v2
if: ${{ steps.server-checkout.outcome != 'success' }}
with:
repository: nextcloud/server
path: nextcloud
- name: Sign app
run: |
# Extracting release
cd ${{ env.APP_NAME }}/build/artifacts
tar -xvf ${{ env.APP_NAME }}.tar.gz
cd ../../../
# Setting up keys
echo "${{ secrets.APP_PRIVATE_KEY }}" > ${{ env.APP_NAME }}.key
wget --quiet "https://github.com/nextcloud/app-certificate-requests/raw/master/${{ env.APP_NAME }}/${{ env.APP_NAME }}.crt"
# Signing
php nextcloud/occ integrity:sign-app --privateKey=../${{ env.APP_NAME }}.key --certificate=../${{ env.APP_NAME }}.crt --path=../${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}
# Rebuilding archive
cd ${{ env.APP_NAME }}/build/artifacts
tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }}
- name: Attach tarball to github release
uses: svenstaro/upload-release-action@v2
id: attach_to_release
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}.tar.gz
asset_name: ${{ env.APP_NAME }}-${{ env.APP_VERSION }}.tar.gz
tag: ${{ github.ref }}
overwrite: true
- name: Upload app to Nextcloud appstore
uses: nextcloud-releases/nextcloud-appstore-push-action@v1
with:
app_name: ${{ env.APP_NAME }}
appstore_token: ${{ secrets.APPSTORE_TOKEN }}
download_url: ${{ steps.attach_to_release.outputs.browser_download_url }}
app_private_key: ${{ secrets.APP_PRIVATE_KEY }}

View File

@@ -61,7 +61,7 @@ jobs:
path: apps/${{ env.APP_NAME }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2.15.0
uses: shivammathur/setup-php@2.16.0
with:
php-version: ${{ matrix.php-versions }}
tools: phpunit

View File

@@ -19,7 +19,7 @@ jobs:
steps:
- uses: actions/checkout@v2.4.0
- name: Set up php${{ matrix.php-versions }}
uses: shivammathur/setup-php@2.15.0
uses: shivammathur/setup-php@2.16.0
with:
php-version: ${{ matrix.php-versions }}
coverage: none
@@ -33,7 +33,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v2.4.0
- name: Set up php
uses: shivammathur/setup-php@2.15.0
uses: shivammathur/setup-php@2.16.0
with:
php-version: 7.4
coverage: none

View File

@@ -25,7 +25,7 @@ jobs:
- name: Set up npm7
run: npm i -g npm@7
- name: Setup PHP
uses: shivammathur/setup-php@2.15.0
uses: shivammathur/setup-php@2.16.0
with:
php-version: '7.4'
tools: composer

View File

@@ -62,7 +62,7 @@ jobs:
path: apps/${{ env.APP_NAME }}
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2.15.0
uses: shivammathur/setup-php@2.16.0
with:
php-version: ${{ matrix.php-versions }}
tools: phpunit

View File

@@ -18,7 +18,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v2.4.0
- name: Set up php
uses: shivammathur/setup-php@2.15.0
uses: shivammathur/setup-php@2.16.0
with:
php-version: 7.4
tools: composer:v1

View File

@@ -16,7 +16,7 @@
- 🚀 Get your project organized
</description>
<version>1.6.0-beta1</version>
<version>1.7.0-alpha1</version>
<licence>agpl</licence>
<author>Julius Härtl</author>
<namespace>Deck</namespace>
@@ -34,8 +34,8 @@
<php min-version="7.3"/>
<database min-version="9.4">pgsql</database>
<database>sqlite</database>
<database min-version="5.5">mysql</database>
<nextcloud min-version="23" max-version="23"/>
<database min-version="8.0">mysql</database>
<nextcloud min-version="24" max-version="24"/>
</dependencies>
<background-jobs>
<job>OCA\Deck\Cron\DeleteCron</job>

26
composer.lock generated
View File

@@ -3637,16 +3637,16 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v4.4.30",
"version": "v4.4.34",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "2fe81680070043c4c80e7cedceb797e34f377bac"
"reference": "1a024b45369c9d55d76b6b8a241bd20c9ea1cbd8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/2fe81680070043c4c80e7cedceb797e34f377bac",
"reference": "2fe81680070043c4c80e7cedceb797e34f377bac",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1a024b45369c9d55d76b6b8a241bd20c9ea1cbd8",
"reference": "1a024b45369c9d55d76b6b8a241bd20c9ea1cbd8",
"shasum": ""
},
"require": {
@@ -3701,7 +3701,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v4.4.30"
"source": "https://github.com/symfony/event-dispatcher/tree/v4.4.34"
},
"funding": [
{
@@ -3717,20 +3717,20 @@
"type": "tidelift"
}
],
"time": "2021-08-04T20:31:23+00:00"
"time": "2021-11-15T14:42:25+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
"version": "v1.1.9",
"version": "v1.1.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7"
"reference": "01e9a4efac0ee33a05dfdf93b346f62e7d0e998c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/84e23fdcd2517bf37aecbd16967e83f0caee25a7",
"reference": "84e23fdcd2517bf37aecbd16967e83f0caee25a7",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/01e9a4efac0ee33a05dfdf93b346f62e7d0e998c",
"reference": "01e9a4efac0ee33a05dfdf93b346f62e7d0e998c",
"shasum": ""
},
"require": {
@@ -3743,7 +3743,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
"dev-main": "1.1-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -3780,7 +3780,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.9"
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v1.1.11"
},
"funding": [
{
@@ -3796,7 +3796,7 @@
"type": "tidelift"
}
],
"time": "2020-07-06T13:19:58+00:00"
"time": "2021-03-23T15:25:38+00:00"
},
{
"name": "symfony/filesystem",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Чакащо споделяне",
"Add this attachment" : "Добавете този прикачен файл",
"Show in Files" : "Показване във файлове",
"Download" : "Изтегляне",
"Remove attachment" : "Премахване на прикачен файл",
"Delete Attachment" : "Изтриване на прикачен файл",
"Restore Attachment" : "Възстановяване на прикачен файл",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Чакащо споделяне",
"Add this attachment" : "Добавете този прикачен файл",
"Show in Files" : "Показване във файлове",
"Download" : "Изтегляне",
"Remove attachment" : "Премахване на прикачен файл",
"Delete Attachment" : "Изтриване на прикачен файл",
"Restore Attachment" : "Възстановяване на прикачен файл",

View File

@@ -70,9 +70,15 @@ OC.L10N.register(
"Upcoming cards" : "Pròximes targetes",
"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 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}.",
"The board \"%s\" has been shared with you by %s." : "El tauler \"%s\" se us ha compartit per %s.",
"{user} has shared {deck-board} with you." : "{user} us ha compartit {board}.",
"Card comments" : "Comentaris de la targeta",
"%s on %s" : "%s a %s",
"No data was provided to create an attachment." : "No sha proporcionat cap dada per crear un fitxer adjunt.",
"Finished" : "Acabat",
"To review" : "Per revisar",
@@ -94,6 +100,9 @@ OC.L10N.register(
"Could not write file to disk" : "No sha pogut escriure el fitxer al disc",
"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",
"Card not found" : "No s'ha trobat la targeta",
"Path is already shared with this card" : "Aquesta ruta ja ha estat compartida amb aquesta targeta",
"Invalid date, date format must be YYYY-MM-DD" : "La data no és vàlida, el format de la data ha de ser YYYY-MM-DD",
"Personal planning and team project organization" : "Planificació personal i organització de projectes en equip",
"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" : "Tauler és una eina d'organització a l'estil kanban dirigida a la planificació personal i a l'organització de projectes per equips integrada a Nextcloud.\n\n\n- 📥 Afegiu les tasques en targetes i poseu-les en ordre\n- 📄 Apunteu notes addicionals en markdown\n- 🔖 Assigneu etiquetes per una organització encara millor\n- 👥 Compartiu amb el vostre equip, família o amics\n- 📎 Adjunteu fitxers i encasteu-los en la descripció en markdown\n- 💬 Debateu amb el vostre equip fent servir comentaris\n- ⚡ Mantingueu el seguiment de canvis al flux d'activitat\n- 🚀 Tingueu el vostre projecte organitzat",
"Card details" : "Detalls de la targeta",
@@ -101,9 +110,16 @@ OC.L10N.register(
"Select the board to link to a project" : "Selecciona el tauler per enllaçar a un projecte",
"Search by board title" : "Cerca per títol del tauler",
"Select board" : "Selecciona un tauler",
"Create a new card" : "Crea una nova targeta",
"Select a board" : "Selecciona un tauler",
"Select a list" : "Seleccioneu una llista",
"Card title" : "Títol de la targeta",
"Cancel" : "Cancel·la",
"Creating the new card …" : "Creant la nova targeta",
"Card \"{card}\" was added to \"{board}\"" : "La targeta \"{card}\" s'ha afegit a \"{board}\"",
"Open card" : "Obre la targeta",
"Close" : "Tanca",
"Create card" : "Crea una targeta",
"Select a card" : "Selecciona una targeta",
"Select the card to link to a project" : "Selecciona la targeta per enllaçar a un projecte",
"Link to card" : "Enllaç a la targeta",
@@ -167,9 +183,16 @@ OC.L10N.register(
"title and color value must be provided" : "sha de proporcionar el valor del títol i del color",
"Board name" : "Nom del taulell",
"Members" : "Membres",
"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",
"Remove attachment" : "Treu l'adjunt",
"Delete Attachment" : "Suprimeix ladjunt",
"Restore Attachment" : "Restaura l'adjunt",
"File to share" : "Fitxer a compartir",
"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",
@@ -178,6 +201,7 @@ OC.L10N.register(
"Created" : "Creat",
"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…" : "Assigna una etiqueta a aquesta targeta…",
"Assign to users" : "Assigna als usuaris",
"Assign to users/groups/circles" : "Assigna a usuaris/grups/cercles",
@@ -188,10 +212,13 @@ OC.L10N.register(
"Select Date" : "Selecciona la data",
"Today" : "Avui",
"Tomorrow" : "Demà",
"Next week" : "Setmana següent",
"Next month" : "Mes següent",
"Save" : "Desa",
"The comment cannot be empty." : "El comentari no pot estar buit.",
"The comment cannot be longer than 1000 characters." : "El comentari no pot ser més llarg que 1000 caràcters.",
"In reply to" : "En resposta a",
"Cancel reply" : "Cancel·la la resposta",
"Reply" : "Respon",
"Update" : "Actualitza",
"Description" : "Descripció",
@@ -204,6 +231,7 @@ OC.L10N.register(
"Write a description …" : "Escriviu una descripció...",
"Choose attachment" : "Triar adjunt",
"(group)" : "(grup)",
"{count} comments, {unread} unread" : "{count} comentaris, {unread} no llegits",
"Assign to me" : "Assigna'm a mi",
"Unassign myself" : "Desasignar a mi mateix",
"Move card" : "Mou la targeta",
@@ -220,7 +248,7 @@ OC.L10N.register(
"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.",
"Board details" : "Detalls de la junta",
"Board details" : "Detalls del tauler",
"Edit board" : "Edita el tauler",
"Clone board" : "Clonar tauler",
"Unarchive board" : "Desarxiva el tauler",
@@ -241,12 +269,20 @@ OC.L10N.register(
"Loading filtered view" : "S'està carregant la visualització filtrada",
"This week" : "Aquesta setmana",
"No due" : "Sense venciment",
"Search for {searchQuery} in all boards" : "Busca {searchQuery} a tots els taulers",
"No results found" : "No s'han trobat resultats",
"No upcoming cards" : "No hi ha pròximes targetes",
"upcoming cards" : "pròximes targetes",
"Link to a board" : "Enllaça a un tauler",
"Link to a card" : "Enllaç una targeta",
"Create a card" : "Crea una targeta",
"Message from {author} in {conversationName}" : "Missatge de {author} a {conversationName}",
"Something went wrong" : "Alguna cosa ha anat malament",
"Failed to upload {name}" : "No s'ha pogut pujar {name}",
"Maximum file size of {size} exceeded" : "S'ha superat la mida màxima per fitxer de {size}"
"Maximum file size of {size} exceeded" : "S'ha superat la mida màxima per fitxer de {size}",
"Error creating the share" : "S'ha produït un error en crear la compartició",
"Share with a Deck card" : "Compartir amb una targeta de Deck",
"Share {file} with a Deck card" : "Compartir {file} amb una targeta de Deck",
"Share" : "Compartir"
},
"nplurals=2; plural=(n != 1);");

View File

@@ -68,9 +68,15 @@
"Upcoming cards" : "Pròximes targetes",
"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 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}.",
"The board \"%s\" has been shared with you by %s." : "El tauler \"%s\" se us ha compartit per %s.",
"{user} has shared {deck-board} with you." : "{user} us ha compartit {board}.",
"Card comments" : "Comentaris de la targeta",
"%s on %s" : "%s a %s",
"No data was provided to create an attachment." : "No sha proporcionat cap dada per crear un fitxer adjunt.",
"Finished" : "Acabat",
"To review" : "Per revisar",
@@ -92,6 +98,9 @@
"Could not write file to disk" : "No sha pogut escriure el fitxer al disc",
"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",
"Card not found" : "No s'ha trobat la targeta",
"Path is already shared with this card" : "Aquesta ruta ja ha estat compartida amb aquesta targeta",
"Invalid date, date format must be YYYY-MM-DD" : "La data no és vàlida, el format de la data ha de ser YYYY-MM-DD",
"Personal planning and team project organization" : "Planificació personal i organització de projectes en equip",
"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" : "Tauler és una eina d'organització a l'estil kanban dirigida a la planificació personal i a l'organització de projectes per equips integrada a Nextcloud.\n\n\n- 📥 Afegiu les tasques en targetes i poseu-les en ordre\n- 📄 Apunteu notes addicionals en markdown\n- 🔖 Assigneu etiquetes per una organització encara millor\n- 👥 Compartiu amb el vostre equip, família o amics\n- 📎 Adjunteu fitxers i encasteu-los en la descripció en markdown\n- 💬 Debateu amb el vostre equip fent servir comentaris\n- ⚡ Mantingueu el seguiment de canvis al flux d'activitat\n- 🚀 Tingueu el vostre projecte organitzat",
"Card details" : "Detalls de la targeta",
@@ -99,9 +108,16 @@
"Select the board to link to a project" : "Selecciona el tauler per enllaçar a un projecte",
"Search by board title" : "Cerca per títol del tauler",
"Select board" : "Selecciona un tauler",
"Create a new card" : "Crea una nova targeta",
"Select a board" : "Selecciona un tauler",
"Select a list" : "Seleccioneu una llista",
"Card title" : "Títol de la targeta",
"Cancel" : "Cancel·la",
"Creating the new card …" : "Creant la nova targeta",
"Card \"{card}\" was added to \"{board}\"" : "La targeta \"{card}\" s'ha afegit a \"{board}\"",
"Open card" : "Obre la targeta",
"Close" : "Tanca",
"Create card" : "Crea una targeta",
"Select a card" : "Selecciona una targeta",
"Select the card to link to a project" : "Selecciona la targeta per enllaçar a un projecte",
"Link to card" : "Enllaç a la targeta",
@@ -165,9 +181,16 @@
"title and color value must be provided" : "sha de proporcionar el valor del títol i del color",
"Board name" : "Nom del taulell",
"Members" : "Membres",
"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",
"Remove attachment" : "Treu l'adjunt",
"Delete Attachment" : "Suprimeix ladjunt",
"Restore Attachment" : "Restaura l'adjunt",
"File to share" : "Fitxer a compartir",
"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",
@@ -176,6 +199,7 @@
"Created" : "Creat",
"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…" : "Assigna una etiqueta a aquesta targeta…",
"Assign to users" : "Assigna als usuaris",
"Assign to users/groups/circles" : "Assigna a usuaris/grups/cercles",
@@ -186,10 +210,13 @@
"Select Date" : "Selecciona la data",
"Today" : "Avui",
"Tomorrow" : "Demà",
"Next week" : "Setmana següent",
"Next month" : "Mes següent",
"Save" : "Desa",
"The comment cannot be empty." : "El comentari no pot estar buit.",
"The comment cannot be longer than 1000 characters." : "El comentari no pot ser més llarg que 1000 caràcters.",
"In reply to" : "En resposta a",
"Cancel reply" : "Cancel·la la resposta",
"Reply" : "Respon",
"Update" : "Actualitza",
"Description" : "Descripció",
@@ -202,6 +229,7 @@
"Write a description …" : "Escriviu una descripció...",
"Choose attachment" : "Triar adjunt",
"(group)" : "(grup)",
"{count} comments, {unread} unread" : "{count} comentaris, {unread} no llegits",
"Assign to me" : "Assigna'm a mi",
"Unassign myself" : "Desasignar a mi mateix",
"Move card" : "Mou la targeta",
@@ -218,7 +246,7 @@
"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.",
"Board details" : "Detalls de la junta",
"Board details" : "Detalls del tauler",
"Edit board" : "Edita el tauler",
"Clone board" : "Clonar tauler",
"Unarchive board" : "Desarxiva el tauler",
@@ -239,12 +267,20 @@
"Loading filtered view" : "S'està carregant la visualització filtrada",
"This week" : "Aquesta setmana",
"No due" : "Sense venciment",
"Search for {searchQuery} in all boards" : "Busca {searchQuery} a tots els taulers",
"No results found" : "No s'han trobat resultats",
"No upcoming cards" : "No hi ha pròximes targetes",
"upcoming cards" : "pròximes targetes",
"Link to a board" : "Enllaça a un tauler",
"Link to a card" : "Enllaç una targeta",
"Create a card" : "Crea una targeta",
"Message from {author} in {conversationName}" : "Missatge de {author} a {conversationName}",
"Something went wrong" : "Alguna cosa ha anat malament",
"Failed to upload {name}" : "No s'ha pogut pujar {name}",
"Maximum file size of {size} exceeded" : "S'ha superat la mida màxima per fitxer de {size}"
"Maximum file size of {size} exceeded" : "S'ha superat la mida màxima per fitxer de {size}",
"Error creating the share" : "S'ha produït un error en crear la compartició",
"Share with a Deck card" : "Compartir amb una targeta de Deck",
"Share {file} with a Deck card" : "Compartir {file} amb una targeta de Deck",
"Share" : "Compartir"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
}

View File

@@ -85,7 +85,7 @@ OC.L10N.register(
"Action needed" : "Nutná akce",
"Later" : "Později",
"copy" : "kopie",
"To do" : "Udělat",
"To do" : "Zbývá udělat",
"Doing" : "Provádí se",
"Done" : "Hotovo",
"Example Task 3" : "Třetí úkol pro ukázku",
@@ -101,7 +101,7 @@ OC.L10N.register(
"A PHP extension stopped the file upload" : "PHP rozšíření zastavilo nahrávání souboru.",
"No file uploaded or file size exceeds maximum of %s" : "Nebyl nahrán žádný soubor nebo jeho velikost přesáhla %s",
"Card not found" : "Karta nebyla nalezena",
"Path is already shared with this card" : "Cesta je již s touto kartou sdílena",
"Path is already shared with this card" : "Popis umístění už je touto kartou sdíleno",
"Invalid date, date format must be YYYY-MM-DD" : "Neplatné datum je třeba, aby formát data byl RRRR-MM-DD",
"Personal planning and team project organization" : "Osobní plánování a organizování týmového projektu",
"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 je nástroj cílený na osobní nebo projektové plánování týmů v Kanban stylu, vestavěný v Nextcloud.\n\n\n- 📥 Zadávejte a uspořádávejte své úkoly do karet\n- 📄 Zapisujte si dodatečné poznámky \n- 🔖 Přiřazujte štítky pro ještě lepší organizaci\n- 👥 Sdílejte se svým týmem, přáteli nebo rodinou\n- 🚀 Dostaňte svůj projekt pod kontrolu",
@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Čekající sdílení",
"Add this attachment" : "Přidat tuto přílohu",
"Show in Files" : "Zobrazit v Souborech",
"Download" : "Stáhnout",
"Remove attachment" : "Odebrat přílohu",
"Delete Attachment" : "Smazat přílohu",
"Restore Attachment" : "Obnovit přílohu",

View File

@@ -83,7 +83,7 @@
"Action needed" : "Nutná akce",
"Later" : "Později",
"copy" : "kopie",
"To do" : "Udělat",
"To do" : "Zbývá udělat",
"Doing" : "Provádí se",
"Done" : "Hotovo",
"Example Task 3" : "Třetí úkol pro ukázku",
@@ -99,7 +99,7 @@
"A PHP extension stopped the file upload" : "PHP rozšíření zastavilo nahrávání souboru.",
"No file uploaded or file size exceeds maximum of %s" : "Nebyl nahrán žádný soubor nebo jeho velikost přesáhla %s",
"Card not found" : "Karta nebyla nalezena",
"Path is already shared with this card" : "Cesta je již s touto kartou sdílena",
"Path is already shared with this card" : "Popis umístění už je touto kartou sdíleno",
"Invalid date, date format must be YYYY-MM-DD" : "Neplatné datum je třeba, aby formát data byl RRRR-MM-DD",
"Personal planning and team project organization" : "Osobní plánování a organizování týmového projektu",
"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 je nástroj cílený na osobní nebo projektové plánování týmů v Kanban stylu, vestavěný v Nextcloud.\n\n\n- 📥 Zadávejte a uspořádávejte své úkoly do karet\n- 📄 Zapisujte si dodatečné poznámky \n- 🔖 Přiřazujte štítky pro ještě lepší organizaci\n- 👥 Sdílejte se svým týmem, přáteli nebo rodinou\n- 🚀 Dostaňte svůj projekt pod kontrolu",
@@ -186,6 +186,7 @@
"Pending share" : "Čekající sdílení",
"Add this attachment" : "Přidat tuto přílohu",
"Show in Files" : "Zobrazit v Souborech",
"Download" : "Stáhnout",
"Remove attachment" : "Odebrat přílohu",
"Delete Attachment" : "Smazat přílohu",
"Restore Attachment" : "Obnovit přílohu",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Ausstehende Freigabe",
"Add this attachment" : "Diesen Anhang anhängen",
"Show in Files" : "In Dateien anzeigen",
"Download" : "Herunterladen",
"Remove attachment" : "Anhang entfernen",
"Delete Attachment" : "Anhang löschen",
"Restore Attachment" : "Anhang wiederherstellen",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Ausstehende Freigabe",
"Add this attachment" : "Diesen Anhang anhängen",
"Show in Files" : "In Dateien anzeigen",
"Download" : "Herunterladen",
"Remove attachment" : "Anhang entfernen",
"Delete Attachment" : "Anhang löschen",
"Restore Attachment" : "Anhang wiederherstellen",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Ausstehende Freigabe",
"Add this attachment" : "Diesen Anhang anhängen",
"Show in Files" : "In Dateien anzeigen",
"Download" : "Herunterladen",
"Remove attachment" : "Anhang entfernen",
"Delete Attachment" : "Anhang löschen",
"Restore Attachment" : "Anhang wiederherstellen",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Ausstehende Freigabe",
"Add this attachment" : "Diesen Anhang anhängen",
"Show in Files" : "In Dateien anzeigen",
"Download" : "Herunterladen",
"Remove attachment" : "Anhang entfernen",
"Delete Attachment" : "Anhang löschen",
"Restore Attachment" : "Anhang wiederherstellen",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Pendiente de compartir",
"Add this attachment" : "Añadir este adjunto",
"Show in Files" : "Mostrar en Archivos",
"Download" : "Descargar",
"Remove attachment" : "Quitar adjunto",
"Delete Attachment" : "Borrar adjunto",
"Restore Attachment" : "Restaurar Adjunto",
@@ -212,6 +213,8 @@ OC.L10N.register(
"Select Date" : "Seleccione la fecha",
"Today" : "Hoy",
"Tomorrow" : "Mañana",
"Next week" : "Semana siguiente",
"Next month" : "Mes siguiente",
"Save" : "Guardar",
"The comment cannot be empty." : "El comentario no puede estar vacío.",
"The comment cannot be longer than 1000 characters." : "El comentario no puede tener más de 1000 caracteres.",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Pendiente de compartir",
"Add this attachment" : "Añadir este adjunto",
"Show in Files" : "Mostrar en Archivos",
"Download" : "Descargar",
"Remove attachment" : "Quitar adjunto",
"Delete Attachment" : "Borrar adjunto",
"Restore Attachment" : "Restaurar Adjunto",
@@ -210,6 +211,8 @@
"Select Date" : "Seleccione la fecha",
"Today" : "Hoy",
"Tomorrow" : "Mañana",
"Next week" : "Semana siguiente",
"Next month" : "Mes siguiente",
"Save" : "Guardar",
"The comment cannot be empty." : "El comentario no puede estar vacío.",
"The comment cannot be longer than 1000 characters." : "El comentario no puede tener más de 1000 caracteres.",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Partekatzeko zain",
"Add this attachment" : "Gehitu eranskin hau",
"Show in Files" : "Erakutsi fitxategietan",
"Download" : "Deskargatu",
"Remove attachment" : "Kendu eranskina",
"Delete Attachment" : "Ezabatu eranskina",
"Restore Attachment" : "Berezarri eranskina",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Partekatzeko zain",
"Add this attachment" : "Gehitu eranskin hau",
"Show in Files" : "Erakutsi fitxategietan",
"Download" : "Deskargatu",
"Remove attachment" : "Kendu eranskina",
"Delete Attachment" : "Ezabatu eranskina",
"Restore Attachment" : "Berezarri eranskina",

View File

@@ -184,6 +184,8 @@ OC.L10N.register(
"Select Date" : "Valitse päivä",
"Today" : "Tänään",
"Tomorrow" : "Huomenna",
"Next week" : "Seuraava viikko",
"Next month" : "Seuraava kuukausi",
"Save" : "Tallenna",
"The comment cannot be empty." : "Kommentti ei voi olla tyhjä.",
"The comment cannot be longer than 1000 characters." : "Kommentin on oltava alle 1000 merkkiä pitkä.",

View File

@@ -182,6 +182,8 @@
"Select Date" : "Valitse päivä",
"Today" : "Tänään",
"Tomorrow" : "Huomenna",
"Next week" : "Seuraava viikko",
"Next month" : "Seuraava kuukausi",
"Save" : "Tallenna",
"The comment cannot be empty." : "Kommentti ei voi olla tyhjä.",
"The comment cannot be longer than 1000 characters." : "Kommentin on oltava alle 1000 merkkiä pitkä.",

View File

@@ -185,8 +185,11 @@ OC.L10N.register(
"Members" : "Membres",
"Upload new files" : "Téléverser de nouveaux fichiers",
"Share from Files" : "Partager vos fichiers déjà stockés",
"Pending share" : "Partage en attente",
"Add this attachment" : "Ajouter cette pièce jointe",
"Show in Files" : "Afficher dans Fichiers",
"Download" : "Télécharger",
"Remove attachment" : "Supprimer la pièce jointe",
"Delete Attachment" : "Supprimer la pièce jointe",
"Restore Attachment" : "Restaurer la pièce jointe",
"File to share" : "Fichier à partager",
@@ -210,6 +213,8 @@ OC.L10N.register(
"Select Date" : "Sélectionnez une date",
"Today" : "Aujourd'hui",
"Tomorrow" : "Demain",
"Next week" : "Semaine suivante",
"Next month" : "Mois suivant",
"Save" : "Enregistrer",
"The comment cannot be empty." : "Un commentaire ne peut pas être vide.",
"The comment cannot be longer than 1000 characters." : "Un commentaire est limité à 1 000 caractères.",

View File

@@ -183,8 +183,11 @@
"Members" : "Membres",
"Upload new files" : "Téléverser de nouveaux fichiers",
"Share from Files" : "Partager vos fichiers déjà stockés",
"Pending share" : "Partage en attente",
"Add this attachment" : "Ajouter cette pièce jointe",
"Show in Files" : "Afficher dans Fichiers",
"Download" : "Télécharger",
"Remove attachment" : "Supprimer la pièce jointe",
"Delete Attachment" : "Supprimer la pièce jointe",
"Restore Attachment" : "Restaurer la pièce jointe",
"File to share" : "Fichier à partager",
@@ -208,6 +211,8 @@
"Select Date" : "Sélectionnez une date",
"Today" : "Aujourd'hui",
"Tomorrow" : "Demain",
"Next week" : "Semaine suivante",
"Next month" : "Mois suivant",
"Save" : "Enregistrer",
"The comment cannot be empty." : "Un commentaire ne peut pas être vide.",
"The comment cannot be longer than 1000 characters." : "Un commentaire est limité à 1 000 caractères.",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Függőben lévő megosztás",
"Add this attachment" : "E melléklet hozzáadása",
"Show in Files" : "Megjelenítés a Fájlokban",
"Download" : "Letöltés",
"Remove attachment" : "Melléklet eltávolítása",
"Delete Attachment" : "Melléklet törlése",
"Restore Attachment" : "Melléklet visszaállítása",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Függőben lévő megosztás",
"Add this attachment" : "E melléklet hozzáadása",
"Show in Files" : "Megjelenítés a Fájlokban",
"Download" : "Letöltés",
"Remove attachment" : "Melléklet eltávolítása",
"Delete Attachment" : "Melléklet törlése",
"Restore Attachment" : "Melléklet visszaállítása",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Condivisione in attesa",
"Add this attachment" : "Aggiungi questo allegato",
"Show in Files" : "Mostra in File",
"Download" : "Scarica",
"Remove attachment" : "Rimuovi allegato",
"Delete Attachment" : "Elimina allegato",
"Restore Attachment" : "Ripristina allegato",
@@ -212,6 +213,8 @@ OC.L10N.register(
"Select Date" : "Seleziona data",
"Today" : "Oggi",
"Tomorrow" : "Domani",
"Next week" : "Settimana successiva",
"Next month" : "Mese successivo",
"Save" : "Salva",
"The comment cannot be empty." : "Il commento non può essere vuoto.",
"The comment cannot be longer than 1000 characters." : "Il commento non può essere più lungo di 1000 caratteri.",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Condivisione in attesa",
"Add this attachment" : "Aggiungi questo allegato",
"Show in Files" : "Mostra in File",
"Download" : "Scarica",
"Remove attachment" : "Rimuovi allegato",
"Delete Attachment" : "Elimina allegato",
"Restore Attachment" : "Ripristina allegato",
@@ -210,6 +211,8 @@
"Select Date" : "Seleziona data",
"Today" : "Oggi",
"Tomorrow" : "Domani",
"Next week" : "Settimana successiva",
"Next month" : "Mese successivo",
"Save" : "Salva",
"The comment cannot be empty." : "Il commento non può essere vuoto.",
"The comment cannot be longer than 1000 characters." : "Il commento non può essere più lungo di 1000 caratteri.",

View File

@@ -101,9 +101,16 @@ OC.L10N.register(
"Select the board to link to a project" : "Pasirinkite lentą, kurią susieti su projektu",
"Search by board title" : "Ieškoti pagal lentos pavadinimą",
"Select board" : "Pasirinkti lentą",
"Create a new card" : "Sukurti naują kortelę",
"Select a board" : "Pasirinkite lentą",
"Select a list" : "Pasirinkite sąrašą",
"Card title" : "Kortelės pavadinimas",
"Cancel" : "Atsisakyti",
"Creating the new card …" : "Kuriama nauja kortelė…",
"Card \"{card}\" was added to \"{board}\"" : "Kortelė „{card}“ buvo pridėta į lentą „{board}“",
"Open card" : "Atverti kortelę",
"Close" : "Užverti",
"Create card" : "Sukurti kortelę",
"Select a card" : "Pasirinkti kortelę",
"Select the card to link to a project" : "Pasirinkite kortelę, kurią susieti su projektu",
"Link to card" : "Susieti su kortele",
@@ -113,6 +120,7 @@ OC.L10N.register(
"Overwrite file" : "Perrašyti failą",
"Keep existing file" : "Palikti esamą failą",
"This board is read only" : "Ši lenta yra tik skaitymui",
"Drop your files to upload" : "Tempkite failus, norėdami juos išsiųsti",
"Add card" : "Pridėti kortelę",
"Archived cards" : "Archyvuotos kortelės",
"Add list" : "Pridėti sąrašą",
@@ -151,6 +159,7 @@ OC.L10N.register(
"Can share" : "Can share",
"Can manage" : "Gali tvarkyti",
"Delete" : "Ištrinti",
"Failed to create share with {displayName}" : "Nepavyko sukurti viešinio su {displayName}",
"Add a new list" : "Pridėti naują sąrašą",
"Archive all cards" : "Archyvuoti visas korteles",
"Delete list" : "Ištrinti sąrašą",
@@ -163,9 +172,15 @@ OC.L10N.register(
"title and color value must be provided" : "privalo būti pateiktos pavadinimo ir spalvos reikšmės",
"Board name" : "Lentos pavadinimas",
"Members" : "Nariai",
"Upload new files" : "Išsiųsti naujus failus",
"Share from Files" : "Bendrinti iš failų",
"Add this attachment" : "Pridėti šį priedą",
"Show in Files" : "Rodyti failuose",
"Download" : "Atsisiųsti",
"Remove attachment" : "Šalinti priedą",
"Delete Attachment" : "Ištrinti priedą",
"Restore Attachment" : "Atkurti priedą",
"File to share" : "Failas, kurį bendrinti",
"Invalid path selected" : "Pasirinktas neteisingas kelias",
"Open in sidebar view" : "Atverti šoninės juostos rodinyje",
"Open in bigger view" : "Atverti didesniame rodinyje",
@@ -173,7 +188,9 @@ OC.L10N.register(
"Comments" : "Komentarai",
"Modified" : "Pakeistas",
"Created" : "Sukurta",
"The title cannot be empty." : "Pavadinimas negali būti tuščias.",
"No comments yet. Begin the discussion!" : "Kol kas komentarų nėra. Pradėkite diskusiją!",
"Failed to load comments" : "Nepavyko įkelti komentarų",
"Assign a tag to this card…" : "Priskirti šiai kortelei žymę…",
"Assign to users" : "Priskirti naudotojams",
"Assign to users/groups/circles" : "Priskirti naudotojams/grupėms/ratams",
@@ -199,6 +216,7 @@ OC.L10N.register(
"Write a description …" : "Parašykite aprašą…",
"Choose attachment" : "Pasirinkite priedą",
"(group)" : "(grupė)",
"{count} comments, {unread} unread" : "Komentarų: {count}, neskaityta: {unread}",
"Assign to me" : "Priskirti sau",
"Move card" : "Perkelti kortelę",
"Unarchive card" : "Išarchyvuoti kortelę",
@@ -210,6 +228,7 @@ OC.L10N.register(
"All boards" : "Visos lentos",
"Archived boards" : "Archyvuotos lentos",
"Shared with you" : "Bendrinama su jumis",
"Use bigger card view" : "Naudoti didesnį kortelių rodinį",
"Show boards in calendar/tasks" : "Rodyti darbus kalendoriuje/užduotyse",
"Board details" : "Išsamiau apie lentą",
"Edit board" : "Taisyti lentą",
@@ -230,8 +249,10 @@ OC.L10N.register(
"Delete the board?" : "Ištrinti lentą?",
"This week" : "Šią savaitę",
"No due" : "Be galutinio termino",
"No results found" : "Nerasta jokių rezultatų",
"Link to a board" : "Susieti su lenta",
"Link to a card" : "Susieti su kortele",
"Create a card" : "Sukurti kortelę",
"Something went wrong" : "Kažkas nutiko",
"Maximum file size of {size} exceeded" : "Viršytas maksimalus {size} failo dydis",
"Error creating the share" : "Klaida kuriant viešinį",

View File

@@ -99,9 +99,16 @@
"Select the board to link to a project" : "Pasirinkite lentą, kurią susieti su projektu",
"Search by board title" : "Ieškoti pagal lentos pavadinimą",
"Select board" : "Pasirinkti lentą",
"Create a new card" : "Sukurti naują kortelę",
"Select a board" : "Pasirinkite lentą",
"Select a list" : "Pasirinkite sąrašą",
"Card title" : "Kortelės pavadinimas",
"Cancel" : "Atsisakyti",
"Creating the new card …" : "Kuriama nauja kortelė…",
"Card \"{card}\" was added to \"{board}\"" : "Kortelė „{card}“ buvo pridėta į lentą „{board}“",
"Open card" : "Atverti kortelę",
"Close" : "Užverti",
"Create card" : "Sukurti kortelę",
"Select a card" : "Pasirinkti kortelę",
"Select the card to link to a project" : "Pasirinkite kortelę, kurią susieti su projektu",
"Link to card" : "Susieti su kortele",
@@ -111,6 +118,7 @@
"Overwrite file" : "Perrašyti failą",
"Keep existing file" : "Palikti esamą failą",
"This board is read only" : "Ši lenta yra tik skaitymui",
"Drop your files to upload" : "Tempkite failus, norėdami juos išsiųsti",
"Add card" : "Pridėti kortelę",
"Archived cards" : "Archyvuotos kortelės",
"Add list" : "Pridėti sąrašą",
@@ -149,6 +157,7 @@
"Can share" : "Can share",
"Can manage" : "Gali tvarkyti",
"Delete" : "Ištrinti",
"Failed to create share with {displayName}" : "Nepavyko sukurti viešinio su {displayName}",
"Add a new list" : "Pridėti naują sąrašą",
"Archive all cards" : "Archyvuoti visas korteles",
"Delete list" : "Ištrinti sąrašą",
@@ -161,9 +170,15 @@
"title and color value must be provided" : "privalo būti pateiktos pavadinimo ir spalvos reikšmės",
"Board name" : "Lentos pavadinimas",
"Members" : "Nariai",
"Upload new files" : "Išsiųsti naujus failus",
"Share from Files" : "Bendrinti iš failų",
"Add this attachment" : "Pridėti šį priedą",
"Show in Files" : "Rodyti failuose",
"Download" : "Atsisiųsti",
"Remove attachment" : "Šalinti priedą",
"Delete Attachment" : "Ištrinti priedą",
"Restore Attachment" : "Atkurti priedą",
"File to share" : "Failas, kurį bendrinti",
"Invalid path selected" : "Pasirinktas neteisingas kelias",
"Open in sidebar view" : "Atverti šoninės juostos rodinyje",
"Open in bigger view" : "Atverti didesniame rodinyje",
@@ -171,7 +186,9 @@
"Comments" : "Komentarai",
"Modified" : "Pakeistas",
"Created" : "Sukurta",
"The title cannot be empty." : "Pavadinimas negali būti tuščias.",
"No comments yet. Begin the discussion!" : "Kol kas komentarų nėra. Pradėkite diskusiją!",
"Failed to load comments" : "Nepavyko įkelti komentarų",
"Assign a tag to this card…" : "Priskirti šiai kortelei žymę…",
"Assign to users" : "Priskirti naudotojams",
"Assign to users/groups/circles" : "Priskirti naudotojams/grupėms/ratams",
@@ -197,6 +214,7 @@
"Write a description …" : "Parašykite aprašą…",
"Choose attachment" : "Pasirinkite priedą",
"(group)" : "(grupė)",
"{count} comments, {unread} unread" : "Komentarų: {count}, neskaityta: {unread}",
"Assign to me" : "Priskirti sau",
"Move card" : "Perkelti kortelę",
"Unarchive card" : "Išarchyvuoti kortelę",
@@ -208,6 +226,7 @@
"All boards" : "Visos lentos",
"Archived boards" : "Archyvuotos lentos",
"Shared with you" : "Bendrinama su jumis",
"Use bigger card view" : "Naudoti didesnį kortelių rodinį",
"Show boards in calendar/tasks" : "Rodyti darbus kalendoriuje/užduotyse",
"Board details" : "Išsamiau apie lentą",
"Edit board" : "Taisyti lentą",
@@ -228,8 +247,10 @@
"Delete the board?" : "Ištrinti lentą?",
"This week" : "Šią savaitę",
"No due" : "Be galutinio termino",
"No results found" : "Nerasta jokių rezultatų",
"Link to a board" : "Susieti su lenta",
"Link to a card" : "Susieti su kortele",
"Create a card" : "Sukurti kortelę",
"Something went wrong" : "Kažkas nutiko",
"Maximum file size of {size} exceeded" : "Viršytas maksimalus {size} failo dydis",
"Error creating the share" : "Klaida kuriant viešinį",

View File

@@ -135,7 +135,7 @@ OC.L10N.register(
"Add list" : "Lijst toevoegen",
"List name" : "Lijstnaam",
"Apply filter" : "Filter toepassen",
"Filter by tag" : "Filter op label",
"Filter by tag" : "Filteren op label",
"Filter by assigned user" : "Filter op toegewezen gebruiker",
"Unassigned" : "Niet-toegewezen",
"Filter by due date" : "Filter op vervaldatum",
@@ -185,8 +185,10 @@ OC.L10N.register(
"Members" : "Leden",
"Upload new files" : "Uploaden nieuwe bestanden",
"Share from Files" : "Delen vanuit Bestanden",
"Pending share" : "Share in afwachting",
"Add this attachment" : "Voeg deze bijlage toe",
"Show in Files" : "Tonen in Bestanden",
"Download" : "Download",
"Remove attachment" : "Bijlage verwijderen",
"Delete Attachment" : "Verwijderen bijlage",
"Restore Attachment" : "Herstellen bijlage",
@@ -211,6 +213,8 @@ OC.L10N.register(
"Select Date" : "Selecteer datum",
"Today" : "Vandaag",
"Tomorrow" : "Morgen",
"Next week" : "Volgende week",
"Next month" : "Volgende maand",
"Save" : "Opslaan",
"The comment cannot be empty." : "De reactie kan niet leeg zijn.",
"The comment cannot be longer than 1000 characters." : "De reactie kan niet langer dan 1000 tekens zijn.",

View File

@@ -133,7 +133,7 @@
"Add list" : "Lijst toevoegen",
"List name" : "Lijstnaam",
"Apply filter" : "Filter toepassen",
"Filter by tag" : "Filter op label",
"Filter by tag" : "Filteren op label",
"Filter by assigned user" : "Filter op toegewezen gebruiker",
"Unassigned" : "Niet-toegewezen",
"Filter by due date" : "Filter op vervaldatum",
@@ -183,8 +183,10 @@
"Members" : "Leden",
"Upload new files" : "Uploaden nieuwe bestanden",
"Share from Files" : "Delen vanuit Bestanden",
"Pending share" : "Share in afwachting",
"Add this attachment" : "Voeg deze bijlage toe",
"Show in Files" : "Tonen in Bestanden",
"Download" : "Download",
"Remove attachment" : "Bijlage verwijderen",
"Delete Attachment" : "Verwijderen bijlage",
"Restore Attachment" : "Herstellen bijlage",
@@ -209,6 +211,8 @@
"Select Date" : "Selecteer datum",
"Today" : "Vandaag",
"Tomorrow" : "Morgen",
"Next week" : "Volgende week",
"Next month" : "Volgende maand",
"Save" : "Opslaan",
"The comment cannot be empty." : "De reactie kan niet leeg zijn.",
"The comment cannot be longer than 1000 characters." : "De reactie kan niet langer dan 1000 tekens zijn.",

View File

@@ -19,6 +19,8 @@ OC.L10N.register(
"Upload new files" : "Enviar fichièrs novèls",
"Today" : "Uèi",
"Tomorrow" : "Deman",
"Next week" : "Setmana seguenta",
"Next month" : "Mes seguent",
"Save" : "Salvar",
"Cancel reply" : "Anullar la responsa",
"Reply" : "Respondre",

View File

@@ -17,6 +17,8 @@
"Upload new files" : "Enviar fichièrs novèls",
"Today" : "Uèi",
"Tomorrow" : "Deman",
"Next week" : "Setmana seguenta",
"Next month" : "Mes seguent",
"Save" : "Salvar",
"Cancel reply" : "Anullar la responsa",
"Reply" : "Respondre",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Oczekujące udostępnienie",
"Add this attachment" : "Dodaj ten załącznik",
"Show in Files" : "Pokaż w Plikach",
"Download" : "Pobierz",
"Remove attachment" : "Usuń załącznik",
"Delete Attachment" : "Usuń załącznik",
"Restore Attachment" : "Przywróć załącznik",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Oczekujące udostępnienie",
"Add this attachment" : "Dodaj ten załącznik",
"Show in Files" : "Pokaż w Plikach",
"Download" : "Pobierz",
"Remove attachment" : "Usuń załącznik",
"Delete Attachment" : "Usuń załącznik",
"Restore Attachment" : "Przywróć załącznik",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Compartilhamento pendente",
"Add this attachment" : "Adicionar este anexo",
"Show in Files" : "Mostrar em Arquivos",
"Download" : "Baixar",
"Remove attachment" : "Remover anexo",
"Delete Attachment" : "Excluir Anexo",
"Restore Attachment" : "Restaurar Anexo",
@@ -212,6 +213,8 @@ OC.L10N.register(
"Select Date" : "Selecionar Data",
"Today" : "Hoje",
"Tomorrow" : "Amanhã",
"Next week" : "Próxima semana",
"Next month" : "Próximo mês",
"Save" : "Salvar",
"The comment cannot be empty." : "O comentário não pode zer vazio.",
"The comment cannot be longer than 1000 characters." : "O comentário não pode ter mais que 1000 caracteres.",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Compartilhamento pendente",
"Add this attachment" : "Adicionar este anexo",
"Show in Files" : "Mostrar em Arquivos",
"Download" : "Baixar",
"Remove attachment" : "Remover anexo",
"Delete Attachment" : "Excluir Anexo",
"Restore Attachment" : "Restaurar Anexo",
@@ -210,6 +211,8 @@
"Select Date" : "Selecionar Data",
"Today" : "Hoje",
"Tomorrow" : "Amanhã",
"Next week" : "Próxima semana",
"Next month" : "Próximo mês",
"Save" : "Salvar",
"The comment cannot be empty." : "O comentário não pode zer vazio.",
"The comment cannot be longer than 1000 characters." : "O comentário não pode ter mais que 1000 caracteres.",

View File

@@ -187,6 +187,7 @@ OC.L10N.register(
"Share from Files" : "Опубликовать из приложения «Файлы»",
"Add this attachment" : "Добавить это вложение",
"Show in Files" : "Показать в приложении «Файлы»",
"Remove attachment" : "Убрать вложение",
"Delete Attachment" : "Удалить вложение",
"Restore Attachment" : "Восстановить вложение",
"File to share" : "Файл для публикации",
@@ -210,6 +211,8 @@ OC.L10N.register(
"Select Date" : "Выберите дату",
"Today" : "Сегодня",
"Tomorrow" : "Завтра",
"Next week" : "Следующая неделя",
"Next month" : "Следующий месяц",
"Save" : "Сохранить",
"The comment cannot be empty." : "Комментарий не может быть пустым.",
"The comment cannot be longer than 1000 characters." : "Комментарий не может быть длиннее 1 000 символов.",

View File

@@ -185,6 +185,7 @@
"Share from Files" : "Опубликовать из приложения «Файлы»",
"Add this attachment" : "Добавить это вложение",
"Show in Files" : "Показать в приложении «Файлы»",
"Remove attachment" : "Убрать вложение",
"Delete Attachment" : "Удалить вложение",
"Restore Attachment" : "Восстановить вложение",
"File to share" : "Файл для публикации",
@@ -208,6 +209,8 @@
"Select Date" : "Выберите дату",
"Today" : "Сегодня",
"Tomorrow" : "Завтра",
"Next week" : "Следующая неделя",
"Next month" : "Следующий месяц",
"Save" : "Сохранить",
"The comment cannot be empty." : "Комментарий не может быть пустым.",
"The comment cannot be longer than 1000 characters." : "Комментарий не может быть длиннее 1 000 символов.",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Čakajúce zdeľanie",
"Add this attachment" : "Pridať túto prílohu",
"Show in Files" : "Zobraziť v Súboroch",
"Download" : "Sťahovanie",
"Remove attachment" : "Odstrániť prílohu",
"Delete Attachment" : "Odstrániť prílohu",
"Restore Attachment" : "Obnoviť prílohu",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Čakajúce zdeľanie",
"Add this attachment" : "Pridať túto prílohu",
"Show in Files" : "Zobraziť v Súboroch",
"Download" : "Sťahovanie",
"Remove attachment" : "Odstrániť prílohu",
"Delete Attachment" : "Odstrániť prílohu",
"Restore Attachment" : "Obnoviť prílohu",

View File

@@ -181,12 +181,13 @@ OC.L10N.register(
"Edit" : "Uredi",
"Add a new tag" : "Dodaj novo oznako",
"title and color value must be provided" : "navedena morata biti podatka naslova in barve",
"Board name" : "Ime zbirke",
"Board name" : "Ime zbirke",
"Members" : "Člani",
"Upload new files" : "Pošlji nove datoteke",
"Share from Files" : "Poveži iz oblaka",
"Add this attachment" : "Dodaj prilogo",
"Show in Files" : "Poveži iz oblaka",
"Download" : "Prejmi",
"Remove attachment" : "Odstrani prilogo",
"Delete Attachment" : "Izbriši prilogo",
"Restore Attachment" : "Obnovi prilogo",
@@ -211,6 +212,8 @@ OC.L10N.register(
"Select Date" : "Izbor datuma",
"Today" : "Danes",
"Tomorrow" : "Jutri",
"Next week" : "Naslednji teden",
"Next month" : "Naslednji mesec",
"Save" : "Shrani",
"The comment cannot be empty." : "Polje opombe ne sme biti prazno.",
"The comment cannot be longer than 1000 characters." : "Opomba ne sme biti daljša od 1000 znakov.",

View File

@@ -179,12 +179,13 @@
"Edit" : "Uredi",
"Add a new tag" : "Dodaj novo oznako",
"title and color value must be provided" : "navedena morata biti podatka naslova in barve",
"Board name" : "Ime zbirke",
"Board name" : "Ime zbirke",
"Members" : "Člani",
"Upload new files" : "Pošlji nove datoteke",
"Share from Files" : "Poveži iz oblaka",
"Add this attachment" : "Dodaj prilogo",
"Show in Files" : "Poveži iz oblaka",
"Download" : "Prejmi",
"Remove attachment" : "Odstrani prilogo",
"Delete Attachment" : "Izbriši prilogo",
"Restore Attachment" : "Obnovi prilogo",
@@ -209,6 +210,8 @@
"Select Date" : "Izbor datuma",
"Today" : "Danes",
"Tomorrow" : "Jutri",
"Next week" : "Naslednji teden",
"Next month" : "Naslednji mesec",
"Save" : "Shrani",
"The comment cannot be empty." : "Polje opombe ne sme biti prazno.",
"The comment cannot be longer than 1000 characters." : "Opomba ne sme biti daljša od 1000 znakov.",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "Bekleyen paylaşım",
"Add this attachment" : "Bu dosyayı ekle",
"Show in Files" : "Dosyalarda görüntüle",
"Download" : "İndir",
"Remove attachment" : "Ek dosyayı sil",
"Delete Attachment" : "Ek dosyasını sil",
"Restore Attachment" : "Ek dosyasını geri yükle",

View File

@@ -186,6 +186,7 @@
"Pending share" : "Bekleyen paylaşım",
"Add this attachment" : "Bu dosyayı ekle",
"Show in Files" : "Dosyalarda görüntüle",
"Download" : "İndir",
"Remove attachment" : "Ek dosyayı sil",
"Delete Attachment" : "Ek dosyasını sil",
"Restore Attachment" : "Ek dosyasını geri yükle",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "待分享",
"Add this attachment" : "添加此附件",
"Show in Files" : "在文件中显示",
"Download" : "下载",
"Remove attachment" : "删除附件",
"Delete Attachment" : "删除附件",
"Restore Attachment" : "恢复附件",

View File

@@ -186,6 +186,7 @@
"Pending share" : "待分享",
"Add this attachment" : "添加此附件",
"Show in Files" : "在文件中显示",
"Download" : "下载",
"Remove attachment" : "删除附件",
"Delete Attachment" : "删除附件",
"Restore Attachment" : "恢复附件",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "等待分享",
"Add this attachment" : "添加此附件",
"Show in Files" : "顯示在檔案中",
"Download" : "下載",
"Remove attachment" : "移除附件",
"Delete Attachment" : "刪除附件",
"Restore Attachment" : "恢復附件",

View File

@@ -186,6 +186,7 @@
"Pending share" : "等待分享",
"Add this attachment" : "添加此附件",
"Show in Files" : "顯示在檔案中",
"Download" : "下載",
"Remove attachment" : "移除附件",
"Delete Attachment" : "刪除附件",
"Restore Attachment" : "恢復附件",

View File

@@ -188,6 +188,7 @@ OC.L10N.register(
"Pending share" : "待分享",
"Add this attachment" : "新增此附件",
"Show in Files" : "在「檔案」中顯示",
"Download" : "下載",
"Remove attachment" : "移除附件",
"Delete Attachment" : "刪除附件",
"Restore Attachment" : "還原附件",
@@ -212,6 +213,8 @@ OC.L10N.register(
"Select Date" : "選擇日期",
"Today" : "今天",
"Tomorrow" : "明天",
"Next week" : "下週",
"Next month" : "下個月",
"Save" : "儲存",
"The comment cannot be empty." : "留言不能為空。",
"The comment cannot be longer than 1000 characters." : "留言不能多於 1000 個字元。",

View File

@@ -186,6 +186,7 @@
"Pending share" : "待分享",
"Add this attachment" : "新增此附件",
"Show in Files" : "在「檔案」中顯示",
"Download" : "下載",
"Remove attachment" : "移除附件",
"Delete Attachment" : "刪除附件",
"Restore Attachment" : "還原附件",
@@ -210,6 +211,8 @@
"Select Date" : "選擇日期",
"Today" : "今天",
"Tomorrow" : "明天",
"Next week" : "下週",
"Next month" : "下個月",
"Save" : "儲存",
"The comment cannot be empty." : "留言不能為空。",
"The comment cannot be longer than 1000 characters." : "留言不能多於 1000 個字元。",

View File

@@ -100,6 +100,9 @@ class ResourceProvider implements IProvider {
if ($board->getOwner() === $user->getUID()) {
return true;
}
if ($board->getAcl() === null) {
return false;
}
return $this->permissionService->userCan($board->getAcl(), Acl::PERMISSION_READ, $user->getUID());
}

View File

@@ -127,6 +127,9 @@ class ResourceProviderCard implements IProvider {
if ($board->getOwner() === $user->getUID()) {
return true;
}
if ($board->getAcl() === null) {
return false;
}
return $this->permissionService->userCan($board->getAcl(), Acl::PERMISSION_READ, $user->getUID());
}

View File

@@ -28,8 +28,10 @@ class Board extends RelationalEntity {
protected $owner;
protected $color;
protected $archived = false;
protected $labels = [];
protected $acl = [];
/** @var Label[]|null */
protected $labels = null;
/** @var Acl[]|null */
protected $acl = null;
protected $permissions = [];
protected $users = [];
protected $shared;
@@ -61,6 +63,10 @@ class Board extends RelationalEntity {
if ($this->shared === -1) {
unset($json['shared']);
}
// FIXME: Ideally the API responses should follow the internal data structure and return null if the labels/acls have not been fetched from the db
// however this would be a breaking change for consumers of the API
$json['acl'] = $this->acl ?? [];
$json['labels'] = $this->labels ?? [];
return $json;
}
@@ -68,21 +74,27 @@ class Board extends RelationalEntity {
* @param Label[] $labels
*/
public function setLabels($labels) {
foreach ($labels as $l) {
$this->labels[] = $l;
}
$this->labels = $labels;
}
/**
* @param Acl[] $acl
*/
public function setAcl($acl) {
foreach ($acl as $a) {
$this->acl[] = $a;
}
$this->acl = $acl;
}
public function getETag() {
return md5((string)$this->getLastModified());
}
/** @returns Acl[]|null */
public function getAcl(): ?array {
return $this->acl;
}
/** @returns Label[]|null */
public function getLabels(): ?array {
return $this->labels;
}
}

View File

@@ -25,12 +25,14 @@ namespace OCA\Deck\Db;
use OC\Cache\CappedMemoryCache;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IUserManager;
use OCP\IGroupManager;
use Psr\Log\LoggerInterface;
class BoardMapper extends DeckMapper implements IPermissionMapper {
class BoardMapper extends QBMapper implements IPermissionMapper {
private $labelMapper;
private $aclMapper;
private $stackMapper;
@@ -40,7 +42,10 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
private $circlesEnabled;
/** @var CappedMemoryCache */
private $userBoardCache;
/** @var CappedMemoryCache */
private $boardCache;
public function __construct(
IDBConnection $db,
@@ -60,7 +65,7 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
$this->logger = $logger;
$this->userBoardCache = new CappedMemoryCache();
$this->boardCache = new CappedMemoryCache();
$this->circlesEnabled = \OC::$server->getAppManager()->isEnabledForUser('circles');
}
@@ -70,28 +75,36 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
* @param $id
* @param bool $withLabels
* @param bool $withAcl
* @return \OCP\AppFramework\Db\Entity
* @return Board
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @throws DoesNotExistException
*/
public function find($id, $withLabels = false, $withAcl = false) {
$sql = 'SELECT id, title, owner, color, archived, deleted_at, last_modified FROM `*PREFIX*deck_boards` ' .
'WHERE `id` = ?';
$board = $this->findEntity($sql, [$id]);
public function find($id, $withLabels = false, $withAcl = false): Board {
if (!isset($this->boardCache[$id])) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from('deck_boards')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT)))
->orderBy('id');
$this->boardCache[$id] = $this->findEntity($qb);
}
// FIXME is this necessary? it was NOT done with the old mapper
// $this->mapOwner($board);
// Add labels
if ($withLabels) {
if ($withLabels && $this->boardCache[$id]->getLabels() === null) {
$labels = $this->labelMapper->findAll($id);
$board->setLabels($labels);
$this->boardCache[$id]->setLabels($labels);
}
// Add acl
if ($withAcl) {
if ($withAcl && $this->boardCache[$id]->getAcl() === null) {
$acl = $this->aclMapper->findAll($id);
$board->setAcl($acl);
$this->boardCache[$id]->setAcl($acl);
}
return $board;
return $this->boardCache[$id];
}
public function findAllForUser(string $userId, ?int $since = null, bool $includeArchived = true, ?int $before = null,
@@ -105,6 +118,9 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
$groupBoards = $this->findAllByGroups($userId, $groups, null, null, $since, $includeArchived, $before, $term);
$circleBoards = $this->findAllByCircles($userId, null, null, $since, $includeArchived, $before, $term);
$allBoards = array_unique(array_merge($userBoards, $groupBoards, $circleBoards));
foreach ($allBoards as $board) {
$this->boardCache[$board->getId()] = $board;
}
if ($useCache) {
$this->userBoardCache[$userId] = $allBoards;
}
@@ -123,44 +139,89 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
*/
public function findAllByUser(string $userId, ?int $limit = null, ?int $offset = null, ?int $since = null,
bool $includeArchived = true, ?int $before = null, ?string $term = null) {
// FIXME: One moving to QBMapper we should allow filtering the boards probably by method chaining for additional where clauses
$sql = 'SELECT id, title, owner, color, archived, deleted_at, 0 as shared, last_modified FROM `*PREFIX*deck_boards` WHERE owner = ?';
$params = [$userId];
// 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();
$qb->select('id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
// this does not work in MySQL/PostgreSQL
//->selectAlias('0', 'shared')
->from('deck_boards', 'b')
->where($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
if (!$includeArchived) {
$sql .= ' AND NOT archived AND deleted_at = 0';
$qb->andWhere($qb->expr()->eq('archived', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
}
if ($since !== null) {
$sql .= ' AND last_modified > ?';
$params[] = $since;
$qb->andWhere($qb->expr()->gt('last_modified', $qb->createNamedParameter($since, IQueryBuilder::PARAM_INT)));
}
if ($before !== null) {
$sql .= ' AND last_modified < ?';
$params[] = $before;
$qb->andWhere($qb->expr()->lt('last_modified', $qb->createNamedParameter($before, IQueryBuilder::PARAM_INT)));
}
if ($term !== null) {
$sql .= ' AND lower(title) LIKE ?';
$params[] = '%' . $term . '%';
$qb->andWhere(
$qb->expr()->iLike(
'title',
$qb->createNamedParameter(
'%' . $this->db->escapeLikeParameter($term) . '%',
IQueryBuilder::PARAM_STR
)
)
);
}
$sql .= ' UNION ' .
'SELECT boards.id, title, owner, color, archived, deleted_at, 1 as shared, last_modified FROM `*PREFIX*deck_boards` as boards ' .
'JOIN `*PREFIX*deck_board_acl` as acl ON boards.id=acl.board_id WHERE acl.participant=? AND acl.type=? AND boards.owner != ?';
array_push($params, $userId, Acl::PERMISSION_TYPE_USER, $userId);
$qb->orderBy('b.id');
if ($limit !== null) {
$qb->setMaxResults($limit);
}
if ($offset !== null) {
$qb->setFirstResult($offset);
}
$entries = $this->findEntities($qb);
foreach ($entries as $entry) {
$entry->setShared(0);
}
// shared with user
$qb->resetQueryParts();
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
//->selectAlias('1', 'shared')
->from('deck_boards', 'b')
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
->where($qb->expr()->eq('acl.participant', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)))
->andWhere($qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_USER, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->neq('b.owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
if (!$includeArchived) {
$sql .= ' AND NOT archived AND deleted_at = 0';
$qb->andWhere($qb->expr()->eq('archived', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
}
if ($since !== null) {
$sql .= ' AND last_modified > ?';
$params[] = $since;
$qb->andWhere($qb->expr()->gt('last_modified', $qb->createNamedParameter($since, IQueryBuilder::PARAM_INT)));
}
if ($before !== null) {
$sql .= ' AND last_modified < ?';
$params[] = $before;
$qb->andWhere($qb->expr()->lt('last_modified', $qb->createNamedParameter($before, IQueryBuilder::PARAM_INT)));
}
if ($term !== null) {
$sql .= ' AND lower(title) LIKE ?';
$params[] = '%' . $term . '%';
$qb->andWhere(
$qb->expr()->iLike(
'title',
$qb->createNamedParameter(
'%' . $this->db->escapeLikeParameter($term) . '%',
IQueryBuilder::PARAM_STR
)
)
);
}
$entries = $this->findEntities($sql, $params, $limit, $offset);
$qb->orderBy('b.id');
if ($limit !== null) {
$qb->setMaxResults($limit);
}
if ($offset !== null) {
$qb->setFirstResult($offset);
}
$sharedEntries = $this->findEntities($qb);
foreach ($sharedEntries as $entry) {
$entry->setShared(1);
}
$entries = array_merge($entries, $sharedEntries);
/* @var Board $entry */
foreach ($entries as $entry) {
$acl = $this->aclMapper->findAll($entry->id);
@@ -169,9 +230,19 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
return $entries;
}
public function findAllByOwner(string $userId, int $limit = null, int $offset = null) {
$sql = 'SELECT * FROM `*PREFIX*deck_boards` WHERE owner = ?';
return $this->findEntities($sql, [$userId], $limit, $offset);
public function findAllByOwner(string $userId, ?int $limit = null, ?int $offset = null) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from('deck_boards')
->where($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)))
->orderBy('id');
if ($limit !== null) {
$qb->setMaxResults($limit);
}
if ($offset !== null) {
$qb->setFirstResult($offset);
}
return $this->findEntities($qb);
}
/**
@@ -188,33 +259,52 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
if (count($groups) <= 0) {
return [];
}
$sql = 'SELECT boards.id, title, owner, color, archived, deleted_at, 2 as shared, last_modified FROM `*PREFIX*deck_boards` as boards ' .
'INNER JOIN `*PREFIX*deck_board_acl` as acl ON boards.id=acl.board_id WHERE owner != ? AND type=? AND (';
$params = [$userId, Acl::PERMISSION_TYPE_GROUP];
$qb = $this->db->getQueryBuilder();
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
//->selectAlias('2', 'shared')
->from('deck_boards', 'b')
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
->where($qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_GROUP, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->neq('b.owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
$or = $qb->expr()->orx();
for ($i = 0, $iMax = count($groups); $i < $iMax; $i++) {
$sql .= 'acl.participant = ? ';
if (count($groups) > 1 && $i < count($groups) - 1) {
$sql .= ' OR ';
}
$or->add(
$qb->expr()->eq('acl.participant', $qb->createNamedParameter($groups[$i], IQueryBuilder::PARAM_STR))
);
}
$sql .= ')';
array_push($params, ...$groups);
$qb->andWhere($or);
if (!$includeArchived) {
$sql .= ' AND NOT archived AND deleted_at = 0';
$qb->andWhere($qb->expr()->eq('archived', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
}
if ($since !== null) {
$sql .= ' AND last_modified > ?';
$params[] = $since;
$qb->andWhere($qb->expr()->gt('last_modified', $qb->createNamedParameter($since, IQueryBuilder::PARAM_INT)));
}
if ($before !== null) {
$sql .= ' AND last_modified < ?';
$params[] = $before;
$qb->andWhere($qb->expr()->lt('last_modified', $qb->createNamedParameter($before, IQueryBuilder::PARAM_INT)));
}
if ($term !== null) {
$sql .= ' AND lower(title) LIKE ?';
$params[] = '%' . $term . '%';
$qb->andWhere(
$qb->expr()->iLike(
'title',
$qb->createNamedParameter(
'%' . $this->db->escapeLikeParameter($term) . '%',
IQueryBuilder::PARAM_STR
)
)
);
}
$qb->orderBy('b.id');
if ($limit !== null) {
$qb->setMaxResults($limit);
}
if ($offset !== null) {
$qb->setFirstResult($offset);
}
$entries = $this->findEntities($qb);
foreach ($entries as $entry) {
$entry->setShared(2);
}
$entries = $this->findEntities($sql, $params, $limit, $offset);
/* @var Board $entry */
foreach ($entries as $entry) {
$acl = $this->aclMapper->findAll($entry->id);
@@ -235,33 +325,52 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
return [];
}
$sql = 'SELECT boards.id, title, owner, color, archived, deleted_at, 2 as shared, last_modified FROM `*PREFIX*deck_boards` as boards ' .
'INNER JOIN `*PREFIX*deck_board_acl` as acl ON boards.id=acl.board_id WHERE owner != ? AND type=? AND (';
$params = [$userId, Acl::PERMISSION_TYPE_CIRCLE];
$qb = $this->db->getQueryBuilder();
$qb->select('b.id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
//->selectAlias('2', 'shared')
->from('deck_boards', 'b')
->innerJoin('b', 'deck_board_acl', 'acl', $qb->expr()->eq('b.id', 'acl.board_id'))
->where($qb->expr()->eq('acl.type', $qb->createNamedParameter(Acl::PERMISSION_TYPE_CIRCLE, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->neq('b.owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR)));
$or = $qb->expr()->orx();
for ($i = 0, $iMax = count($circles); $i < $iMax; $i++) {
$sql .= 'acl.participant = ? ';
if (count($circles) > 1 && $i < count($circles) - 1) {
$sql .= ' OR ';
}
$or->add(
$qb->expr()->eq('acl.participant', $qb->createNamedParameter($circles[$i], IQueryBuilder::PARAM_STR))
);
}
$sql .= ')';
array_push($params, ...$circles);
$qb->andWhere($or);
if (!$includeArchived) {
$sql .= ' AND NOT archived AND deleted_at = 0';
$qb->andWhere($qb->expr()->eq('archived', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)))
->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)));
}
if ($since !== null) {
$sql .= ' AND last_modified > ?';
$params[] = $since;
$qb->andWhere($qb->expr()->gt('last_modified', $qb->createNamedParameter($since, IQueryBuilder::PARAM_INT)));
}
if ($before !== null) {
$sql .= ' AND last_modified < ?';
$params[] = $before;
$qb->andWhere($qb->expr()->lt('last_modified', $qb->createNamedParameter($before, IQueryBuilder::PARAM_INT)));
}
if ($term !== null) {
$sql .= ' AND lower(title) LIKE ?';
$params[] = '%' . $term . '%';
$qb->andWhere(
$qb->expr()->iLike(
'title',
$qb->createNamedParameter(
'%' . $this->db->escapeLikeParameter($term) . '%',
IQueryBuilder::PARAM_STR
)
)
);
}
$qb->orderBy('b.id');
if ($limit !== null) {
$qb->setMaxResults($limit);
}
if ($offset !== null) {
$qb->setFirstResult($offset);
}
$entries = $this->findEntities($qb);
foreach ($entries as $entry) {
$entry->setShared(2);
}
$entries = $this->findEntities($sql, $params, $limit, $offset);
/* @var Board $entry */
foreach ($entries as $entry) {
$acl = $this->aclMapper->findAll($entry->id);
@@ -270,21 +379,26 @@ class BoardMapper extends DeckMapper implements IPermissionMapper {
return $entries;
}
public function findAll() {
$sql = 'SELECT id from *PREFIX*deck_boards;';
return $this->findEntities($sql);
public function findAll(): array {
$qb = $this->db->getQueryBuilder();
$qb->select('id')
->from('deck_boards');
return $this->findEntities($qb);
}
public function findToDelete() {
// add buffer of 5 min
$timeLimit = time() - (60 * 5);
$sql = 'SELECT id, title, owner, color, archived, deleted_at, last_modified FROM `*PREFIX*deck_boards` ' .
'WHERE `deleted_at` > 0 AND `deleted_at` < ?';
return $this->findEntities($sql, [$timeLimit]);
$qb = $this->db->getQueryBuilder();
$qb->select('id', 'title', 'owner', 'color', 'archived', 'deleted_at', 'last_modified')
->from('deck_boards')
->where($qb->expr()->gt('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->lt('deleted_at', $qb->createNamedParameter($timeLimit, IQueryBuilder::PARAM_INT)));
return $this->findEntities($qb);
}
public function delete(/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
\OCP\AppFramework\Db\Entity $entity) {
\OCP\AppFramework\Db\Entity $entity): \OCP\AppFramework\Db\Entity {
// delete acl
$acl = $this->aclMapper->findAll($entity->getId());
foreach ($acl as $item) {

View File

@@ -30,6 +30,8 @@ use OCA\Deck\Search\Query\SearchQuery;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IDBConnection;
use OCP\IGroupManager;
use OCP\IUser;
@@ -46,6 +48,8 @@ class CardMapper extends QBMapper implements IPermissionMapper {
private $groupManager;
/** @var IManager */
private $notificationManager;
/** @var ICache */
private $cache;
private $databaseType;
private $database4ByteSupport;
@@ -55,6 +59,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
IUserManager $userManager,
IGroupManager $groupManager,
IManager $notificationManager,
ICacheFactory $cacheFactory,
$databaseType = 'sqlite3',
$database4ByteSupport = true
) {
@@ -63,6 +68,7 @@ class CardMapper extends QBMapper implements IPermissionMapper {
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->notificationManager = $notificationManager;
$this->cache = $cacheFactory->createDistributed('deck-cardMapper');
$this->databaseType = $databaseType;
$this->database4ByteSupport = $database4ByteSupport;
}
@@ -75,7 +81,9 @@ class CardMapper extends QBMapper implements IPermissionMapper {
$description = preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $entity->getDescription());
$entity->setDescription($description);
}
return parent::insert($entity);
$entity = parent::insert($entity);
$this->cache->remove('findBoardId:' . $entity->getId());
return $entity;
}
public function update(Entity $entity, $updateModified = true): Entity {
@@ -107,6 +115,10 @@ class CardMapper extends QBMapper implements IPermissionMapper {
} catch (Exception $e) {
}
}
// Invalidate cache when the card may be moved to a different board
if (isset($updatedFields['stackId'])) {
$this->cache->remove('findBoardId:' . $entity->getId());
}
return parent::update($entity);
}
@@ -479,8 +491,8 @@ class CardMapper extends QBMapper implements IPermissionMapper {
}
return $qb->createNamedParameter($dateTime, IQueryBuilder::PARAM_DATE);
}
public function searchRaw($boardIds, $term, $limit = null, $offset = null) {
$qb = $this->queryCardsByBoards($boardIds)
@@ -506,9 +518,8 @@ class CardMapper extends QBMapper implements IPermissionMapper {
}
public function delete(Entity $entity): Entity {
// delete assigned labels
$this->labelMapper->deleteLabelAssignmentsForCard($entity->getId());
// delete card
$this->cache->remove('findBoardId:' . $entity->getId());
return parent::delete($entity);
}
@@ -547,11 +558,22 @@ class CardMapper extends QBMapper implements IPermissionMapper {
}
public function findBoardId($id): ?int {
$sql = 'SELECT id 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);
$stmt->execute();
return $stmt->fetchColumn() ?? null;
$result = $this->cache->get('findBoardId:' . $id);
if ($result === null) {
try {
$qb = $this->db->getQueryBuilder();
$qb->select('board_id')
->from('deck_stacks', 's')
->innerJoin('s', 'deck_cards', 'c', 'c.stack_id = s.id')
->where($qb->expr()->eq('c.id', $qb->createNamedParameter($id)));
$queryResult = $qb->executeQuery();
$result = $queryResult->fetchOne();
} catch (\Exception $e) {
$result = false;
}
$this->cache->set('findBoardId:' . $id, $result);
}
return $result !== false ? $result : null;
}
public function mapOwner(Card &$card) {

View File

@@ -139,6 +139,6 @@ class DeckProvider implements IProvider {
$cardTimestamps = array_map(function (Card $card) {
return $card->getLastModified();
}, $cards);
return (min($boardTimestamps) ?: '') . '|' . (min($cardTimestamps) ?: '');
return (count($boardTimestamps) > 0 ? min($boardTimestamps) : '') . '|' . (count($cardTimestamps) > 0 ? min($cardTimestamps) : '');
}
}

View File

@@ -179,9 +179,11 @@ class BoardService {
/** @var Board $board */
$board = $this->boardMapper->find($boardId, true, true);
$this->boardMapper->mapOwner($board);
foreach ($board->getAcl() as &$acl) {
if ($acl !== null) {
$this->boardMapper->mapAcl($acl);
if ($board->getAcl() !== null) {
foreach ($board->getAcl() as $acl) {
if ($acl !== null) {
$this->boardMapper->mapAcl($acl);
}
}
}
$permissions = $this->permissionService->matchPermissions($board);

View File

@@ -117,7 +117,7 @@ class PermissionService {
*/
public function matchPermissions(Board $board) {
$owner = $this->userIsBoardOwner($board->getId());
$acls = $board->getAcl();
$acls = $board->getAcl() ?? [];
return [
Acl::PERMISSION_READ => $owner || $this->userCan($acls, Acl::PERMISSION_READ),
Acl::PERMISSION_EDIT => $owner || $this->userCan($acls, Acl::PERMISSION_EDIT),
@@ -155,7 +155,7 @@ class PermissionService {
}
try {
$acls = $this->getBoard($boardId)->getAcl();
$acls = $this->getBoard($boardId)->getAcl() ?? [];
$result = $this->userCan($acls, $permission, $userId);
if ($result) {
return true;

1093
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "deck",
"description": "",
"version": "1.6.0-beta1",
"version": "1.7.0-beta1",
"authors": [
{
"name": "Julius Härtl",
@@ -29,10 +29,10 @@
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.16.0",
"@babel/runtime": "^7.16.3",
"@juliushaertl/vue-richtext": "^1.0.1",
"@nextcloud/auth": "^1.3.0",
"@nextcloud/axios": "^1.7.0",
"@nextcloud/axios": "^1.8.0",
"@nextcloud/dialogs": "^3.1.2",
"@nextcloud/event-bus": "^2.1.1",
"@nextcloud/files": "^2.1.0",
@@ -43,7 +43,7 @@
"@nextcloud/vue": "^4.2.0",
"@nextcloud/vue-dashboard": "^2.0.1",
"blueimp-md5": "^2.19.0",
"dompurify": "^2.3.3",
"dompurify": "^2.3.4",
"lodash": "^4.17.21",
"markdown-it": "^12.2.0",
"markdown-it-task-lists": "^2.1.1",
@@ -66,17 +66,17 @@
"extends @nextcloud/browserslist-config"
],
"engines": {
"node": ">=14.0.0",
"npm": ">=7.0.0"
"node": "^14.0.0",
"npm": "^7.0.0"
},
"devDependencies": {
"@nextcloud/babel-config": "^1.0.0",
"@nextcloud/browserslist-config": "^2.2.0",
"@nextcloud/eslint-config": "^6.1.0",
"@nextcloud/eslint-config": "^6.1.1",
"@nextcloud/stylelint-config": "^1.0.0-beta.0",
"@nextcloud/webpack-vue-config": "^4.1.2",
"@nextcloud/webpack-vue-config": "^4.1.4",
"@relative-ci/agent": "^3.0.0",
"@vue/test-utils": "^1.2.2",
"@vue/test-utils": "^1.3.0",
"jest": "^27.3.1",
"jest-serializer-vue": "^2.0.2",
"vue-jest": "^3.0.7"

View File

@@ -22,7 +22,7 @@
<template>
<AttachmentDragAndDrop :card-id="cardId" class="drop-upload--sidebar">
<div class="button-group" v-if="!isReadOnly">
<div v-if="!isReadOnly" class="button-group">
<button class="icon-upload" @click="uploadNewFile()">
{{ t('deck', 'Upload new files') }}
</button>
@@ -79,6 +79,12 @@
<ActionLink v-if="attachment.extendedData.fileid" icon="icon-folder" :href="internalLink(attachment)">
{{ t('deck', 'Show in Files') }}
</ActionLink>
<ActionLink v-if="attachment.extendedData.fileid"
icon="icon-download"
:href="downloadLink(attachment)"
download>
{{ t('deck', 'Download') }}
</ActionLink>
<ActionButton v-if="attachment.extendedData.fileid && !isReadOnly" icon="icon-delete" @click="unshareAttachment(attachment)">
{{ t('deck', 'Remove attachment') }}
</ActionButton>
@@ -101,7 +107,8 @@ import { Actions, ActionButton, ActionLink } from '@nextcloud/vue'
import AttachmentDragAndDrop from '../AttachmentDragAndDrop'
import relativeDate from '../../mixins/relativeDate'
import { formatFileSize } from '@nextcloud/files'
import { generateUrl, generateOcsUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { generateUrl, generateOcsUrl, generateRemoteUrl } from '@nextcloud/router'
import { mapState } from 'vuex'
import { loadState } from '@nextcloud/initial-state'
import attachmentUpload from '../../mixins/attachmentUpload'
@@ -174,6 +181,9 @@ export default {
internalLink() {
return (attachment) => generateUrl('/f/' + attachment.extendedData.fileid)
},
downloadLink() {
return (attachment) => generateRemoteUrl(`dav/files/${getCurrentUser().uid}/${attachment.extendedData.path}`)
},
formattedFileSize() {
return (filesize) => formatFileSize(filesize)
},

View File

@@ -57,7 +57,7 @@
ref="markdownEditor"
v-model="description"
:configs="mdeConfig"
@input="updateDescription"
@update:modelValue="updateDescription"
@blur="saveDescription" />
<Modal v-if="modalShow" :title="t('deck', 'Choose attachment')" @close="modalShow=false">

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.9.3@4c262932602b9bbab5020863d1eb22d49de0dbf4">
<files psalm-version="4.11.2@6fba5eb554f9507b72932f9c75533d8af593688d">
<file src="lib/Activity/ActivityManager.php">
<TypeDoesNotContainType occurrences="1">
<code>$message !== null</code>
@@ -116,6 +116,14 @@
<ParamNameMismatch occurrences="1">
<code>$boardId</code>
</ParamNameMismatch>
<TypeDoesNotContainType occurrences="6">
<code>$limit !== null</code>
<code>$limit !== null</code>
<code>$limit !== null</code>
<code>$offset !== null</code>
<code>$offset !== null</code>
<code>$offset !== null</code>
</TypeDoesNotContainType>
<UndefinedClass occurrences="2">
<code>\OCA\Circles\Api\v1\Circles</code>
<code>\OCA\Circles\Api\v1\Circles</code>

View File

@@ -161,6 +161,7 @@ class BoardMapperTest extends MapperTestUtility {
$actual = $this->boardMapper->find($this->boards[0]->getId(), true, false);
/** @var Board $expected */
$expected = $this->boards[0];
$expected->setLabels([]);
$this->assertEquals($expected->getLabels(), $actual->getLabels());
}

View File

@@ -36,6 +36,29 @@ class BoardTest extends TestCase {
], $board->jsonSerialize());
}
public function testUnfetchedValues() {
$board = $this->createBoard();
$board->setUsers(['user1', 'user2']);
self::assertNull($board->getAcl());
self::assertNull($board->getLabels());
$this->assertEquals([
'id' => 1,
'title' => "My Board",
'owner' => "admin",
'color' => "000000",
'labels' => [],
'permissions' => [],
'stacks' => [],
'deletedAt' => 0,
'lastModified' => 0,
'acl' => [],
'archived' => false,
'users' => ['user1', 'user2'],
'settings' => [],
'ETag' => $board->getETag(),
], $board->jsonSerialize());
}
public function testSetLabels() {
$board = $this->createBoard();
$board->setLabels(["foo", "bar"]);