Compare commits

..

14 Commits

Author SHA1 Message Date
grnd-alt
981d1cbd38 fix: remove deprecated ToolTip
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-14 09:54:43 +02:00
grnd-alt
85af54cd6f fix: do not clean webpack-stats.json from build files
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:38:28 +02:00
grnd-alt
f3a8de2c48 fix: stabilize cypress
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:38:22 +02:00
grnd-alt
1d7bf30e8f bump @nextcloud/dialogs to 7.0.0-rc.1
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:12:31 +02:00
grnd-alt
ee10097c24 fix: adapt NcButtons to nextcloud-vue 9
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:12:31 +02:00
grnd-alt
03d2bd945c fix: remove extra component for NcAction entries
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:12:29 +02:00
grnd-alt
1110a4f125 use correct prop name for nextcloud/vue vue3
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
f4acf38035 replace Vue.set with direct setting
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
30e74a7919 fix: rename parameter names deprecated in vue3
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
b59b2edb37 use v-model instead of value:sync
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
8e805dbec3 fix: use vue3 slot syntax
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
0f1d1181e3 fix: correct syntax for scss variables
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
c32115dea6 vue3-with non-local dependencies and part of the functionality
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:39 +02:00
grnd-alt
452dc5f230 get deck to build with vue3 with broken functionality
Signed-off-by: grnd-alt <github@belakkaf.net>
2025-07-09 14:10:38 +02:00
90 changed files with 7881 additions and 6979 deletions

View File

@@ -173,7 +173,7 @@ jobs:
tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }} tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }}
- name: Attach tarball to github release - name: Attach tarball to github release
uses: svenstaro/upload-release-action@81c65b7cd4de9b2570615ce3aad67a41de5b1a13 # v2 uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # v2
id: attach_to_release id: attach_to_release
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}

View File

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

View File

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

View File

@@ -62,7 +62,6 @@
<command>OCA\Deck\Command\UserExport</command> <command>OCA\Deck\Command\UserExport</command>
<command>OCA\Deck\Command\BoardImport</command> <command>OCA\Deck\Command\BoardImport</command>
<command>OCA\Deck\Command\TransferOwnership</command> <command>OCA\Deck\Command\TransferOwnership</command>
<command>OCA\Deck\Command\CalendarToggle</command>
</commands> </commands>
<activity> <activity>
<settings> <settings>

20
composer.lock generated
View File

@@ -8,16 +8,16 @@
"packages": [ "packages": [
{ {
"name": "justinrainbow/json-schema", "name": "justinrainbow/json-schema",
"version": "6.4.2", "version": "6.4.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/jsonrainbow/json-schema.git", "url": "https://github.com/jsonrainbow/json-schema.git",
"reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02" "reference": "35d262c94959571e8736db1e5c9bc36ab94ae900"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/ce1fd2d47799bb60668643bc6220f6278a4c1d02", "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/35d262c94959571e8736db1e5c9bc36ab94ae900",
"reference": "ce1fd2d47799bb60668643bc6220f6278a4c1d02", "reference": "35d262c94959571e8736db1e5c9bc36ab94ae900",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -77,9 +77,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/jsonrainbow/json-schema/issues", "issues": "https://github.com/jsonrainbow/json-schema/issues",
"source": "https://github.com/jsonrainbow/json-schema/tree/6.4.2" "source": "https://github.com/jsonrainbow/json-schema/tree/6.4.1"
}, },
"time": "2025-06-03T18:27:04+00:00" "time": "2025-04-04T13:08:07+00:00"
}, },
{ {
"name": "marc-mabe/php-enum", "name": "marc-mabe/php-enum",
@@ -380,12 +380,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nextcloud-deps/ocp.git", "url": "https://github.com/nextcloud-deps/ocp.git",
"reference": "c2c75ad8fdc54cbc6341764b5a2a8ecf860e6160" "reference": "97d7aa6e535670437a178084eea91a42998fef5c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/c2c75ad8fdc54cbc6341764b5a2a8ecf860e6160", "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/97d7aa6e535670437a178084eea91a42998fef5c",
"reference": "c2c75ad8fdc54cbc6341764b5a2a8ecf860e6160", "reference": "97d7aa6e535670437a178084eea91a42998fef5c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -421,7 +421,7 @@
"issues": "https://github.com/nextcloud-deps/ocp/issues", "issues": "https://github.com/nextcloud-deps/ocp/issues",
"source": "https://github.com/nextcloud-deps/ocp/tree/master" "source": "https://github.com/nextcloud-deps/ocp/tree/master"
}, },
"time": "2025-08-10T01:01:23+00:00" "time": "2025-06-13T00:53:13+00:00"
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",

View File

@@ -84,7 +84,7 @@ describe('Card', function () {
cy.get('.modal-mask.card-selector .multiselect-list').should('be.visible').click() cy.get('.modal-mask.card-selector .multiselect-list').should('be.visible').click()
cy.get('.vs__dropdown-menu span[title="TestList"]').should('be.visible').click() cy.get('.vs__dropdown-menu span[title="TestList"]').should('be.visible').click()
cy.get('.modal-mask.card-selector button.button-vue--vue-primary').should('be.visible').click() cy.get('.modal-mask.card-selector button.button-vue--primary').contains('Create card').should('be.visible').click()
cy.wait('@save', { timeout: 7000 }) cy.wait('@save', { timeout: 7000 })
cy.reload() cy.reload()
@@ -187,7 +187,7 @@ describe('Card', function () {
cy.get('.file-picker__main').should('be.visible') cy.get('.file-picker__main').should('be.visible')
cy.get('.file-picker__main [data-filename="welcome.txt"]', { timeout: 30000 }).should('be.visible') cy.get('.file-picker__main [data-filename="welcome.txt"]', { timeout: 30000 }).should('be.visible')
.click() .click()
cy.get('.dialog__actions button.button-vue--vue-primary').click() cy.get('.dialog__actions button.button-vue--primary').click()
cy.get('.attachment-list .filename').contains('welcome') cy.get('.attachment-list .filename').contains('welcome')
cy.get('.attachment-list .filename .extension').contains('txt') cy.get('.attachment-list .filename .extension').contains('txt')
}) })
@@ -302,11 +302,10 @@ describe('Card', function () {
.first().click() .first().click()
cy.get(`.card:contains("${newCardTitle}")`).should('be.visible').click() cy.get(`.card:contains("${newCardTitle}")`).should('be.visible').click()
// Add delay to ensure the events are bound cy.get('#app-sidebar-vue [data-test="tag-selector"] .vs__dropdown-toggle .vs__actions').should('be.visible').click()
cy.wait(1000)
cy.get('#app-sidebar-vue [data-test="tag-selector"] .vs__dropdown-toggle').should('be.visible').click()
cy.get('.vs__dropdown-menu .tag:contains("Action needed")').should('be.visible').click() cy.get('.vs__dropdown-menu .tag:contains("Action needed")').should('be.visible').click()
cy.get('.vs__dropdown-menu .tag:contains("Later")').should('not.exist')
cy.get('#app-sidebar-vue [data-test="tag-selector"] .vs__dropdown-toggle .vs__actions').should('be.visible').click()
cy.get('.vs__dropdown-menu .tag:contains("Later")').should('be.visible').click() cy.get('.vs__dropdown-menu .tag:contains("Later")').should('be.visible').click()
cy.get('.vs__selected .tag:contains("Action needed")').should('be.visible') cy.get('.vs__selected .tag:contains("Action needed")').should('be.visible')

View File

@@ -27,7 +27,7 @@ describe('Deck dashboard', function() {
const defaultBoard = 'Welcome to Nextcloud Deck!' const defaultBoard = 'Welcome to Nextcloud Deck!'
cy.get('.app-navigation-entry-wrapper[icon=icon-deck]') cy.get('#deck-navigation-all')
.find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + defaultBoard + ')') .find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + defaultBoard + ')')
.first() .first()
.contains(defaultBoard) .contains(defaultBoard)

View File

@@ -93,7 +93,7 @@ Cypress.Commands.add('createExampleBoard', ({ user, board }) => {
}) })
Cypress.Commands.add('getNavigationEntry', (boardTitle) => { Cypress.Commands.add('getNavigationEntry', (boardTitle) => {
return cy.get('.app-navigation-entry-wrapper[icon=icon-deck]') return cy.get('#deck-navigation-all')
.find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + boardTitle + ')') .find('ul.app-navigation-entry__children .app-navigation-entry:contains(' + boardTitle + ')')
.find('a.app-navigation-entry-link') .find('a.app-navigation-entry-link')
}) })
@@ -102,11 +102,7 @@ Cypress.Commands.add('shareBoardWithUi', (query, userId=query) => {
cy.intercept({ method: 'GET', url: `**/ocs/v2.php/apps/files_sharing/api/v1/sharees?search=${query}*` }).as('fetchRecipients') cy.intercept({ method: 'GET', url: `**/ocs/v2.php/apps/files_sharing/api/v1/sharees?search=${query}*` }).as('fetchRecipients')
cy.get('[aria-label="Open details"]').click() cy.get('[aria-label="Open details"]').click()
cy.get('.app-sidebar').should('be.visible') cy.get('.app-sidebar').should('be.visible')
cy.get('.select input').type(`${query}`)
// Add delay to ensure the events are bound
cy.wait(1000)
cy.get('.select input').click().type(`${query}`)
cy.wait('@fetchRecipients', { timeout: 7000 }) cy.wait('@fetchRecipients', { timeout: 7000 })
cy.get('.vs__dropdown-menu .option').first().contains(query) cy.get('.vs__dropdown-menu .option').first().contains(query)

View File

@@ -1,40 +0,0 @@
OC.L10N.register(
"deck",
{
"Missing a temporary folder" : "Адсутнічае часовая папка",
"Could not write file to disk" : "Не ўдалося запісаць файл на дыск",
"A PHP extension stopped the file upload" : "Пашырэнне PHP спыніла запампоўванне файла",
"copy" : "копія",
"Done" : "Гатова",
"File" : "Файл",
"Cancel" : "Скасаваць",
"Active filters" : "Актыўныя фільтры",
"Apply filter" : "Ужыць фільтр",
"Open" : "Адкрыць",
"Clear filter" : "Ачысціць фільтр",
"Tags" : "Тэгі",
"Activity" : "Актыўнасць",
"Can edit" : "Можа рэдагаваць",
"Can share" : "Можа абагульваць",
"Owner" : "Уладальнік",
"Delete" : "Выдаліць",
"Edit" : "Рэдагаваць",
"Download" : "Спампаваць",
"Modified" : "Зменены",
"Save" : "Захаваць",
"Created:" : "Створана:",
"Reply" : "Адказаць",
"Open link" : "Адкрыць спасылку",
"seconds ago" : "с таму",
"Keyboard shortcuts" : "Спалучэнні клавіш",
"Keyboard shortcut" : "Спалучэнне клавіш",
"Action" : "Дзеянне",
"Search" : "Пошук",
"Shared with you" : "Абагулена з вамі",
"An error occurred" : "Узнікла памылка",
"No notifications" : "Няма апавяшчэнняў",
"Today" : "Сёння",
"Close" : "Закрыць",
"Share" : "Абагуліць"
},
"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);");

View File

@@ -1,38 +0,0 @@
{ "translations": {
"Missing a temporary folder" : "Адсутнічае часовая папка",
"Could not write file to disk" : "Не ўдалося запісаць файл на дыск",
"A PHP extension stopped the file upload" : "Пашырэнне PHP спыніла запампоўванне файла",
"copy" : "копія",
"Done" : "Гатова",
"File" : "Файл",
"Cancel" : "Скасаваць",
"Active filters" : "Актыўныя фільтры",
"Apply filter" : "Ужыць фільтр",
"Open" : "Адкрыць",
"Clear filter" : "Ачысціць фільтр",
"Tags" : "Тэгі",
"Activity" : "Актыўнасць",
"Can edit" : "Можа рэдагаваць",
"Can share" : "Можа абагульваць",
"Owner" : "Уладальнік",
"Delete" : "Выдаліць",
"Edit" : "Рэдагаваць",
"Download" : "Спампаваць",
"Modified" : "Зменены",
"Save" : "Захаваць",
"Created:" : "Створана:",
"Reply" : "Адказаць",
"Open link" : "Адкрыць спасылку",
"seconds ago" : "с таму",
"Keyboard shortcuts" : "Спалучэнні клавіш",
"Keyboard shortcut" : "Спалучэнне клавіш",
"Action" : "Дзеянне",
"Search" : "Пошук",
"Shared with you" : "Абагулена з вамі",
"An error occurred" : "Узнікла памылка",
"No notifications" : "Няма апавяшчэнняў",
"Today" : "Сёння",
"Close" : "Закрыць",
"Share" : "Абагуліць"
},"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"
}

View File

@@ -37,9 +37,9 @@ OC.L10N.register(
"{user} has archived card {card} in list {stack} on board {board}" : "{user} ha archivado la tarjeta {card} en la lista {stack} del tablero {board}", "{user} has archived card {card} in list {stack} on board {board}" : "{user} ha archivado la tarjeta {card} en la lista {stack} del tablero {board}",
"You have unarchived card {card} in list {stack} on board {board}" : "Has desarchivado la tarjeta {card} en la lista {stack} del tablero {board}", "You have unarchived card {card} in list {stack} on board {board}" : "Has desarchivado la tarjeta {card} en la lista {stack} del tablero {board}",
"{user} has unarchived card {card} in list {stack} on board {board}" : "{user} ha desarchivado la tarjeta {card} en la lista {stack} del tablero {board}", "{user} has unarchived card {card} in list {stack} on board {board}" : "{user} ha desarchivado la tarjeta {card} en la lista {stack} del tablero {board}",
"You have marked the card {card} as done in list {stack} on board {board}" : "Ud. ha marcado la tarjeta {card} como completada en la lista {stack} del tablero {board}", "You have marked the card {card} as done in list {stack} on board {board}" : "Has marcado la tarjeta {card} como completada en la lista {stack} del tablero {board}",
"{user} has marked card {card} as done in list {stack} on board {board}" : "{user} ha marcado la tarjeta {card} como completada en la lista {stack} del tablero {board}", "{user} has marked card {card} as done in list {stack} on board {board}" : "{user} ha marcado la tarjeta {card} como completada en la lista {stack} del tablero {board}",
"You have marked the card {card} as undone in list {stack} on board {board}" : "Ud. ha marcado la tarjeta {card} como no completada en la lista {stack} del tablero {board}", "You have marked the card {card} as undone in list {stack} on board {board}" : "Has marcado la tarjeta {card} como no completada en la lista {stack} del tablero {board}",
"{user} has marked the card {card} as undone in list {stack} on board {board}" : "{user} ha marcado la tarjeta {card} como no completada en la lista {stack} del tablero {board}", "{user} has marked the card {card} as undone in list {stack} on board {board}" : "{user} ha marcado la tarjeta {card} como no completada en la lista {stack} del tablero {board}",
"You have removed the due date of card {card}" : "Has eliminado la fecha de vencimiento de {card}", "You have removed the due date of card {card}" : "Has eliminado la fecha de vencimiento de {card}",
"{user} has removed the due date of card {card}" : "{user} ha eliminado la fecha de vencimiento de {card}", "{user} has removed the due date of card {card}" : "{user} ha eliminado la fecha de vencimiento de {card}",
@@ -81,14 +81,10 @@ OC.L10N.register(
"Could not write file to disk" : "No se ha podido escribir el archivo al disco", "Could not write file to disk" : "No se ha podido escribir el archivo al disco",
"A PHP extension stopped the file upload" : "Una extensión de PHP ha detenido la subida del archivo", "A PHP extension stopped the file upload" : "Una extensión de PHP ha detenido la subida del archivo",
"No file uploaded or file size exceeds maximum of %s" : "No se ha subido ningún archivo, o el tamaño del archivo excede el máximo de %s", "No file uploaded or file size exceeds maximum of %s" : "No se ha subido ningún archivo, o el tamaño del archivo excede el máximo de %s",
"Invalid file type. Only JSON files are allowed." : "Tipo de archivo inválido. Solo se permiten archivos JSON",
"Invalid JSON data" : "Datos JSON inválidos",
"Failed to import board" : "Fallo al importar tablero",
"Cards due today" : "Tarjetas que vencen hoy", "Cards due today" : "Tarjetas que vencen hoy",
"Cards due tomorrow" : "Tarjetas que vencen mañana", "Cards due tomorrow" : "Tarjetas que vencen mañana",
"Upcoming cards" : "Próximas tarjetas", "Upcoming cards" : "Próximas tarjetas",
"Load more" : "Cargar más", "Load more" : "Cargar más",
"Welcome to Nextcloud Deck!" : "¡Bienvenido a Nextcloud Deck!",
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "La tarjeta \"%s\" en \"%s\" te ha sido asignada por %s.", "The card \"%s\" on \"%s\" has been assigned to you by %s." : "La tarjeta \"%s\" en \"%s\" te ha sido asignada por %s.",
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} te ha asigando la tarjeta {deck-card} de {deck-board} a ti.", "{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} te ha asigando la tarjeta {deck-card} de {deck-board} a ti.",
"The card \"%s\" on \"%s\" has reached its due date." : "La tarjeta \"%s\" en \"%s\" ha alcanzado su fecha límite.", "The card \"%s\" on \"%s\" has reached its due date." : "La tarjeta \"%s\" en \"%s\" ha alcanzado su fecha límite.",
@@ -98,7 +94,7 @@ OC.L10N.register(
"The board \"%s\" has been shared with you by %s." : "El tablero \"%s\" ha sido compartido contigo por %s.", "The board \"%s\" has been shared with you by %s." : "El tablero \"%s\" ha sido compartido contigo por %s.",
"{user} has shared {deck-board} with you." : "{user} ha compartido {deck-board} contigo.", "{user} has shared {deck-board} with you." : "{user} ha compartido {deck-board} contigo.",
"Deck board" : "Tablero Deck", "Deck board" : "Tablero Deck",
"Owned by %1$s" : "Propiedad de %1$s", "Owned by %1$s" : "Apropiado por %1$s",
"Deck boards, cards and comments" : "Tableros Deck, tarjetas y comentarios", "Deck boards, cards and comments" : "Tableros Deck, tarjetas y comentarios",
"From %1$s, in %2$s/%3$s, owned by %4$s" : "De %1$s, en %2$s/%3$s, propiedad de %4$s", "From %1$s, in %2$s/%3$s, owned by %4$s" : "De %1$s, en %2$s/%3$s, propiedad de %4$s",
"Create a new deck card" : "Crear una nueva tarjeta de tablero", "Create a new deck card" : "Crear una nueva tarjeta de tablero",
@@ -111,25 +107,17 @@ OC.L10N.register(
"Action needed" : "Acción necesaria", "Action needed" : "Acción necesaria",
"Later" : "Después", "Later" : "Después",
"copy" : "copiar", "copy" : "copiar",
"Read more inside" : "Lea más, adentro",
"Custom lists - click to rename!" : "Listas personalizadas - ¡Haga clic para renombrar!",
"To Do" : "Por hacer", "To Do" : "Por hacer",
"In Progress" : "En progreso", "In Progress" : "En progreso",
"Done" : "Hecho", "Done" : "Hecho",
"1. Open to learn more about boards and cards" : "1. Abra aquí para aprender más sobre los tableros y las tarjetas", "This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Este comentario tiene más de %s caracteres.\nAñadido como adjunto a la tarjeta con el nombre %s.\nAccesible en la URL: %s.",
"2. Drag cards left and right, up and down" : "2. Arrastre las tarjetas a la izquierda y derecha, arriba y abajo",
"3. Apply rich formatting and link content" : "3. Aplique formato enriquecido y contenido a los enlaces",
"4. Share, comment and collaborate!" : "4. ¡Comparta, comente y colabore!",
"Create your first card!" : "¡Cree su primera tarjeta!",
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Este comentario tiene más de %s caracteres.\nSe ha añadido como adjunto a la tarjeta con el nombre %s.\nAccesible en la URL: %s.",
"Attachments" : "Adjuntos", "Attachments" : "Adjuntos",
"File" : "Archivo", "File" : "Archivo",
"date" : "fecha",
"Card not found" : "Tarjeta no encontrada", "Card not found" : "Tarjeta no encontrada",
"Path is already shared with this card" : "La ruta ya se ha compartido con esta tarjeta", "Path is already shared with this card" : "La ruta ya se ha compartido con esta tarjeta",
"Invalid date, date format must be YYYY-MM-DD" : "Fecha no válida, el formato de las fechas debe ser AAAA-MM-DD", "Invalid date, date format must be YYYY-MM-DD" : "Fecha no válida, el formato de las fechas debe ser AAAA-MM-DD",
"Personal planning and team project organization" : "Planificación personal y organización de proyecto de equipo", "Personal planning and team project organization" : "Planificación personal y organización de proyecto de equipo",
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck es una herramienta de organización de estilo kanban dirigida a la planificación personal y la organización de proyectos para equipos, integrada a Nextcloud.\n\n\n- 📥 Agregue sus tareas a las tarjetas y póngalas en orden.\n- 📄 Escriba notas adicionales en Markdown\n- 🔖 Asigne etiquetas para una organización mejor\n- 👥 Comparta con su equipo, amigos o familia.\n- 📎 Adjunte archivos e incruste los mismos en su descripción Markdown\n- 💬 Discuta con su equipo usando comentarios.\n- ⚡ Mantenga un registro de los cambios en el flujo de actividad\n- 🚀 Organice su proyecto", "Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck es una herramienta de organización de estilo kanban dirigida a la planificación personal y la organización de proyectos para equipos integrados con Nextcloud.\n\n\n- 📥 Agrega tus tareas a las tarjetas y ordénalas.\n- 📄 Escriba notas adicionales\n- 🔖 Asignar etiquetas para una organización mejor\n- 👥 Comparte con tu equipo, amigos o familia.\n- 📎 Adjuntar archivos e incrustarlos en su descripción\n- 💬 Discuta con su equipo usando comentarios.\n- ⚡ Mantenga un registro de los cambios en el flujo de actividad\n- 🚀 Organiza tu proyecto",
"Add board" : "Añadir tablero", "Add board" : "Añadir tablero",
"Card details" : "Detalles de la tarjeta", "Card details" : "Detalles de la tarjeta",
"Select the board to link to a project" : "Selecciona el tablero que enlazar a un proyecto", "Select the board to link to a project" : "Selecciona el tablero que enlazar a un proyecto",
@@ -177,8 +165,8 @@ OC.L10N.register(
"Hide archived cards" : "Ocultar tarjetas archivadas", "Hide archived cards" : "Ocultar tarjetas archivadas",
"Show archived cards" : "Mostrar tarjetas archivadas", "Show archived cards" : "Mostrar tarjetas archivadas",
"Toggle compact mode" : "Mostrar/ocultar modo compacto", "Toggle compact mode" : "Mostrar/ocultar modo compacto",
"Hide card cover images" : "Ocultar la imagen de portada de las tarjetas", "Hide card cover images" : "Ocultar la imagen principal de las tarjetas",
"Show card cover images" : "Mostrar la imagen de portada de las tarjetas", "Show card cover images" : "Mostrar la imagen principal de las tarjetas",
"Open details" : "Abrir detalles", "Open details" : "Abrir detalles",
"Details" : "Detalles", "Details" : "Detalles",
"Currently present people" : "Personas presentes actualmente", "Currently present people" : "Personas presentes actualmente",
@@ -193,11 +181,11 @@ OC.L10N.register(
"Undo" : "Deshacer", "Undo" : "Deshacer",
"Deleted cards" : "Cartas eliminadas", "Deleted cards" : "Cartas eliminadas",
"Failed to create share with {displayName}" : "Fallo al crear el recurso compartido denominado {displayName}", "Failed to create share with {displayName}" : "Fallo al crear el recurso compartido denominado {displayName}",
"Are you sure you want to transfer the board {title} to {user}?" : "¿Está seguro de que quiere transferir el tablero {title} a {user}?", "Are you sure you want to transfer the board {title} to {user}?" : "¿Estás seguro de que quieres transferir el tablero {título} a {usuario}?",
"Transfer the board." : "Transfiera el tablero.", "Transfer the board." : "Transfiere el tablero.",
"Transfer" : "Transferir", "Transfer" : "Transferir",
"The board has been transferred to {user}" : "El tablero ha sido transferido a {user}", "The board has been transferred to {user}" : "El tablero ha sido transferido a {usuario}",
"Failed to transfer the board to {user}" : "Fallo al transferir el tablero a {user}", "Failed to transfer the board to {user}" : "Failed to transfer the board to {user}",
"Share board with a user, group or team …" : "Compartir tablero con un usuario, grupo o equipo …", "Share board with a user, group or team …" : "Compartir tablero con un usuario, grupo o equipo …",
"Searching for users, groups and teams …" : "Buscando usuarios, grupos y equipos …", "Searching for users, groups and teams …" : "Buscando usuarios, grupos y equipos …",
"No participants found" : "No se encontraron participantes", "No participants found" : "No se encontraron participantes",
@@ -230,7 +218,7 @@ OC.L10N.register(
"Invalid path selected" : "Ruta seleccionada no válida", "Invalid path selected" : "Ruta seleccionada no válida",
"Upload new files" : "Subir nuevos archivos", "Upload new files" : "Subir nuevos archivos",
"Share from Files" : "Compartir desde Archivos", "Share from Files" : "Compartir desde Archivos",
"Pending share" : "Recurso compartido pendiente", "Pending share" : "Pendiente de compartir",
"Add this attachment" : "Añadir este adjunto", "Add this attachment" : "Añadir este adjunto",
"Show in Files" : "Mostrar en Archivos", "Show in Files" : "Mostrar en Archivos",
"Download" : "Descargar", "Download" : "Descargar",
@@ -240,7 +228,6 @@ OC.L10N.register(
"Modified" : "Modificado", "Modified" : "Modificado",
"Created" : "Creado", "Created" : "Creado",
"The title cannot be empty." : "El título no puede estar vacío.", "The title cannot be empty." : "El título no puede estar vacío.",
"Cannot close unsaved card!" : "¡No se puede cerrar esta tarjeta no guardada!",
"Open in sidebar view" : "Abrir en vista de barra lateral", "Open in sidebar view" : "Abrir en vista de barra lateral",
"Open in bigger view" : "Abrir en vista más grande", "Open in bigger view" : "Abrir en vista más grande",
"Comments" : "Comentarios", "Comments" : "Comentarios",
@@ -255,7 +242,6 @@ OC.L10N.register(
"Reply" : "Responder", "Reply" : "Responder",
"Update" : "Actualizar", "Update" : "Actualizar",
"Write a description …" : "Escribe una descripción...", "Write a description …" : "Escribe una descripción...",
"Could not save description" : "No se pudo guardar la descripción",
"Description" : "Descripción", "Description" : "Descripción",
"(Unsaved)" : "(Sin salvar)", "(Unsaved)" : "(Sin salvar)",
"(Saving…)" : "(Guardando...)", "(Saving…)" : "(Guardando...)",
@@ -273,12 +259,12 @@ OC.L10N.register(
"Set due date for this weekend" : "Establecer este fin de semana como fecha de vencimiento", "Set due date for this weekend" : "Establecer este fin de semana como fecha de vencimiento",
"Next week {timeLocale}" : "Próxima semana {timeLocale}", "Next week {timeLocale}" : "Próxima semana {timeLocale}",
"Set due date for next week" : "Establecer la próxima semana como fecha de vencimiento", "Set due date for next week" : "Establecer la próxima semana como fecha de vencimiento",
"Assign a due date to this card…" : "Asignar una fecha de vencimiento a esta tarjeta…", "Assign a due date to this card…" : "Asignar una fecha de caducidad a esta tarjeta…",
"Set a due date" : "Fijar una fecha límite", "Set a due date" : "Fijar una fecha límite",
"Add due date" : "Añadir fecha de vencimiento", "Add due date" : "Añadir fecha de vencimiento",
"Choose a date" : "Elija una fecha", "Choose a date" : "Elija una fecha",
"Remove due date" : "Eliminar fecha límite", "Remove due date" : "Eliminar fecha límite",
"Mark as done" : "Marcar como completado", "Mark as done" : "Marcar como hecho",
"Due at:" : "Vence el:", "Due at:" : "Vence el:",
"Not done" : "No está finalizado", "Not done" : "No está finalizado",
"Unarchive card" : "Desarchivar tarjeta", "Unarchive card" : "Desarchivar tarjeta",
@@ -342,7 +328,6 @@ OC.L10N.register(
"An error occurred" : "Ocurrió un error", "An error occurred" : "Ocurrió un error",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "¿Está seguro de querer eliminar el tablero {title}? Esto eliminará todos los datos del tablero incluyendo las tarjetas archivadas.", "Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "¿Está seguro de querer eliminar el tablero {title}? Esto eliminará todos los datos del tablero incluyendo las tarjetas archivadas.",
"Delete the board?" : "¿Borrar el tablero?", "Delete the board?" : "¿Borrar el tablero?",
"Exporting board..." : "Exportando tablero...",
"Board details" : "Detalles del tablero", "Board details" : "Detalles del tablero",
"Edit board" : "Editar tablero", "Edit board" : "Editar tablero",
"Clone board" : "Clonar tablero", "Clone board" : "Clonar tablero",
@@ -355,22 +340,16 @@ OC.L10N.register(
"Assigned cards" : "Tarjetas asignadas", "Assigned cards" : "Tarjetas asignadas",
"No notifications" : "No hay notificaciones", "No notifications" : "No hay notificaciones",
"Delete board" : "Eliminar tablero", "Delete board" : "Eliminar tablero",
"Importing board..." : "Importando tablero...",
"Board imported successfully" : "Se importó el tablero exitosamente",
"Import board" : "Importar tablero",
"Clone {boardTitle}" : "Clonar {boardTitle}", "Clone {boardTitle}" : "Clonar {boardTitle}",
"Clone cards" : "Clonar tarjetas", "Clone cards" : "Clonar tarjetas",
"Clone assignments" : "Clonar asignaciones", "Clone assignments" : "Clonar asignaciones",
"Clone labels" : "Clonar etiquetas", "Clone labels" : "Clonar etiquetas",
"Clone due dates" : "Clonar fechas de vencimiento", "Clone due dates" : "Clonar fechas límite",
"Advanced options" : "Opciones avanzadas", "Advanced options" : "Opciones avanzadas",
"Move all cards to the first list" : "Mover todas las tarjetas a la primera lista", "Move all cards to the first list" : "Mover todas las tarjetas a la primera lista",
"Restore archived cards" : "Restaurar tarjetas archivadas", "Restore archived cards" : "Restaurar tarjetas archivadas",
"Clone" : "Clonar", "Clone" : "Clonar",
"Export {boardTitle}" : "Exportar {boardTitle}",
"Export as JSON" : "Exportar como JSON",
"Export as CSV" : "Exportar como CSV", "Export as CSV" : "Exportar como CSV",
"Note: Only the JSON format is supported for importing back into the Deck app." : "Nota: Solo el formato JSON es soportar al importar de vuelta en la app Deck.",
"Export" : "Exportar", "Export" : "Exportar",
"Loading filtered view" : "Cargando vista filtrada", "Loading filtered view" : "Cargando vista filtrada",
"Today" : "Hoy", "Today" : "Hoy",
@@ -378,17 +357,17 @@ OC.L10N.register(
"No due" : "Sin finalizar", "No due" : "Sin finalizar",
"Search for {searchQuery} in all boards" : "Buscar {searchQuery} en todos los tableros", "Search for {searchQuery} in all boards" : "Buscar {searchQuery} en todos los tableros",
"No results found" : "No se encontraron resultados", "No results found" : "No se encontraron resultados",
"Deck board {name}\n* Last modified on {lastMod}" : "Tablero Deck {name}\n* Se modificó por última vez el {lastMod}", "Deck board {name}\n* Last modified on {lastMod}" : "Tablero Deck {name}\n* Última modificación en {lastMod}",
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Creado en {created}\n* Se modificó por última vez el {lastMod}\n* {nbAttachments} adjuntos\n* {nbComments} comentarios", "* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Creada en {created}\n* Ultima moficiación en {lastMod}\n* {nbAttachments} adjuntos\n* {nbComments} comentarios",
"{nbCards} cards" : "{nbCards} tarjetas", "{nbCards} cards" : "{nbCards} tarjetas",
"Due on {date}" : "Vence en {date}", "Due on {date}" : "Vence en {date}",
"{stack} in {board}" : "{stack} en {board}", "{stack} in {board}" : "{stack} en {board}",
"Click to expand description" : "Haga clic para expandir la descripción", "Click to expand description" : "Pulse para expandir la descripción",
"Click to expand comment" : "Haga clic para expandir el comentario", "Click to expand comment" : "Pulse para expandir el comentario",
"Create card" : "Crear tarjeta", "Create card" : "Crear tarjeta",
"Create a new card" : "Crear una tarjeta nueva", "Create a new card" : "Crear una nueva tarjeta",
"Card title" : "Título de la tarjeta", "Card title" : "Título de la tarjeta",
"Creating the new card …" : "Creando una tarjeta nueva …", "Creating the new card …" : "Creando una nueva tarjeta …",
"Card \"{card}\" was added to \"{board}\"" : "La tarjeta \"{card}\" fue añadida a \"{board}\"", "Card \"{card}\" was added to \"{board}\"" : "La tarjeta \"{card}\" fue añadida a \"{board}\"",
"Open card" : "Abrir tarjeta", "Open card" : "Abrir tarjeta",
"Close" : "Cerrar", "Close" : "Cerrar",
@@ -404,8 +383,7 @@ OC.L10N.register(
"Something went wrong" : "Algo ha ido mal", "Something went wrong" : "Algo ha ido mal",
"Failed to upload {name}" : "Error al subir {name}", "Failed to upload {name}" : "Error al subir {name}",
"Maximum file size of {size} exceeded" : "Tamaño máximo de archivo de {size} excedido", "Maximum file size of {size} exceeded" : "Tamaño máximo de archivo de {size} excedido",
"Assigned users" : "Usuarios asignados", "Due date" : "Fecha de fin",
"Due date" : "Fecha de vencimiento",
"Error creating the share" : "Error creando el recurso compartido", "Error creating the share" : "Error creando el recurso compartido",
"Share with a Deck card" : "Compartir con una tarjeta de Deck", "Share with a Deck card" : "Compartir con una tarjeta de Deck",
"Share {file} with a Deck card" : "Compartir {file} con una tarjeta de Deck", "Share {file} with a Deck card" : "Compartir {file} con una tarjeta de Deck",

View File

@@ -35,9 +35,9 @@
"{user} has archived card {card} in list {stack} on board {board}" : "{user} ha archivado la tarjeta {card} en la lista {stack} del tablero {board}", "{user} has archived card {card} in list {stack} on board {board}" : "{user} ha archivado la tarjeta {card} en la lista {stack} del tablero {board}",
"You have unarchived card {card} in list {stack} on board {board}" : "Has desarchivado la tarjeta {card} en la lista {stack} del tablero {board}", "You have unarchived card {card} in list {stack} on board {board}" : "Has desarchivado la tarjeta {card} en la lista {stack} del tablero {board}",
"{user} has unarchived card {card} in list {stack} on board {board}" : "{user} ha desarchivado la tarjeta {card} en la lista {stack} del tablero {board}", "{user} has unarchived card {card} in list {stack} on board {board}" : "{user} ha desarchivado la tarjeta {card} en la lista {stack} del tablero {board}",
"You have marked the card {card} as done in list {stack} on board {board}" : "Ud. ha marcado la tarjeta {card} como completada en la lista {stack} del tablero {board}", "You have marked the card {card} as done in list {stack} on board {board}" : "Has marcado la tarjeta {card} como completada en la lista {stack} del tablero {board}",
"{user} has marked card {card} as done in list {stack} on board {board}" : "{user} ha marcado la tarjeta {card} como completada en la lista {stack} del tablero {board}", "{user} has marked card {card} as done in list {stack} on board {board}" : "{user} ha marcado la tarjeta {card} como completada en la lista {stack} del tablero {board}",
"You have marked the card {card} as undone in list {stack} on board {board}" : "Ud. ha marcado la tarjeta {card} como no completada en la lista {stack} del tablero {board}", "You have marked the card {card} as undone in list {stack} on board {board}" : "Has marcado la tarjeta {card} como no completada en la lista {stack} del tablero {board}",
"{user} has marked the card {card} as undone in list {stack} on board {board}" : "{user} ha marcado la tarjeta {card} como no completada en la lista {stack} del tablero {board}", "{user} has marked the card {card} as undone in list {stack} on board {board}" : "{user} ha marcado la tarjeta {card} como no completada en la lista {stack} del tablero {board}",
"You have removed the due date of card {card}" : "Has eliminado la fecha de vencimiento de {card}", "You have removed the due date of card {card}" : "Has eliminado la fecha de vencimiento de {card}",
"{user} has removed the due date of card {card}" : "{user} ha eliminado la fecha de vencimiento de {card}", "{user} has removed the due date of card {card}" : "{user} ha eliminado la fecha de vencimiento de {card}",
@@ -79,14 +79,10 @@
"Could not write file to disk" : "No se ha podido escribir el archivo al disco", "Could not write file to disk" : "No se ha podido escribir el archivo al disco",
"A PHP extension stopped the file upload" : "Una extensión de PHP ha detenido la subida del archivo", "A PHP extension stopped the file upload" : "Una extensión de PHP ha detenido la subida del archivo",
"No file uploaded or file size exceeds maximum of %s" : "No se ha subido ningún archivo, o el tamaño del archivo excede el máximo de %s", "No file uploaded or file size exceeds maximum of %s" : "No se ha subido ningún archivo, o el tamaño del archivo excede el máximo de %s",
"Invalid file type. Only JSON files are allowed." : "Tipo de archivo inválido. Solo se permiten archivos JSON",
"Invalid JSON data" : "Datos JSON inválidos",
"Failed to import board" : "Fallo al importar tablero",
"Cards due today" : "Tarjetas que vencen hoy", "Cards due today" : "Tarjetas que vencen hoy",
"Cards due tomorrow" : "Tarjetas que vencen mañana", "Cards due tomorrow" : "Tarjetas que vencen mañana",
"Upcoming cards" : "Próximas tarjetas", "Upcoming cards" : "Próximas tarjetas",
"Load more" : "Cargar más", "Load more" : "Cargar más",
"Welcome to Nextcloud Deck!" : "¡Bienvenido a Nextcloud Deck!",
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "La tarjeta \"%s\" en \"%s\" te ha sido asignada por %s.", "The card \"%s\" on \"%s\" has been assigned to you by %s." : "La tarjeta \"%s\" en \"%s\" te ha sido asignada por %s.",
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} te ha asigando la tarjeta {deck-card} de {deck-board} a ti.", "{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} te ha asigando la tarjeta {deck-card} de {deck-board} a ti.",
"The card \"%s\" on \"%s\" has reached its due date." : "La tarjeta \"%s\" en \"%s\" ha alcanzado su fecha límite.", "The card \"%s\" on \"%s\" has reached its due date." : "La tarjeta \"%s\" en \"%s\" ha alcanzado su fecha límite.",
@@ -96,7 +92,7 @@
"The board \"%s\" has been shared with you by %s." : "El tablero \"%s\" ha sido compartido contigo por %s.", "The board \"%s\" has been shared with you by %s." : "El tablero \"%s\" ha sido compartido contigo por %s.",
"{user} has shared {deck-board} with you." : "{user} ha compartido {deck-board} contigo.", "{user} has shared {deck-board} with you." : "{user} ha compartido {deck-board} contigo.",
"Deck board" : "Tablero Deck", "Deck board" : "Tablero Deck",
"Owned by %1$s" : "Propiedad de %1$s", "Owned by %1$s" : "Apropiado por %1$s",
"Deck boards, cards and comments" : "Tableros Deck, tarjetas y comentarios", "Deck boards, cards and comments" : "Tableros Deck, tarjetas y comentarios",
"From %1$s, in %2$s/%3$s, owned by %4$s" : "De %1$s, en %2$s/%3$s, propiedad de %4$s", "From %1$s, in %2$s/%3$s, owned by %4$s" : "De %1$s, en %2$s/%3$s, propiedad de %4$s",
"Create a new deck card" : "Crear una nueva tarjeta de tablero", "Create a new deck card" : "Crear una nueva tarjeta de tablero",
@@ -109,25 +105,17 @@
"Action needed" : "Acción necesaria", "Action needed" : "Acción necesaria",
"Later" : "Después", "Later" : "Después",
"copy" : "copiar", "copy" : "copiar",
"Read more inside" : "Lea más, adentro",
"Custom lists - click to rename!" : "Listas personalizadas - ¡Haga clic para renombrar!",
"To Do" : "Por hacer", "To Do" : "Por hacer",
"In Progress" : "En progreso", "In Progress" : "En progreso",
"Done" : "Hecho", "Done" : "Hecho",
"1. Open to learn more about boards and cards" : "1. Abra aquí para aprender más sobre los tableros y las tarjetas", "This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Este comentario tiene más de %s caracteres.\nAñadido como adjunto a la tarjeta con el nombre %s.\nAccesible en la URL: %s.",
"2. Drag cards left and right, up and down" : "2. Arrastre las tarjetas a la izquierda y derecha, arriba y abajo",
"3. Apply rich formatting and link content" : "3. Aplique formato enriquecido y contenido a los enlaces",
"4. Share, comment and collaborate!" : "4. ¡Comparta, comente y colabore!",
"Create your first card!" : "¡Cree su primera tarjeta!",
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Este comentario tiene más de %s caracteres.\nSe ha añadido como adjunto a la tarjeta con el nombre %s.\nAccesible en la URL: %s.",
"Attachments" : "Adjuntos", "Attachments" : "Adjuntos",
"File" : "Archivo", "File" : "Archivo",
"date" : "fecha",
"Card not found" : "Tarjeta no encontrada", "Card not found" : "Tarjeta no encontrada",
"Path is already shared with this card" : "La ruta ya se ha compartido con esta tarjeta", "Path is already shared with this card" : "La ruta ya se ha compartido con esta tarjeta",
"Invalid date, date format must be YYYY-MM-DD" : "Fecha no válida, el formato de las fechas debe ser AAAA-MM-DD", "Invalid date, date format must be YYYY-MM-DD" : "Fecha no válida, el formato de las fechas debe ser AAAA-MM-DD",
"Personal planning and team project organization" : "Planificación personal y organización de proyecto de equipo", "Personal planning and team project organization" : "Planificación personal y organización de proyecto de equipo",
"Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck es una herramienta de organización de estilo kanban dirigida a la planificación personal y la organización de proyectos para equipos, integrada a Nextcloud.\n\n\n- 📥 Agregue sus tareas a las tarjetas y póngalas en orden.\n- 📄 Escriba notas adicionales en Markdown\n- 🔖 Asigne etiquetas para una organización mejor\n- 👥 Comparta con su equipo, amigos o familia.\n- 📎 Adjunte archivos e incruste los mismos en su descripción Markdown\n- 💬 Discuta con su equipo usando comentarios.\n- ⚡ Mantenga un registro de los cambios en el flujo de actividad\n- 🚀 Organice su proyecto", "Deck is a kanban style organization tool aimed at personal planning and project organization for teams integrated with Nextcloud.\n\n\n- 📥 Add your tasks to cards and put them in order\n- 📄 Write down additional notes in Markdown\n- 🔖 Assign labels for even better organization\n- 👥 Share with your team, friends or family\n- 📎 Attach files and embed them in your Markdown description\n- 💬 Discuss with your team using comments\n- ⚡ Keep track of changes in the activity stream\n- 🚀 Get your project organized" : "Deck es una herramienta de organización de estilo kanban dirigida a la planificación personal y la organización de proyectos para equipos integrados con Nextcloud.\n\n\n- 📥 Agrega tus tareas a las tarjetas y ordénalas.\n- 📄 Escriba notas adicionales\n- 🔖 Asignar etiquetas para una organización mejor\n- 👥 Comparte con tu equipo, amigos o familia.\n- 📎 Adjuntar archivos e incrustarlos en su descripción\n- 💬 Discuta con su equipo usando comentarios.\n- ⚡ Mantenga un registro de los cambios en el flujo de actividad\n- 🚀 Organiza tu proyecto",
"Add board" : "Añadir tablero", "Add board" : "Añadir tablero",
"Card details" : "Detalles de la tarjeta", "Card details" : "Detalles de la tarjeta",
"Select the board to link to a project" : "Selecciona el tablero que enlazar a un proyecto", "Select the board to link to a project" : "Selecciona el tablero que enlazar a un proyecto",
@@ -175,8 +163,8 @@
"Hide archived cards" : "Ocultar tarjetas archivadas", "Hide archived cards" : "Ocultar tarjetas archivadas",
"Show archived cards" : "Mostrar tarjetas archivadas", "Show archived cards" : "Mostrar tarjetas archivadas",
"Toggle compact mode" : "Mostrar/ocultar modo compacto", "Toggle compact mode" : "Mostrar/ocultar modo compacto",
"Hide card cover images" : "Ocultar la imagen de portada de las tarjetas", "Hide card cover images" : "Ocultar la imagen principal de las tarjetas",
"Show card cover images" : "Mostrar la imagen de portada de las tarjetas", "Show card cover images" : "Mostrar la imagen principal de las tarjetas",
"Open details" : "Abrir detalles", "Open details" : "Abrir detalles",
"Details" : "Detalles", "Details" : "Detalles",
"Currently present people" : "Personas presentes actualmente", "Currently present people" : "Personas presentes actualmente",
@@ -191,11 +179,11 @@
"Undo" : "Deshacer", "Undo" : "Deshacer",
"Deleted cards" : "Cartas eliminadas", "Deleted cards" : "Cartas eliminadas",
"Failed to create share with {displayName}" : "Fallo al crear el recurso compartido denominado {displayName}", "Failed to create share with {displayName}" : "Fallo al crear el recurso compartido denominado {displayName}",
"Are you sure you want to transfer the board {title} to {user}?" : "¿Está seguro de que quiere transferir el tablero {title} a {user}?", "Are you sure you want to transfer the board {title} to {user}?" : "¿Estás seguro de que quieres transferir el tablero {título} a {usuario}?",
"Transfer the board." : "Transfiera el tablero.", "Transfer the board." : "Transfiere el tablero.",
"Transfer" : "Transferir", "Transfer" : "Transferir",
"The board has been transferred to {user}" : "El tablero ha sido transferido a {user}", "The board has been transferred to {user}" : "El tablero ha sido transferido a {usuario}",
"Failed to transfer the board to {user}" : "Fallo al transferir el tablero a {user}", "Failed to transfer the board to {user}" : "Failed to transfer the board to {user}",
"Share board with a user, group or team …" : "Compartir tablero con un usuario, grupo o equipo …", "Share board with a user, group or team …" : "Compartir tablero con un usuario, grupo o equipo …",
"Searching for users, groups and teams …" : "Buscando usuarios, grupos y equipos …", "Searching for users, groups and teams …" : "Buscando usuarios, grupos y equipos …",
"No participants found" : "No se encontraron participantes", "No participants found" : "No se encontraron participantes",
@@ -228,7 +216,7 @@
"Invalid path selected" : "Ruta seleccionada no válida", "Invalid path selected" : "Ruta seleccionada no válida",
"Upload new files" : "Subir nuevos archivos", "Upload new files" : "Subir nuevos archivos",
"Share from Files" : "Compartir desde Archivos", "Share from Files" : "Compartir desde Archivos",
"Pending share" : "Recurso compartido pendiente", "Pending share" : "Pendiente de compartir",
"Add this attachment" : "Añadir este adjunto", "Add this attachment" : "Añadir este adjunto",
"Show in Files" : "Mostrar en Archivos", "Show in Files" : "Mostrar en Archivos",
"Download" : "Descargar", "Download" : "Descargar",
@@ -238,7 +226,6 @@
"Modified" : "Modificado", "Modified" : "Modificado",
"Created" : "Creado", "Created" : "Creado",
"The title cannot be empty." : "El título no puede estar vacío.", "The title cannot be empty." : "El título no puede estar vacío.",
"Cannot close unsaved card!" : "¡No se puede cerrar esta tarjeta no guardada!",
"Open in sidebar view" : "Abrir en vista de barra lateral", "Open in sidebar view" : "Abrir en vista de barra lateral",
"Open in bigger view" : "Abrir en vista más grande", "Open in bigger view" : "Abrir en vista más grande",
"Comments" : "Comentarios", "Comments" : "Comentarios",
@@ -253,7 +240,6 @@
"Reply" : "Responder", "Reply" : "Responder",
"Update" : "Actualizar", "Update" : "Actualizar",
"Write a description …" : "Escribe una descripción...", "Write a description …" : "Escribe una descripción...",
"Could not save description" : "No se pudo guardar la descripción",
"Description" : "Descripción", "Description" : "Descripción",
"(Unsaved)" : "(Sin salvar)", "(Unsaved)" : "(Sin salvar)",
"(Saving…)" : "(Guardando...)", "(Saving…)" : "(Guardando...)",
@@ -271,12 +257,12 @@
"Set due date for this weekend" : "Establecer este fin de semana como fecha de vencimiento", "Set due date for this weekend" : "Establecer este fin de semana como fecha de vencimiento",
"Next week {timeLocale}" : "Próxima semana {timeLocale}", "Next week {timeLocale}" : "Próxima semana {timeLocale}",
"Set due date for next week" : "Establecer la próxima semana como fecha de vencimiento", "Set due date for next week" : "Establecer la próxima semana como fecha de vencimiento",
"Assign a due date to this card…" : "Asignar una fecha de vencimiento a esta tarjeta…", "Assign a due date to this card…" : "Asignar una fecha de caducidad a esta tarjeta…",
"Set a due date" : "Fijar una fecha límite", "Set a due date" : "Fijar una fecha límite",
"Add due date" : "Añadir fecha de vencimiento", "Add due date" : "Añadir fecha de vencimiento",
"Choose a date" : "Elija una fecha", "Choose a date" : "Elija una fecha",
"Remove due date" : "Eliminar fecha límite", "Remove due date" : "Eliminar fecha límite",
"Mark as done" : "Marcar como completado", "Mark as done" : "Marcar como hecho",
"Due at:" : "Vence el:", "Due at:" : "Vence el:",
"Not done" : "No está finalizado", "Not done" : "No está finalizado",
"Unarchive card" : "Desarchivar tarjeta", "Unarchive card" : "Desarchivar tarjeta",
@@ -340,7 +326,6 @@
"An error occurred" : "Ocurrió un error", "An error occurred" : "Ocurrió un error",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "¿Está seguro de querer eliminar el tablero {title}? Esto eliminará todos los datos del tablero incluyendo las tarjetas archivadas.", "Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "¿Está seguro de querer eliminar el tablero {title}? Esto eliminará todos los datos del tablero incluyendo las tarjetas archivadas.",
"Delete the board?" : "¿Borrar el tablero?", "Delete the board?" : "¿Borrar el tablero?",
"Exporting board..." : "Exportando tablero...",
"Board details" : "Detalles del tablero", "Board details" : "Detalles del tablero",
"Edit board" : "Editar tablero", "Edit board" : "Editar tablero",
"Clone board" : "Clonar tablero", "Clone board" : "Clonar tablero",
@@ -353,22 +338,16 @@
"Assigned cards" : "Tarjetas asignadas", "Assigned cards" : "Tarjetas asignadas",
"No notifications" : "No hay notificaciones", "No notifications" : "No hay notificaciones",
"Delete board" : "Eliminar tablero", "Delete board" : "Eliminar tablero",
"Importing board..." : "Importando tablero...",
"Board imported successfully" : "Se importó el tablero exitosamente",
"Import board" : "Importar tablero",
"Clone {boardTitle}" : "Clonar {boardTitle}", "Clone {boardTitle}" : "Clonar {boardTitle}",
"Clone cards" : "Clonar tarjetas", "Clone cards" : "Clonar tarjetas",
"Clone assignments" : "Clonar asignaciones", "Clone assignments" : "Clonar asignaciones",
"Clone labels" : "Clonar etiquetas", "Clone labels" : "Clonar etiquetas",
"Clone due dates" : "Clonar fechas de vencimiento", "Clone due dates" : "Clonar fechas límite",
"Advanced options" : "Opciones avanzadas", "Advanced options" : "Opciones avanzadas",
"Move all cards to the first list" : "Mover todas las tarjetas a la primera lista", "Move all cards to the first list" : "Mover todas las tarjetas a la primera lista",
"Restore archived cards" : "Restaurar tarjetas archivadas", "Restore archived cards" : "Restaurar tarjetas archivadas",
"Clone" : "Clonar", "Clone" : "Clonar",
"Export {boardTitle}" : "Exportar {boardTitle}",
"Export as JSON" : "Exportar como JSON",
"Export as CSV" : "Exportar como CSV", "Export as CSV" : "Exportar como CSV",
"Note: Only the JSON format is supported for importing back into the Deck app." : "Nota: Solo el formato JSON es soportar al importar de vuelta en la app Deck.",
"Export" : "Exportar", "Export" : "Exportar",
"Loading filtered view" : "Cargando vista filtrada", "Loading filtered view" : "Cargando vista filtrada",
"Today" : "Hoy", "Today" : "Hoy",
@@ -376,17 +355,17 @@
"No due" : "Sin finalizar", "No due" : "Sin finalizar",
"Search for {searchQuery} in all boards" : "Buscar {searchQuery} en todos los tableros", "Search for {searchQuery} in all boards" : "Buscar {searchQuery} en todos los tableros",
"No results found" : "No se encontraron resultados", "No results found" : "No se encontraron resultados",
"Deck board {name}\n* Last modified on {lastMod}" : "Tablero Deck {name}\n* Se modificó por última vez el {lastMod}", "Deck board {name}\n* Last modified on {lastMod}" : "Tablero Deck {name}\n* Última modificación en {lastMod}",
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Creado en {created}\n* Se modificó por última vez el {lastMod}\n* {nbAttachments} adjuntos\n* {nbComments} comentarios", "* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Creada en {created}\n* Ultima moficiación en {lastMod}\n* {nbAttachments} adjuntos\n* {nbComments} comentarios",
"{nbCards} cards" : "{nbCards} tarjetas", "{nbCards} cards" : "{nbCards} tarjetas",
"Due on {date}" : "Vence en {date}", "Due on {date}" : "Vence en {date}",
"{stack} in {board}" : "{stack} en {board}", "{stack} in {board}" : "{stack} en {board}",
"Click to expand description" : "Haga clic para expandir la descripción", "Click to expand description" : "Pulse para expandir la descripción",
"Click to expand comment" : "Haga clic para expandir el comentario", "Click to expand comment" : "Pulse para expandir el comentario",
"Create card" : "Crear tarjeta", "Create card" : "Crear tarjeta",
"Create a new card" : "Crear una tarjeta nueva", "Create a new card" : "Crear una nueva tarjeta",
"Card title" : "Título de la tarjeta", "Card title" : "Título de la tarjeta",
"Creating the new card …" : "Creando una tarjeta nueva …", "Creating the new card …" : "Creando una nueva tarjeta …",
"Card \"{card}\" was added to \"{board}\"" : "La tarjeta \"{card}\" fue añadida a \"{board}\"", "Card \"{card}\" was added to \"{board}\"" : "La tarjeta \"{card}\" fue añadida a \"{board}\"",
"Open card" : "Abrir tarjeta", "Open card" : "Abrir tarjeta",
"Close" : "Cerrar", "Close" : "Cerrar",
@@ -402,8 +381,7 @@
"Something went wrong" : "Algo ha ido mal", "Something went wrong" : "Algo ha ido mal",
"Failed to upload {name}" : "Error al subir {name}", "Failed to upload {name}" : "Error al subir {name}",
"Maximum file size of {size} exceeded" : "Tamaño máximo de archivo de {size} excedido", "Maximum file size of {size} exceeded" : "Tamaño máximo de archivo de {size} excedido",
"Assigned users" : "Usuarios asignados", "Due date" : "Fecha de fin",
"Due date" : "Fecha de vencimiento",
"Error creating the share" : "Error creando el recurso compartido", "Error creating the share" : "Error creando el recurso compartido",
"Share with a Deck card" : "Compartir con una tarjeta de Deck", "Share with a Deck card" : "Compartir con una tarjeta de Deck",
"Share {file} with a Deck card" : "Compartir {file} con una tarjeta de Deck", "Share {file} with a Deck card" : "Compartir {file} con una tarjeta de Deck",

View File

@@ -33,7 +33,6 @@ OC.L10N.register(
"Tags" : "Etiquetas", "Tags" : "Etiquetas",
"Activity" : "Actividad", "Activity" : "Actividad",
"Undo" : "Deshacer", "Undo" : "Deshacer",
"Transfer" : "Transferencia",
"Can edit" : "Puede editar", "Can edit" : "Puede editar",
"Can share" : "Puede compartir", "Can share" : "Puede compartir",
"Owner" : "Dueño", "Owner" : "Dueño",
@@ -59,7 +58,6 @@ OC.L10N.register(
"Search" : "Buscar", "Search" : "Buscar",
"Archived boards" : "Tableros archivados", "Archived boards" : "Tableros archivados",
"Shared with you" : "Compartido con usted", "Shared with you" : "Compartido con usted",
"Cancel edit" : "Cancelar edición",
"Board details" : "Detalles del tablero", "Board details" : "Detalles del tablero",
"Edit board" : "Editar el tablero", "Edit board" : "Editar el tablero",
"Unarchive board" : "Desarchivar tablero", "Unarchive board" : "Desarchivar tablero",

View File

@@ -31,7 +31,6 @@
"Tags" : "Etiquetas", "Tags" : "Etiquetas",
"Activity" : "Actividad", "Activity" : "Actividad",
"Undo" : "Deshacer", "Undo" : "Deshacer",
"Transfer" : "Transferencia",
"Can edit" : "Puede editar", "Can edit" : "Puede editar",
"Can share" : "Puede compartir", "Can share" : "Puede compartir",
"Owner" : "Dueño", "Owner" : "Dueño",
@@ -57,7 +56,6 @@
"Search" : "Buscar", "Search" : "Buscar",
"Archived boards" : "Tableros archivados", "Archived boards" : "Tableros archivados",
"Shared with you" : "Compartido con usted", "Shared with you" : "Compartido con usted",
"Cancel edit" : "Cancelar edición",
"Board details" : "Detalles del tablero", "Board details" : "Detalles del tablero",
"Edit board" : "Editar el tablero", "Edit board" : "Editar el tablero",
"Unarchive board" : "Desarchivar tablero", "Unarchive board" : "Desarchivar tablero",

View File

@@ -274,7 +274,6 @@ OC.L10N.register(
"{count} comments, {unread} unread" : "コメント {count} 件あり、 {unread} 件未読", "{count} comments, {unread} unread" : "コメント {count} 件あり、 {unread} 件未読",
"Todo items" : "Todo項目", "Todo items" : "Todo項目",
"Edit card title" : "カードタイトルを編集する", "Edit card title" : "カードタイトルを編集する",
"Open link" : "リンクを開く",
"Card deleted" : "カードが削除されました", "Card deleted" : "カードが削除されました",
"Edit title" : "タイトルを編集", "Edit title" : "タイトルを編集",
"Assign to me" : "自分に割り当てる", "Assign to me" : "自分に割り当てる",

View File

@@ -272,7 +272,6 @@
"{count} comments, {unread} unread" : "コメント {count} 件あり、 {unread} 件未読", "{count} comments, {unread} unread" : "コメント {count} 件あり、 {unread} 件未読",
"Todo items" : "Todo項目", "Todo items" : "Todo項目",
"Edit card title" : "カードタイトルを編集する", "Edit card title" : "カードタイトルを編集する",
"Open link" : "リンクを開く",
"Card deleted" : "カードが削除されました", "Card deleted" : "カードが削除されました",
"Edit title" : "タイトルを編集", "Edit title" : "タイトルを編集",
"Assign to me" : "自分に割り当てる", "Assign to me" : "自分に割り当てる",

View File

@@ -65,7 +65,6 @@ OC.L10N.register(
"Description" : "Apraksts", "Description" : "Apraksts",
"Select Date" : "Izvēlieties datumu", "Select Date" : "Izvēlieties datumu",
"Later today {timeLocale}" : "Vēlāk šodien {timeLocale}", "Later today {timeLocale}" : "Vēlāk šodien {timeLocale}",
"Set due date for later today" : "Iestatīt beigu datumu vēlāk šodienā",
"(group)" : "(grupa)", "(group)" : "(grupa)",
"Open link" : "Atvērt saiti", "Open link" : "Atvērt saiti",
"seconds ago" : "pirms vairākām sekundēm", "seconds ago" : "pirms vairākām sekundēm",
@@ -81,8 +80,6 @@ OC.L10N.register(
"Export" : "Izgūt", "Export" : "Izgūt",
"Today" : "Šodien", "Today" : "Šodien",
"Tomorrow" : "Rīt", "Tomorrow" : "Rīt",
"Deck board {name}\n* Last modified on {lastMod}" : "Kavas dēlis {name}\n* Pēdējoreiz izmainīts {lastMod}",
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Izveidots {created}\n* Pēdējoreiz izmainīts {lastMod}\n* {nbAttachments} pielikumi\n* {nbComments} piebildes",
"Close" : "Aizvērt", "Close" : "Aizvērt",
"Due date" : "Izpildes datums", "Due date" : "Izpildes datums",
"Share" : "Koplietot", "Share" : "Koplietot",

View File

@@ -63,7 +63,6 @@
"Description" : "Apraksts", "Description" : "Apraksts",
"Select Date" : "Izvēlieties datumu", "Select Date" : "Izvēlieties datumu",
"Later today {timeLocale}" : "Vēlāk šodien {timeLocale}", "Later today {timeLocale}" : "Vēlāk šodien {timeLocale}",
"Set due date for later today" : "Iestatīt beigu datumu vēlāk šodienā",
"(group)" : "(grupa)", "(group)" : "(grupa)",
"Open link" : "Atvērt saiti", "Open link" : "Atvērt saiti",
"seconds ago" : "pirms vairākām sekundēm", "seconds ago" : "pirms vairākām sekundēm",
@@ -79,8 +78,6 @@
"Export" : "Izgūt", "Export" : "Izgūt",
"Today" : "Šodien", "Today" : "Šodien",
"Tomorrow" : "Rīt", "Tomorrow" : "Rīt",
"Deck board {name}\n* Last modified on {lastMod}" : "Kavas dēlis {name}\n* Pēdējoreiz izmainīts {lastMod}",
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Izveidots {created}\n* Pēdējoreiz izmainīts {lastMod}\n* {nbAttachments} pielikumi\n* {nbComments} piebildes",
"Close" : "Aizvērt", "Close" : "Aizvērt",
"Due date" : "Izpildes datums", "Due date" : "Izpildes datums",
"Share" : "Koplietot", "Share" : "Koplietot",

View File

@@ -266,7 +266,6 @@ OC.L10N.register(
"{count} comments, {unread} unread" : "Komentarze: {count}, nieprzeczytane: {unread}", "{count} comments, {unread} unread" : "Komentarze: {count}, nieprzeczytane: {unread}",
"Todo items" : "Do zrobienia", "Todo items" : "Do zrobienia",
"Edit card title" : "Edytuj nazwę karty", "Edit card title" : "Edytuj nazwę karty",
"Open link" : "Otwórz link",
"Card deleted" : "Karta usunięta", "Card deleted" : "Karta usunięta",
"Edit title" : "Edytuj tytuł", "Edit title" : "Edytuj tytuł",
"Assign to me" : "Przydziel do mnie", "Assign to me" : "Przydziel do mnie",
@@ -313,7 +312,6 @@ OC.L10N.register(
"Clone cards" : "Klonuj karty", "Clone cards" : "Klonuj karty",
"Advanced options" : "Opcje zaawansowane", "Advanced options" : "Opcje zaawansowane",
"Clone" : "Klonuj", "Clone" : "Klonuj",
"Export {boardTitle}" : "Eksportuj {boardTitle}",
"Export" : "Eksportuj", "Export" : "Eksportuj",
"Loading filtered view" : "Wczytywanie przefiltrowanego widoku", "Loading filtered view" : "Wczytywanie przefiltrowanego widoku",
"Today" : "Dzisiaj", "Today" : "Dzisiaj",

View File

@@ -264,7 +264,6 @@
"{count} comments, {unread} unread" : "Komentarze: {count}, nieprzeczytane: {unread}", "{count} comments, {unread} unread" : "Komentarze: {count}, nieprzeczytane: {unread}",
"Todo items" : "Do zrobienia", "Todo items" : "Do zrobienia",
"Edit card title" : "Edytuj nazwę karty", "Edit card title" : "Edytuj nazwę karty",
"Open link" : "Otwórz link",
"Card deleted" : "Karta usunięta", "Card deleted" : "Karta usunięta",
"Edit title" : "Edytuj tytuł", "Edit title" : "Edytuj tytuł",
"Assign to me" : "Przydziel do mnie", "Assign to me" : "Przydziel do mnie",
@@ -311,7 +310,6 @@
"Clone cards" : "Klonuj karty", "Clone cards" : "Klonuj karty",
"Advanced options" : "Opcje zaawansowane", "Advanced options" : "Opcje zaawansowane",
"Clone" : "Klonuj", "Clone" : "Klonuj",
"Export {boardTitle}" : "Eksportuj {boardTitle}",
"Export" : "Eksportuj", "Export" : "Eksportuj",
"Loading filtered view" : "Wczytywanie przefiltrowanego widoku", "Loading filtered view" : "Wczytywanie przefiltrowanego widoku",
"Today" : "Dzisiaj", "Today" : "Dzisiaj",

View File

@@ -274,7 +274,6 @@ OC.L10N.register(
"{count} comments, {unread} unread" : "{count} комментариев, {unread} непрочитано", "{count} comments, {unread} unread" : "{count} комментариев, {unread} непрочитано",
"Todo items" : "Элементы списка задач", "Todo items" : "Элементы списка задач",
"Edit card title" : "Изменить заголовок карточки", "Edit card title" : "Изменить заголовок карточки",
"Open link" : "Открыть ссылку",
"Card deleted" : "Карточка удалена", "Card deleted" : "Карточка удалена",
"Edit title" : "Редактировать заголовок", "Edit title" : "Редактировать заголовок",
"Assign to me" : "Назначить себе", "Assign to me" : "Назначить себе",

View File

@@ -272,7 +272,6 @@
"{count} comments, {unread} unread" : "{count} комментариев, {unread} непрочитано", "{count} comments, {unread} unread" : "{count} комментариев, {unread} непрочитано",
"Todo items" : "Элементы списка задач", "Todo items" : "Элементы списка задач",
"Edit card title" : "Изменить заголовок карточки", "Edit card title" : "Изменить заголовок карточки",
"Open link" : "Открыть ссылку",
"Card deleted" : "Карточка удалена", "Card deleted" : "Карточка удалена",
"Edit title" : "Редактировать заголовок", "Edit title" : "Редактировать заголовок",
"Assign to me" : "Назначить себе", "Assign to me" : "Назначить себе",

View File

@@ -124,7 +124,6 @@ OC.L10N.register(
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Овај коментар има више од %s карактера.\nДодат је као прилог картици под именом %s.\nДоступно је на URL адреси: %s.", "This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Овај коментар има више од %s карактера.\nДодат је као прилог картици под именом %s.\nДоступно је на URL адреси: %s.",
"Attachments" : "Прилози", "Attachments" : "Прилози",
"File" : "Фајл", "File" : "Фајл",
"date" : "датум",
"Card not found" : "Картица није нађена", "Card not found" : "Картица није нађена",
"Path is already shared with this card" : "Путања се већ дели са овом картицом", "Path is already shared with this card" : "Путања се већ дели са овом картицом",
"Invalid date, date format must be YYYY-MM-DD" : "Неисправан датум, формат датума мора бити ГГГГ-ММ-ДД", "Invalid date, date format must be YYYY-MM-DD" : "Неисправан датум, формат датума мора бити ГГГГ-ММ-ДД",
@@ -240,7 +239,6 @@ OC.L10N.register(
"Modified" : "Измењен", "Modified" : "Измењен",
"Created" : "Направљен", "Created" : "Направљен",
"The title cannot be empty." : "Наслов не може бити празан.", "The title cannot be empty." : "Наслов не може бити празан.",
"Cannot close unsaved card!" : "Не може да се затвори несачувана картица!",
"Open in sidebar view" : "Отвори у бочном прегледу", "Open in sidebar view" : "Отвори у бочном прегледу",
"Open in bigger view" : "Отвори на већем приказу", "Open in bigger view" : "Отвори на већем приказу",
"Comments" : "Коментари", "Comments" : "Коментари",
@@ -255,7 +253,6 @@ OC.L10N.register(
"Reply" : "Одговори", "Reply" : "Одговори",
"Update" : "Ажурирај", "Update" : "Ажурирај",
"Write a description …" : "Напишите опис ...", "Write a description …" : "Напишите опис ...",
"Could not save description" : "Не може да се сачува опис",
"Description" : "Опис", "Description" : "Опис",
"(Unsaved)" : "(несачуван)", "(Unsaved)" : "(несачуван)",
"(Saving…)" : "(чувам…)", "(Saving…)" : "(чувам…)",

View File

@@ -122,7 +122,6 @@
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Овај коментар има више од %s карактера.\nДодат је као прилог картици под именом %s.\nДоступно је на URL адреси: %s.", "This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Овај коментар има више од %s карактера.\nДодат је као прилог картици под именом %s.\nДоступно је на URL адреси: %s.",
"Attachments" : "Прилози", "Attachments" : "Прилози",
"File" : "Фајл", "File" : "Фајл",
"date" : "датум",
"Card not found" : "Картица није нађена", "Card not found" : "Картица није нађена",
"Path is already shared with this card" : "Путања се већ дели са овом картицом", "Path is already shared with this card" : "Путања се већ дели са овом картицом",
"Invalid date, date format must be YYYY-MM-DD" : "Неисправан датум, формат датума мора бити ГГГГ-ММ-ДД", "Invalid date, date format must be YYYY-MM-DD" : "Неисправан датум, формат датума мора бити ГГГГ-ММ-ДД",
@@ -238,7 +237,6 @@
"Modified" : "Измењен", "Modified" : "Измењен",
"Created" : "Направљен", "Created" : "Направљен",
"The title cannot be empty." : "Наслов не може бити празан.", "The title cannot be empty." : "Наслов не може бити празан.",
"Cannot close unsaved card!" : "Не може да се затвори несачувана картица!",
"Open in sidebar view" : "Отвори у бочном прегледу", "Open in sidebar view" : "Отвори у бочном прегледу",
"Open in bigger view" : "Отвори на већем приказу", "Open in bigger view" : "Отвори на већем приказу",
"Comments" : "Коментари", "Comments" : "Коментари",
@@ -253,7 +251,6 @@
"Reply" : "Одговори", "Reply" : "Одговори",
"Update" : "Ажурирај", "Update" : "Ажурирај",
"Write a description …" : "Напишите опис ...", "Write a description …" : "Напишите опис ...",
"Could not save description" : "Не може да се сачува опис",
"Description" : "Опис", "Description" : "Опис",
"(Unsaved)" : "(несачуван)", "(Unsaved)" : "(несачуван)",
"(Saving…)" : "(чувам…)", "(Saving…)" : "(чувам…)",

View File

@@ -240,7 +240,6 @@ OC.L10N.register(
"Modified" : "Değiştirilme", "Modified" : "Değiştirilme",
"Created" : "Oluşturulma", "Created" : "Oluşturulma",
"The title cannot be empty." : "Başlık boş olamaz.", "The title cannot be empty." : "Başlık boş olamaz.",
"Cannot close unsaved card!" : "Kaydedilmemiş bir kart kapatılamaz!",
"Open in sidebar view" : "Kenar çubuğu görünümünde aç", "Open in sidebar view" : "Kenar çubuğu görünümünde aç",
"Open in bigger view" : "Daha büyük görünümde aç", "Open in bigger view" : "Daha büyük görünümde aç",
"Comments" : "Yorumlar", "Comments" : "Yorumlar",
@@ -255,7 +254,6 @@ OC.L10N.register(
"Reply" : "Yanıtla", "Reply" : "Yanıtla",
"Update" : "Güncelle", "Update" : "Güncelle",
"Write a description …" : "Bir açıklama yazın …", "Write a description …" : "Bir açıklama yazın …",
"Could not save description" : "Açıklama kaydedilemedi",
"Description" : "Açıklama", "Description" : "Açıklama",
"(Unsaved)" : "(Kaydedilmemiş)", "(Unsaved)" : "(Kaydedilmemiş)",
"(Saving…)" : "(Kaydediliyor…)", "(Saving…)" : "(Kaydediliyor…)",

View File

@@ -238,7 +238,6 @@
"Modified" : "Değiştirilme", "Modified" : "Değiştirilme",
"Created" : "Oluşturulma", "Created" : "Oluşturulma",
"The title cannot be empty." : "Başlık boş olamaz.", "The title cannot be empty." : "Başlık boş olamaz.",
"Cannot close unsaved card!" : "Kaydedilmemiş bir kart kapatılamaz!",
"Open in sidebar view" : "Kenar çubuğu görünümünde aç", "Open in sidebar view" : "Kenar çubuğu görünümünde aç",
"Open in bigger view" : "Daha büyük görünümde aç", "Open in bigger view" : "Daha büyük görünümde aç",
"Comments" : "Yorumlar", "Comments" : "Yorumlar",
@@ -253,7 +252,6 @@
"Reply" : "Yanıtla", "Reply" : "Yanıtla",
"Update" : "Güncelle", "Update" : "Güncelle",
"Write a description …" : "Bir açıklama yazın …", "Write a description …" : "Bir açıklama yazın …",
"Could not save description" : "Açıklama kaydedilemedi",
"Description" : "Açıklama", "Description" : "Açıklama",
"(Unsaved)" : "(Kaydedilmemiş)", "(Unsaved)" : "(Kaydedilmemiş)",
"(Saving…)" : "(Kaydediliyor…)", "(Saving…)" : "(Kaydediliyor…)",

View File

@@ -48,30 +48,8 @@ OC.L10N.register(
"You have updated the due date of card {card} to {after}" : "Ви оновили дату завершення картки {card} на {after}", "You have updated the due date of card {card} to {after}" : "Ви оновили дату завершення картки {card} на {after}",
"{user} has updated the due date of card {card} to {after}" : "{user} оновив(-ла) дату завершення картки {card} на {after}", "{user} has updated the due date of card {card} to {after}" : "{user} оновив(-ла) дату завершення картки {card} на {after}",
"You have added the tag {label} to card {card} in list {stack} on board {board}" : "Ви додали мітку {label} до картки {card} в списку {board}", "You have added the tag {label} to card {card} in list {stack} on board {board}" : "Ви додали мітку {label} до картки {card} в списку {board}",
"{user} has added the tag {label} to card {card} in list {stack} on board {board}" : "{user} додав тег {label} до карти {card} у списку {stack} на борту {board}",
"You have removed the tag {label} from card {card} in list {stack} on board {board}" : "Ви видалили тег {label} з карти {card} у списку {stack} на борту {board}",
"{user} has removed the tag {label} from card {card} in list {stack} on board {board}" : "{user} видалив тег {label} з карти {card} у списку {stack} на борту {board}",
"You have assigned {assigneduser} to card {card} on board {board}" : "Ви призначили {assigneduser} на картку {card} на борту {board}",
"{user} has assigned {assigneduser} to card {card} on board {board}" : "{user} призначив {assigneduser} на картку {card} на дошці {board}",
"You have unassigned {assigneduser} from card {card} on board {board}" : "Ви скасували призначення {assigneduser} з карти {card} на борту {board}",
"{user} has unassigned {assigneduser} from card {card} on board {board}" : "{user} скасував призначення {assigneduser} з карти {card} на дошці {board}",
"You have moved the card {card} from list {stackBefore} to {stack}" : "Ви перемістили картку {card} зі списку {stackBefore} до {stack}",
"{user} has moved the card {card} from list {stackBefore} to {stack}" : "{user} перемістив картку {card} зі списку {stackBefore} до {stack}",
"You have added the attachment {attachment} to card {card}" : "Ви додали вкладення {attachment} до картки {card}",
"{user} has added the attachment {attachment} to card {card}" : "{user} додав вкладення {attachment} до картки {card}",
"You have updated the attachment {attachment} on card {card}" : "Ви оновили вкладення {attachment} на картці {card}",
"{user} has updated the attachment {attachment} on card {card}" : " {user}оновив вкладення {attachment} на картці {card}",
"You have deleted the attachment {attachment} from card {card}" : "Ви видалили вкладення {attachment} з картки {card}",
"{user} has deleted the attachment {attachment} from card {card}" : "{user} видалив вкладення {attachment} з картки {card}",
"You have restored the attachment {attachment} to card {card}" : "Ви відновили вкладення {attachment} до картки {card}",
"{user} has restored the attachment {attachment} to card {card}" : "{user} відновив вкладення {attachment} до картки {card}",
"You have commented on card {card}" : "Ви залишили коментар до картки {card}",
"{user} has commented on card {card}" : "{user} прокоментував картку {card}",
"Deck" : "Колода", "Deck" : "Колода",
"Changes in the <strong>Deck app</strong>" : "Зміни у застосунку <strong>Колода</strong>", "Changes in the <strong>Deck app</strong>" : "Зміни у застосунку <strong>Колода</strong>",
"A <strong>board, list or card</strong> was changed" : "Змінено <strong>таблицю, список або картку</strong>",
"A <strong>comment</strong> was created on a card" : "Створено <strong>коментар</strong> на картці",
"A <strong>card description</strong> has been changed" : "Змінено <strong>опис картки</strong>",
"The file was uploaded" : "Файл завантажено", "The file was uploaded" : "Файл завантажено",
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "Файл для завантаження перевищує параметр upload_max_filesize у php.ini", "The uploaded file exceeds the upload_max_filesize directive in php.ini" : "Файл для завантаження перевищує параметр upload_max_filesize у php.ini",
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Розмір завантаженого файлу перевищує значення MAX_FILE_SIZE, яке було зазначено у HTML формі", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Розмір завантаженого файлу перевищує значення MAX_FILE_SIZE, яке було зазначено у HTML формі",
@@ -81,66 +59,30 @@ OC.L10N.register(
"Could not write file to disk" : "Неможливо записати файл на диск", "Could not write file to disk" : "Неможливо записати файл на диск",
"A PHP extension stopped the file upload" : "Розширення PHP призупинило завантаження файлу", "A PHP extension stopped the file upload" : "Розширення PHP призупинило завантаження файлу",
"No file uploaded or file size exceeds maximum of %s" : "Немає завантажених файлів або розмір файлу перевищує максимум %s", "No file uploaded or file size exceeds maximum of %s" : "Немає завантажених файлів або розмір файлу перевищує максимум %s",
"Invalid file type. Only JSON files are allowed." : "Неправильний тип файлу. Допускаються тільки файли у форматі JSON.",
"Invalid JSON data" : "Неправильні дані JSON",
"Failed to import board" : "Не вдалося імпортувати дошку",
"Cards due today" : "Картки повинні бути оплачені сьогодні",
"Cards due tomorrow" : "Картки на завтра",
"Upcoming cards" : "Очікують на виконання", "Upcoming cards" : "Очікують на виконання",
"Load more" : "Більше", "Load more" : "Більше",
"Welcome to Nextcloud Deck!" : "Ласкаво просимо до колоди Nextcloud!",
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "Картка \"%s\" на \"%s\" була призначена вам %s.",
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} призначив вам карту {deck-card} на {deck-board}.",
"The card \"%s\" on \"%s\" has reached its due date." : "Термін дії картки \"%s\" на \"%s\" закінчився.",
"The card {deck-card} on {deck-board} has reached its due date." : "Термін дії карти {deck-card} на {deck-board} закінчився.",
"%s has mentioned you in a comment on \"%s\"." : "%s згадав вас у коментарі до \"%s\".",
"{user} has mentioned you in a comment on {deck-card}." : "{user} згадав вас у коментарі до {deck-card}.",
"The board \"%s\" has been shared with you by %s." : "Дошку \"%s\" з вами поділився %s.",
"{user} has shared {deck-board} with you." : "{user} поділився з вами {deck-board}.",
"Deck board" : "Дошка Deck", "Deck board" : "Дошка Deck",
"Owned by %1$s" : "Належить %1$s",
"Deck boards, cards and comments" : "Дошки колод, карти та коментарі",
"From %1$s, in %2$s/%3$s, owned by %4$s" : "З %1$s, в %2$s/%3$s, у власності %4$s",
"Create a new deck card" : "Створіть нову карту колоди",
"Card comments" : "Коментарі до картки",
"%s on %s" : "%s на %s", "%s on %s" : "%s на %s",
"Deck boards and cards" : "Колода та карти",
"No data was provided to create an attachment." : "Для створення вкладення не було надано жодних даних.",
"Finished" : "Завершено", "Finished" : "Завершено",
"To review" : "На перегляд", "To review" : "На перегляд",
"Action needed" : "Потребує дій", "Action needed" : "Потребує дій",
"Later" : "Пізніше", "Later" : "Пізніше",
"copy" : "копіювати", "copy" : "копіювати",
"Read more inside" : "Читайте більше всередині",
"Custom lists - click to rename!" : "Користувацькі списки - натисніть, щоб перейменувати!",
"To Do" : "Зробити", "To Do" : "Зробити",
"In Progress" : "В процесі", "In Progress" : "В процесі",
"Done" : "Готово", "Done" : "Готово",
"1. Open to learn more about boards and cards" : "1. Відкриті, щоб дізнатися більше про дошки та картки",
"2. Drag cards left and right, up and down" : "2. Перетягування карток вліво і вправо, вгору і вниз",
"3. Apply rich formatting and link content" : "3. Застосовуйте багате форматування та посилання на вміст",
"4. Share, comment and collaborate!" : "4. Діліться, коментуйте та співпрацюйте!",
"Create your first card!" : "Створіть свою першу листівку!",
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Цей коментар містить більше %s символів.\nДодано як вкладення до картки з іменем %s.\nДоступний за URL: %s.",
"Attachments" : "Вкладення", "Attachments" : "Вкладення",
"File" : "Файл", "File" : "Файл",
"date" : "дата",
"Card not found" : "Картку не знайдено", "Card not found" : "Картку не знайдено",
"Path is already shared with this card" : "Шлях вже є спільним з цією карткою",
"Invalid date, date format must be YYYY-MM-DD" : "Недійсна дата, формат дати має бути РРРР-ММ-ДД", "Invalid date, date format must be YYYY-MM-DD" : "Недійсна дата, формат дати має бути РРРР-ММ-ДД",
"Personal planning and team project organization" : "Особисте планування та організація командних проектів",
"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 - це інструмент організації в стилі канбан, призначений для особистого планування та організації проектів для команд, інтегрованих з Nextcloud.\n\n\n- 📥 Додавайте свої завдання на картки та впорядковуйте їх\n- 📄 Записуйте додаткові нотатки в Markdown\n- 🔖 Призначайте мітки для ще кращої організації\n- 👥 Діліться з командою, друзями чи родиною\n- Прикріплюйте файли та вбудовуйте їх в опис Markdown\n- 💬 Обговорюйте зі своєю командою за допомогою коментарів\n- ⚡ Відстежуйте зміни в потоці активностей\n- 🚀 Організуйте свій проект",
"Add board" : "Додати дошку", "Add board" : "Додати дошку",
"Card details" : "Деталі картки", "Card details" : "Деталі картки",
"Select the board to link to a project" : "Виберіть дошку для прив'зки до проєкту", "Select the board to link to a project" : "Виберіть дошку для прив'зки до проєкту",
"Search by board title" : "Шукати за назвою дошки", "Search by board title" : "Шукати за назвою дошки",
"Select board" : "Вибрати дошку", "Select board" : "Вибрати дошку",
"Move/copy card" : "Картка переміщення/копіювання",
"Select a board" : "Вибрати дошку", "Select a board" : "Вибрати дошку",
"No lists available" : "Списки відсутні",
"Select a list" : "Виберіть список", "Select a list" : "Виберіть список",
"Move card" : "Пересунути картку", "Move card" : "Пересунути картку",
"Copy card" : "Копіювальна картка",
"Select the card to link to a project" : "Виберіть картку для прив'язки до проєкту", "Select the card to link to a project" : "Виберіть картку для прив'язки до проєкту",
"Link to card" : "Прив'язати до картки", "Link to card" : "Прив'язати до картки",
"Select a card" : "Вибрати картку", "Select a card" : "Вибрати картку",
@@ -161,27 +103,19 @@ OC.L10N.register(
"Filter by tag" : "Відібрати за мітками", "Filter by tag" : "Відібрати за мітками",
"Filter by assigned user" : "Відібрати за призначеним користувачем", "Filter by assigned user" : "Відібрати за призначеним користувачем",
"Unassigned" : "Скасовано призначення", "Unassigned" : "Скасовано призначення",
"Filter by status" : "Фільтр за статусом",
"Open and completed" : "Відкрито та завершено",
"Open" : "Відкрити", "Open" : "Відкрити",
"Completed" : "Виконано", "Completed" : "Виконано",
"Filter by due date" : "Відібрати за датою завершення", "Filter by due date" : "Відібрати за датою завершення",
"Overdue" : "Протерміновано", "Overdue" : "Протерміновано",
"Next 24 hours" : "Наступні 24 години",
"Next 7 days" : "Наступні 7 днів", "Next 7 days" : "Наступні 7 днів",
"Next 30 days" : "Наступні 30 днів", "Next 30 days" : "Наступні 30 днів",
"No due date" : "Без дати завершення", "No due date" : "Без дати завершення",
"Clear filter" : "Очистити фільтр", "Clear filter" : "Очистити фільтр",
"View Modes" : "Режими перегляду",
"Toggle View Modes" : "Перемикання режимів перегляду",
"Hide archived cards" : "Приховати архівні картки", "Hide archived cards" : "Приховати архівні картки",
"Show archived cards" : "Показати архівні картки", "Show archived cards" : "Показати архівні картки",
"Toggle compact mode" : "Перемкнути компактний вигляд", "Toggle compact mode" : "Перемкнути компактний вигляд",
"Hide card cover images" : "Приховати зображення обкладинок карток",
"Show card cover images" : "Показати зображення обкладинки картки",
"Open details" : "Показати деталі", "Open details" : "Показати деталі",
"Details" : "Деталі", "Details" : "Деталі",
"Currently present people" : "Наразі присутні люди",
"Loading board" : "Завантаження дошки", "Loading board" : "Завантаження дошки",
"Board not found" : "Дошку не знайдено", "Board not found" : "Дошку не знайдено",
"Create a new list to add cards to this board" : "Створіть список щоб додати картки на цю дошку", "Create a new list to add cards to this board" : "Створіть список щоб додати картки на цю дошку",
@@ -192,62 +126,35 @@ OC.L10N.register(
"Deleted lists" : "Вилучені списки", "Deleted lists" : "Вилучені списки",
"Undo" : "Скасувати", "Undo" : "Скасувати",
"Deleted cards" : "Вилучені картки", "Deleted cards" : "Вилучені картки",
"Failed to create share with {displayName}" : "Не вдалося створити спільний доступ з {displayName}",
"Are you sure you want to transfer the board {title} to {user}?" : "Ви впевнені, що хочете перенести дошку {title} користувачеві {user}?",
"Transfer the board." : "Перенесіть дошку.",
"Transfer" : "Передати", "Transfer" : "Передати",
"The board has been transferred to {user}" : "Дошка була передана {user}",
"Failed to transfer the board to {user}" : "Не вдалося передати дошку користувачеві {user}",
"Share board with a user, group or team …" : "Спільний доступ до дошки з користувачем, групою або командою ...",
"Searching for users, groups and teams …" : "Пошук користувачів, груп і команд ...",
"No participants found" : "Учасників не знайдено",
"Board owner" : "Власник дошки", "Board owner" : "Власник дошки",
"(Group)" : "(група)", "(Group)" : "(група)",
"(Team)" : "(Команда)",
"Can edit" : "Може редагувати", "Can edit" : "Може редагувати",
"Can share" : "Can share", "Can share" : "Can share",
"Can manage" : "Може керувати", "Can manage" : "Може керувати",
"Owner" : "Власник", "Owner" : "Власник",
"Delete" : "Вилучити", "Delete" : "Вилучити",
"List deleted" : "Список видалено",
"Edit list title" : "Редагувати заголовок списку",
"Archive all cards" : "Архівувати всі картки",
"Unarchive all cards" : "Розархівувати всі картки",
"Delete list" : "Вилучити список", "Delete list" : "Вилучити список",
"Archive all cards in this list" : "Архівуйте всі картки в цьому списку",
"Unarchive all cards in this list" : "Розархівувати всі картки в цьому списку",
"Add a new card" : "Додати нову картку", "Add a new card" : "Додати нову картку",
"Card name" : "Назва картки",
"title and color value must be provided" : "потрібно зазначити назву та колір", "title and color value must be provided" : "потрібно зазначити назву та колір",
"Edit" : "Редагувати", "Edit" : "Редагувати",
"Add a new tag" : "Додати нову мітку", "Add a new tag" : "Додати нову мітку",
"Board name" : "Назва дошки", "Board name" : "Назва дошки",
"Members" : "Учасники", "Members" : "Учасники",
"Assign to users/groups/team" : "Призначити користувачам/групам/команді",
"Assign a user to this card…" : "Призначити користувачеві цю картку", "Assign a user to this card…" : "Призначити користувачеві цю картку",
"Select a user to assign to this card…" : "Виберіть користувача, якого слід призначити на цю картку...",
"File to share" : "Виберіть файл для надання доступу", "File to share" : "Виберіть файл для надання доступу",
"Invalid path selected" : "Вибрано неправильний шлях", "Invalid path selected" : "Вибрано неправильний шлях",
"Upload new files" : "Додати файл", "Upload new files" : "Додати файл",
"Share from Files" : "Відкрити Файли", "Share from Files" : "Відкрити Файли",
"Pending share" : "Очікувана акція",
"Add this attachment" : "Долучити вкладення", "Add this attachment" : "Долучити вкладення",
"Show in Files" : "Показати в Файлах", "Show in Files" : "Показати в Файлах",
"Download" : "Звантажити", "Download" : "Звантажити",
"Remove attachment" : "Зніміть вкладення",
"Delete Attachment" : "Забрати вкладення", "Delete Attachment" : "Забрати вкладення",
"Restore Attachment" : "Відновити вкладення", "Restore Attachment" : "Відновити вкладення",
"Modified" : "Змінено", "Modified" : "Змінено",
"Created" : "Створено", "Created" : "Створено",
"The title cannot be empty." : "Заголовок не може бути порожнім.",
"Cannot close unsaved card!" : "Неможливо закрити незбережену картку!",
"Open in sidebar view" : "Відкрити у вигляді бічної панелі",
"Open in bigger view" : "Відкрити в більшому розмірі",
"Comments" : "Коментарі", "Comments" : "Коментарі",
"Failed to load comments" : "Не вдалося завантажити коментарі",
"No comments yet. Begin the discussion!" : "Коментарів немає, почніть обговорення!", "No comments yet. Begin the discussion!" : "Коментарів немає, почніть обговорення!",
"The comment cannot be empty." : "Коментар не може бути порожнім.",
"The comment cannot be longer than 1000 characters." : "Коментар не може бути довшим за 1000 символів.",
"Save" : "Зберегти", "Save" : "Зберегти",
"Created:" : "Створено:", "Created:" : "Створено:",
"In reply to" : "У відповідь", "In reply to" : "У відповідь",
@@ -255,7 +162,6 @@ OC.L10N.register(
"Reply" : "Відповісти", "Reply" : "Відповісти",
"Update" : "Оновлення", "Update" : "Оновлення",
"Write a description …" : "Додайте опис ...", "Write a description …" : "Додайте опис ...",
"Could not save description" : "Не вдалося зберегти опис",
"Description" : "Опис", "Description" : "Опис",
"(Unsaved)" : "(Не збережено)", "(Unsaved)" : "(Не збережено)",
"(Saving…)" : "(Зберігання...)", "(Saving…)" : "(Зберігання...)",
@@ -265,150 +171,73 @@ OC.L10N.register(
"Add Attachment" : "Долучити вкладення", "Add Attachment" : "Долучити вкладення",
"Choose attachment" : "Вибрати вкладення", "Choose attachment" : "Вибрати вкладення",
"Select Date" : "Вкажіть дату", "Select Date" : "Вкажіть дату",
"Later today {timeLocale}" : "Пізніше сьогодні - {timeLocale}",
"Set due date for later today" : "Встановіть термін сплати на сьогоднішній день",
"Tomorrow {timeLocale}" : "Завтра - {timeLocale}",
"Set due date for tomorrow" : "Встановіть дедлайн на завтра",
"This weekend {timeLocale}" : "На цих вихідних - {timeLocale}", "This weekend {timeLocale}" : "На цих вихідних - {timeLocale}",
"Set due date for this weekend" : "Встановіть термін виконання на ці вихідні",
"Next week {timeLocale}" : "Наступного тижня - {timeLocale}", "Next week {timeLocale}" : "Наступного тижня - {timeLocale}",
"Set due date for next week" : "Встановіть термін виконання на наступний тиждень",
"Assign a due date to this card…" : "Призначте цій картці термін оплати...",
"Set a due date" : "Встановити дату завершення", "Set a due date" : "Встановити дату завершення",
"Add due date" : "Додати термін сплати",
"Choose a date" : "Виберіть дату", "Choose a date" : "Виберіть дату",
"Remove due date" : "Вилучити до", "Remove due date" : "Вилучити до",
"Mark as done" : "Позначити як виконане", "Mark as done" : "Позначити як виконане",
"Due at:" : "На часі:",
"Not done" : "Ще не все.",
"Unarchive card" : "Розархівувати картку", "Unarchive card" : "Розархівувати картку",
"Archive card" : "Архівувати картку", "Archive card" : "Архівувати картку",
"Assign a tag to this card…" : "Додати мітку до цієї картки", "Assign a tag to this card…" : "Додати мітку до цієї картки",
"Select or create a tag…" : "Виберіть або створіть тег...",
"Create a new tag:" : "Створіть новий тег:",
"(group)" : "(група)", "(group)" : "(група)",
"{count} comments, {unread} unread" : "{count} коментарів, {unread} непрочитаних",
"Todo items" : "Пункти завдань", "Todo items" : "Пункти завдань",
"Edit card title" : "Редагувати заголовок картки", "Edit card title" : "Редагувати заголовок картки",
"Open link" : "Відкрити посилання", "Open link" : "Відкрити посилання",
"Card deleted" : "Картку видалено",
"Edit title" : "Редагувати", "Edit title" : "Редагувати",
"Assign to me" : "Призначити мені", "Assign to me" : "Призначити мені",
"Unassign myself" : "Зняти з себе повноваження.",
"Mark as not done" : "Позначити як не виконано",
"Delete card" : "Вилучити картку", "Delete card" : "Вилучити картку",
"seconds ago" : "секунд тому", "seconds ago" : "секунд тому",
"Keyboard shortcuts" : "Скорочення", "Keyboard shortcuts" : "Скорочення",
"Boost your productivity using Deck with keyboard shortcuts." : "Підвищуйте свою продуктивність, використовуючи Deck за допомогою комбінацій клавіш.",
"Board actions" : "Дії правління",
"Keyboard shortcut" : "Сполучення клавіш", "Keyboard shortcut" : "Сполучення клавіш",
"Action" : "Дія ", "Action" : "Дія ",
"Shift" : "Shift", "Shift" : "Shift",
"Scroll" : "Прокрутка",
"Scroll sideways" : "Прокрутіть вбік",
"Navigate between cards" : "Перехід між картками",
"Esc" : "Esc",
"Close card details" : "Закрити дані картки",
"Ctrl" : "Ctrl", "Ctrl" : "Ctrl",
"Search" : "Пошук", "Search" : "Пошук",
"Show card filters" : "Показати фільтри карток",
"Clear card filters" : "Очистити фільтри карток",
"Show help dialog" : "Показати діалогове вікно довідки",
"Card actions" : "Дії з карткою",
"The following actions can be triggered on the currently highlighted card" : "На поточній виділеній картці можна виконати такі дії",
"Enter" : "Ввід", "Enter" : "Ввід",
"Space" : "Простір",
"Open card details" : "Відкрити реквізити картки",
"Edit the card title" : "Відредагуйте назву картки",
"Assign yourself to the current card" : "Приєднайте себе до поточної картки",
"Archive/unarchive the current card" : "Архівувати/розархівувати поточну картку",
"Mark card as completed/not completed" : "Позначте картку як завершену/не завершену",
"Open card menu" : "Відкрити меню картки",
"All boards" : "Усі дошки", "All boards" : "Усі дошки",
"Archived boards" : "Архівні дошки", "Archived boards" : "Архівні дошки",
"Shared with you" : "Вам надано доступ", "Shared with you" : "Вам надано доступ",
"Deck settings" : "Налаштування колоди", "Deck settings" : "Налаштування колоди",
"Use bigger card view" : "Режим перегляду зі збільшеними картками", "Use bigger card view" : "Режим перегляду зі збільшеними картками",
"Show card ID badge" : "Покажіть бейдж з ідентифікаційною карткою",
"Show boards in calendar/tasks" : "Показувати дошки в календарі та завданнях", "Show boards in calendar/tasks" : "Показувати дошки в календарі та завданнях",
"Limit board creation to some groups" : "Обмежити створення дошки для деяких груп",
"Users outside of those groups will not be able to create their own boards, but will still be able to work on boards that have been shared with them." : "Користувачі поза цими групами не зможуть створювати власні дошки, але зможуть працювати на дошках, до яких їм надано спільний доступ.",
"Cancel edit" : "Скасувати редагування", "Cancel edit" : "Скасувати редагування",
"Save board" : "Зберегти дошку",
"Board {0} deleted" : "Дошку {0} вилучено", "Board {0} deleted" : "Дошку {0} вилучено",
"All cards" : "Всі карти",
"Only assigned cards" : "Тільки призначені картки",
"No reminder" : "Відсутні нагадування", "No reminder" : "Відсутні нагадування",
"An error occurred" : "Виникла помилка", "An error occurred" : "Виникла помилка",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Ви впевнені, що хочете вилучити дошку {title}? Це призведе до видалення всіх даних цієї дошки, включно архівні картки.", "Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Ви впевнені, що хочете вилучити дошку {title}? Це призведе до видалення всіх даних цієї дошки, включно архівні картки.",
"Delete the board?" : "Вилучити дошку?", "Delete the board?" : "Вилучити дошку?",
"Exporting board..." : "Експортна дошка...",
"Board details" : "Деталі дошки", "Board details" : "Деталі дошки",
"Edit board" : "Редагувати дошку", "Edit board" : "Редагувати дошку",
"Clone board" : "Копіювати дошку", "Clone board" : "Копіювати дошку",
"Unarchive board" : "Розархівувати дошку", "Unarchive board" : "Розархівувати дошку",
"Archive board" : "Архівувати дошку", "Archive board" : "Архівувати дошку",
"Export board" : "Дошка експорту",
"Turn on due date reminders" : "Нагадування про термін виконання", "Turn on due date reminders" : "Нагадування про термін виконання",
"Turn off due date reminders" : "Вимкнути нагадування про терміни виконання", "Turn off due date reminders" : "Вимкнути нагадування про терміни виконання",
"Due date reminders" : "Нагадування про терміни виконання", "Due date reminders" : "Нагадування про терміни виконання",
"Assigned cards" : "Призначені картки",
"No notifications" : "Немає сповіщень", "No notifications" : "Немає сповіщень",
"Delete board" : "Вилучити дошку", "Delete board" : "Вилучити дошку",
"Importing board..." : "Імпортна дошка...",
"Board imported successfully" : "Плату успішно імпортовано",
"Import board" : "Імпортна дошка",
"Clone {boardTitle}" : "Клон {boardTitle}",
"Clone cards" : "Копіювати картки", "Clone cards" : "Копіювати картки",
"Clone assignments" : "Призначення клонів",
"Clone labels" : "Етикетки клонів",
"Clone due dates" : "Клонувати дві дати",
"Advanced options" : "Розширені налаштування", "Advanced options" : "Розширені налаштування",
"Move all cards to the first list" : "Перемістіть усі картки до першого списку",
"Restore archived cards" : "Відновлення заархівованих карток",
"Clone" : "Копіювати", "Clone" : "Копіювати",
"Export {boardTitle}" : "Експорт {boardTitle}",
"Export as JSON" : "Експорт як JSON",
"Export as CSV" : "Експорт у CSV", "Export as CSV" : "Експорт у CSV",
"Note: Only the JSON format is supported for importing back into the Deck app." : "Примітка: Для імпорту в додаток Deck підтримується лише формат JSON.",
"Export" : "Експортувати", "Export" : "Експортувати",
"Loading filtered view" : "Завантаження відфільтрованого перегляду",
"Today" : "Сьогодні", "Today" : "Сьогодні",
"Tomorrow" : "Завтра", "Tomorrow" : "Завтра",
"No due" : "Без призначеної дати", "No due" : "Без призначеної дати",
"Search for {searchQuery} in all boards" : "Шукати {searchQuery} на всіх дошках оголошень",
"No results found" : "Не знайдено жодного результату",
"Deck board {name}\n* Last modified on {lastMod}" : "Колода {name}\n* Востаннє змінено на {lastMod}",
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Створено на {created}\n* Востаннє змінено на {lastMod}\n* {nbAttachments} вкладення\n* {nbComments} коментарі",
"{nbCards} cards" : "{nbCards} картки",
"Due on {date}" : "До {date}", "Due on {date}" : "До {date}",
"{stack} in {board}" : "{stack} в {board}",
"Click to expand description" : "Натисніть, щоб розгорнути опис",
"Click to expand comment" : "Натисніть, щоб розгорнути коментар",
"Create card" : "Створити картку",
"Create a new card" : "Створити нову картку", "Create a new card" : "Створити нову картку",
"Card title" : "Заголовок картки", "Card title" : "Заголовок картки",
"Creating the new card …" : "Створення нової картки ...",
"Card \"{card}\" was added to \"{board}\"" : "Картку \"{card}\" додано до \"{board}\"",
"Open card" : "Відкрити картку",
"Close" : "Закрити", "Close" : "Закрити",
"No upcoming cards" : "Немає майбутніх завдань", "No upcoming cards" : "Немає майбутніх завдань",
"upcoming cards today" : "найближчі картки на сьогодні",
"upcoming cards tomorrow" : "найближчі картки завтра",
"upcoming cards" : "очікують на виконання", "upcoming cards" : "очікують на виконання",
"New card" : "Нова картка",
"Link to a board" : "Прив'язати до дошки", "Link to a board" : "Прив'язати до дошки",
"Link to a card" : "Прив'язати до картки", "Link to a card" : "Прив'язати до картки",
"Create a card" : "Створити картку",
"Message from {author} in {conversationName}" : "Повідомлення від {author} у {conversationName}", "Message from {author} in {conversationName}" : "Повідомлення від {author} у {conversationName}",
"Something went wrong" : "От халепа!", "Something went wrong" : "От халепа!",
"Failed to upload {name}" : "Не вдалося завантажити {name}",
"Maximum file size of {size} exceeded" : "Досягнуто максимальний розмір файлу {size}", "Maximum file size of {size} exceeded" : "Досягнуто максимальний розмір файлу {size}",
"Assigned users" : "Призначені користувачі",
"Due date" : "Дата виконання", "Due date" : "Дата виконання",
"Error creating the share" : "Помилка створення спільного доступу", "Error creating the share" : "Помилка створення спільного доступу",
"Share with a Deck card" : "Поділіться з картою з колоди",
"Share {file} with a Deck card" : "Поділіться {file} з картою колоди",
"Share" : "Спільний доступ", "Share" : "Спільний доступ",
"Personal" : "Особисте", "Personal" : "Особисте",
"To do" : "Заплановано", "To do" : "Заплановано",

View File

@@ -46,30 +46,8 @@
"You have updated the due date of card {card} to {after}" : "Ви оновили дату завершення картки {card} на {after}", "You have updated the due date of card {card} to {after}" : "Ви оновили дату завершення картки {card} на {after}",
"{user} has updated the due date of card {card} to {after}" : "{user} оновив(-ла) дату завершення картки {card} на {after}", "{user} has updated the due date of card {card} to {after}" : "{user} оновив(-ла) дату завершення картки {card} на {after}",
"You have added the tag {label} to card {card} in list {stack} on board {board}" : "Ви додали мітку {label} до картки {card} в списку {board}", "You have added the tag {label} to card {card} in list {stack} on board {board}" : "Ви додали мітку {label} до картки {card} в списку {board}",
"{user} has added the tag {label} to card {card} in list {stack} on board {board}" : "{user} додав тег {label} до карти {card} у списку {stack} на борту {board}",
"You have removed the tag {label} from card {card} in list {stack} on board {board}" : "Ви видалили тег {label} з карти {card} у списку {stack} на борту {board}",
"{user} has removed the tag {label} from card {card} in list {stack} on board {board}" : "{user} видалив тег {label} з карти {card} у списку {stack} на борту {board}",
"You have assigned {assigneduser} to card {card} on board {board}" : "Ви призначили {assigneduser} на картку {card} на борту {board}",
"{user} has assigned {assigneduser} to card {card} on board {board}" : "{user} призначив {assigneduser} на картку {card} на дошці {board}",
"You have unassigned {assigneduser} from card {card} on board {board}" : "Ви скасували призначення {assigneduser} з карти {card} на борту {board}",
"{user} has unassigned {assigneduser} from card {card} on board {board}" : "{user} скасував призначення {assigneduser} з карти {card} на дошці {board}",
"You have moved the card {card} from list {stackBefore} to {stack}" : "Ви перемістили картку {card} зі списку {stackBefore} до {stack}",
"{user} has moved the card {card} from list {stackBefore} to {stack}" : "{user} перемістив картку {card} зі списку {stackBefore} до {stack}",
"You have added the attachment {attachment} to card {card}" : "Ви додали вкладення {attachment} до картки {card}",
"{user} has added the attachment {attachment} to card {card}" : "{user} додав вкладення {attachment} до картки {card}",
"You have updated the attachment {attachment} on card {card}" : "Ви оновили вкладення {attachment} на картці {card}",
"{user} has updated the attachment {attachment} on card {card}" : " {user}оновив вкладення {attachment} на картці {card}",
"You have deleted the attachment {attachment} from card {card}" : "Ви видалили вкладення {attachment} з картки {card}",
"{user} has deleted the attachment {attachment} from card {card}" : "{user} видалив вкладення {attachment} з картки {card}",
"You have restored the attachment {attachment} to card {card}" : "Ви відновили вкладення {attachment} до картки {card}",
"{user} has restored the attachment {attachment} to card {card}" : "{user} відновив вкладення {attachment} до картки {card}",
"You have commented on card {card}" : "Ви залишили коментар до картки {card}",
"{user} has commented on card {card}" : "{user} прокоментував картку {card}",
"Deck" : "Колода", "Deck" : "Колода",
"Changes in the <strong>Deck app</strong>" : "Зміни у застосунку <strong>Колода</strong>", "Changes in the <strong>Deck app</strong>" : "Зміни у застосунку <strong>Колода</strong>",
"A <strong>board, list or card</strong> was changed" : "Змінено <strong>таблицю, список або картку</strong>",
"A <strong>comment</strong> was created on a card" : "Створено <strong>коментар</strong> на картці",
"A <strong>card description</strong> has been changed" : "Змінено <strong>опис картки</strong>",
"The file was uploaded" : "Файл завантажено", "The file was uploaded" : "Файл завантажено",
"The uploaded file exceeds the upload_max_filesize directive in php.ini" : "Файл для завантаження перевищує параметр upload_max_filesize у php.ini", "The uploaded file exceeds the upload_max_filesize directive in php.ini" : "Файл для завантаження перевищує параметр upload_max_filesize у php.ini",
"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Розмір завантаженого файлу перевищує значення MAX_FILE_SIZE, яке було зазначено у HTML формі", "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form" : "Розмір завантаженого файлу перевищує значення MAX_FILE_SIZE, яке було зазначено у HTML формі",
@@ -79,66 +57,30 @@
"Could not write file to disk" : "Неможливо записати файл на диск", "Could not write file to disk" : "Неможливо записати файл на диск",
"A PHP extension stopped the file upload" : "Розширення PHP призупинило завантаження файлу", "A PHP extension stopped the file upload" : "Розширення PHP призупинило завантаження файлу",
"No file uploaded or file size exceeds maximum of %s" : "Немає завантажених файлів або розмір файлу перевищує максимум %s", "No file uploaded or file size exceeds maximum of %s" : "Немає завантажених файлів або розмір файлу перевищує максимум %s",
"Invalid file type. Only JSON files are allowed." : "Неправильний тип файлу. Допускаються тільки файли у форматі JSON.",
"Invalid JSON data" : "Неправильні дані JSON",
"Failed to import board" : "Не вдалося імпортувати дошку",
"Cards due today" : "Картки повинні бути оплачені сьогодні",
"Cards due tomorrow" : "Картки на завтра",
"Upcoming cards" : "Очікують на виконання", "Upcoming cards" : "Очікують на виконання",
"Load more" : "Більше", "Load more" : "Більше",
"Welcome to Nextcloud Deck!" : "Ласкаво просимо до колоди Nextcloud!",
"The card \"%s\" on \"%s\" has been assigned to you by %s." : "Картка \"%s\" на \"%s\" була призначена вам %s.",
"{user} has assigned the card {deck-card} on {deck-board} to you." : "{user} призначив вам карту {deck-card} на {deck-board}.",
"The card \"%s\" on \"%s\" has reached its due date." : "Термін дії картки \"%s\" на \"%s\" закінчився.",
"The card {deck-card} on {deck-board} has reached its due date." : "Термін дії карти {deck-card} на {deck-board} закінчився.",
"%s has mentioned you in a comment on \"%s\"." : "%s згадав вас у коментарі до \"%s\".",
"{user} has mentioned you in a comment on {deck-card}." : "{user} згадав вас у коментарі до {deck-card}.",
"The board \"%s\" has been shared with you by %s." : "Дошку \"%s\" з вами поділився %s.",
"{user} has shared {deck-board} with you." : "{user} поділився з вами {deck-board}.",
"Deck board" : "Дошка Deck", "Deck board" : "Дошка Deck",
"Owned by %1$s" : "Належить %1$s",
"Deck boards, cards and comments" : "Дошки колод, карти та коментарі",
"From %1$s, in %2$s/%3$s, owned by %4$s" : "З %1$s, в %2$s/%3$s, у власності %4$s",
"Create a new deck card" : "Створіть нову карту колоди",
"Card comments" : "Коментарі до картки",
"%s on %s" : "%s на %s", "%s on %s" : "%s на %s",
"Deck boards and cards" : "Колода та карти",
"No data was provided to create an attachment." : "Для створення вкладення не було надано жодних даних.",
"Finished" : "Завершено", "Finished" : "Завершено",
"To review" : "На перегляд", "To review" : "На перегляд",
"Action needed" : "Потребує дій", "Action needed" : "Потребує дій",
"Later" : "Пізніше", "Later" : "Пізніше",
"copy" : "копіювати", "copy" : "копіювати",
"Read more inside" : "Читайте більше всередині",
"Custom lists - click to rename!" : "Користувацькі списки - натисніть, щоб перейменувати!",
"To Do" : "Зробити", "To Do" : "Зробити",
"In Progress" : "В процесі", "In Progress" : "В процесі",
"Done" : "Готово", "Done" : "Готово",
"1. Open to learn more about boards and cards" : "1. Відкриті, щоб дізнатися більше про дошки та картки",
"2. Drag cards left and right, up and down" : "2. Перетягування карток вліво і вправо, вгору і вниз",
"3. Apply rich formatting and link content" : "3. Застосовуйте багате форматування та посилання на вміст",
"4. Share, comment and collaborate!" : "4. Діліться, коментуйте та співпрацюйте!",
"Create your first card!" : "Створіть свою першу листівку!",
"This comment has more than %s characters.\nAdded as an attachment to the card with name %s.\nAccessible on URL: %s." : "Цей коментар містить більше %s символів.\nДодано як вкладення до картки з іменем %s.\nДоступний за URL: %s.",
"Attachments" : "Вкладення", "Attachments" : "Вкладення",
"File" : "Файл", "File" : "Файл",
"date" : "дата",
"Card not found" : "Картку не знайдено", "Card not found" : "Картку не знайдено",
"Path is already shared with this card" : "Шлях вже є спільним з цією карткою",
"Invalid date, date format must be YYYY-MM-DD" : "Недійсна дата, формат дати має бути РРРР-ММ-ДД", "Invalid date, date format must be YYYY-MM-DD" : "Недійсна дата, формат дати має бути РРРР-ММ-ДД",
"Personal planning and team project organization" : "Особисте планування та організація командних проектів",
"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 - це інструмент організації в стилі канбан, призначений для особистого планування та організації проектів для команд, інтегрованих з Nextcloud.\n\n\n- 📥 Додавайте свої завдання на картки та впорядковуйте їх\n- 📄 Записуйте додаткові нотатки в Markdown\n- 🔖 Призначайте мітки для ще кращої організації\n- 👥 Діліться з командою, друзями чи родиною\n- Прикріплюйте файли та вбудовуйте їх в опис Markdown\n- 💬 Обговорюйте зі своєю командою за допомогою коментарів\n- ⚡ Відстежуйте зміни в потоці активностей\n- 🚀 Організуйте свій проект",
"Add board" : "Додати дошку", "Add board" : "Додати дошку",
"Card details" : "Деталі картки", "Card details" : "Деталі картки",
"Select the board to link to a project" : "Виберіть дошку для прив'зки до проєкту", "Select the board to link to a project" : "Виберіть дошку для прив'зки до проєкту",
"Search by board title" : "Шукати за назвою дошки", "Search by board title" : "Шукати за назвою дошки",
"Select board" : "Вибрати дошку", "Select board" : "Вибрати дошку",
"Move/copy card" : "Картка переміщення/копіювання",
"Select a board" : "Вибрати дошку", "Select a board" : "Вибрати дошку",
"No lists available" : "Списки відсутні",
"Select a list" : "Виберіть список", "Select a list" : "Виберіть список",
"Move card" : "Пересунути картку", "Move card" : "Пересунути картку",
"Copy card" : "Копіювальна картка",
"Select the card to link to a project" : "Виберіть картку для прив'язки до проєкту", "Select the card to link to a project" : "Виберіть картку для прив'язки до проєкту",
"Link to card" : "Прив'язати до картки", "Link to card" : "Прив'язати до картки",
"Select a card" : "Вибрати картку", "Select a card" : "Вибрати картку",
@@ -159,27 +101,19 @@
"Filter by tag" : "Відібрати за мітками", "Filter by tag" : "Відібрати за мітками",
"Filter by assigned user" : "Відібрати за призначеним користувачем", "Filter by assigned user" : "Відібрати за призначеним користувачем",
"Unassigned" : "Скасовано призначення", "Unassigned" : "Скасовано призначення",
"Filter by status" : "Фільтр за статусом",
"Open and completed" : "Відкрито та завершено",
"Open" : "Відкрити", "Open" : "Відкрити",
"Completed" : "Виконано", "Completed" : "Виконано",
"Filter by due date" : "Відібрати за датою завершення", "Filter by due date" : "Відібрати за датою завершення",
"Overdue" : "Протерміновано", "Overdue" : "Протерміновано",
"Next 24 hours" : "Наступні 24 години",
"Next 7 days" : "Наступні 7 днів", "Next 7 days" : "Наступні 7 днів",
"Next 30 days" : "Наступні 30 днів", "Next 30 days" : "Наступні 30 днів",
"No due date" : "Без дати завершення", "No due date" : "Без дати завершення",
"Clear filter" : "Очистити фільтр", "Clear filter" : "Очистити фільтр",
"View Modes" : "Режими перегляду",
"Toggle View Modes" : "Перемикання режимів перегляду",
"Hide archived cards" : "Приховати архівні картки", "Hide archived cards" : "Приховати архівні картки",
"Show archived cards" : "Показати архівні картки", "Show archived cards" : "Показати архівні картки",
"Toggle compact mode" : "Перемкнути компактний вигляд", "Toggle compact mode" : "Перемкнути компактний вигляд",
"Hide card cover images" : "Приховати зображення обкладинок карток",
"Show card cover images" : "Показати зображення обкладинки картки",
"Open details" : "Показати деталі", "Open details" : "Показати деталі",
"Details" : "Деталі", "Details" : "Деталі",
"Currently present people" : "Наразі присутні люди",
"Loading board" : "Завантаження дошки", "Loading board" : "Завантаження дошки",
"Board not found" : "Дошку не знайдено", "Board not found" : "Дошку не знайдено",
"Create a new list to add cards to this board" : "Створіть список щоб додати картки на цю дошку", "Create a new list to add cards to this board" : "Створіть список щоб додати картки на цю дошку",
@@ -190,62 +124,35 @@
"Deleted lists" : "Вилучені списки", "Deleted lists" : "Вилучені списки",
"Undo" : "Скасувати", "Undo" : "Скасувати",
"Deleted cards" : "Вилучені картки", "Deleted cards" : "Вилучені картки",
"Failed to create share with {displayName}" : "Не вдалося створити спільний доступ з {displayName}",
"Are you sure you want to transfer the board {title} to {user}?" : "Ви впевнені, що хочете перенести дошку {title} користувачеві {user}?",
"Transfer the board." : "Перенесіть дошку.",
"Transfer" : "Передати", "Transfer" : "Передати",
"The board has been transferred to {user}" : "Дошка була передана {user}",
"Failed to transfer the board to {user}" : "Не вдалося передати дошку користувачеві {user}",
"Share board with a user, group or team …" : "Спільний доступ до дошки з користувачем, групою або командою ...",
"Searching for users, groups and teams …" : "Пошук користувачів, груп і команд ...",
"No participants found" : "Учасників не знайдено",
"Board owner" : "Власник дошки", "Board owner" : "Власник дошки",
"(Group)" : "(група)", "(Group)" : "(група)",
"(Team)" : "(Команда)",
"Can edit" : "Може редагувати", "Can edit" : "Може редагувати",
"Can share" : "Can share", "Can share" : "Can share",
"Can manage" : "Може керувати", "Can manage" : "Може керувати",
"Owner" : "Власник", "Owner" : "Власник",
"Delete" : "Вилучити", "Delete" : "Вилучити",
"List deleted" : "Список видалено",
"Edit list title" : "Редагувати заголовок списку",
"Archive all cards" : "Архівувати всі картки",
"Unarchive all cards" : "Розархівувати всі картки",
"Delete list" : "Вилучити список", "Delete list" : "Вилучити список",
"Archive all cards in this list" : "Архівуйте всі картки в цьому списку",
"Unarchive all cards in this list" : "Розархівувати всі картки в цьому списку",
"Add a new card" : "Додати нову картку", "Add a new card" : "Додати нову картку",
"Card name" : "Назва картки",
"title and color value must be provided" : "потрібно зазначити назву та колір", "title and color value must be provided" : "потрібно зазначити назву та колір",
"Edit" : "Редагувати", "Edit" : "Редагувати",
"Add a new tag" : "Додати нову мітку", "Add a new tag" : "Додати нову мітку",
"Board name" : "Назва дошки", "Board name" : "Назва дошки",
"Members" : "Учасники", "Members" : "Учасники",
"Assign to users/groups/team" : "Призначити користувачам/групам/команді",
"Assign a user to this card…" : "Призначити користувачеві цю картку", "Assign a user to this card…" : "Призначити користувачеві цю картку",
"Select a user to assign to this card…" : "Виберіть користувача, якого слід призначити на цю картку...",
"File to share" : "Виберіть файл для надання доступу", "File to share" : "Виберіть файл для надання доступу",
"Invalid path selected" : "Вибрано неправильний шлях", "Invalid path selected" : "Вибрано неправильний шлях",
"Upload new files" : "Додати файл", "Upload new files" : "Додати файл",
"Share from Files" : "Відкрити Файли", "Share from Files" : "Відкрити Файли",
"Pending share" : "Очікувана акція",
"Add this attachment" : "Долучити вкладення", "Add this attachment" : "Долучити вкладення",
"Show in Files" : "Показати в Файлах", "Show in Files" : "Показати в Файлах",
"Download" : "Звантажити", "Download" : "Звантажити",
"Remove attachment" : "Зніміть вкладення",
"Delete Attachment" : "Забрати вкладення", "Delete Attachment" : "Забрати вкладення",
"Restore Attachment" : "Відновити вкладення", "Restore Attachment" : "Відновити вкладення",
"Modified" : "Змінено", "Modified" : "Змінено",
"Created" : "Створено", "Created" : "Створено",
"The title cannot be empty." : "Заголовок не може бути порожнім.",
"Cannot close unsaved card!" : "Неможливо закрити незбережену картку!",
"Open in sidebar view" : "Відкрити у вигляді бічної панелі",
"Open in bigger view" : "Відкрити в більшому розмірі",
"Comments" : "Коментарі", "Comments" : "Коментарі",
"Failed to load comments" : "Не вдалося завантажити коментарі",
"No comments yet. Begin the discussion!" : "Коментарів немає, почніть обговорення!", "No comments yet. Begin the discussion!" : "Коментарів немає, почніть обговорення!",
"The comment cannot be empty." : "Коментар не може бути порожнім.",
"The comment cannot be longer than 1000 characters." : "Коментар не може бути довшим за 1000 символів.",
"Save" : "Зберегти", "Save" : "Зберегти",
"Created:" : "Створено:", "Created:" : "Створено:",
"In reply to" : "У відповідь", "In reply to" : "У відповідь",
@@ -253,7 +160,6 @@
"Reply" : "Відповісти", "Reply" : "Відповісти",
"Update" : "Оновлення", "Update" : "Оновлення",
"Write a description …" : "Додайте опис ...", "Write a description …" : "Додайте опис ...",
"Could not save description" : "Не вдалося зберегти опис",
"Description" : "Опис", "Description" : "Опис",
"(Unsaved)" : "(Не збережено)", "(Unsaved)" : "(Не збережено)",
"(Saving…)" : "(Зберігання...)", "(Saving…)" : "(Зберігання...)",
@@ -263,150 +169,73 @@
"Add Attachment" : "Долучити вкладення", "Add Attachment" : "Долучити вкладення",
"Choose attachment" : "Вибрати вкладення", "Choose attachment" : "Вибрати вкладення",
"Select Date" : "Вкажіть дату", "Select Date" : "Вкажіть дату",
"Later today {timeLocale}" : "Пізніше сьогодні - {timeLocale}",
"Set due date for later today" : "Встановіть термін сплати на сьогоднішній день",
"Tomorrow {timeLocale}" : "Завтра - {timeLocale}",
"Set due date for tomorrow" : "Встановіть дедлайн на завтра",
"This weekend {timeLocale}" : "На цих вихідних - {timeLocale}", "This weekend {timeLocale}" : "На цих вихідних - {timeLocale}",
"Set due date for this weekend" : "Встановіть термін виконання на ці вихідні",
"Next week {timeLocale}" : "Наступного тижня - {timeLocale}", "Next week {timeLocale}" : "Наступного тижня - {timeLocale}",
"Set due date for next week" : "Встановіть термін виконання на наступний тиждень",
"Assign a due date to this card…" : "Призначте цій картці термін оплати...",
"Set a due date" : "Встановити дату завершення", "Set a due date" : "Встановити дату завершення",
"Add due date" : "Додати термін сплати",
"Choose a date" : "Виберіть дату", "Choose a date" : "Виберіть дату",
"Remove due date" : "Вилучити до", "Remove due date" : "Вилучити до",
"Mark as done" : "Позначити як виконане", "Mark as done" : "Позначити як виконане",
"Due at:" : "На часі:",
"Not done" : "Ще не все.",
"Unarchive card" : "Розархівувати картку", "Unarchive card" : "Розархівувати картку",
"Archive card" : "Архівувати картку", "Archive card" : "Архівувати картку",
"Assign a tag to this card…" : "Додати мітку до цієї картки", "Assign a tag to this card…" : "Додати мітку до цієї картки",
"Select or create a tag…" : "Виберіть або створіть тег...",
"Create a new tag:" : "Створіть новий тег:",
"(group)" : "(група)", "(group)" : "(група)",
"{count} comments, {unread} unread" : "{count} коментарів, {unread} непрочитаних",
"Todo items" : "Пункти завдань", "Todo items" : "Пункти завдань",
"Edit card title" : "Редагувати заголовок картки", "Edit card title" : "Редагувати заголовок картки",
"Open link" : "Відкрити посилання", "Open link" : "Відкрити посилання",
"Card deleted" : "Картку видалено",
"Edit title" : "Редагувати", "Edit title" : "Редагувати",
"Assign to me" : "Призначити мені", "Assign to me" : "Призначити мені",
"Unassign myself" : "Зняти з себе повноваження.",
"Mark as not done" : "Позначити як не виконано",
"Delete card" : "Вилучити картку", "Delete card" : "Вилучити картку",
"seconds ago" : "секунд тому", "seconds ago" : "секунд тому",
"Keyboard shortcuts" : "Скорочення", "Keyboard shortcuts" : "Скорочення",
"Boost your productivity using Deck with keyboard shortcuts." : "Підвищуйте свою продуктивність, використовуючи Deck за допомогою комбінацій клавіш.",
"Board actions" : "Дії правління",
"Keyboard shortcut" : "Сполучення клавіш", "Keyboard shortcut" : "Сполучення клавіш",
"Action" : "Дія ", "Action" : "Дія ",
"Shift" : "Shift", "Shift" : "Shift",
"Scroll" : "Прокрутка",
"Scroll sideways" : "Прокрутіть вбік",
"Navigate between cards" : "Перехід між картками",
"Esc" : "Esc",
"Close card details" : "Закрити дані картки",
"Ctrl" : "Ctrl", "Ctrl" : "Ctrl",
"Search" : "Пошук", "Search" : "Пошук",
"Show card filters" : "Показати фільтри карток",
"Clear card filters" : "Очистити фільтри карток",
"Show help dialog" : "Показати діалогове вікно довідки",
"Card actions" : "Дії з карткою",
"The following actions can be triggered on the currently highlighted card" : "На поточній виділеній картці можна виконати такі дії",
"Enter" : "Ввід", "Enter" : "Ввід",
"Space" : "Простір",
"Open card details" : "Відкрити реквізити картки",
"Edit the card title" : "Відредагуйте назву картки",
"Assign yourself to the current card" : "Приєднайте себе до поточної картки",
"Archive/unarchive the current card" : "Архівувати/розархівувати поточну картку",
"Mark card as completed/not completed" : "Позначте картку як завершену/не завершену",
"Open card menu" : "Відкрити меню картки",
"All boards" : "Усі дошки", "All boards" : "Усі дошки",
"Archived boards" : "Архівні дошки", "Archived boards" : "Архівні дошки",
"Shared with you" : "Вам надано доступ", "Shared with you" : "Вам надано доступ",
"Deck settings" : "Налаштування колоди", "Deck settings" : "Налаштування колоди",
"Use bigger card view" : "Режим перегляду зі збільшеними картками", "Use bigger card view" : "Режим перегляду зі збільшеними картками",
"Show card ID badge" : "Покажіть бейдж з ідентифікаційною карткою",
"Show boards in calendar/tasks" : "Показувати дошки в календарі та завданнях", "Show boards in calendar/tasks" : "Показувати дошки в календарі та завданнях",
"Limit board creation to some groups" : "Обмежити створення дошки для деяких груп",
"Users outside of those groups will not be able to create their own boards, but will still be able to work on boards that have been shared with them." : "Користувачі поза цими групами не зможуть створювати власні дошки, але зможуть працювати на дошках, до яких їм надано спільний доступ.",
"Cancel edit" : "Скасувати редагування", "Cancel edit" : "Скасувати редагування",
"Save board" : "Зберегти дошку",
"Board {0} deleted" : "Дошку {0} вилучено", "Board {0} deleted" : "Дошку {0} вилучено",
"All cards" : "Всі карти",
"Only assigned cards" : "Тільки призначені картки",
"No reminder" : "Відсутні нагадування", "No reminder" : "Відсутні нагадування",
"An error occurred" : "Виникла помилка", "An error occurred" : "Виникла помилка",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Ви впевнені, що хочете вилучити дошку {title}? Це призведе до видалення всіх даних цієї дошки, включно архівні картки.", "Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Ви впевнені, що хочете вилучити дошку {title}? Це призведе до видалення всіх даних цієї дошки, включно архівні картки.",
"Delete the board?" : "Вилучити дошку?", "Delete the board?" : "Вилучити дошку?",
"Exporting board..." : "Експортна дошка...",
"Board details" : "Деталі дошки", "Board details" : "Деталі дошки",
"Edit board" : "Редагувати дошку", "Edit board" : "Редагувати дошку",
"Clone board" : "Копіювати дошку", "Clone board" : "Копіювати дошку",
"Unarchive board" : "Розархівувати дошку", "Unarchive board" : "Розархівувати дошку",
"Archive board" : "Архівувати дошку", "Archive board" : "Архівувати дошку",
"Export board" : "Дошка експорту",
"Turn on due date reminders" : "Нагадування про термін виконання", "Turn on due date reminders" : "Нагадування про термін виконання",
"Turn off due date reminders" : "Вимкнути нагадування про терміни виконання", "Turn off due date reminders" : "Вимкнути нагадування про терміни виконання",
"Due date reminders" : "Нагадування про терміни виконання", "Due date reminders" : "Нагадування про терміни виконання",
"Assigned cards" : "Призначені картки",
"No notifications" : "Немає сповіщень", "No notifications" : "Немає сповіщень",
"Delete board" : "Вилучити дошку", "Delete board" : "Вилучити дошку",
"Importing board..." : "Імпортна дошка...",
"Board imported successfully" : "Плату успішно імпортовано",
"Import board" : "Імпортна дошка",
"Clone {boardTitle}" : "Клон {boardTitle}",
"Clone cards" : "Копіювати картки", "Clone cards" : "Копіювати картки",
"Clone assignments" : "Призначення клонів",
"Clone labels" : "Етикетки клонів",
"Clone due dates" : "Клонувати дві дати",
"Advanced options" : "Розширені налаштування", "Advanced options" : "Розширені налаштування",
"Move all cards to the first list" : "Перемістіть усі картки до першого списку",
"Restore archived cards" : "Відновлення заархівованих карток",
"Clone" : "Копіювати", "Clone" : "Копіювати",
"Export {boardTitle}" : "Експорт {boardTitle}",
"Export as JSON" : "Експорт як JSON",
"Export as CSV" : "Експорт у CSV", "Export as CSV" : "Експорт у CSV",
"Note: Only the JSON format is supported for importing back into the Deck app." : "Примітка: Для імпорту в додаток Deck підтримується лише формат JSON.",
"Export" : "Експортувати", "Export" : "Експортувати",
"Loading filtered view" : "Завантаження відфільтрованого перегляду",
"Today" : "Сьогодні", "Today" : "Сьогодні",
"Tomorrow" : "Завтра", "Tomorrow" : "Завтра",
"No due" : "Без призначеної дати", "No due" : "Без призначеної дати",
"Search for {searchQuery} in all boards" : "Шукати {searchQuery} на всіх дошках оголошень",
"No results found" : "Не знайдено жодного результату",
"Deck board {name}\n* Last modified on {lastMod}" : "Колода {name}\n* Востаннє змінено на {lastMod}",
"* Created on {created}\n* Last modified on {lastMod}\n* {nbAttachments} attachments\n* {nbComments} comments" : "* Створено на {created}\n* Востаннє змінено на {lastMod}\n* {nbAttachments} вкладення\n* {nbComments} коментарі",
"{nbCards} cards" : "{nbCards} картки",
"Due on {date}" : "До {date}", "Due on {date}" : "До {date}",
"{stack} in {board}" : "{stack} в {board}",
"Click to expand description" : "Натисніть, щоб розгорнути опис",
"Click to expand comment" : "Натисніть, щоб розгорнути коментар",
"Create card" : "Створити картку",
"Create a new card" : "Створити нову картку", "Create a new card" : "Створити нову картку",
"Card title" : "Заголовок картки", "Card title" : "Заголовок картки",
"Creating the new card …" : "Створення нової картки ...",
"Card \"{card}\" was added to \"{board}\"" : "Картку \"{card}\" додано до \"{board}\"",
"Open card" : "Відкрити картку",
"Close" : "Закрити", "Close" : "Закрити",
"No upcoming cards" : "Немає майбутніх завдань", "No upcoming cards" : "Немає майбутніх завдань",
"upcoming cards today" : "найближчі картки на сьогодні",
"upcoming cards tomorrow" : "найближчі картки завтра",
"upcoming cards" : "очікують на виконання", "upcoming cards" : "очікують на виконання",
"New card" : "Нова картка",
"Link to a board" : "Прив'язати до дошки", "Link to a board" : "Прив'язати до дошки",
"Link to a card" : "Прив'язати до картки", "Link to a card" : "Прив'язати до картки",
"Create a card" : "Створити картку",
"Message from {author} in {conversationName}" : "Повідомлення від {author} у {conversationName}", "Message from {author} in {conversationName}" : "Повідомлення від {author} у {conversationName}",
"Something went wrong" : "От халепа!", "Something went wrong" : "От халепа!",
"Failed to upload {name}" : "Не вдалося завантажити {name}",
"Maximum file size of {size} exceeded" : "Досягнуто максимальний розмір файлу {size}", "Maximum file size of {size} exceeded" : "Досягнуто максимальний розмір файлу {size}",
"Assigned users" : "Призначені користувачі",
"Due date" : "Дата виконання", "Due date" : "Дата виконання",
"Error creating the share" : "Помилка створення спільного доступу", "Error creating the share" : "Помилка створення спільного доступу",
"Share with a Deck card" : "Поділіться з картою з колоди",
"Share {file} with a Deck card" : "Поділіться {file} з картою колоди",
"Share" : "Спільний доступ", "Share" : "Спільний доступ",
"Personal" : "Особисте", "Personal" : "Особисте",
"To do" : "Заплановано", "To do" : "Заплановано",

View File

@@ -20,12 +20,12 @@ OC.L10N.register(
"Card not found" : "Karta topilmadi", "Card not found" : "Karta topilmadi",
"Add board" : "Doska qo'shing", "Add board" : "Doska qo'shing",
"Move card" : "Kartani ko'chirish", "Move card" : "Kartani ko'chirish",
"Cancel" : "Bekor qilish", "Cancel" : "Cancel",
"Add card" : "Karta qo'shing", "Add card" : "Karta qo'shing",
"Archived cards" : "Arxivlangan kartalar", "Archived cards" : "Arxivlangan kartalar",
"Add list" : "Roʻyxat qoʻshish", "Add list" : "Roʻyxat qoʻshish",
"Unassigned" : "Tayinlanmagan", "Unassigned" : "Tayinlanmagan",
"Open" : "Ochish", "Open" : "Open",
"Overdue" : "Muddati o'tgan", "Overdue" : "Muddati o'tgan",
"Next 7 days" : "Keyingi 7 kun", "Next 7 days" : "Keyingi 7 kun",
"Next 30 days" : "Keyingi 30 kun", "Next 30 days" : "Keyingi 30 kun",
@@ -37,13 +37,13 @@ OC.L10N.register(
"Undo" : "Bekor qilish", "Undo" : "Bekor qilish",
"Can edit" : "Can edit", "Can edit" : "Can edit",
"Owner" : "Owner", "Owner" : "Owner",
"Delete" : "O'chirish", "Delete" : "Delete",
"Delete list" : "Roʻyxatni oʻchirish", "Delete list" : "Roʻyxatni oʻchirish",
"Edit" : "Tahrirlash", "Edit" : "Tahrirlash",
"Download" : "Yuklab olish", "Download" : "Download",
"Modified" : "Modified", "Modified" : "Modified",
"Comments" : "Comments", "Comments" : "Comments",
"Save" : "Saqlash", "Save" : "Save",
"In reply to" : "ga javoban", "In reply to" : "ga javoban",
"Reply" : "Javob bering", "Reply" : "Javob bering",
"Update" : "Update", "Update" : "Update",
@@ -55,7 +55,7 @@ OC.L10N.register(
"Edit title" : "Sarlavhani tahrirlash", "Edit title" : "Sarlavhani tahrirlash",
"Delete card" : "Kartani o'chirish", "Delete card" : "Kartani o'chirish",
"seconds ago" : "seconds ago", "seconds ago" : "seconds ago",
"Search" : "Qidirish", "Search" : "Search",
"Archived boards" : "Arxivlangan taxtalar", "Archived boards" : "Arxivlangan taxtalar",
"Shared with you" : "Shared with you", "Shared with you" : "Shared with you",
"No reminder" : "Eslatma yo'q", "No reminder" : "Eslatma yo'q",

View File

@@ -18,12 +18,12 @@
"Card not found" : "Karta topilmadi", "Card not found" : "Karta topilmadi",
"Add board" : "Doska qo'shing", "Add board" : "Doska qo'shing",
"Move card" : "Kartani ko'chirish", "Move card" : "Kartani ko'chirish",
"Cancel" : "Bekor qilish", "Cancel" : "Cancel",
"Add card" : "Karta qo'shing", "Add card" : "Karta qo'shing",
"Archived cards" : "Arxivlangan kartalar", "Archived cards" : "Arxivlangan kartalar",
"Add list" : "Roʻyxat qoʻshish", "Add list" : "Roʻyxat qoʻshish",
"Unassigned" : "Tayinlanmagan", "Unassigned" : "Tayinlanmagan",
"Open" : "Ochish", "Open" : "Open",
"Overdue" : "Muddati o'tgan", "Overdue" : "Muddati o'tgan",
"Next 7 days" : "Keyingi 7 kun", "Next 7 days" : "Keyingi 7 kun",
"Next 30 days" : "Keyingi 30 kun", "Next 30 days" : "Keyingi 30 kun",
@@ -35,13 +35,13 @@
"Undo" : "Bekor qilish", "Undo" : "Bekor qilish",
"Can edit" : "Can edit", "Can edit" : "Can edit",
"Owner" : "Owner", "Owner" : "Owner",
"Delete" : "O'chirish", "Delete" : "Delete",
"Delete list" : "Roʻyxatni oʻchirish", "Delete list" : "Roʻyxatni oʻchirish",
"Edit" : "Tahrirlash", "Edit" : "Tahrirlash",
"Download" : "Yuklab olish", "Download" : "Download",
"Modified" : "Modified", "Modified" : "Modified",
"Comments" : "Comments", "Comments" : "Comments",
"Save" : "Saqlash", "Save" : "Save",
"In reply to" : "ga javoban", "In reply to" : "ga javoban",
"Reply" : "Javob bering", "Reply" : "Javob bering",
"Update" : "Update", "Update" : "Update",
@@ -53,7 +53,7 @@
"Edit title" : "Sarlavhani tahrirlash", "Edit title" : "Sarlavhani tahrirlash",
"Delete card" : "Kartani o'chirish", "Delete card" : "Kartani o'chirish",
"seconds ago" : "seconds ago", "seconds ago" : "seconds ago",
"Search" : "Qidirish", "Search" : "Search",
"Archived boards" : "Arxivlangan taxtalar", "Archived boards" : "Arxivlangan taxtalar",
"Shared with you" : "Shared with you", "Shared with you" : "Shared with you",
"No reminder" : "Eslatma yo'q", "No reminder" : "Eslatma yo'q",

View File

@@ -1,67 +0,0 @@
<?php
/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Deck\Command;
use OCP\IConfig;
use OCP\IUserManager;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class CalendarToggle extends Command {
private IUserManager $userManager;
private IConfig $config;
public function __construct(IUserManager $userManager, IConfig $config) {
parent::__construct();
$this->userManager = $userManager;
$this->config = $config;
}
protected function configure() {
$this
->setName('deck:calendar-toggle')
->setDescription('Enable or disable Deck calendar/tasks integration for all existing users. Users can still change their own setting afterwards. Only affects users that already exist at the time of execution.')
->addOption(
'on',
null,
InputOption::VALUE_NONE,
'Enable calendar/tasks integration for all existing users (users can opt-out later)'
)
->addOption(
'off',
null,
InputOption::VALUE_NONE,
'Disable calendar/tasks integration for all existing users (users can opt-in later)'
);
}
protected function execute(InputInterface $input, OutputInterface $output): int {
$enable = $input->getOption('on');
$disable = $input->getOption('off');
if ($enable && $disable) {
$output->writeln('<error>Cannot use --on and --off together.</error>');
return 1;
}
if (!$enable && !$disable) {
$output->writeln('<error>Please specify either --on or --off.</error>');
return 1;
}
$value = $enable ? 'yes' : '';
$users = $this->userManager->search('');
$count = 0;
foreach ($users as $user) {
$uid = $user->getUID();
$this->config->setUserValue($uid, 'deck', 'calendar', $value);
$output->writeln("Set calendar integration to '" . ($enable ? 'on' : 'off') . "' for user: $uid");
$count++;
}
$output->writeln("Done. Updated $count existing users.");
return 0;
}
}

View File

@@ -65,11 +65,11 @@ class CardController extends Controller {
$card = $this->cardService->create($title, $stackId, $type, $order, $this->userId, $description, $duedate); $card = $this->cardService->create($title, $stackId, $type, $order, $this->userId, $description, $duedate);
foreach ($labels as $label) { foreach ($labels as $label) {
$this->assignLabel($card->getId(), $label); $this->assignLabel($card->id, $label);
} }
foreach ($users as $user) { foreach ($users as $user) {
$this->assignmentService->assignUser($card->getId(), $user['id'], $user['type']); $this->assignmentService->assignUser($card->id, $user['id'], $user['type']);
} }
return $card; return $card;

View File

@@ -45,7 +45,8 @@ class SessionMapper extends QBMapper {
$qb->select('id', 'board_id', 'last_contact', 'user_id', 'token') $qb->select('id', 'board_id', 'last_contact', 'user_id', 'token')
->from($this->getTableName()) ->from($this->getTableName())
->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId))) ->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId)))
->andWhere($qb->expr()->gt('last_contact', $qb->createNamedParameter(time() - SessionService::SESSION_VALID_TIME))); ->andWhere($qb->expr()->gt('last_contact', $qb->createNamedParameter(time() - SessionService::SESSION_VALID_TIME)))
->executeQuery();
return $this->findEntities($qb); return $this->findEntities($qb);
} }

View File

@@ -320,14 +320,14 @@ class BoardService {
return $board; return $board;
} }
private function applyPermissions($boardId, $edit, $share, $manage, $oldAcl = null) { private function applyPermissions($boardId, $edit, $share, $manage) {
try { try {
$this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_MANAGE);
} catch (NoPermissionException $e) { } catch (NoPermissionException $e) {
$acls = $this->aclMapper->findAll($boardId); $acls = $this->aclMapper->findAll($boardId);
$edit = $this->permissionService->userCan($acls, Acl::PERMISSION_EDIT, $this->userId) ? $edit : $oldAcl?->getPermissionEdit() ?? false; $edit = $this->permissionService->userCan($acls, Acl::PERMISSION_EDIT, $this->userId) && $edit;
$share = $this->permissionService->userCan($acls, Acl::PERMISSION_SHARE, $this->userId) ? $share : $oldAcl?->getPermissionShare() ?? false; $share = $this->permissionService->userCan($acls, Acl::PERMISSION_SHARE, $this->userId) && $share;
$manage = $this->permissionService->userCan($acls, Acl::PERMISSION_MANAGE, $this->userId) ? $manage : $oldAcl?->getPermissionManage() ?? false; $manage = $this->permissionService->userCan($acls, Acl::PERMISSION_MANAGE, $this->userId) && $manage;
} }
return [$edit, $share, $manage]; return [$edit, $share, $manage];
} }
@@ -417,7 +417,7 @@ class BoardService {
/** @var Acl $acl */ /** @var Acl $acl */
$acl = $this->aclMapper->find($id); $acl = $this->aclMapper->find($id);
[$edit, $share, $manage] = $this->applyPermissions($acl->getBoardId(), $edit, $share, $manage, $acl); [$edit, $share, $manage] = $this->applyPermissions($acl->getBoardId(), $edit, $share, $manage);
$acl->setPermissionEdit($edit); $acl->setPermissionEdit($edit);
$acl->setPermissionShare($share); $acl->setPermissionShare($share);
$acl->setPermissionManage($manage); $acl->setPermissionManage($manage);
@@ -439,7 +439,7 @@ class BoardService {
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
*/ */
public function deleteAcl(int $id): ?Acl { public function deleteAcl(int $id): ?Acl {
$this->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_MANAGE); $this->permissionService->checkPermission($this->aclMapper, $id, Acl::PERMISSION_SHARE);
/** @var Acl $acl */ /** @var Acl $acl */
$acl = $this->aclMapper->find($id); $acl = $this->aclMapper->find($id);
$this->boardMapper->mapAcl($acl); $this->boardMapper->mapAcl($acl);
@@ -621,9 +621,7 @@ class BoardService {
if ($fullDetails) { if ($fullDetails) {
$this->enrichWithStacks($board); $this->enrichWithStacks($board);
if ($board->getLabels() === null) { $this->enrichWithLabels($board);
$this->enrichWithLabels($board);
}
$this->enrichWithUsers($board); $this->enrichWithUsers($board);
$this->enrichWithBoardSettings($board); $this->enrichWithBoardSettings($board);
$this->enrichWithActiveSessions($board); $this->enrichWithActiveSessions($board);

View File

@@ -356,7 +356,7 @@ class CardService {
if ($resetDuedateNotification) { if ($resetDuedateNotification) {
$this->notificationHelper->markDuedateAsRead($card); $this->notificationHelper->markDuedateAsRead($card);
} }
$this->changeHelper->cardChanged($card->getId()); $this->changeHelper->cardChanged($card->getId(), true);
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore())); $this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore()));
@@ -418,12 +418,11 @@ class CardService {
if ($card->getArchived()) { if ($card->getArchived()) {
throw new StatusException('Operation not allowed. This card is archived.'); throw new StatusException('Operation not allowed. This card is archived.');
} }
$changes = new ChangeSet($card);
$card->setTitle($title); $card->setTitle($title);
$this->changeHelper->cardChanged($card->getId(), false); $this->changeHelper->cardChanged($card->getId(), false);
$update = $this->cardMapper->update($card); $update = $this->cardMapper->update($card);
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore())); $this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
return $update; return $update;
} }
@@ -442,6 +441,7 @@ class CardService {
public function reorder($id, $stackId, $order) { public function reorder($id, $stackId, $order) {
$this->cardServiceValidator->check(compact('id', 'stackId', 'order')); $this->cardServiceValidator->check(compact('id', 'stackId', 'order'));
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
$this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->stackMapper, $stackId, Acl::PERMISSION_EDIT);
@@ -459,30 +459,30 @@ class CardService {
$changes->setAfter($card); $changes->setAfter($card);
$this->activityManager->triggerUpdateEvents(ActivityManager::DECK_OBJECT_CARD, $changes, ActivityManager::SUBJECT_CARD_UPDATE); $this->activityManager->triggerUpdateEvents(ActivityManager::DECK_OBJECT_CARD, $changes, ActivityManager::SUBJECT_CARD_UPDATE);
$cardsToReorder = $this->cardMapper->findAll($stackId); $cards = $this->cardMapper->findAll($stackId);
$result = []; $result = [];
$i = 0; $i = 0;
foreach ($cardsToReorder as $cardToReorder) { foreach ($cards as $card) {
if ($cardToReorder->getArchived()) { if ($card->getArchived()) {
throw new StatusException('Operation not allowed. This card is archived.'); throw new StatusException('Operation not allowed. This card is archived.');
} }
if ($cardToReorder->id === $id) { if ($card->id === $id) {
$cardToReorder->setOrder($order); $card->setOrder($order);
$cardToReorder->setLastModified(time()); $card->setLastModified(time());
} }
if ($i === $order) { if ($i === $order) {
$i++; $i++;
} }
if ($cardToReorder->id !== $id) { if ($card->id !== $id) {
$cardToReorder->setOrder($i++); $card->setOrder($i++);
} }
$this->cardMapper->update($cardToReorder); $this->cardMapper->update($card);
$result[$cardToReorder->getOrder()] = $cardToReorder; $result[$card->getOrder()] = $card;
} }
$this->changeHelper->cardChanged($id, false); $this->changeHelper->cardChanged($id, false);
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore())); $this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
return array_values($result); return array_values($result);
} }
@@ -499,19 +499,19 @@ class CardService {
public function archive($id) { public function archive($id) {
$this->cardServiceValidator->check(compact('id')); $this->cardServiceValidator->check(compact('id'));
$this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT); $this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_EDIT);
if ($this->boardService->isArchived($this->cardMapper, $id)) { if ($this->boardService->isArchived($this->cardMapper, $id)) {
throw new StatusException('Operation not allowed. This board is archived.'); throw new StatusException('Operation not allowed. This board is archived.');
} }
$card = $this->cardMapper->find($id); $card = $this->cardMapper->find($id);
$changes = new ChangeSet($card);
$card->setArchived(true); $card->setArchived(true);
$newCard = $this->cardMapper->update($card); $newCard = $this->cardMapper->update($card);
$this->notificationHelper->markDuedateAsRead($card); $this->notificationHelper->markDuedateAsRead($card);
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_ARCHIVE); $this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_ARCHIVE);
$this->changeHelper->cardChanged($id, false); $this->changeHelper->cardChanged($id, false);
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore())); $this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
return $newCard; return $newCard;
} }
@@ -534,13 +534,12 @@ class CardService {
throw new StatusException('Operation not allowed. This board is archived.'); throw new StatusException('Operation not allowed. This board is archived.');
} }
$card = $this->cardMapper->find($id); $card = $this->cardMapper->find($id);
$changes = new ChangeSet($card);
$card->setArchived(false); $card->setArchived(false);
$newCard = $this->cardMapper->update($card); $newCard = $this->cardMapper->update($card);
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_UNARCHIVE); $this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_UNARCHIVE);
$this->changeHelper->cardChanged($id, false); $this->changeHelper->cardChanged($id, false);
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore())); $this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
return $newCard; return $newCard;
} }
@@ -560,14 +559,13 @@ class CardService {
throw new StatusException('Operation not allowed. This board is archived.'); throw new StatusException('Operation not allowed. This board is archived.');
} }
$card = $this->cardMapper->find($id); $card = $this->cardMapper->find($id);
$changes = new ChangeSet($card);
$card->setDone(new \DateTime()); $card->setDone(new \DateTime());
$newCard = $this->cardMapper->update($card); $newCard = $this->cardMapper->update($card);
$this->notificationHelper->markDuedateAsRead($card); $this->notificationHelper->markDuedateAsRead($card);
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_DONE); $this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_DONE);
$this->changeHelper->cardChanged($id, false); $this->changeHelper->cardChanged($id, false);
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore())); $this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
return $newCard; return $newCard;
} }
@@ -587,13 +585,12 @@ class CardService {
throw new StatusException('Operation not allowed. This board is archived.'); throw new StatusException('Operation not allowed. This board is archived.');
} }
$card = $this->cardMapper->find($id); $card = $this->cardMapper->find($id);
$changes = new ChangeSet($card);
$card->setDone(null); $card->setDone(null);
$newCard = $this->cardMapper->update($card); $newCard = $this->cardMapper->update($card);
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_UNDONE); $this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $newCard, ActivityManager::SUBJECT_CARD_UPDATE_UNDONE);
$this->changeHelper->cardChanged($id, false); $this->changeHelper->cardChanged($id, false);
$this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card, $changes->getBefore())); $this->eventDispatcher->dispatchTyped(new CardUpdatedEvent($card));
return $newCard; return $newCard;
} }
@@ -655,6 +652,9 @@ class CardService {
throw new StatusException('Operation not allowed. This card is archived.'); throw new StatusException('Operation not allowed. This card is archived.');
} }
$label = $this->labelMapper->find($labelId); $label = $this->labelMapper->find($labelId);
if ($label->getBoardId() !== $this->cardMapper->findBoardId($card->getId())) {
throw new StatusException('Operation not allowed. Label does not exist.');
}
$this->cardMapper->removeLabel($cardId, $labelId); $this->cardMapper->removeLabel($cardId, $labelId);
$this->changeHelper->cardChanged($cardId); $this->changeHelper->cardChanged($cardId);
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_LABEL_UNASSING, ['label' => $label]); $this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_CARD, $card, ActivityManager::SUBJECT_LABEL_UNASSING, ['label' => $label]);

View File

@@ -214,7 +214,7 @@ class PermissionService {
} }
try { try {
$board = $this->getBoard($boardId); $board = $this->boardMapper->find($boardId);
} catch (DoesNotExistException $e) { } catch (DoesNotExistException $e) {
return []; return [];
} catch (MultipleObjectsReturnedException $e) { } catch (MultipleObjectsReturnedException $e) {
@@ -227,7 +227,7 @@ class PermissionService {
} else { } else {
$users[$board->getOwner()] = new User($board->getOwner(), $this->userManager); $users[$board->getOwner()] = new User($board->getOwner(), $this->userManager);
} }
$acls = $board->getAcl(); $acls = $this->aclMapper->findAll($boardId);
/** @var Acl $acl */ /** @var Acl $acl */
foreach ($acls as $acl) { foreach ($acls as $acl) {
if ($acl->getType() === Acl::PERMISSION_TYPE_USER) { if ($acl->getType() === Acl::PERMISSION_TYPE_USER) {

12751
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -31,19 +31,22 @@
}, },
"dependencies": { "dependencies": {
"@babel/polyfill": "^7.12.1", "@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.27.1", "@babel/runtime": "^7.27.0",
"@nextcloud/auth": "^2.4.0", "@nextcloud/auth": "^2.4.0",
"@nextcloud/axios": "^2.5.1", "@nextcloud/axios": "^2.5.1",
"@nextcloud/capabilities": "^1.2.0", "@nextcloud/capabilities": "^1.2.0",
"@nextcloud/dialogs": "^6.0.1", "@nextcloud/dialogs": "^7.0.0-rc.1",
"@nextcloud/event-bus": "^3.3.2", "@nextcloud/event-bus": "^3.3.2",
"@nextcloud/files": "^3.10.1", "@nextcloud/files": "^3.10.1",
"@nextcloud/initial-state": "^2.2.0", "@nextcloud/initial-state": "^2.2.0",
"@nextcloud/l10n": "^3.1.0", "@nextcloud/l10n": "^3.1.0",
"@nextcloud/moment": "^1.3.4", "@nextcloud/moment": "^1.3.2",
"@nextcloud/notify_push": "^1.3.0", "@nextcloud/notify_push": "^1.3.0",
"@nextcloud/router": "^3.0.1", "@nextcloud/router": "^3.0.1",
"@nextcloud/vue": "^8.27.0", "@nextcloud/vue": "^9.0.0-rc.3",
"@vue/compiler-sfc": "^3.5.13",
"@vue/vue3-jest": "^29.2.6",
"@vueuse/core": "^13.1.0",
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"chroma-js": "^3.1.2", "chroma-js": "^3.1.2",
"dompurify": "^3.2.5", "dompurify": "^3.2.5",
@@ -54,16 +57,14 @@
"moment": "^2.30.1", "moment": "^2.30.1",
"p-queue": "^8.0.1", "p-queue": "^8.0.1",
"url-search-params-polyfill": "^8.2.5", "url-search-params-polyfill": "^8.2.5",
"vue": "^2.7.15", "v3-infinite-loading": "^1.3.2",
"vue-at": "^2.5.1", "vue": "^3.5.13",
"vue-click-outside": "^1.1.0", "vue-click-outside": "^1.1.0",
"vue-easymde": "^2.0.0", "vue-easymde": "^2.0.0",
"vue-infinite-loading": "^2.4.5",
"vue-material-design-icons": "^5.3.1", "vue-material-design-icons": "^5.3.1",
"vue-router": "^3.6.5", "vue-router": "^4.5.0",
"vue-smooth-dnd": "^0.8.1", "vue3-smooth-dnd": "^0.0.6",
"vuex": "^3.6.2", "vuex": "^4.1.0"
"vuex-router-sync": "^5.0.0"
}, },
"browserslist": [ "browserslist": [
"extends @nextcloud/browserslist-config" "extends @nextcloud/browserslist-config"
@@ -75,20 +76,18 @@
"devDependencies": { "devDependencies": {
"@nextcloud/babel-config": "^1.2.0", "@nextcloud/babel-config": "^1.2.0",
"@nextcloud/browserslist-config": "^3.0.1", "@nextcloud/browserslist-config": "^3.0.1",
"@nextcloud/cypress": "^1.0.0-beta.15", "@nextcloud/cypress": "^1.0.0-beta.13",
"@nextcloud/eslint-config": "^8.4.2", "@nextcloud/eslint-config": "^8.4.2",
"@nextcloud/stylelint-config": "^3.0.1", "@nextcloud/stylelint-config": "^3.0.1",
"@nextcloud/webpack-vue-config": "^6.3.0", "@nextcloud/webpack-vue-config": "github:nextcloud-libraries/webpack-vue-config#vue3",
"@relative-ci/agent": "^4.3.1", "@relative-ci/agent": "^4.2.14",
"@vue/test-utils": "^2.4.6", "@vue/test-utils": "^2.4.6",
"@vue/vue2-jest": "^29.2.6",
"cypress": "^13.17.0", "cypress": "^13.17.0",
"eslint-plugin-cypress": "^3.6.0", "eslint-plugin-cypress": "^3.6.0",
"eslint-webpack-plugin": "^5.0.1", "eslint-webpack-plugin": "^5.0.1",
"jest": "^29.7.0", "jest": "^29.7.0",
"jest-serializer-vue": "^3.1.0", "jest-serializer-vue": "^3.1.0",
"stylelint-webpack-plugin": "^5.0.1", "stylelint-webpack-plugin": "^5.0.1"
"vue-template-compiler": "^2.7.16"
}, },
"jest": { "jest": {
"moduleFileExtensions": [ "moduleFileExtensions": [

View File

@@ -1,15 +1,51 @@
<!-- <!--
- SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors - SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later - SPDX-License-Identifier: AGPL-3.0-or-later
--> -->
<script>
import { NcAppContent, NcContent, NcModal } from '@nextcloud/vue'
import CardMoveDialog from './CardMoveDialog.vue'
import AppNavigation from './components/navigation/AppNavigation.vue'
import KeyboardShortcuts from './components/KeyboardShortcuts.vue'
import { BoardApi } from './services/BoardApi.js'
const boardApi = new BoardApi()
export default {
name: 'App',
components: {
NcContent,
AppNavigation,
NcAppContent,
KeyboardShortcuts,
CardMoveDialog,
NcModal,
},
provide() {
return {
boardApi,
}
},
computed: {
cardDetailsInModal() {
return this.$store.getters.config('cardDetailsInModal')
},
},
methods: {
hideModal() {
this.$router.push({ name: 'board' })
},
},
}
</script>
<template> <template>
<NcContent app-name="deck" :class="{ 'nav-hidden': !navShown, 'sidebar-hidden': !sidebarRouterView }"> <NcContent app-name="deck">
<AppNavigation /> <AppNavigation />
<NcAppContent :allow-swipe-navigation="false"> <NcAppContent :allow-swipe-navigation="false">
<router-view /> <router-view />
</NcAppContent> </NcAppContent>
<div v-if="$route.params.id || $route.params.cardId"> <div v-if="$route.params.id || $route.params.cardId">
<NcModal v-if="cardDetailsInModal && $route.params.cardId" <NcModal v-if="cardDetailsInModal && $route.params.cardId"
:name="t('deck', 'Card details')" :name="t('deck', 'Card details')"
@@ -21,179 +57,10 @@
<router-view name="sidebar" /> <router-view name="sidebar" />
</div> </div>
</NcModal> </NcModal>
<router-view name="sidebar" :visible="!cardDetailsInModal || !$route.params.cardId" /> <router-view name="sidebar" :visible="!cardDetailsInModal || !$route.params.cardId" />
</div> </div>
<KeyboardShortcuts /> <KeyboardShortcuts />
<CardMoveDialog /> <CardMoveDialog />
</NcContent> </NcContent>
</template> </template>
<script>
import { mapState } from 'vuex'
import AppNavigation from './components/navigation/AppNavigation.vue'
import KeyboardShortcuts from './components/KeyboardShortcuts.vue'
import { NcModal, NcContent, NcAppContent, isMobile } from '@nextcloud/vue'
import { BoardApi } from './services/BoardApi.js'
import { emit, subscribe } from '@nextcloud/event-bus'
import { loadState } from '@nextcloud/initial-state'
import CardMoveDialog from './CardMoveDialog.vue'
const boardApi = new BoardApi()
export default {
name: 'App',
components: {
CardMoveDialog,
AppNavigation,
NcModal,
NcContent,
NcAppContent,
KeyboardShortcuts,
},
mixins: [isMobile],
provide() {
return {
boardApi,
}
},
data() {
return {
addButton: {
icon: 'icon-add',
classes: [],
text: t('deck', 'Add board'),
edit: {
text: t('deck', 'Add board'),
action: () => {
},
reset: () => {
},
},
action: () => {
this.addButton.classes.push('editing')
},
},
}
},
computed: {
...mapState({
navShown: state => state.navShown,
sidebarShownState: state => state.sidebarShown,
currentBoard: state => state.currentBoard,
}),
// TODO: properly handle sidebar showing for route subview and board sidebar
sidebarRouterView() {
// console.log(this.$route)
return this.$route.name === 'card' || this.$route.name === 'board.details'
},
sidebarShown() {
return this.sidebarRouterView || this.sidebarShownState
},
cardDetailsInModal: {
get() {
return this.$store.getters.config('cardDetailsInModal')
},
set(newValue) {
this.$store.dispatch('setConfig', { cardDetailsInModal: newValue })
},
},
},
created() {
const initialState = loadState('deck', 'initialBoards', null)
if (initialState !== null) {
this.$store.dispatch('loadBoards')
}
this.$store.dispatch('loadSharees')
},
mounted() {
// Set navigation to initial state and update in case it gets toggled
emit('toggle-navigation', { open: !this.isMobile && this.navShown, _initial: true })
this.$nextTick(() => {
subscribe('navigation-toggled', (navState) => {
this.$store.dispatch('toggleNav', navState.open)
})
})
},
methods: {
hideModal() {
this.$router.push({ name: 'board' })
},
},
}
</script>
<style lang="scss" scoped>
#content-vue {
#app-content {
transition: margin-left 100ms ease;
position: relative;
overflow-x: hidden;
align-items: stretch;
}
#app-sidebar {
transition: max-width 100ms ease;
}
&.nav-hidden {
#app-content {
margin-left: 0;
}
}
&.sidebar-hidden {
#app-sidebar {
max-width: 0;
min-width: 0;
}
}
}
</style>
<style lang="scss">
@import '../css/print';
.icon-activity {
background-image: url(../img/activity-dark.svg);
body[data-theme-dark] & {
background-image: url(../img/activity.svg);
}
}
.avatardiv.circles {
background: var(--color-primary-element);
}
.icon-circles {
background-image: url(../img/circles-dark.svg);
opacity: 1;
background-size: 20px;
background-position: center center;
}
.icon-circles-white, .icon-circles.icon-white {
background-image: url(../img/circles.svg);
opacity: 1;
background-size: 20px;
background-position: center center;
}
.icon-colorpicker {
background-image: url('../img/color_picker.svg');
}
.v-select {
width: 100%;
}
.modal__card {
width: 100%;
min-width: 100%;
height: calc(100% - 20px);
overflow: hidden;
}
</style>

View File

@@ -22,10 +22,10 @@
label="title" /> label="title" />
</div> </div>
<template #actions> <template #actions>
<NcButton :disabled="!isBoardAndStackChoosen" type="secondary" @click="moveCard"> <NcButton :disabled="!isBoardAndStackChoosen" variant="secondary" @click="moveCard">
{{ t('deck', 'Move card') }} {{ t('deck', 'Move card') }}
</NcButton> </NcButton>
<NcButton :disabled="!isBoardAndStackChoosen" type="primary" @click="cloneCard"> <NcButton :disabled="!isBoardAndStackChoosen" variant="primary" @click="cloneCard">
{{ t('deck', 'Copy card') }} {{ t('deck', 'Copy card') }}
</NcButton> </NcButton>
</template> </template>
@@ -72,7 +72,7 @@ export default {
mounted() { mounted() {
subscribe('deck:card:show-move-dialog', this.openModal) subscribe('deck:card:show-move-dialog', this.openModal)
}, },
destroyed() { unmounted() {
unsubscribe('deck:card:show-move-dialog', this.openModal) unsubscribe('deck:card:show-move-dialog', this.openModal)
}, },
methods: { methods: {

View File

@@ -10,9 +10,15 @@
:key="activity.activity_id" :key="activity.activity_id"
:activity="activity" /> :activity="activity" />
<InfiniteLoading :identifier="objectId" @infinite="infiniteHandler" @change="changeObject"> <InfiniteLoading :identifier="objectId" @infinite="infiniteHandler" @change="changeObject">
<div slot="spinner" class="icon-loading" /> <template #spinner>
<div slot="no-more" /> <div class="icon-loading" />
<div slot="no-results" /> </template>
<template #no-more>
<div />
</template>
<template #no-results>
<div />
</template>
</InfiniteLoading> </InfiniteLoading>
</div> </div>
</template> </template>
@@ -21,7 +27,7 @@
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import ActivityEntry from './ActivityEntry.vue' import ActivityEntry from './ActivityEntry.vue'
import InfiniteLoading from 'vue-infinite-loading' // import InfiniteLoading from 'v3-infinite-loading'
const ACTIVITY_FETCH_LIMIT = 50 const ACTIVITY_FETCH_LIMIT = 50
@@ -29,7 +35,6 @@ export default {
name: 'ActivityList', name: 'ActivityList',
components: { components: {
ActivityEntry, ActivityEntry,
InfiniteLoading,
}, },
props: { props: {
filter: { filter: {

View File

@@ -84,7 +84,7 @@
:title="t('deck', 'Apply filter')" :title="t('deck', 'Apply filter')"
:aria-label="t('deck', 'Apply filter')" :aria-label="t('deck', 'Apply filter')"
class="filter-button" class="filter-button"
:type="isFilterActive ? 'primary' : 'tertiary'"> :variant="isFilterActive ? 'primary' : 'tertiary'">
<template #icon> <template #icon>
<FilterIcon v-if="isFilterActive" :size="20" decorative /> <FilterIcon v-if="isFilterActive" :size="20" decorative />
<FilterOffIcon v-else :size="20" decorative /> <FilterOffIcon v-else :size="20" decorative />
@@ -231,12 +231,16 @@
</NcActionButton> </NcActionButton>
<NcActionButton v-if="compactMode" <NcActionButton v-if="compactMode"
@click="toggleCompactMode"> @click="toggleCompactMode">
<ArrowExpandVerticalIcon slot="icon" :size="20" decorative /> <template #icon>
<ArrowExpandVerticalIcon :size="20" decorative />
</template>
{{ t('deck', 'Toggle compact mode') }} {{ t('deck', 'Toggle compact mode') }}
</NcActionButton> </NcActionButton>
<NcActionButton v-else <NcActionButton v-else
@click="toggleCompactMode"> @click="toggleCompactMode">
<ArrowCollapseVerticalIcon slot="icon" :size="20" decorative /> <template #icon>
<ArrowCollapseVerticalIcon :size="20" decorative />
</template>
{{ t('deck', 'Toggle compact mode') }} {{ t('deck', 'Toggle compact mode') }}
</NcActionButton> </NcActionButton>
<NcActionButton @click="toggleShowCardCover"> <NcActionButton @click="toggleShowCardCover">
@@ -263,10 +267,10 @@ import { mapState, mapGetters } from 'vuex'
import { subscribe, unsubscribe } from '@nextcloud/event-bus' import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import { NcActions, NcActionButton, NcAvatar, NcButton, NcPopover, NcModal } from '@nextcloud/vue' import { NcActions, NcActionButton, NcAvatar, NcButton, NcPopover, NcModal } from '@nextcloud/vue'
import labelStyle from '../mixins/labelStyle.js' import labelStyle from '../mixins/labelStyle.js'
import ArchiveIcon from 'vue-material-design-icons/ArchiveOutline.vue' import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import ImageIcon from 'vue-material-design-icons/ImageMultipleOutline.vue' import ImageIcon from 'vue-material-design-icons/ImageMultiple.vue'
import FilterIcon from 'vue-material-design-icons/FilterOutline.vue' import FilterIcon from 'vue-material-design-icons/Filter.vue'
import FilterOffIcon from 'vue-material-design-icons/FilterOffOutline.vue' import FilterOffIcon from 'vue-material-design-icons/FilterOff.vue'
import TableColumnPlusAfter from 'vue-material-design-icons/TableColumnPlusAfter.vue' import TableColumnPlusAfter from 'vue-material-design-icons/TableColumnPlusAfter.vue'
import ArrowCollapseVerticalIcon from 'vue-material-design-icons/ArrowCollapseVertical.vue' import ArrowCollapseVerticalIcon from 'vue-material-design-icons/ArrowCollapseVertical.vue'
import ArrowExpandVerticalIcon from 'vue-material-design-icons/ArrowExpandVertical.vue' import ArrowExpandVerticalIcon from 'vue-material-design-icons/ArrowExpandVertical.vue'
@@ -274,6 +278,7 @@ import SessionList from './SessionList.vue'
import { isNotifyPushEnabled } from '../sessions.js' import { isNotifyPushEnabled } from '../sessions.js'
import CreateNewCardCustomPicker from '../views/CreateNewCardCustomPicker.vue' import CreateNewCardCustomPicker from '../views/CreateNewCardCustomPicker.vue'
import { getCurrentUser } from '@nextcloud/auth' import { getCurrentUser } from '@nextcloud/auth'
import { onClickOutside } from '@vueuse/core'
export default { export default {
name: 'Controls', name: 'Controls',
@@ -359,6 +364,11 @@ export default {
} }
}, },
}, },
created() {
onClickOutside(() => {
this.hideAddStack()
})
},
beforeMount() { beforeMount() {
subscribe('deck:board:show-new-card', this.clickShowAddCardModel) subscribe('deck:board:show-new-card', this.clickShowAddCardModel)
subscribe('deck:board:toggle-filter-popover', this.triggerOpenFilters) subscribe('deck:board:toggle-filter-popover', this.triggerOpenFilters)
@@ -366,7 +376,7 @@ export default {
subscribe('deck:board:toggle-filter-by-me', this.triggerFilterByMe) subscribe('deck:board:toggle-filter-by-me', this.triggerFilterByMe)
}, },
beforeDestroy() { beforeUnmount() {
unsubscribe('deck:board:show-new-card', this.clickShowAddCardModel) unsubscribe('deck:board:show-new-card', this.clickShowAddCardModel)
unsubscribe('deck:board:toggle-filter-popover', this.triggerOpenFilters) unsubscribe('deck:board:toggle-filter-popover', this.triggerOpenFilters)
unsubscribe('deck:board:clear-filter', this.triggerClearFilter) unsubscribe('deck:board:clear-filter', this.triggerClearFilter)
@@ -508,20 +518,6 @@ export default {
#stack-add form { #stack-add form {
display: flex; display: flex;
#new-stack-input-main {
margin-right: 8px;
}
.icon-confirm {
border: 2px solid var(--color-border-maxcontrast) !important;
border-left: none !important;
}
&:focus-within, &:focus, &:focus-visible,
&:hover {
.icon-confirm {
border-color: var(--color-main-text) !important;
}
}
} }
} }

View File

@@ -6,7 +6,6 @@
<!-- :style="{top:cardTop, left:cardLeft}" --> <!-- :style="{top:cardTop, left:cardLeft}" -->
<div v-if="card && selector" <div v-if="card && selector"
ref="shortcutModal" ref="shortcutModal"
v-click-outside="close"
class="keyboard-shortcuts__modal" class="keyboard-shortcuts__modal"
tabindex="0" tabindex="0"
@keydown.esc="close"> @keydown.esc="close">
@@ -18,6 +17,7 @@
</template> </template>
<script> <script>
import DueDateSelector from './card/DueDateSelector.vue' import DueDateSelector from './card/DueDateSelector.vue'
import { onClickOutside } from '@vueuse/core'
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus' import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
import { mapState } from 'vuex' import { mapState } from 'vuex'
import TagSelector from './card/TagSelector.vue' import TagSelector from './card/TagSelector.vue'
@@ -50,8 +50,9 @@ export default {
subscribe('deck:card:show-assignment-selector', this.handleShowAssignemnt) subscribe('deck:card:show-assignment-selector', this.handleShowAssignemnt)
subscribe('deck:card:show-due-date-selector', this.handleShowDueDate) subscribe('deck:card:show-due-date-selector', this.handleShowDueDate)
subscribe('deck:card:show-label-selector', this.handleShowLabel) subscribe('deck:card:show-label-selector', this.handleShowLabel)
onClickOutside(this.close)
}, },
destroyed() { unmounted() {
document.removeEventListener('keydown', this.onKeydown) document.removeEventListener('keydown', this.onKeydown)
unsubscribe('deck:card:show-assignment-selector', this.handleShowAssignemnt) unsubscribe('deck:card:show-assignment-selector', this.handleShowAssignemnt)
unsubscribe('deck:card:show-due-date-selector', this.handleShowDueDate) unsubscribe('deck:card:show-due-date-selector', this.handleShowDueDate)

View File

@@ -29,12 +29,12 @@
{{ t('deck', 'Create a new list to add cards to this board') }} {{ t('deck', 'Create a new list to add cards to this board') }}
<form @submit.prevent="addNewStack()"> <form @submit.prevent="addNewStack()">
<NcTextField ref="newStackInput" <NcTextField ref="newStackInput"
v-model="newStackTitle"
:disable="loading" :disable="loading"
:value.sync="newStackTitle"
:placeholder="t('deck', 'List name')" :placeholder="t('deck', 'List name')"
type="text" /> type="text" />
<NcButton type="secondary" <NcButton variant="secondary"
native-type="submit" type="submit"
:disabled="loading" :disabled="loading"
:title="t('deck', 'Add list')"> :title="t('deck', 'Add list')">
<template #icon> <template #icon>
@@ -63,7 +63,10 @@
data-click-closes-sidebar="true" data-click-closes-sidebar="true"
data-dragscroll-enabled data-dragscroll-enabled
class="stack-draggable-wrapper"> class="stack-draggable-wrapper">
<Stack :stack="stack" :dragging="draggingStack" data-click-closes-sidebar="true" /> <Stack :stack="stack"
:dragging="draggingStack"
data-click-closes-sidebar="true"
@open-card="openCard" />
</Draggable> </Draggable>
</Container> </Container>
</div> </div>
@@ -82,7 +85,7 @@
</template> </template>
<script> <script>
import { Container, Draggable } from 'vue-smooth-dnd' import { Container, Draggable } from 'vue3-smooth-dnd'
import { mapState, mapGetters } from 'vuex' import { mapState, mapGetters } from 'vuex'
import Controls from '../Controls.vue' import Controls from '../Controls.vue'
import DeckIcon from '../icons/DeckIcon.vue' import DeckIcon from '../icons/DeckIcon.vue'
@@ -165,14 +168,14 @@ export default {
created() { created() {
this.session = createSession(this.id) this.session = createSession(this.id)
this.fetchData() this.fetchData()
this.$root.$on('open-card', (cardId) => {
this.localModal = cardId
})
}, },
beforeDestroy() { beforeUnmount() {
this.session.close() this.session.close()
}, },
methods: { methods: {
openCard(cardId) {
},
async fetchData() { async fetchData() {
this.loading = true this.loading = true
try { try {
@@ -253,8 +256,8 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '../../css/animations'; @use '../../css/animations';
@import '../../css/variables'; @use '../../css/variables';
form { form {
text-align: center; text-align: center;
@@ -282,7 +285,7 @@ export default {
} }
.board { .board {
padding-left: $board-spacing; padding-left: variables.$board-spacing;
position: relative; position: relative;
max-height: calc(100% - var(--default-clickable-area)); max-height: calc(100% - var(--default-clickable-area));
overflow: hidden; overflow: hidden;
@@ -313,8 +316,8 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
// Margin left instead of padidng to avoid jumps on dropping a card // Margin left instead of padidng to avoid jumps on dropping a card
margin-left: $stack-spacing; margin-left: variables.$stack-spacing;
padding-right: $stack-spacing; padding-right: variables.$stack-spacing;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
padding-top: 15px; padding-top: 15px;

View File

@@ -56,9 +56,9 @@ import DeletedTabSidebar from './DeletedTabSidebar.vue'
import TimelineTabSidebar from './TimelineTabSidebar.vue' import TimelineTabSidebar from './TimelineTabSidebar.vue'
import { NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue' import { NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue'
import ActivityIcon from 'vue-material-design-icons/LightningBolt.vue' import ActivityIcon from 'vue-material-design-icons/LightningBolt.vue'
import SharingIcon from 'vue-material-design-icons/ShareVariantOutline.vue' import SharingIcon from 'vue-material-design-icons/ShareVariant.vue'
import TagsIcon from 'vue-material-design-icons/TagMultipleOutline.vue' import TagsIcon from 'vue-material-design-icons/TagMultiple.vue'
import TrashIcon from 'vue-material-design-icons/DeleteOutline.vue' import TrashIcon from 'vue-material-design-icons/Delete.vue'
const capabilities = window.OC.getCapabilities() const capabilities = window.OC.getCapabilities()
export default { export default {

View File

@@ -94,7 +94,7 @@
non-drag-area-selector=".dragDisabled" non-drag-area-selector=".dragDisabled"
:drag-handle-selector="dragHandleSelector" :drag-handle-selector="dragHandleSelector"
data-dragscroll-enabled data-dragscroll-enabled
@should-accept-drop="canEdit" :should-accept-drop="() => canEdit"
@drag-start="draggingCard = true" @drag-start="draggingCard = true"
@drag-end="draggingCard = false" @drag-end="draggingCard = false"
@drop="($event) => onDropCard(stack.id, $event)"> @drop="($event) => onDropCard(stack.id, $event)">
@@ -102,7 +102,10 @@
<transition :appear="animate && !card.animated && (card.animated=true)" <transition :appear="animate && !card.animated && (card.animated=true)"
:appear-class="'zoom-appear-class'" :appear-class="'zoom-appear-class'"
:appear-active-class="'zoom-appear-active-class'"> :appear-active-class="'zoom-appear-active-class'">
<CardItem :id="card.id" ref="card" :dragging="draggingCard" /> <CardItem :id="card.id"
ref="card"
:dragging="draggingCard"
@open-card="openCard" />
</transition> </transition>
</Draggable> </Draggable>
</Container> </Container>
@@ -136,8 +139,8 @@
<script> <script>
import ClickOutside from 'vue-click-outside' import ClickOutside from 'vue-click-outside'
import { mapGetters, mapState } from 'vuex' import { mapGetters, mapState } from 'vuex'
import { Container, Draggable } from 'vue-smooth-dnd' import { Container, Draggable } from 'vue3-smooth-dnd'
import ArchiveIcon from 'vue-material-design-icons/ArchiveOutline.vue' import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import CardPlusOutline from 'vue-material-design-icons/CardPlusOutline.vue' import CardPlusOutline from 'vue-material-design-icons/CardPlusOutline.vue'
import { NcActions, NcActionButton, NcModal } from '@nextcloud/vue' import { NcActions, NcActionButton, NcModal } from '@nextcloud/vue'
import { showError, showUndo } from '@nextcloud/dialogs' import { showError, showUndo } from '@nextcloud/dialogs'
@@ -171,6 +174,9 @@ export default {
default: undefined, default: undefined,
}, },
}, },
emits: [
'open-card',
],
data() { data() {
return { return {
editing: false, editing: false,
@@ -233,6 +239,9 @@ export default {
}, },
methods: { methods: {
openCard(cardId) {
this.$emit('open-card', cardId)
},
stopCardCreation(e) { stopCardCreation(e) {
// For some reason the submit event triggers a MouseEvent that is bubbling to the outside // For some reason the submit event triggers a MouseEvent that is bubbling to the outside
// so we have to ignore it // so we have to ignore it
@@ -362,10 +371,10 @@ export default {
@use 'sass:math'; @use 'sass:math';
@import './../../css/variables'; @use './../../css/variables';
.stack { .stack {
width: $stack-width + $stack-spacing * 3; width: variables.$stack-width + variables.$stack-spacing * 3;
} }
.stack__header { .stack__header {
@@ -373,8 +382,8 @@ export default {
position: sticky; position: sticky;
top: 0; top: 0;
z-index: 100; z-index: 100;
padding-left: $card-spacing; padding-left: variables.$card-spacing;
padding-right: $card-spacing; padding-right: variables.$card-spacing;
margin: 6px; margin: 6px;
margin-top: 0; margin-top: 0;
cursor: grab; cursor: grab;
@@ -418,7 +427,7 @@ export default {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
max-width: calc($stack-width - 60px); max-width: calc(variables.$stack-width - 60px);
border-radius: 3px; border-radius: 3px;
padding: 4px 4px; padding: 4px 4px;
font-size: var(--default-font-size); font-size: var(--default-font-size);
@@ -459,8 +468,8 @@ export default {
form { form {
display: flex; display: flex;
margin-left: $stack-spacing; margin-left: variables.$stack-spacing;
margin-right: $stack-spacing; margin-right: variables.$stack-spacing;
width: 100%; width: 100%;
border: 2px solid var(--color-border-maxcontrast); border: 2px solid var(--color-border-maxcontrast);
border-radius: var(--border-radius-large); border-radius: var(--border-radius-large);

View File

@@ -44,7 +44,7 @@
<script> <script>
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
import { NcAvatar, NcSelect } from '@nextcloud/vue' import { NcAvatar, NcSelect } from '@nextcloud/vue'
import AccountMultiple from 'vue-material-design-icons/AccountMultipleOutline.vue' import AccountMultiple from 'vue-material-design-icons/AccountMultiple.vue'
export default defineComponent({ export default defineComponent({
name: 'AssignmentSelector', name: 'AssignmentSelector',

View File

@@ -3,16 +3,16 @@
- SPDX-License-Identifier: AGPL-3.0-or-later - SPDX-License-Identifier: AGPL-3.0-or-later
--> -->
<!-- eslint-disable vue/no-v-model-argument -->
<template> <template>
<NcAppSidebar v-if="currentBoard && currentCard" <NcAppSidebar v-if="currentBoard && currentCard"
ref="cardSidebar" ref="cardSidebar"
v-model:name-editable="isEditingTitle"
:active="tabId" :active="tabId"
:name="displayTitle" :name="displayTitle"
:subname="subtitle" :subname="subtitle"
:subtitle="subtitleTooltip" :subtitle="subtitleTooltip"
:name-editable.sync="isEditingTitle" @update:name="value => titleEditing = value"
@update:name="(value) => titleEditing = value"
@update:active="(value) => activeTabId = value"
@dismiss-editing="titleEditing = currentCard.title" @dismiss-editing="titleEditing = currentCard.title"
@submit-name="handleSubmitTitle" @submit-name="handleSubmitTitle"
@opened="focusHeader" @opened="focusHeader"
@@ -25,39 +25,71 @@
{{ t('deck', 'Open in bigger view') }} {{ t('deck', 'Open in bigger view') }}
</NcActionButton> </NcActionButton>
<CardMenuEntries :card="currentCard" :hide-details-entry="true" /> <NcActionButton v-if="canEdit && !isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="assignCardToMe()">
{{ t('deck', 'Assign to me') }}
</NcActionButton>
<NcActionButton v-if="canEdit && isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="unassignCardFromMe()">
{{ t('deck', 'Unassign myself') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-checkmark"
:close-after-click="true"
@click="changeCardDoneStatus()">
{{ currentCard.done ? t('deck', 'Mark as not done') : t('deck', 'Mark as done') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-external"
:close-after-click="true"
@click="openCardMoveDialog">
{{ t('deck', 'Move/copy card') }}
</NcActionButton>
<NcActionButton v-for="action in cardActions"
:key="action.label"
:close-after-click="true"
:icon="action.icon"
@click="action.callback(cardRichObject)">
{{ action.label }}
</NcActionButton>
<NcActionButton v-if="canEditBoard" :close-after-click="true" @click="archiveUnarchiveCard()">
<template #icon>
<ArchiveIcon :size="20" decorative />
</template>
{{ currentCard.archived ? t('deck', 'Unarchive card') : t('deck', 'Archive card') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-delete"
:close-after-click="true"
@click="deleteCard()">
{{ t('deck', 'Delete card') }}
</NcActionButton>
</template> </template>
<template #description> <template #description>
<NcReferenceList v-if="currentCard.referenceData" <NcReferenceList v-if="currentCard.referenceData" :text="currentCard.title" :interactive="false" />
:text="currentCard.title"
:interactive="false" />
</template> </template>
<NcAppSidebarTab id="details" <NcAppSidebarTab id="details" :order="0" :name="t('deck', 'Details')">
:order="0"
:name="t('deck', 'Details')">
<CardSidebarTabDetails :card="currentCard" /> <CardSidebarTabDetails :card="currentCard" />
<template #icon> <template #icon>
<HomeIcon v-if="activeTabId === 'details'" :size="20" /> <HomeIcon :size="20" />
<HomeOutlineIcon v-else :size="20" />
</template> </template>
</NcAppSidebarTab> </NcAppSidebarTab>
<NcAppSidebarTab id="attachments" <NcAppSidebarTab id="attachments" :order="1" :name="t('deck', 'Attachments')">
:order="1"
:name="t('deck', 'Attachments')">
<template #icon> <template #icon>
<AttachmentIcon :size="20" /> <AttachmentIcon :size="20" />
</template> </template>
<CardSidebarTabAttachments :card="currentCard" /> <CardSidebarTabAttachments :card="currentCard" />
</NcAppSidebarTab> </NcAppSidebarTab>
<NcAppSidebarTab id="comments" <NcAppSidebarTab id="comments" :order="2" :name="t('deck', 'Comments')">
:order="2"
:name="t('deck', 'Comments')">
<template #icon> <template #icon>
<CommentIcon v-if="activeTabId === 'comments'" :size="20" /> <CommentIcon :size="20" />
<CommentOutlineIcon v-else :size="20" />
</template> </template>
<CardSidebarTabComments :card="currentCard" :tab-query="tabQuery" /> <CardSidebarTabComments :card="currentCard" :tab-query="tabQuery" />
</NcAppSidebarTab> </NcAppSidebarTab>
@@ -76,7 +108,7 @@
<script> <script>
import { NcActionButton, NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue' import { NcActionButton, NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue'
import { NcReferenceList } from '@nextcloud/vue/dist/Components/NcRichText.js' import { NcReferenceList } from '@nextcloud/vue/components/NcRichText'
import { getCapabilities } from '@nextcloud/capabilities' import { getCapabilities } from '@nextcloud/capabilities'
import { mapState, mapGetters } from 'vuex' import { mapState, mapGetters } from 'vuex'
import CardSidebarTabDetails from './CardSidebarTabDetails.vue' import CardSidebarTabDetails from './CardSidebarTabDetails.vue'
@@ -87,14 +119,18 @@ import relativeDate from '../../mixins/relativeDate.js'
import moment from '@nextcloud/moment' import moment from '@nextcloud/moment'
import AttachmentIcon from 'vue-material-design-icons/Paperclip.vue' import AttachmentIcon from 'vue-material-design-icons/Paperclip.vue'
import HomeIcon from 'vue-material-design-icons/Home.vue' import HomeIcon from 'vue-material-design-icons/Home.vue'
import HomeOutlineIcon from 'vue-material-design-icons/HomeOutline.vue'
import CommentIcon from 'vue-material-design-icons/Comment.vue' import CommentIcon from 'vue-material-design-icons/Comment.vue'
import CommentOutlineIcon from 'vue-material-design-icons/CommentOutline.vue'
import ActivityIcon from 'vue-material-design-icons/LightningBolt.vue' import ActivityIcon from 'vue-material-design-icons/LightningBolt.vue'
import { showError, showWarning } from '@nextcloud/dialogs' import { showError, showWarning, showUndo } from '@nextcloud/dialogs'
import { getLocale } from '@nextcloud/l10n' import { getLocale } from '@nextcloud/l10n'
import CardMenuEntries from '../cards/CardMenuEntries.vue' import { emit } from '@nextcloud/event-bus'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import { getCurrentUser } from '@nextcloud/auth'
import { generateUrl } from '@nextcloud/router'
import '@nextcloud/dialogs/style.css'
const capabilities = getCapabilities() const capabilities = getCapabilities()
@@ -112,10 +148,8 @@ export default {
ActivityIcon, ActivityIcon,
AttachmentIcon, AttachmentIcon,
CommentIcon, CommentIcon,
CommentOutlineIcon,
HomeIcon, HomeIcon,
HomeOutlineIcon, ArchiveIcon,
CardMenuEntries,
}, },
mixins: [relativeDate], mixins: [relativeDate],
props: { props: {
@@ -140,7 +174,6 @@ export default {
titleEditing: '', titleEditing: '',
hasActivity: capabilities && capabilities.activity, hasActivity: capabilities && capabilities.activity,
locale: getLocale(), locale: getLocale(),
activeTabId: this.tabId || 'details',
} }
}, },
computed: { computed: {
@@ -148,8 +181,17 @@ export default {
isFullApp: (state) => state.isFullApp, isFullApp: (state) => state.isFullApp,
currentBoard: (state) => state.currentBoard, currentBoard: (state) => state.currentBoard,
hasCardSaveError: (state) => state.hasCardSaveError, hasCardSaveError: (state) => state.hasCardSaveError,
showArchived: (state) => state.showArchived,
}), }),
...mapGetters(['canEdit', 'assignables', 'cardActions', 'stackById']), ...mapGetters([
'canEdit',
'assignables',
'cardActions',
'stackById',
'isArchived',
'boards',
'boardById',
]),
currentCard() { currentCard() {
return this.$store.getters.cardById(this.id) return this.$store.getters.cardById(this.id)
}, },
@@ -176,6 +218,31 @@ export default {
return reference ? reference.openGraphObject.name : this.currentCard.title return reference ? reference.openGraphObject.name : this.currentCard.title
}, },
}, },
canEdit() {
return !this.currentCard.archived
},
canEditBoard() {
if (this.currentBoard) {
return this.$store.getters.canEdit
}
const board = this.$store.getters.boards.find((item) => item.id === this.currentCard.boardId)
return !!board?.permissions?.PERMISSION_EDIT
},
isCurrentUserAssigned() {
return this.currentCard.assignedUsers.find((item) => item.type === 0 && item.participant.uid === getCurrentUser()?.uid)
},
boardId() {
return this.card?.boardId ? this.currentCard.boardId : Number(this.$route.params.id)
},
cardRichObject() {
return {
id: '' + this.currentCard.id,
name: this.currentCard.title,
boardname: this.boardById(this.boardId)?.title,
stackname: this.stackById(this.currentCard.stackId)?.title,
link: window.location.protocol + '//' + window.location.host + generateUrl('/apps/deck/') + `card/${this.currentCard.id}`,
}
},
}, },
watch: { watch: {
currentCard() { currentCard() {
@@ -224,12 +291,46 @@ export default {
formatDate(timestamp) { formatDate(timestamp) {
return moment.unix(timestamp).locale(this.locale).format('LLLL') return moment.unix(timestamp).locale(this.locale).format('LLLL')
}, },
deleteCard() {
this.$store.dispatch('deleteCard', this.currentCard)
const undoCard = { ...this.currentCard, deletedAt: 0 }
showUndo(t('deck', 'Card deleted'), () => this.$store.dispatch('cardUndoDelete', undoCard))
if (this.$router.currentRoute.name === 'card') {
this.$router.push({ name: 'board' })
}
},
changeCardDoneStatus() {
this.$store.dispatch('changeCardDoneStatus', { ...this.currentCard, done: !this.currentCard.done })
},
archiveUnarchiveCard() {
this.$store.dispatch('archiveUnarchiveCard', { ...this.currentCard, archived: !this.currentCard.archived })
},
assignCardToMe() {
this.$store.dispatch('assignCardToUser', {
card: this.currentCard,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
unassignCardFromMe() {
this.$store.dispatch('removeUserFromCard', {
card: this.currentCard,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
openCardMoveDialog() {
emit('deck:card:show-move-dialog', this.currentCard)
},
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
section.app-sidebar__tab--active { section.app-sidebar__tab--active {
min-height: auto; min-height: auto;
display: flex; display: flex;
@@ -281,6 +382,7 @@ section.app-sidebar__tab--active {
z-index: 100; z-index: 100;
background-color: var(--color-main-background); background-color: var(--color-main-background);
} }
.app-sidebar-tabs__nav { .app-sidebar-tabs__nav {
position: sticky; position: sticky;
top: 87px; top: 87px;
@@ -293,10 +395,10 @@ section.app-sidebar__tab--active {
overflow: initial; overflow: initial;
} }
#emptycontent, .emptycontent { #emptycontent,
.emptycontent {
margin-top: 88px; margin-top: 88px;
} }
} }
} }
</style> </style>

View File

@@ -23,11 +23,11 @@
:key="comment.id" :key="comment.id"
:comment="comment" :comment="comment"
@doReload="loadComments" /> @doReload="loadComments" />
<InfiniteLoading :identifier="card.id" @infinite="infiniteHandler"> <!-- <InfiniteLoading :identifier="card.id" @infinite="infiniteHandler">
<div slot="spinner" class="icon-loading" /> <div slot="spinner" class="icon-loading" />
<div slot="no-more" /> <div slot="no-more" />
<div slot="no-results" /> <div slot="no-results" />
</InfiniteLoading> </InfiniteLoading> -->
</ul> </ul>
<div v-else-if="isLoading" class="icon icon-loading" /> <div v-else-if="isLoading" class="icon icon-loading" />
<div v-else class="emptycontent"> <div v-else class="emptycontent">
@@ -42,7 +42,7 @@ import { mapState, mapGetters } from 'vuex'
import { NcAvatar } from '@nextcloud/vue' import { NcAvatar } from '@nextcloud/vue'
import CommentItem from './CommentItem.vue' import CommentItem from './CommentItem.vue'
import CommentForm from './CommentForm.vue' import CommentForm from './CommentForm.vue'
import InfiniteLoading from 'vue-infinite-loading' // import InfiniteLoading from 'v3-infinite-loading'
import { getCurrentUser } from '@nextcloud/auth' import { getCurrentUser } from '@nextcloud/auth'
export default { export default {
@@ -51,7 +51,7 @@ export default {
NcAvatar, NcAvatar,
CommentItem, CommentItem,
CommentForm, CommentForm,
InfiniteLoading, // InfiniteLoading,
}, },
props: { props: {
card: { card: {

View File

@@ -2,8 +2,13 @@
- SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors - SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later - SPDX-License-Identifier: AGPL-3.0-or-later
--> -->
<template> <template>
<div>
THIS HAS AT
</div>
</template>
<!-- <template>
<div class="comment-form"> <div class="comment-form">
<form @submit.prevent="submit"> <form @submit.prevent="submit">
<At ref="at" <At ref="at"
@@ -191,4 +196,4 @@ export default {
.atwho-li--avatar { .atwho-li--avatar {
margin-right: 10px; margin-right: 10px;
} }
</style> </style> -->

View File

@@ -82,7 +82,7 @@ import CommentForm from './CommentForm.vue'
import { getCurrentUser } from '@nextcloud/auth' import { getCurrentUser } from '@nextcloud/auth'
import md5 from 'blueimp-md5' import md5 from 'blueimp-md5'
import relativeDate from '../../mixins/relativeDate.js' import relativeDate from '../../mixins/relativeDate.js'
import ReplyIcon from 'vue-material-design-icons/ReplyOutline.vue' import ReplyIcon from 'vue-material-design-icons/Reply.vue'
import moment from 'moment' import moment from 'moment'
const AtMention = { const AtMention = {

View File

@@ -175,7 +175,7 @@ export default {
mounted() { mounted() {
this.setupEditor() this.setupEditor()
}, },
async beforeDestroy() { async beforeUnmount() {
await this.destroyEditor() await this.destroyEditor()
}, },
methods: { methods: {

View File

@@ -4,8 +4,12 @@
--> -->
<template> <template>
<CardDetailEntry :label="t('deck', 'Assign a due date to this card…')" data-test="due-date-selector"> <CardDetailEntry :label="t('deck', 'Assign a due date to this card…')" data-test="due-date-selector">
<Calendar v-if="!card.done" slot="icon" :size="20" /> <template v-if="!card.done" #icon>
<CalendarCheck v-else slot="icon" :size="20" /> <Calendar :size="20" />
</template>
<template v-else #icon>
<CalendarCheck :size="20" />
</template>
<template v-if="!card.done && !card.archived"> <template v-if="!card.done && !card.archived">
<NcDateTimePickerNative v-if="duedate" <NcDateTimePickerNative v-if="duedate"
id="card-duedate-picker" id="card-duedate-picker"
@@ -15,7 +19,7 @@
type="datetime-local" /> type="datetime-local" />
<NcActions v-if="canEdit" <NcActions v-if="canEdit"
:menu-title="!duedate ? t('deck', 'Add due date') : null" :menu-title="!duedate ? t('deck', 'Add due date') : null"
type="tertiary" variant="tertiary"
data-cy-due-date-actions> data-cy-due-date-actions>
<template v-if="!duedate" #icon> <template v-if="!duedate" #icon>
<Plus :size="20" /> <Plus :size="20" />
@@ -48,7 +52,7 @@
</NcActions> </NcActions>
<NcButton v-if="!card.done" <NcButton v-if="!card.done"
type="secondary" variant="secondary"
class="completed-button" class="completed-button"
@click="changeCardDoneStatus()"> @click="changeCardDoneStatus()">
<template #icon> <template #icon>
@@ -69,14 +73,14 @@
</div> </div>
<div class="due-actions"> <div class="due-actions">
<NcButton v-if="!card.archived" <NcButton v-if="!card.archived"
type="tertiary" variant="tertiary"
:name="t('deck', 'Not done')" :name="t('deck', 'Not done')"
@click="changeCardDoneStatus()"> @click="changeCardDoneStatus()">
<template #icon> <template #icon>
<ClearIcon :size="20" /> <ClearIcon :size="20" />
</template> </template>
</NcButton> </NcButton>
<NcButton type="secondary" @click="archiveUnarchiveCard()"> <NcButton variant="secondary" @click="archiveUnarchiveCard()">
<template #icon> <template #icon>
<ArchiveIcon :size="20" /> <ArchiveIcon :size="20" />
</template> </template>
@@ -99,10 +103,10 @@ import {
import readableDate from '../../mixins/readableDate.js' import readableDate from '../../mixins/readableDate.js'
import { getDayNamesMin, getFirstDay, getMonthNamesShort } from '@nextcloud/l10n' import { getDayNamesMin, getFirstDay, getMonthNamesShort } from '@nextcloud/l10n'
import moment from '@nextcloud/moment' import moment from '@nextcloud/moment'
import ArchiveIcon from 'vue-material-design-icons/ArchiveOutline.vue' import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import Plus from 'vue-material-design-icons/Plus.vue' import Plus from 'vue-material-design-icons/Plus.vue'
import Calendar from 'vue-material-design-icons/CalendarOutline.vue' import Calendar from 'vue-material-design-icons/Calendar.vue'
import CalendarCheck from 'vue-material-design-icons/CalendarCheckOutline.vue' import CalendarCheck from 'vue-material-design-icons/CalendarCheck.vue'
import CheckIcon from 'vue-material-design-icons/Check.vue' import CheckIcon from 'vue-material-design-icons/Check.vue'
import ClearIcon from 'vue-material-design-icons/Close.vue' import ClearIcon from 'vue-material-design-icons/Close.vue'
import CardDetailEntry from './CardDetailEntry.vue' import CardDetailEntry from './CardDetailEntry.vue'

View File

@@ -7,7 +7,7 @@
<div class="selector-wrapper--icon"> <div class="selector-wrapper--icon">
<TagMultiple :size="20" /> <TagMultiple :size="20" />
</div> </div>
<NcSelect :value="assignedLabels" <NcSelect v-model="assignedLabels"
class="selector-wrapper--selector" class="selector-wrapper--selector"
:multiple="true" :multiple="true"
:disabled="disabled" :disabled="disabled"
@@ -44,7 +44,7 @@
<script> <script>
import { NcSelect } from '@nextcloud/vue' import { NcSelect } from '@nextcloud/vue'
import Color from '../../mixins/color.js' import Color from '../../mixins/color.js'
import TagMultiple from 'vue-material-design-icons/TagMultipleOutline.vue' import TagMultiple from 'vue-material-design-icons/TagMultiple.vue'
export default { export default {
name: 'TagSelector', name: 'TagSelector',

View File

@@ -70,7 +70,7 @@
<script> <script>
import { NcAvatar, NcPopover } from '@nextcloud/vue' import { NcAvatar, NcPopover } from '@nextcloud/vue'
import { generateUrl } from '@nextcloud/router' import { generateUrl } from '@nextcloud/router'
import AccountMultiple from 'vue-material-design-icons/AccountMultipleOutline.vue' import AccountMultiple from 'vue-material-design-icons/AccountMultiple.vue'
export default { export default {
name: 'AvatarList', name: 'AvatarList',

View File

@@ -49,8 +49,8 @@ import CardId from './badges/CardId.vue'
import TextIcon from 'vue-material-design-icons/Text.vue' import TextIcon from 'vue-material-design-icons/Text.vue'
import AttachmentIcon from 'vue-material-design-icons/Paperclip.vue' import AttachmentIcon from 'vue-material-design-icons/Paperclip.vue'
import CheckmarkIcon from 'vue-material-design-icons/CheckboxMarked.vue' import CheckmarkIcon from 'vue-material-design-icons/CheckboxMarked.vue'
import CommentIcon from 'vue-material-design-icons/CommentOutline.vue' import CommentIcon from 'vue-material-design-icons/Comment.vue'
import CommentUnreadIcon from 'vue-material-design-icons/CommentAccountOutline.vue' import CommentUnreadIcon from 'vue-material-design-icons/CommentAccount.vue'
import DueDate from './badges/DueDate.vue' import DueDate from './badges/DueDate.vue'
export default { export default {

View File

@@ -72,7 +72,7 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '../../css/variables'; @use '../../css/variables';
.card-cover { .card-cover {
height: 90px; height: 90px;

View File

@@ -88,6 +88,7 @@ import CardMenu from './CardMenu.vue'
import CardCover from './CardCover.vue' import CardCover from './CardCover.vue'
import DueDate from './badges/DueDate.vue' import DueDate from './badges/DueDate.vue'
import { getCurrentUser } from '@nextcloud/auth' import { getCurrentUser } from '@nextcloud/auth'
import { emit } from '@nextcloud/event-bus'
const TITLE_EDITING_STATE = { const TITLE_EDITING_STATE = {
OFF: 0, OFF: 0,
@@ -120,6 +121,7 @@ export default {
default: false, default: false,
}, },
}, },
emits: ['open-card'],
data() { data() {
return { return {
highlight: false, highlight: false,
@@ -226,8 +228,9 @@ export default {
this.$router.push({ name: 'card', params: { id: boardId, cardId: this.card.id } }).catch(() => {}) this.$router.push({ name: 'card', params: { id: boardId, cardId: this.card.id } }).catch(() => {})
return return
} }
emit('open-card', {
this.$root.$emit('open-card', this.card.id) cardId: this.card.id,
})
}, },
triggerEditTitle() { triggerEditTitle() {
this.editingTitle = TITLE_EDITING_STATE.PENDING this.editingTitle = TITLE_EDITING_STATE.PENDING
@@ -318,8 +321,8 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import './../../css/animations'; @use './../../css/animations';
@import './../../css/variables'; @use './../../css/variables';
@mixin dark-card { @mixin dark-card {
border: 2px solid var(--color-border-dark); border: 2px solid var(--color-border-dark);
@@ -331,8 +334,8 @@ export default {
border-radius: var(--border-radius-large); border-radius: var(--border-radius-large);
font-size: 100%; font-size: 100%;
background-color: var(--color-main-background); background-color: var(--color-main-background);
margin-bottom: $card-spacing; margin-bottom: variables.$card-spacing;
padding: var(--default-grid-baseline) $card-padding; padding: var(--default-grid-baseline) variables.$card-padding;
border: 2px solid var(--color-border-dark); border: 2px solid var(--color-border-dark);
width: 100%; width: 100%;
display: flex; display: flex;
@@ -470,7 +473,7 @@ export default {
width: 32px; width: 32px;
} }
&.has-labels { &.has-labels {
padding-bottom: $card-padding; padding-bottom: variables.$card-padding;
} }
.labels { .labels {
height: 6px; height: 6px;

View File

@@ -6,40 +6,190 @@
<template> <template>
<div v-if="card" class="card-menu" @click.stop.prevent> <div v-if="card" class="card-menu" @click.stop.prevent>
<NcButton v-if="card.referenceData" <NcButton v-if="card.referenceData"
type="tertiary" variant="tertiary"
:title="t('deck','Open link')" :title="t('deck', 'Open link')"
@click="openLink"> @click="openLink">
<template #icon> <template #icon>
<LinkIcon :size="20" /> <LinkIcon :size="20" />
</template> </template>
</NcButton> </NcButton>
<NcActions> <NcActions>
<CardMenuEntries :card="card" @edit-title="editTitle" /> <NcActionButton v-if="!hideDetailsEntry" :close-after-click="true" @click="openCard">
<template #icon>
<CardBulletedIcon icon :size="20" decorative />
</template>
{{ t('deck', 'Card details') }}
</NcActionButton>
<NcActionButton v-if="canEdit" :close-after-click="true" @click="editTitle">
<template #icon>
<PencilIcon :size="20" decorative />
</template>
{{ t('deck', 'Edit title') }}
</NcActionButton>
<NcActionButton v-if="canEdit && !isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="assignCardToMe()">
{{ t('deck', 'Assign to me') }}
</NcActionButton>
<NcActionButton v-if="canEdit && isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="unassignCardFromMe()">
{{ t('deck', 'Unassign myself') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-checkmark"
:close-after-click="true"
@click="changeCardDoneStatus()">
{{ card.done ? t('deck', 'Mark as not done') : t('deck', 'Mark as done') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-external"
:close-after-click="true"
@click="openCardMoveDialog">
{{ t('deck', 'Move/copy card') }}
</NcActionButton>
<NcActionButton v-for="action in cardActions"
:key="action.label"
:close-after-click="true"
:icon="action.icon"
@click="action.callback(cardRichObject)">
{{ action.label }}
</NcActionButton>
<NcActionButton v-if="canEditBoard" :close-after-click="true" @click="archiveUnarchiveCard()">
<template #icon>
<ArchiveIcon :size="20" decorative />
</template>
{{ card.archived ? t('deck', 'Unarchive card') : t('deck', 'Archive card') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-delete"
:close-after-click="true"
@click="deleteCard()">
{{ t('deck', 'Delete card') }}
</NcActionButton>
</NcActions> </NcActions>
</div> </div>
</template> </template>
<script> <script>
import { NcActions, NcButton } from '@nextcloud/vue' import { NcActions, NcButton, NcActionButton } from '@nextcloud/vue'
import LinkIcon from 'vue-material-design-icons/Link.vue' import LinkIcon from 'vue-material-design-icons/Link.vue'
import CardMenuEntries from './CardMenuEntries.vue' import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import { getCurrentUser } from '@nextcloud/auth'
import CardBulletedIcon from 'vue-material-design-icons/CardBulleted.vue'
import PencilIcon from 'vue-material-design-icons/Pencil.vue'
import { mapGetters, mapState } from 'vuex'
import { showUndo } from '@nextcloud/dialogs'
import { generateUrl } from '@nextcloud/router'
import '@nextcloud/dialogs/style.css'
import { emit } from '@nextcloud/event-bus'
export default { export default {
name: 'CardMenu', name: 'CardMenu',
components: { NcActions, NcButton, LinkIcon, CardMenuEntries }, components: { NcActions, NcButton, LinkIcon, NcActionButton, PencilIcon, CardBulletedIcon, ArchiveIcon },
props: { props: {
card: { card: {
type: Object, type: Object,
default: null, default: null,
}, },
hideDetailsEntry: {
type: Boolean,
default: false,
},
}, },
emits: ['edit-title'], emits: ['edit-title'],
computed: {
...mapGetters([
'isArchived',
'boards',
'cardActions',
'stackById',
'boardById',
]),
...mapState({
showArchived: state => state.showArchived,
currentBoard: state => state.currentBoard,
}),
canEdit() {
return !this.card.archived
},
canEditBoard() {
if (this.currentBoard) {
return this.$store.getters.canEdit
}
const board = this.$store.getters.boards.find((item) => item.id === this.card.boardId)
return !!board?.permissions?.PERMISSION_EDIT
},
isCurrentUserAssigned() {
return this.card.assignedUsers.find((item) => item.type === 0 && item.participant.uid === getCurrentUser()?.uid)
},
boardId() {
return this.card?.boardId ? this.card.boardId : Number(this.$route.params.id)
},
cardRichObject() {
return {
id: '' + this.card.id,
name: this.card.title,
boardname: this.boardById(this.boardId)?.title,
stackname: this.stackById(this.card.stackId)?.title,
link: window.location.protocol + '//' + window.location.host + generateUrl('/apps/deck/') + `card/${this.card.id}`,
}
},
},
methods: { methods: {
openLink() { openLink() {
window.open(this.card?.referenceData?.openGraphObject?.link) window.open(this.card?.referenceData?.openGraphObject?.link)
return false return false
}, },
editTitle(id) { openCard() {
this.$emit('edit-title', id) const boardId = this.card?.boardId ? this.card.boardId : this.$route?.params.id ?? this.currentBoard.id
if (this.$router) {
this.$router?.push({ name: 'card', params: { id: boardId, cardId: this.card.id } }).catch(() => { })
return
}
this.$root.$emit('open-card', this.card.id)
},
editTitle() {
this.$emit('edit-title', this.card.id)
},
deleteCard() {
this.$store.dispatch('deleteCard', this.card)
const undoCard = { ...this.card, deletedAt: 0 }
showUndo(t('deck', 'Card deleted'), () => this.$store.dispatch('cardUndoDelete', undoCard))
if (this.$router.currentRoute.name === 'card') {
this.$router.push({ name: 'board' })
}
},
changeCardDoneStatus() {
this.$store.dispatch('changeCardDoneStatus', { ...this.card, done: !this.card.done })
},
archiveUnarchiveCard() {
this.$store.dispatch('archiveUnarchiveCard', { ...this.card, archived: !this.card.archived })
},
assignCardToMe() {
this.$store.dispatch('assignCardToUser', {
card: this.card,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
unassignCardFromMe() {
this.$store.dispatch('removeUserFromCard', {
card: this.card,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
openCardMoveDialog() {
emit('deck:card:show-move-dialog', this.card)
}, },
}, },
} }

View File

@@ -1,187 +0,0 @@
<!--
- SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<div>
<NcActionButton v-if="!hideDetailsEntry" :close-after-click="true" @click="openCard">
<CardBulletedIcon slot="icon" :size="20" decorative />
{{ t('deck', 'Card details') }}
</NcActionButton>
<NcActionButton v-if="canEdit" :close-after-click="true" @click="editTitle">
<template #icon>
<PencilIcon :size="20" decorative />
</template>
{{ t('deck', 'Edit title') }}
</NcActionButton>
<NcActionButton v-if="canEdit && !isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="assignCardToMe()">
{{ t('deck', 'Assign to me') }}
</NcActionButton>
<NcActionButton v-if="canEdit && isCurrentUserAssigned"
icon="icon-user"
:close-after-click="true"
@click="unassignCardFromMe()">
{{ t('deck', 'Unassign myself') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-checkmark"
:close-after-click="true"
@click="changeCardDoneStatus()">
{{ card.done ? t('deck', 'Mark as not done') : t('deck', 'Mark as done') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-external"
:close-after-click="true"
@click="openCardMoveDialog">
{{ t('deck', 'Move/copy card') }}
</NcActionButton>
<NcActionButton v-for="action in cardActions"
:key="action.label"
:close-after-click="true"
:icon="action.icon"
@click="action.callback(cardRichObject)">
{{ action.label }}
</NcActionButton>
<NcActionButton v-if="canEditBoard" :close-after-click="true" @click="archiveUnarchiveCard()">
<template #icon>
<ArchiveIcon :size="20" decorative />
</template>
{{ card.archived ? t('deck', 'Unarchive card') : t('deck', 'Archive card') }}
</NcActionButton>
<NcActionButton v-if="canEdit"
icon="icon-delete"
:close-after-click="true"
@click="deleteCard()">
{{ t('deck', 'Delete card') }}
</NcActionButton>
</div>
</template>
<script>
import { NcActionButton } from '@nextcloud/vue'
import { mapGetters, mapState } from 'vuex'
import ArchiveIcon from 'vue-material-design-icons/ArchiveOutline.vue'
import CardBulletedIcon from 'vue-material-design-icons/CardBulletedOutline.vue'
import PencilIcon from 'vue-material-design-icons/PencilOutline.vue'
import { generateUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { showUndo } from '@nextcloud/dialogs'
import '@nextcloud/dialogs/style.css'
import { emit } from '@nextcloud/event-bus'
export default {
name: 'CardMenuEntries',
components: { NcActionButton, ArchiveIcon, CardBulletedIcon, PencilIcon },
props: {
card: {
type: Object,
default: null,
},
hideDetailsEntry: {
type: Boolean,
default: false,
},
},
emits: ['edit-title'],
data() {
return {
modalShow: false,
selectedBoard: '',
selectedStack: '',
stacksFromBoard: [],
}
},
computed: {
...mapGetters([
'isArchived',
'boards',
'cardActions',
'stackById',
'boardById',
]),
...mapState({
showArchived: state => state.showArchived,
currentBoard: state => state.currentBoard,
}),
canEdit() {
return !this.card.archived
},
canEditBoard() {
if (this.currentBoard) {
return this.$store.getters.canEdit
}
const board = this.$store.getters.boards.find((item) => item.id === this.card.boardId)
return !!board?.permissions?.PERMISSION_EDIT
},
isCurrentUserAssigned() {
return this.card.assignedUsers.find((item) => item.type === 0 && item.participant.uid === getCurrentUser()?.uid)
},
boardId() {
return this.card?.boardId ? this.card.boardId : Number(this.$route.params.id)
},
cardRichObject() {
return {
id: '' + this.card.id,
name: this.card.title,
boardname: this.boardById(this.boardId)?.title,
stackname: this.stackById(this.card.stackId)?.title,
link: window.location.protocol + '//' + window.location.host + generateUrl('/apps/deck/') + `card/${this.card.id}`,
}
},
},
methods: {
openCard() {
const boardId = this.card?.boardId ? this.card.boardId : this.$route?.params.id ?? this.currentBoard.id
if (this.$router) {
this.$router?.push({ name: 'card', params: { id: boardId, cardId: this.card.id } }).catch(() => {})
return
}
this.$root.$emit('open-card', this.card.id)
},
editTitle() {
this.$emit('edit-title', this.card.id)
},
deleteCard() {
this.$store.dispatch('deleteCard', this.card)
const undoCard = { ...this.card, deletedAt: 0 }
showUndo(t('deck', 'Card deleted'), () => this.$store.dispatch('cardUndoDelete', undoCard))
if (this.$router.currentRoute.name === 'card') {
this.$router.push({ name: 'board' })
}
},
changeCardDoneStatus() {
this.$store.dispatch('changeCardDoneStatus', { ...this.card, done: !this.card.done })
},
archiveUnarchiveCard() {
this.$store.dispatch('archiveUnarchiveCard', { ...this.card, archived: !this.card.archived })
},
assignCardToMe() {
this.$store.dispatch('assignCardToUser', {
card: this.card,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
unassignCardFromMe() {
this.$store.dispatch('removeUserFromCard', {
card: this.card,
assignee: {
userId: getCurrentUser()?.uid,
type: 0,
},
})
},
openCardMoveDialog() {
emit('deck:card:show-move-dialog', this.card)
},
},
}
</script>

View File

@@ -151,16 +151,13 @@
</template> </template>
<script> <script>
import { NcModal, Tooltip } from '@nextcloud/vue' import { NcModal } from '@nextcloud/vue'
export default { export default {
name: 'HelpModal', name: 'HelpModal',
components: { components: {
NcModal, NcModal,
}, },
directives: {
Tooltip,
},
} }
</script> </script>

View File

@@ -10,8 +10,7 @@
:exact="true" :exact="true"
to="/"> to="/">
<template #icon> <template #icon>
<CalendarIcon v-if="$route.path === '/'" :size="20" /> <CalendarIcon :size="20" />
<CalendarOutlineIcon v-else :size="20" />
</template> </template>
</NcAppNavigationItem> </NcAppNavigationItem>
<AppNavigationBoardCategory id="deck-navigation-all" <AppNavigationBoardCategory id="deck-navigation-all"
@@ -30,8 +29,7 @@
:text="t('deck', 'Archived boards')" :text="t('deck', 'Archived boards')"
:boards="archivedBoards"> :boards="archivedBoards">
<template #icon> <template #icon>
<ArchiveIcon v-if="$route.path === '/board/archived'" :size="20" decorative /> <ArchiveIcon :size="20" decorative />
<ArchiveOutlineIcon v-else :size="20" decorative />
</template> </template>
</AppNavigationBoardCategory> </AppNavigationBoardCategory>
<AppNavigationBoardCategory id="deck-navigation-shared" <AppNavigationBoardCategory id="deck-navigation-shared"
@@ -114,11 +112,9 @@ import { loadState } from '@nextcloud/initial-state'
import { generateOcsUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth' import { getCurrentUser } from '@nextcloud/auth'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue' import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import ArchiveOutlineIcon from 'vue-material-design-icons/ArchiveOutline.vue'
import CalendarIcon from 'vue-material-design-icons/Calendar.vue' import CalendarIcon from 'vue-material-design-icons/Calendar.vue'
import CalendarOutlineIcon from 'vue-material-design-icons/CalendarOutline.vue'
import DeckIcon from './../icons/DeckIcon.vue' import DeckIcon from './../icons/DeckIcon.vue'
import ShareVariantIcon from 'vue-material-design-icons/ShareOutline.vue' import ShareVariantIcon from 'vue-material-design-icons/Share.vue'
import HelpModal from './../modals/HelpModal.vue' import HelpModal from './../modals/HelpModal.vue'
import { subscribe } from '@nextcloud/event-bus' import { subscribe } from '@nextcloud/event-bus'
import AppNavigationImportBoard from './AppNavigationImportBoard.vue' import AppNavigationImportBoard from './AppNavigationImportBoard.vue'
@@ -137,9 +133,7 @@ export default {
NcSelect, NcSelect,
NcAppNavigationItem, NcAppNavigationItem,
ArchiveIcon, ArchiveIcon,
ArchiveOutlineIcon,
CalendarIcon, CalendarIcon,
CalendarOutlineIcon,
DeckIcon, DeckIcon,
ShareVariantIcon, ShareVariantIcon,
HelpModal, HelpModal,

View File

@@ -13,12 +13,12 @@
</NcColorPicker> </NcColorPicker>
<form @submit.prevent.stop="createBoard"> <form @submit.prevent.stop="createBoard">
<NcTextField ref="inputField" <NcTextField ref="inputField"
v-model="value"
:disable="loading" :disable="loading"
:value.sync="value"
:placeholder="t('deck', 'Board name')" :placeholder="t('deck', 'Board name')"
type="text" type="text"
required /> required />
<NcButton type="tertiary" <NcButton variant="tertiary"
:disabled="loading" :disabled="loading"
:title="t('deck', 'Cancel edit')" :title="t('deck', 'Cancel edit')"
@click.stop.prevent="cancelEdit"> @click.stop.prevent="cancelEdit">
@@ -26,8 +26,8 @@
<CloseIcon :size="20" /> <CloseIcon :size="20" />
</template> </template>
</NcButton> </NcButton>
<NcButton type="tertiary" <NcButton variant="tertiary"
native-type="submit" type="submit"
:disabled="loading" :disabled="loading"
:title="t('deck', 'Save board')"> :title="t('deck', 'Save board')">
<template #icon> <template #icon>
@@ -77,6 +77,7 @@ export default {
}) })
}, },
async createBoard(e) { async createBoard(e) {
alert('createBoard called')
this.loading = true this.loading = true
const title = this.value.trim() const title = this.value.trim()
await this.$store.dispatch('createBoard', { await this.$store.dispatch('createBoard', {
@@ -88,6 +89,7 @@ export default {
this.color = randomColor() this.color = randomColor()
}, },
cancelEdit(e) { cancelEdit(e) {
alert('cancelEdit called')
this.editing = false this.editing = false
this.color = randomColor() this.color = randomColor()
}, },

View File

@@ -25,7 +25,7 @@
<AccountIcon v-if="board.acl.length > 0" /> <AccountIcon v-if="board.acl.length > 0" />
</template> </template>
<template v-if="!deleted" slot="actions"> <template v-if="!deleted" #actions>
<template v-if="!isDueSubmenuActive"> <template v-if="!isDueSubmenuActive">
<NcActionButton icon="icon-info" <NcActionButton icon="icon-info"
:close-after-click="true" :close-after-click="true"
@@ -129,17 +129,17 @@
:placeholder="t('deck', 'Board name')" :placeholder="t('deck', 'Board name')"
type="text" type="text"
required /> required />
<NcButton type="tertiary" <NcButton variant="tertiary"
:disabled="loading" :disabled="loading"
native-type="submit" type="submit"
:title="t('deck', 'Cancel edit')" :title="t('deck', 'Cancel edit')"
@click.stop.prevent="cancelEdit"> @click.stop.prevent="cancelEdit">
<template #icon> <template #icon>
<CloseIcon :size="20" /> <CloseIcon :size="20" />
</template> </template>
</NcButton> </NcButton>
<NcButton type="tertiary" <NcButton variant="tertiary"
native-type="submit" type="submit"
:disabled="loading" :disabled="loading"
:title="t('deck', 'Save board')"> :title="t('deck', 'Save board')">
<template #icon> <template #icon>
@@ -152,11 +152,11 @@
</template> </template>
<script> <script>
import { NcAppNavigationIconBullet, NcAppNavigationItem, NcColorPicker, NcButton, NcTextField, NcActionButton } from '@nextcloud/vue' import { NcAppNavigationIconBullet, NcAppNavigationItem, NcColorPicker, NcButton, NcTextField, NcActionButton, NcLoadingIcon } from '@nextcloud/vue'
import ClickOutside from 'vue-click-outside' import ClickOutside from 'vue-click-outside'
import ArchiveIcon from 'vue-material-design-icons/ArchiveOutline.vue' import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import CloneIcon from 'vue-material-design-icons/ContentDuplicate.vue' import CloneIcon from 'vue-material-design-icons/ContentDuplicate.vue'
import AccountIcon from 'vue-material-design-icons/AccountOutline.vue' import AccountIcon from 'vue-material-design-icons/Account.vue'
import CloseIcon from 'vue-material-design-icons/Close.vue' import CloseIcon from 'vue-material-design-icons/Close.vue'
import CheckIcon from 'vue-material-design-icons/Check.vue' import CheckIcon from 'vue-material-design-icons/Check.vue'
@@ -186,6 +186,7 @@ export default {
CheckIcon, CheckIcon,
BoardCloneModal, BoardCloneModal,
BoardExportModal, BoardExportModal,
NcLoadingIcon,
}, },
directives: { directives: {
ClickOutside, ClickOutside,

View File

@@ -31,10 +31,6 @@ export default {
type: String, type: String,
default: '', default: '',
}, },
id: {
type: String,
required: true,
},
text: { text: {
type: String, type: String,
required: true, required: true,

View File

@@ -5,16 +5,16 @@
<template> <template>
<NcDialog :name="t('deck', 'Clone {boardTitle}', {boardTitle: boardTitle})" :show="true" @close="close(false)"> <NcDialog :name="t('deck', 'Clone {boardTitle}', {boardTitle: boardTitle})" :show="true" @close="close(false)">
<div class="modal__content"> <div class="modal__content">
<NcCheckboxRadioSwitch :checked.sync="withCards"> <NcCheckboxRadioSwitch v-model="withCards">
{{ t('deck', 'Clone cards') }} {{ t('deck', 'Clone cards') }}
</NcCheckboxRadioSwitch> </NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="withCards" :checked.sync="withAssignments"> <NcCheckboxRadioSwitch v-if="withCards" v-model="withAssignments">
{{ t('deck', 'Clone assignments') }} {{ t('deck', 'Clone assignments') }}
</NcCheckboxRadioSwitch> </NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="withCards" :checked.sync="withLabels"> <NcCheckboxRadioSwitch v-if="withCards" v-model="withLabels">
{{ t('deck', 'Clone labels') }} {{ t('deck', 'Clone labels') }}
</NcCheckboxRadioSwitch> </NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="withCards" :checked.sync="withDueDate"> <NcCheckboxRadioSwitch v-if="withCards" v-model="withDueDate">
{{ t('deck', 'Clone due dates') }} {{ t('deck', 'Clone due dates') }}
</NcCheckboxRadioSwitch> </NcCheckboxRadioSwitch>
<div v-if="withCards" class="accordion" :class="{ 'is-open': accordionOpen }"> <div v-if="withCards" class="accordion" :class="{ 'is-open': accordionOpen }">
@@ -25,10 +25,10 @@
{{ t('deck', 'Advanced options') }} {{ t('deck', 'Advanced options') }}
</div> </div>
<div v-if="accordionOpen" class="accordion__content"> <div v-if="accordionOpen" class="accordion__content">
<NcCheckboxRadioSwitch v-if="withCards" :checked.sync="moveCardsToLeftStack"> <NcCheckboxRadioSwitch v-if="withCards" v-model="moveCardsToLeftStack">
{{ t('deck', 'Move all cards to the first list') }} {{ t('deck', 'Move all cards to the first list') }}
</NcCheckboxRadioSwitch> </NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="withCards" :checked.sync="restoreArchivedCards"> <NcCheckboxRadioSwitch v-if="withCards" v-model="restoreArchivedCards">
{{ t('deck', 'Restore archived cards') }} {{ t('deck', 'Restore archived cards') }}
</NcCheckboxRadioSwitch> </NcCheckboxRadioSwitch>
</div> </div>
@@ -39,7 +39,7 @@
<NcButton @click="cancel"> <NcButton @click="cancel">
{{ t('deck', 'Cancel') }} {{ t('deck', 'Cancel') }}
</NcButton> </NcButton>
<NcButton type="primary" @click="save"> <NcButton variant="primary" @click="save">
{{ t('deck', 'Clone') }} {{ t('deck', 'Clone') }}
</NcButton> </NcButton>
</template> </template>

View File

@@ -5,13 +5,13 @@
<template> <template>
<NcDialog :name="t('deck', 'Export {boardTitle}', {boardTitle: boardTitle})" @update:open="close"> <NcDialog :name="t('deck', 'Export {boardTitle}', {boardTitle: boardTitle})" @update:open="close">
<div class="modal__content"> <div class="modal__content">
<NcCheckboxRadioSwitch :checked.sync="exportFormat" <NcCheckboxRadioSwitch v-model="exportFormat"
value="json" value="json"
type="radio" type="radio"
name="board_export_format"> name="board_export_format">
{{ t('deck', 'Export as JSON') }} {{ t('deck', 'Export as JSON') }}
</NcCheckboxRadioSwitch> </NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch :checked.sync="exportFormat" <NcCheckboxRadioSwitch v-model="exportFormat"
value="csv" value="csv"
type="radio" type="radio"
name="board_export_format"> name="board_export_format">
@@ -27,7 +27,7 @@
<NcButton @click="close"> <NcButton @click="close">
{{ t('deck', 'Cancel') }} {{ t('deck', 'Cancel') }}
</NcButton> </NcButton>
<NcButton type="primary" @click="exportBoard"> <NcButton variant="primary" @click="exportBoard">
{{ t('deck', 'Export') }} {{ t('deck', 'Export') }}
</NcButton> </NcButton>
</template> </template>

View File

@@ -145,7 +145,7 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import './../../css/variables'; @use './../../css/variables';
.overview-wrapper { .overview-wrapper {
position: relative; position: relative;
@@ -162,16 +162,16 @@ export default {
overflow-x: scroll; overflow-x: scroll;
display: flex; display: flex;
align-items: stretch; align-items: stretch;
padding-left: $board-spacing; padding-left: variables.$board-spacing;
padding-right: $board-spacing; padding-right: variables.$board-spacing;
.dashboard-column { .dashboard-column {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-width: $stack-width; min-width: variables.$stack-width;
width: $stack-width; width: variables.$stack-width;
margin-left: $stack-spacing; margin-left: variables.$stack-spacing;
margin-right: $stack-spacing; margin-right: variables.$stack-spacing;
h3 { h3 {
font-size: var(--default-font-size); font-size: var(--default-font-size);

View File

@@ -4,7 +4,7 @@
--> -->
<template> <template>
<div v-if="searchQuery!==''" class="global-search"> <div v-if="searchQuery !== ''" class="global-search">
<h2> <h2>
<NcRichText :text="t('deck', 'Search for {searchQuery} in all boards')" :arguments="queryStringArgs" /> <NcRichText :text="t('deck', 'Search for {searchQuery} in all boards')" :arguments="queryStringArgs" />
<div v-if="loading" class="icon-loading-small" /> <div v-if="loading" class="icon-loading-small" />
@@ -19,13 +19,13 @@
:key="card.id" :key="card.id"
:standalone="true" /> :standalone="true" />
<Placeholder v-if="loading" /> <Placeholder v-if="loading" />
<InfiniteLoading :identifier="searchQuery" @infinite="infiniteHandler"> <!-- <InfiniteLoading :identifier="searchQuery" @infinite="infiniteHandler">
<div slot="spinner" /> <div slot="spinner" />
<div slot="no-more" /> <div slot="no-more" />
<div slot="no-results"> <div slot="no-results">
{{ t('deck', 'No results found') }} {{ t('deck', 'No results found') }}
</div> </div>
</InfiniteLoading> </InfiniteLoading> -->
</div> </div>
<div v-else> <div v-else>
<p>{{ t('deck', 'No results found') }}</p> <p>{{ t('deck', 'No results found') }}</p>
@@ -39,7 +39,7 @@ import CardItem from '../cards/CardItem.vue'
import { mapState } from 'vuex' import { mapState } from 'vuex'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import InfiniteLoading from 'vue-infinite-loading' // import InfiniteLoading from 'v3-infinite-loading'
import Placeholder from './Placeholder.vue' import Placeholder from './Placeholder.vue'
import { NcActions, NcActionButton, NcRichText } from '@nextcloud/vue' import { NcActions, NcActionButton, NcRichText } from '@nextcloud/vue'
@@ -70,7 +70,14 @@ function search({ query, cursor }) {
export default { export default {
name: 'GlobalSearchResults', name: 'GlobalSearchResults',
components: { CardItem, InfiniteLoading, NcRichText, Placeholder, NcActions, NcActionButton }, components: {
CardItem,
// InfiniteLoading,
NcRichText,
Placeholder,
NcActions,
NcActionButton,
},
data() { data() {
return { return {
results: [], results: [],
@@ -155,11 +162,11 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '../../css/variables'; @use '../../css/variables';
.global-search { .global-search {
width: 100%; width: 100%;
padding: $board-spacing + $stack-spacing; padding: variables.$board-spacing + variables.$stack-spacing;
padding-bottom: 0; padding-bottom: 0;
overflow: hidden; overflow: hidden;
min-height: 35vh; min-height: 35vh;
@@ -175,6 +182,7 @@ export default {
top: 10px; top: 10px;
right: 10px; right: 10px;
} }
.search-wrapper { .search-wrapper {
overflow: scroll; overflow: scroll;
height: 100%; height: 100%;
@@ -182,13 +190,14 @@ export default {
padding: 10px; padding: 10px;
} }
h2 > div { h2>div {
display: inline-block; display: inline-block;
&.icon-loading-small { &.icon-loading-small {
margin-right: 20px; margin-right: 20px;
} }
} }
h2:deep(span) { h2:deep(span) {
background-color: var(--color-background-dark); background-color: var(--color-background-dark);
padding: 3px; padding: 3px;
@@ -199,13 +208,14 @@ export default {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
& > div { &>div {
flex-grow: 0; flex-grow: 0;
} }
} }
&:deep(.card) { &:deep(.card) {
width: $stack-width; width: variables.$stack-width;
margin-right: $stack-spacing; margin-right: variables.$stack-spacing;
} }
} }
</style> </style>

View File

@@ -58,18 +58,18 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import '../../css/variables'; @use '../../css/variables';
$clickable-area: var(--default-clickable-area); $clickable-area: var(--default-clickable-area);
.card--placeholder { .card--placeholder {
width: $stack-width; width: variables.$stack-width;
margin-right: $stack-spacing; margin-right: variables.$stack-spacing;
padding: $card-padding; padding: variables.$card-padding;
transition: box-shadow 0.1s ease-in-out; transition: box-shadow 0.1s ease-in-out;
box-shadow: 0 0 2px 0 var(--color-box-shadow); box-shadow: 0 0 2px 0 var(--color-box-shadow);
border-radius: var(--border-radius-large); border-radius: var(--border-radius-large);
font-size: 100%; font-size: 100%;
margin-bottom: $card-spacing; margin-bottom: variables.$card-spacing;
height: 100px; height: 100px;
} }

View File

@@ -3,38 +3,34 @@
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */
import Vue from 'vue'
import './../css/collections.css' import './../css/collections.css'
import FileSharingPicker from './views/FileSharingPicker.js' import FileSharingPicker from './views/FileSharingPicker.js'
import { buildSelector } from './helpers/selector.js' import { buildSelector } from './helpers/selector.js'
import './shared-init.js' import './shared-init.js'
Vue.prototype.t = t export function initCollections() {
Vue.prototype.n = n window.addEventListener('DOMContentLoaded', () => {
Vue.prototype.OC = OC if (OCA.Sharing && OCA.Sharing.ShareSearch) {
OCA.Sharing.ShareSearch.addNewResult(FileSharingPicker)
}
window.addEventListener('DOMContentLoaded', () => { window.OCP.Collaboration.registerType('deck', {
if (OCA.Sharing && OCA.Sharing.ShareSearch) { action: () => {
OCA.Sharing.ShareSearch.addNewResult(FileSharingPicker) const BoardSelector = () => import('./BoardSelector.vue')
} return buildSelector(BoardSelector)
},
typeString: t('deck', 'Link to a board'),
typeIconClass: 'icon-deck',
})
window.OCP.Collaboration.registerType('deck', { window.OCP.Collaboration.registerType('deck-card', {
action: () => { action: () => {
const BoardSelector = () => import('./BoardSelector.vue') const CardSelector = () => import('./CardSelector.vue')
return buildSelector(BoardSelector) return buildSelector(CardSelector)
}, },
typeString: t('deck', 'Link to a board'), typeString: t('deck', 'Link to a card'),
typeIconClass: 'icon-deck', typeIconClass: 'icon-deck',
})
}) })
}
window.OCP.Collaboration.registerType('deck-card', {
action: () => {
const CardSelector = () => import('./CardSelector.vue')
return buildSelector(CardSelector)
},
typeString: t('deck', 'Link to a card'),
typeIconClass: 'icon-deck',
})
})

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */
import { registerWidget, registerCustomPickerElement, NcCustomPickerRenderResult } from '@nextcloud/vue/dist/Functions/registerReference.js' import { registerWidget, registerCustomPickerElement, NcCustomPickerRenderResult } from '@nextcloud/vue'
import { translate, translatePlural } from '@nextcloud/l10n' import { translate, translatePlural } from '@nextcloud/l10n'
import './shared-init.js' import './shared-init.js'

View File

@@ -2,11 +2,10 @@
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */
import Vue from 'vue' import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import router from './router.js' import router from './router.js'
import store from './store/main.js' import store from './store/main.js'
import { sync } from 'vuex-router-sync'
import { translate, translatePlural } from '@nextcloud/l10n' import { translate, translatePlural } from '@nextcloud/l10n'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import { subscribe } from '@nextcloud/event-bus' import { subscribe } from '@nextcloud/event-bus'
@@ -14,27 +13,33 @@ import ClickOutside from 'vue-click-outside'
import './shared-init.js' import './shared-init.js'
import './models/index.js' import './models/index.js'
import './sessions.js' import './sessions.js'
import { initCollections } from './init-collections.js'
// the server snap.js conflicts with vertical scrolling so we disable it // the server snap.js conflicts with vertical scrolling so we disable it
document.body.setAttribute('data-snap-ignore', 'true') document.body.setAttribute('data-snap-ignore', 'true')
sync(store, router) const app = createApp(App)
Vue.prototype.t = translate app.config.globalProperties.t = translate
Vue.prototype.n = translatePlural app.config.globalProperties.n = translatePlural
app.config.globalProperties.OC = OC
Vue.directive('click-outside', ClickOutside) initCollections({ t, n, OC })
Vue.directive('focus', { app.directive('click-outside', ClickOutside)
inserted(el) {
app.directive('focus', {
mounted(el) {
el.focus() el.focus()
}, },
}) })
Vue.config.errorHandler = (err, vm, info) => { app.config.errorHandler = (err, vm, info) => {
if (err.response && err.response.data.message) { if (err.response && err.response.data.message) {
const errorMessage = t('deck', 'Something went wrong') const errorMessage = translate('deck', 'Something went wrong')
showError(`${errorMessage}: ${err.response.data.status} ${err.response.data.message}`) showError(
`${errorMessage}: ${err.response.data.status} ${err.response.data.message}`,
)
} }
console.error(err) console.error(err)
} }
@@ -47,16 +52,14 @@ window.addEventListener('DOMContentLoaded', () => {
window.OCA.Files = {} window.OCA.Files = {}
} }
// register unused client for the sidebar to have access to its parser methods // register unused client for the sidebar to have access to its parser methods
Object.assign(window.OCA.Files, { App: { fileList: { filesClient: OC.Files.getClient() } } }, window.OCA.Files) Object.assign(
window.OCA.Files,
{ App: { fileList: { filesClient: OC.Files.getClient() } } },
window.OCA.Files,
)
}) })
/* eslint-disable-next-line no-new */ app.mixin({
new Vue({
el: '#content',
// eslint-disable-next-line vue/match-component-file-name
name: 'Deck',
router,
store,
data() { data() {
return { return {
time: Date.now(), time: Date.now(),
@@ -75,7 +78,7 @@ new Vue({
this.time = Date.now() this.time = Date.now()
}, 1000) }, 1000)
}, },
beforeDestroy() { beforeUnmount() {
clearInterval(this.interval) clearInterval(this.interval)
}, },
methods: { methods: {
@@ -86,9 +89,12 @@ new Vue({
this.$store.commit('setSearchQuery', '') this.$store.commit('setSearchQuery', '')
}, },
}, },
render: h => h(App),
}) })
app.use(router)
app.use(store)
app.mount('#content')
if (!window.OCA.Deck) { if (!window.OCA.Deck) {
window.OCA.Deck = {} window.OCA.Deck = {}
} }

View File

@@ -26,7 +26,8 @@ export default {
return return
} }
this.$set(this.uploadQueue, file.name, { name: file.name, progress: 0 }) this.uploadQueue[file.name] = { name: file.name, progress: 0 }
const bodyFormData = new FormData() const bodyFormData = new FormData()
bodyFormData.append('cardId', this.cardId) bodyFormData.append('cardId', this.cardId)
bodyFormData.append('type', type) bodyFormData.append('type', type)
@@ -39,7 +40,7 @@ export default {
onUploadProgress: (e) => { onUploadProgress: (e) => {
const percentCompleted = Math.round((e.loaded * 100) / e.total) const percentCompleted = Math.round((e.loaded * 100) / e.total)
console.debug(percentCompleted) console.debug(percentCompleted)
this.$set(this.uploadQueue[file.name], 'progress', percentCompleted) this.uploadQueue[file.name].progress = percentCompleted
}, },
}) })
} catch (err) { } catch (err) {
@@ -50,7 +51,7 @@ export default {
showError(err.response.data ? err.response.data.message : 'Failed to upload file') showError(err.response.data ? err.response.data.message : 'Failed to upload file')
} }
} }
this.$delete(this.uploadQueue, file.name) delete this.uploadQueue[file.name]
}) })
}, },

View File

@@ -3,8 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */
import Vue from 'vue' import { createRouter, createWebHistory } from 'vue-router'
import Router from 'vue-router'
import { generateUrl, getRootUrl } from '@nextcloud/router' import { generateUrl, getRootUrl } from '@nextcloud/router'
import { BOARD_FILTERS } from './store/main.js' import { BOARD_FILTERS } from './store/main.js'
import Boards from './components/boards/Boards.vue' import Boards from './components/boards/Boards.vue'
@@ -14,17 +13,14 @@ import BoardSidebar from './components/board/BoardSidebar.vue'
import CardSidebar from './components/card/CardSidebar.vue' import CardSidebar from './components/card/CardSidebar.vue'
import Overview from './components/overview/Overview.vue' import Overview from './components/overview/Overview.vue'
Vue.use(Router)
// We apply a dynamic base URL depending on the URL used in the browser // We apply a dynamic base URL depending on the URL used in the browser
const baseUrl = generateUrl('/apps/deck/') const baseUrl = generateUrl('/apps/deck/')
const webRootWithIndexPHP = getRootUrl() + '/index.php' const webRootWithIndexPHP = getRootUrl() + '/index.php'
const doesURLContainIndexPHP = window.location.pathname.startsWith(webRootWithIndexPHP) const doesURLContainIndexPHP = window.location.pathname.startsWith(webRootWithIndexPHP)
const currentBaseUrl = doesURLContainIndexPHP ? baseUrl : baseUrl.replace('/index.php/', '/') const currentBaseUrl = doesURLContainIndexPHP ? baseUrl : baseUrl.replace('/index.php/', '/')
const router = new Router({ const router = createRouter({
mode: 'history', history: createWebHistory(currentBaseUrl),
base: currentBaseUrl,
linkActiveClass: 'active', linkActiveClass: 'active',
routes: [ routes: [
{ {

View File

@@ -4,7 +4,6 @@
*/ */
import { AttachmentApi } from './../services/AttachmentApi.js' import { AttachmentApi } from './../services/AttachmentApi.js'
import Vue from 'vue'
const apiClient = new AttachmentApi() const apiClient = new AttachmentApi()
@@ -24,20 +23,20 @@ export default {
mutations: { mutations: {
createAttachment(state, { cardId, attachment }) { createAttachment(state, { cardId, attachment }) {
if (typeof state.attachments[cardId] === 'undefined') { if (typeof state.attachments[cardId] === 'undefined') {
Vue.set(state.attachments, cardId, [attachment]) state.attachments[cardId] = [attachment]
} else { } else {
state.attachments[cardId].push(attachment) state.attachments[cardId].push(attachment)
} }
}, },
createAttachments(state, { cardId, attachments }) { createAttachments(state, { cardId, attachments }) {
Vue.set(state.attachments, cardId, attachments) state.attachments[cardId] = attachments
}, },
updateAttachment(state, { cardId, attachment }) { updateAttachment(state, { cardId, attachment }) {
const existingIndex = state.attachments[attachment.cardId].findIndex(a => a.id === attachment.id && a.type === attachment.type) const existingIndex = state.attachments[attachment.cardId].findIndex(a => a.id === attachment.id && a.type === attachment.type)
if (existingIndex !== -1) { if (existingIndex !== -1) {
Vue.set(state.attachments[cardId], existingIndex, attachment) state.attachments[cardId][existingIndex] = attachment
} }
}, },

View File

@@ -5,7 +5,6 @@
import { CardApi } from './../services/CardApi.js' import { CardApi } from './../services/CardApi.js'
import moment from 'moment' import moment from 'moment'
import Vue from 'vue'
const apiClient = new CardApi() const apiClient = new CardApi()
@@ -190,7 +189,7 @@ export default {
const existingIndex = state.cards.findIndex(_card => _card.id === card.id) const existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) { if (existingIndex !== -1) {
const existingCard = state.cards.find(_card => _card.id === card.id) const existingCard = state.cards.find(_card => _card.id === card.id)
Vue.set(state.cards, existingIndex, Object.assign({}, existingCard, card)) state.cards[existingIndex] = { ...existingCard, ...card }
} else { } else {
state.cards.push(card) state.cards.push(card)
} }
@@ -204,15 +203,15 @@ export default {
updateCard(state, card) { updateCard(state, card) {
const existingIndex = state.cards.findIndex(_card => _card.id === card.id) const existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) { if (existingIndex !== -1) {
Vue.set(state.cards, existingIndex, Object.assign({}, state.cards[existingIndex], card)) state.cards[existingIndex] = { ...state.cards[existingIndex], ...card }
} }
}, },
updateCardsReorder(state, cards) { updateCardsReorder(state, cards) {
for (const newCard of cards) { for (const newCard of cards) {
const existingIndex = state.cards.findIndex(_card => _card.id === newCard.id) const existingIndex = state.cards.findIndex(_card => _card.id === newCard.id)
if (existingIndex !== -1) { if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], 'order', newCard.order) state.cards[existingIndex].order = newCard.order
Vue.set(state.cards[existingIndex], 'stackId', newCard.stackId) state.cards[existingIndex].stackId = newCard.stackId
} }
} }
}, },
@@ -234,26 +233,26 @@ export default {
updateCardProperty(state, { card, property }) { updateCardProperty(state, { card, property }) {
const existingIndex = state.cards.findIndex(_card => _card.id === card.id) const existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) { if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], property, card[property]) state.cards[existingIndex][property] = card[property]
Vue.set(state.cards[existingIndex], 'lastModified', Date.now() / 1000) state.cards[existingIndex].lastModifiedBy = Date.now() / 1000
} }
}, },
cardSetAttachmentCount(state, { cardId, count }) { cardSetAttachmentCount(state, { cardId, count }) {
const existingIndex = state.cards.findIndex(_card => _card.id === cardId) const existingIndex = state.cards.findIndex(_card => _card.id === cardId)
if (existingIndex !== -1) { if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], 'attachmentCount', count) state.cards[existingIndex].attachmentCount = count
} }
}, },
cardIncreaseAttachmentCount(state, cardId) { cardIncreaseAttachmentCount(state, cardId) {
const existingIndex = state.cards.findIndex(_card => _card.id === cardId) const existingIndex = state.cards.findIndex(_card => _card.id === cardId)
if (existingIndex !== -1) { if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], 'attachmentCount', state.cards[existingIndex].attachmentCount + 1) state.cards[existingIndex].attachmentCount = state.cards[existingIndex].attachmentCount + 1
} }
}, },
cardDecreaseAttachmentCount(state, cardId) { cardDecreaseAttachmentCount(state, cardId) {
const existingIndex = state.cards.findIndex(_card => _card.id === cardId) const existingIndex = state.cards.findIndex(_card => _card.id === cardId)
if (existingIndex !== -1) { if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], 'attachmentCount', state.cards[existingIndex].attachmentCount - 1) state.cards[existingIndex].attachmentCount = state.cards[existingIndex].attachmentCount - 1
} }
}, },
addNewCard(state, card) { addNewCard(state, card) {

View File

@@ -4,7 +4,6 @@
*/ */
import { CommentApi } from '../services/CommentApi.js' import { CommentApi } from '../services/CommentApi.js'
import Vue from 'vue'
const apiClient = new CommentApi() const apiClient = new CommentApi()
@@ -34,10 +33,10 @@ export default {
}, },
addComments(state, { comments, cardId }) { addComments(state, { comments, cardId }) {
if (state.comments[cardId] === undefined) { if (state.comments[cardId] === undefined) {
Vue.set(state.comments, cardId, { state.comments[cardId] = {
hasMore: comments.length > 0, hasMore: comments.length >= 0,
comments: [...comments], comments: [...comments],
}) }
} else { } else {
const newComments = comments.filter((comment) => { const newComments = comments.filter((comment) => {
return state.comments[cardId].comments.findIndex((item) => item.id === comment.id) === -1 return state.comments[cardId].comments.findIndex((item) => item.id === comment.id) === -1
@@ -59,11 +58,11 @@ export default {
}, },
markCommentsAsRead(state, cardId) { markCommentsAsRead(state, cardId) {
state.comments[cardId].comments.forEach(_comment => { state.comments[cardId].comments.forEach(_comment => {
Vue.set(_comment, 'isUnread', false) _comment.isUnread = false
}) })
}, },
setReplyTo(state, comment) { setReplyTo(state, comment) {
Vue.set(state, 'replyTo', comment) state.replyTo = comment
}, },
}, },
actions: { actions: {

View File

@@ -6,8 +6,7 @@
import 'url-search-params-polyfill' import 'url-search-params-polyfill'
import { loadState } from '@nextcloud/initial-state' import { loadState } from '@nextcloud/initial-state'
import Vue from 'vue' import { createStore } from 'vuex'
import Vuex from 'vuex'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import { generateOcsUrl, generateUrl } from '@nextcloud/router' import { generateOcsUrl, generateUrl } from '@nextcloud/router'
import { BoardApi } from '../services/BoardApi.js' import { BoardApi } from '../services/BoardApi.js'
@@ -18,7 +17,6 @@ import comment from './comment.js'
import trashbin from './trashbin.js' import trashbin from './trashbin.js'
import attachment from './attachment.js' import attachment from './attachment.js'
import overview from './overview.js' import overview from './overview.js'
Vue.use(Vuex)
const apiClient = new BoardApi() const apiClient = new BoardApi()
const debug = process.env.NODE_ENV !== 'production' const debug = process.env.NODE_ENV !== 'production'
@@ -29,7 +27,7 @@ export const BOARD_FILTERS = {
SHARED: 'shared', SHARED: 'shared',
} }
export default new Vuex.Store({ const store = createStore({
modules: { modules: {
actions, actions,
stack, stack,
@@ -130,10 +128,10 @@ export default new Vuex.Store({
}, },
mutations: { mutations: {
setFullApp(state, isFullApp) { setFullApp(state, isFullApp) {
Vue.set(state, 'isFullApp', isFullApp) state.isFullApp = isFullApp
}, },
setHasCardSaveError(state, hasCardSaveError) { setHasCardSaveError(state, hasCardSaveError) {
Vue.set(state, 'hasCardSaveError', hasCardSaveError) state.hasCardSaveError = hasCardSaveError
}, },
SET_CONFIG(state, { key, value }) { SET_CONFIG(state, { key, value }) {
const [scope, id, configKey] = key.split(':', 3) const [scope, id, configKey] = key.split(':', 3)
@@ -145,11 +143,11 @@ export default new Vuex.Store({
}) })
if (indexExisting > -1) { if (indexExisting > -1) {
Vue.set(state.boards[indexExisting].settings, configKey, value) state.boards[indexExisting].settings[configKey] = value
} }
break break
default: default:
Vue.set(state.config, key, value) state.config[key] = value
} }
}, },
setSearchQuery(state, searchQuery) { setSearchQuery(state, searchQuery) {
@@ -162,7 +160,7 @@ export default new Vuex.Store({
Object.keys(filter).forEach((key) => { Object.keys(filter).forEach((key) => {
switch (key) { switch (key) {
case 'due': case 'due':
Vue.set(state.filter, key, filter.due) state.filter[key] = filter.due
break break
default: default:
filter[key].forEach((item) => { filter[key].forEach((item) => {
@@ -189,7 +187,7 @@ export default new Vuex.Store({
}) })
if (indexExisting > -1) { if (indexExisting > -1) {
Vue.set(state.boards, indexExisting, board) state.boards[indexExisting] = board
} else { } else {
state.boards.push(board) state.boards.push(board)
} }
@@ -201,7 +199,7 @@ export default new Vuex.Store({
}) })
if (indexExisting > -1) { if (indexExisting > -1) {
Vue.set(state.boards, indexExisting, board) state.boards[indexExisting] = board
} else { } else {
state.boards.push(board) state.boards.push(board)
} }
@@ -234,7 +232,7 @@ export default new Vuex.Store({
state.boards = boards state.boards = boards
}, },
setSharees(state, shareesUsersAndGroups) { setSharees(state, shareesUsersAndGroups) {
Vue.set(state, 'sharees', shareesUsersAndGroups.exact.users) state.sharees = shareesUsersAndGroups.exact.users
state.sharees.push(...shareesUsersAndGroups.exact.groups) state.sharees.push(...shareesUsersAndGroups.exact.groups)
state.sharees.push(...shareesUsersAndGroups.exact.circles) state.sharees.push(...shareesUsersAndGroups.exact.circles)
@@ -284,7 +282,7 @@ export default new Vuex.Store({
updateAclFromCurrentBoard(state, acl) { updateAclFromCurrentBoard(state, acl) {
for (const acl_ in state.currentBoard.acl) { for (const acl_ in state.currentBoard.acl) {
if (state.currentBoard.acl[acl_].participant.uid === acl.participant.uid) { if (state.currentBoard.acl[acl_].participant.uid === acl.participant.uid) {
Vue.set(state.currentBoard.acl, acl_, acl) state.currentBoard.acl[acl_] = acl
break break
} }
} }
@@ -300,7 +298,7 @@ export default new Vuex.Store({
} }
if (removeIndex > -1) { if (removeIndex > -1) {
Vue.delete(state.currentBoard.acl, removeIndex) state.currentBoard.acl.splice(removeIndex, 1)
} }
}, },
TOGGLE_SHORTCUT_LOCK(state, lock) { TOGGLE_SHORTCUT_LOCK(state, lock) {
@@ -531,3 +529,5 @@ export default new Vuex.Store({
}, },
}, },
}) })
export default store

View File

@@ -3,10 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */
import Vue from 'vue'
import Vuex from 'vuex'
import { OverviewApi } from '../services/OverviewApi.js' import { OverviewApi } from '../services/OverviewApi.js'
Vue.use(Vuex)
const apiClient = new OverviewApi() const apiClient = new OverviewApi()
export default { export default {

View File

@@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */
import Vue from 'vue'
import { StackApi } from './../services/StackApi.js' import { StackApi } from './../services/StackApi.js'
import applyOrderToArray from './../helpers/applyOrderToArray.js' import applyOrderToArray from './../helpers/applyOrderToArray.js'
@@ -26,7 +25,7 @@ export default {
const existingIndex = state.stacks.findIndex(_stack => _stack.id === stack.id) const existingIndex = state.stacks.findIndex(_stack => _stack.id === stack.id)
if (existingIndex !== -1) { if (existingIndex !== -1) {
const existingStack = state.stacks.find(_stack => _stack.id === stack.id) const existingStack = state.stacks.find(_stack => _stack.id === stack.id)
Vue.set(state.stacks, existingIndex, Object.assign({}, existingStack, stack)) state.stacks[existingIndex] = { ...existingStack, ...stack }
} else { } else {
state.stacks.push(stack) state.stacks.push(stack)
} }

View File

@@ -33,7 +33,7 @@ import DeckIcon from '../components/icons/DeckIcon.vue'
import { BoardApi } from './../services/BoardApi.js' import { BoardApi } from './../services/BoardApi.js'
import store from './../store/main.js' import store from './../store/main.js'
import NcUserBubble from '@nextcloud/vue/dist/Components/NcUserBubble.js' import { NcUserBubble } from '@nextcloud/vue'
import moment from '@nextcloud/moment' import moment from '@nextcloud/moment'
import { generateUrl } from '@nextcloud/router' import { generateUrl } from '@nextcloud/router'

View File

@@ -66,7 +66,7 @@
</template> </template>
<script> <script>
import CalendarBlankIcon from 'vue-material-design-icons/CalendarBlankOutline.vue' import CalendarBlankIcon from 'vue-material-design-icons/CalendarBlank.vue'
import TextIcon from 'vue-material-design-icons/Text.vue' import TextIcon from 'vue-material-design-icons/Text.vue'
import CardBulletedOutlineIcon from 'vue-material-design-icons/CardBulletedOutline.vue' import CardBulletedOutlineIcon from 'vue-material-design-icons/CardBulletedOutline.vue'

View File

@@ -78,7 +78,7 @@
</template> </template>
<script> <script>
import CalendarBlankIcon from 'vue-material-design-icons/CalendarBlankOutline.vue' import CalendarBlankIcon from 'vue-material-design-icons/CalendarBlank.vue'
import TextIcon from 'vue-material-design-icons/Text.vue' import TextIcon from 'vue-material-design-icons/Text.vue'
import CardBulletedOutlineIcon from 'vue-material-design-icons/CardBulletedOutline.vue' import CardBulletedOutlineIcon from 'vue-material-design-icons/CardBulletedOutline.vue'
import CommentProcessingOutlineIcon from 'vue-material-design-icons/CommentProcessingOutline.vue' import CommentProcessingOutlineIcon from 'vue-material-design-icons/CommentProcessingOutline.vue'

View File

@@ -82,7 +82,7 @@
{{ t('deck', 'Cancel') }} {{ t('deck', 'Cancel') }}
</NcButton> </NcButton>
<NcButton :disabled="loading || !isBoardAndStackChoosen" <NcButton :disabled="loading || !isBoardAndStackChoosen"
type="primary" variant="primary"
@click="createCard"> @click="createCard">
{{ t('deck', 'Create card') }} {{ t('deck', 'Create card') }}
</NcButton> </NcButton>
@@ -212,8 +212,8 @@ export default {
}, },
}, },
beforeMount() { beforeMount() {
this.$set(this.card, 'title', this.title) this.card.title = this.title
this.$set(this.card, 'description', this.description) this.card.description = this.description
this.fetchBoards() this.fetchBoards()
}, },
mounted() { mounted() {
@@ -276,11 +276,10 @@ export default {
} }
}, },
onSelectLabel(label) { onSelectLabel(label) {
if (!label.id) return
this.card.labels.push(label) this.card.labels.push(label)
}, },
onRemoveLabel(removedLabel) { onRemoveLabel(removedLabel) {
this.card.labels = this.card.labels.filter(label => label.id !== removedLabel.id) this.card.labels = this.card.label.filter(label => label.id !== removedLabel.id)
}, },
onSelectUser(user) { onSelectUser(user) {
this.card.assignedUsers.push(user) this.card.assignedUsers.push(user)

View File

@@ -1 +1 @@
81373 81091

View File

@@ -1,7 +1,7 @@
{ {
"require-dev": { "require-dev": {
"phpunit/phpunit": "~9", "phpunit/phpunit": "~9",
"behat/behat": "~3.23.0", "behat/behat": "~3.21.1",
"guzzlehttp/guzzle": "7.9.2", "guzzlehttp/guzzle": "7.9.2",
"jarnaiz/behat-junit-formatter": "^1.3", "jarnaiz/behat-junit-formatter": "^1.3",
"sabre/dav": "4.7.0", "sabre/dav": "4.7.0",

View File

@@ -475,6 +475,9 @@ class CardServiceTest extends TestCase {
$label->setBoardId(1); $label->setBoardId(1);
$this->cardMapper->expects($this->once())->method('find')->willReturn($card); $this->cardMapper->expects($this->once())->method('find')->willReturn($card);
$this->cardMapper->expects($this->once())->method('removeLabel'); $this->cardMapper->expects($this->once())->method('removeLabel');
$this->cardMapper->expects($this->once())
->method('findBoardId')
->willReturn(1);
$this->labelMapper->expects($this->once()) $this->labelMapper->expects($this->once())
->method('find') ->method('find')
->willReturn($label); ->willReturn($label);

View File

@@ -347,8 +347,9 @@ class PermissionServiceTest extends \Test\TestCase {
->method('__call') ->method('__call')
->with('getOwner', []) ->with('getOwner', [])
->willReturn('user1'); ->willReturn('user1');
$board->expects($this->any()) $this->aclMapper->expects($this->once())
->method('getAcl') ->method('findAll')
->with(123)
->willReturn([$aclUser, $aclGroup]); ->willReturn([$aclUser, $aclGroup]);
$this->boardMapper->expects($this->once()) $this->boardMapper->expects($this->once())
->method('find') ->method('find')

View File

@@ -7,7 +7,7 @@ const isDevServer = process.env.WEBPACK_SERVE
webpackConfig.entry = { webpackConfig.entry = {
...webpackConfig.entry, ...webpackConfig.entry,
collections: path.join(__dirname, 'src', 'init-collections.js'), // collections: path.join(__dirname, 'src', 'init-collections.js'),
dashboard: path.join(__dirname, 'src', 'init-dashboard.js'), dashboard: path.join(__dirname, 'src', 'init-dashboard.js'),
calendar: path.join(__dirname, 'src', 'init-calendar.js'), calendar: path.join(__dirname, 'src', 'init-calendar.js'),
talk: path.join(__dirname, 'src', 'init-talk.js'), talk: path.join(__dirname, 'src', 'init-talk.js'),
@@ -22,6 +22,9 @@ if (isDevServer) {
}) })
) )
} else { } else {
webpackConfig.output.clean = {
keep: /\webpack-stats\.json$/,
}
webpackConfig.stats = { webpackConfig.stats = {
context: path.resolve(__dirname, 'src'), context: path.resolve(__dirname, 'src'),
assets: true, assets: true,
@@ -30,7 +33,5 @@ if (isDevServer) {
modules: true, modules: true,
} }
} }
// Workaround for https://github.com/nextcloud/webpack-vue-config/pull/432 causing problems with nextcloud-vue-collections
webpackConfig.resolve.alias = {}
module.exports = webpackConfig module.exports = webpackConfig