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 }}
- name: Attach tarball to github release
uses: svenstaro/upload-release-action@81c65b7cd4de9b2570615ce3aad67a41de5b1a13 # v2
uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # v2
id: attach_to_release
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}

View File

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

View File

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

View File

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

20
composer.lock generated
View File

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

View File

@@ -84,7 +84,7 @@ describe('Card', function () {
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('.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.reload()
@@ -187,7 +187,7 @@ describe('Card', function () {
cy.get('.file-picker__main').should('be.visible')
cy.get('.file-picker__main [data-filename="welcome.txt"]', { timeout: 30000 }).should('be.visible')
.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 .extension').contains('txt')
})
@@ -302,11 +302,10 @@ describe('Card', function () {
.first().click()
cy.get(`.card:contains("${newCardTitle}")`).should('be.visible').click()
// Add delay to ensure the events are bound
cy.wait(1000)
cy.get('#app-sidebar-vue [data-test="tag-selector"] .vs__dropdown-toggle').should('be.visible').click()
cy.get('#app-sidebar-vue [data-test="tag-selector"] .vs__dropdown-toggle .vs__actions').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__selected .tag:contains("Action needed")').should('be.visible')

View File

@@ -27,7 +27,7 @@ describe('Deck dashboard', function() {
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 + ')')
.first()
.contains(defaultBoard)

View File

@@ -93,7 +93,7 @@ Cypress.Commands.add('createExampleBoard', ({ user, board }) => {
})
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('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.get('[aria-label="Open details"]').click()
cy.get('.app-sidebar').should('be.visible')
// Add delay to ensure the events are bound
cy.wait(1000)
cy.get('.select input').click().type(`${query}`)
cy.get('.select input').type(`${query}`)
cy.wait('@fetchRecipients', { timeout: 7000 })
cy.get('.vs__dropdown-menu .option').first().contains(query)

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}",
"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}",
"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}",
"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}",
"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}",
@@ -81,14 +81,10 @@ OC.L10N.register(
"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",
"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 tomorrow" : "Tarjetas que vencen mañana",
"Upcoming cards" : "Próximas tarjetas",
"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.",
"{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.",
@@ -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.",
"{user} has shared {deck-board} with you." : "{user} ha compartido {deck-board} contigo.",
"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",
"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",
@@ -111,25 +107,17 @@ OC.L10N.register(
"Action needed" : "Acción necesaria",
"Later" : "Después",
"copy" : "copiar",
"Read more inside" : "Lea más, adentro",
"Custom lists - click to rename!" : "Listas personalizadas - ¡Haga clic para renombrar!",
"To Do" : "Por hacer",
"In Progress" : "En progreso",
"Done" : "Hecho",
"1. Open to learn more about boards and cards" : "1. Abra aquí para aprender más sobre los tableros y las tarjetas",
"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.",
"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.",
"Attachments" : "Adjuntos",
"File" : "Archivo",
"date" : "fecha",
"Card not found" : "Tarjeta no encontrada",
"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",
"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",
"Card details" : "Detalles de la tarjeta",
"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",
"Show archived cards" : "Mostrar tarjetas archivadas",
"Toggle compact mode" : "Mostrar/ocultar modo compacto",
"Hide card cover images" : "Ocultar la imagen de portada de las tarjetas",
"Show card cover images" : "Mostrar 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 principal de las tarjetas",
"Open details" : "Abrir detalles",
"Details" : "Detalles",
"Currently present people" : "Personas presentes actualmente",
@@ -193,11 +181,11 @@ OC.L10N.register(
"Undo" : "Deshacer",
"Deleted cards" : "Cartas eliminadas",
"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}?",
"Transfer the board." : "Transfiera el tablero.",
"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." : "Transfiere el tablero.",
"Transfer" : "Transferir",
"The board has been transferred to {user}" : "El tablero ha sido transferido a {user}",
"Failed to transfer the board to {user}" : "Fallo al transferir el tablero a {user}",
"The board has been transferred to {user}" : "El tablero ha sido transferido a {usuario}",
"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 …",
"Searching for users, groups and teams …" : "Buscando usuarios, grupos y equipos …",
"No participants found" : "No se encontraron participantes",
@@ -230,7 +218,7 @@ OC.L10N.register(
"Invalid path selected" : "Ruta seleccionada no válida",
"Upload new files" : "Subir nuevos archivos",
"Share from Files" : "Compartir desde Archivos",
"Pending share" : "Recurso compartido pendiente",
"Pending share" : "Pendiente de compartir",
"Add this attachment" : "Añadir este adjunto",
"Show in Files" : "Mostrar en Archivos",
"Download" : "Descargar",
@@ -240,7 +228,6 @@ OC.L10N.register(
"Modified" : "Modificado",
"Created" : "Creado",
"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 bigger view" : "Abrir en vista más grande",
"Comments" : "Comentarios",
@@ -255,7 +242,6 @@ OC.L10N.register(
"Reply" : "Responder",
"Update" : "Actualizar",
"Write a description …" : "Escribe una descripción...",
"Could not save description" : "No se pudo guardar la descripción",
"Description" : "Descripción",
"(Unsaved)" : "(Sin salvar)",
"(Saving…)" : "(Guardando...)",
@@ -273,12 +259,12 @@ OC.L10N.register(
"Set due date for this weekend" : "Establecer este fin de semana como fecha de vencimiento",
"Next week {timeLocale}" : "Próxima semana {timeLocale}",
"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",
"Add due date" : "Añadir fecha de vencimiento",
"Choose a date" : "Elija una fecha",
"Remove due date" : "Eliminar fecha límite",
"Mark as done" : "Marcar como completado",
"Mark as done" : "Marcar como hecho",
"Due at:" : "Vence el:",
"Not done" : "No está finalizado",
"Unarchive card" : "Desarchivar tarjeta",
@@ -342,7 +328,6 @@ OC.L10N.register(
"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.",
"Delete the board?" : "¿Borrar el tablero?",
"Exporting board..." : "Exportando tablero...",
"Board details" : "Detalles del tablero",
"Edit board" : "Editar tablero",
"Clone board" : "Clonar tablero",
@@ -355,22 +340,16 @@ OC.L10N.register(
"Assigned cards" : "Tarjetas asignadas",
"No notifications" : "No hay notificaciones",
"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 cards" : "Clonar tarjetas",
"Clone assignments" : "Clonar asignaciones",
"Clone labels" : "Clonar etiquetas",
"Clone due dates" : "Clonar fechas de vencimiento",
"Clone due dates" : "Clonar fechas límite",
"Advanced options" : "Opciones avanzadas",
"Move all cards to the first list" : "Mover todas las tarjetas a la primera lista",
"Restore archived cards" : "Restaurar tarjetas archivadas",
"Clone" : "Clonar",
"Export {boardTitle}" : "Exportar {boardTitle}",
"Export as JSON" : "Exportar como JSON",
"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",
"Loading filtered view" : "Cargando vista filtrada",
"Today" : "Hoy",
@@ -378,17 +357,17 @@ OC.L10N.register(
"No due" : "Sin finalizar",
"Search for {searchQuery} in all boards" : "Buscar {searchQuery} en todos los tableros",
"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}",
"* 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",
"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" : "* Creada en {created}\n* Ultima moficiación en {lastMod}\n* {nbAttachments} adjuntos\n* {nbComments} comentarios",
"{nbCards} cards" : "{nbCards} tarjetas",
"Due on {date}" : "Vence en {date}",
"{stack} in {board}" : "{stack} en {board}",
"Click to expand description" : "Haga clic para expandir la descripción",
"Click to expand comment" : "Haga clic para expandir el comentario",
"Click to expand description" : "Pulse para expandir la descripción",
"Click to expand comment" : "Pulse para expandir el comentario",
"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",
"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}\"",
"Open card" : "Abrir tarjeta",
"Close" : "Cerrar",
@@ -404,8 +383,7 @@ OC.L10N.register(
"Something went wrong" : "Algo ha ido mal",
"Failed to upload {name}" : "Error al subir {name}",
"Maximum file size of {size} exceeded" : "Tamaño máximo de archivo de {size} excedido",
"Assigned users" : "Usuarios asignados",
"Due date" : "Fecha de vencimiento",
"Due date" : "Fecha de fin",
"Error creating the share" : "Error creando el recurso compartido",
"Share with a Deck card" : "Compartir 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}",
"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}",
"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}",
"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}",
"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}",
@@ -79,14 +79,10 @@
"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",
"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 tomorrow" : "Tarjetas que vencen mañana",
"Upcoming cards" : "Próximas tarjetas",
"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.",
"{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.",
@@ -96,7 +92,7 @@
"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.",
"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",
"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",
@@ -109,25 +105,17 @@
"Action needed" : "Acción necesaria",
"Later" : "Después",
"copy" : "copiar",
"Read more inside" : "Lea más, adentro",
"Custom lists - click to rename!" : "Listas personalizadas - ¡Haga clic para renombrar!",
"To Do" : "Por hacer",
"In Progress" : "En progreso",
"Done" : "Hecho",
"1. Open to learn more about boards and cards" : "1. Abra aquí para aprender más sobre los tableros y las tarjetas",
"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.",
"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.",
"Attachments" : "Adjuntos",
"File" : "Archivo",
"date" : "fecha",
"Card not found" : "Tarjeta no encontrada",
"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",
"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",
"Card details" : "Detalles de la tarjeta",
"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",
"Show archived cards" : "Mostrar tarjetas archivadas",
"Toggle compact mode" : "Mostrar/ocultar modo compacto",
"Hide card cover images" : "Ocultar la imagen de portada de las tarjetas",
"Show card cover images" : "Mostrar 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 principal de las tarjetas",
"Open details" : "Abrir detalles",
"Details" : "Detalles",
"Currently present people" : "Personas presentes actualmente",
@@ -191,11 +179,11 @@
"Undo" : "Deshacer",
"Deleted cards" : "Cartas eliminadas",
"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}?",
"Transfer the board." : "Transfiera el tablero.",
"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." : "Transfiere el tablero.",
"Transfer" : "Transferir",
"The board has been transferred to {user}" : "El tablero ha sido transferido a {user}",
"Failed to transfer the board to {user}" : "Fallo al transferir el tablero a {user}",
"The board has been transferred to {user}" : "El tablero ha sido transferido a {usuario}",
"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 …",
"Searching for users, groups and teams …" : "Buscando usuarios, grupos y equipos …",
"No participants found" : "No se encontraron participantes",
@@ -228,7 +216,7 @@
"Invalid path selected" : "Ruta seleccionada no válida",
"Upload new files" : "Subir nuevos archivos",
"Share from Files" : "Compartir desde Archivos",
"Pending share" : "Recurso compartido pendiente",
"Pending share" : "Pendiente de compartir",
"Add this attachment" : "Añadir este adjunto",
"Show in Files" : "Mostrar en Archivos",
"Download" : "Descargar",
@@ -238,7 +226,6 @@
"Modified" : "Modificado",
"Created" : "Creado",
"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 bigger view" : "Abrir en vista más grande",
"Comments" : "Comentarios",
@@ -253,7 +240,6 @@
"Reply" : "Responder",
"Update" : "Actualizar",
"Write a description …" : "Escribe una descripción...",
"Could not save description" : "No se pudo guardar la descripción",
"Description" : "Descripción",
"(Unsaved)" : "(Sin salvar)",
"(Saving…)" : "(Guardando...)",
@@ -271,12 +257,12 @@
"Set due date for this weekend" : "Establecer este fin de semana como fecha de vencimiento",
"Next week {timeLocale}" : "Próxima semana {timeLocale}",
"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",
"Add due date" : "Añadir fecha de vencimiento",
"Choose a date" : "Elija una fecha",
"Remove due date" : "Eliminar fecha límite",
"Mark as done" : "Marcar como completado",
"Mark as done" : "Marcar como hecho",
"Due at:" : "Vence el:",
"Not done" : "No está finalizado",
"Unarchive card" : "Desarchivar tarjeta",
@@ -340,7 +326,6 @@
"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.",
"Delete the board?" : "¿Borrar el tablero?",
"Exporting board..." : "Exportando tablero...",
"Board details" : "Detalles del tablero",
"Edit board" : "Editar tablero",
"Clone board" : "Clonar tablero",
@@ -353,22 +338,16 @@
"Assigned cards" : "Tarjetas asignadas",
"No notifications" : "No hay notificaciones",
"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 cards" : "Clonar tarjetas",
"Clone assignments" : "Clonar asignaciones",
"Clone labels" : "Clonar etiquetas",
"Clone due dates" : "Clonar fechas de vencimiento",
"Clone due dates" : "Clonar fechas límite",
"Advanced options" : "Opciones avanzadas",
"Move all cards to the first list" : "Mover todas las tarjetas a la primera lista",
"Restore archived cards" : "Restaurar tarjetas archivadas",
"Clone" : "Clonar",
"Export {boardTitle}" : "Exportar {boardTitle}",
"Export as JSON" : "Exportar como JSON",
"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",
"Loading filtered view" : "Cargando vista filtrada",
"Today" : "Hoy",
@@ -376,17 +355,17 @@
"No due" : "Sin finalizar",
"Search for {searchQuery} in all boards" : "Buscar {searchQuery} en todos los tableros",
"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}",
"* 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",
"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" : "* Creada en {created}\n* Ultima moficiación en {lastMod}\n* {nbAttachments} adjuntos\n* {nbComments} comentarios",
"{nbCards} cards" : "{nbCards} tarjetas",
"Due on {date}" : "Vence en {date}",
"{stack} in {board}" : "{stack} en {board}",
"Click to expand description" : "Haga clic para expandir la descripción",
"Click to expand comment" : "Haga clic para expandir el comentario",
"Click to expand description" : "Pulse para expandir la descripción",
"Click to expand comment" : "Pulse para expandir el comentario",
"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",
"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}\"",
"Open card" : "Abrir tarjeta",
"Close" : "Cerrar",
@@ -402,8 +381,7 @@
"Something went wrong" : "Algo ha ido mal",
"Failed to upload {name}" : "Error al subir {name}",
"Maximum file size of {size} exceeded" : "Tamaño máximo de archivo de {size} excedido",
"Assigned users" : "Usuarios asignados",
"Due date" : "Fecha de vencimiento",
"Due date" : "Fecha de fin",
"Error creating the share" : "Error creando el recurso compartido",
"Share with a Deck card" : "Compartir 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",
"Activity" : "Actividad",
"Undo" : "Deshacer",
"Transfer" : "Transferencia",
"Can edit" : "Puede editar",
"Can share" : "Puede compartir",
"Owner" : "Dueño",
@@ -59,7 +58,6 @@ OC.L10N.register(
"Search" : "Buscar",
"Archived boards" : "Tableros archivados",
"Shared with you" : "Compartido con usted",
"Cancel edit" : "Cancelar edición",
"Board details" : "Detalles del tablero",
"Edit board" : "Editar el tablero",
"Unarchive board" : "Desarchivar tablero",

View File

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

View File

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

View File

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

View File

@@ -65,7 +65,6 @@ OC.L10N.register(
"Description" : "Apraksts",
"Select Date" : "Izvēlieties datumu",
"Later today {timeLocale}" : "Vēlāk šodien {timeLocale}",
"Set due date for later today" : "Iestatīt beigu datumu vēlāk šodienā",
"(group)" : "(grupa)",
"Open link" : "Atvērt saiti",
"seconds ago" : "pirms vairākām sekundēm",
@@ -81,8 +80,6 @@ OC.L10N.register(
"Export" : "Izgūt",
"Today" : "Šodien",
"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",
"Due date" : "Izpildes datums",
"Share" : "Koplietot",

View File

@@ -63,7 +63,6 @@
"Description" : "Apraksts",
"Select Date" : "Izvēlieties datumu",
"Later today {timeLocale}" : "Vēlāk šodien {timeLocale}",
"Set due date for later today" : "Iestatīt beigu datumu vēlāk šodienā",
"(group)" : "(grupa)",
"Open link" : "Atvērt saiti",
"seconds ago" : "pirms vairākām sekundēm",
@@ -79,8 +78,6 @@
"Export" : "Izgūt",
"Today" : "Šodien",
"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",
"Due date" : "Izpildes datums",
"Share" : "Koplietot",

View File

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

View File

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

View File

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

View File

@@ -272,7 +272,6 @@
"{count} comments, {unread} unread" : "{count} комментариев, {unread} непрочитано",
"Todo items" : "Элементы списка задач",
"Edit card title" : "Изменить заголовок карточки",
"Open link" : "Открыть ссылку",
"Card deleted" : "Карточка удалена",
"Edit title" : "Редактировать заголовок",
"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.",
"Attachments" : "Прилози",
"File" : "Фајл",
"date" : "датум",
"Card not found" : "Картица није нађена",
"Path is already shared with this card" : "Путања се већ дели са овом картицом",
"Invalid date, date format must be YYYY-MM-DD" : "Неисправан датум, формат датума мора бити ГГГГ-ММ-ДД",
@@ -240,7 +239,6 @@ OC.L10N.register(
"Modified" : "Измењен",
"Created" : "Направљен",
"The title cannot be empty." : "Наслов не може бити празан.",
"Cannot close unsaved card!" : "Не може да се затвори несачувана картица!",
"Open in sidebar view" : "Отвори у бочном прегледу",
"Open in bigger view" : "Отвори на већем приказу",
"Comments" : "Коментари",
@@ -255,7 +253,6 @@ OC.L10N.register(
"Reply" : "Одговори",
"Update" : "Ажурирај",
"Write a description …" : "Напишите опис ...",
"Could not save description" : "Не може да се сачува опис",
"Description" : "Опис",
"(Unsaved)" : "(несачуван)",
"(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.",
"Attachments" : "Прилози",
"File" : "Фајл",
"date" : "датум",
"Card not found" : "Картица није нађена",
"Path is already shared with this card" : "Путања се већ дели са овом картицом",
"Invalid date, date format must be YYYY-MM-DD" : "Неисправан датум, формат датума мора бити ГГГГ-ММ-ДД",
@@ -238,7 +237,6 @@
"Modified" : "Измењен",
"Created" : "Направљен",
"The title cannot be empty." : "Наслов не може бити празан.",
"Cannot close unsaved card!" : "Не може да се затвори несачувана картица!",
"Open in sidebar view" : "Отвори у бочном прегледу",
"Open in bigger view" : "Отвори на већем приказу",
"Comments" : "Коментари",
@@ -253,7 +251,6 @@
"Reply" : "Одговори",
"Update" : "Ажурирај",
"Write a description …" : "Напишите опис ...",
"Could not save description" : "Не може да се сачува опис",
"Description" : "Опис",
"(Unsaved)" : "(несачуван)",
"(Saving…)" : "(чувам…)",

View File

@@ -240,7 +240,6 @@ OC.L10N.register(
"Modified" : "Değiştirilme",
"Created" : "Oluşturulma",
"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 bigger view" : "Daha büyük görünümde aç",
"Comments" : "Yorumlar",
@@ -255,7 +254,6 @@ OC.L10N.register(
"Reply" : "Yanıtla",
"Update" : "Güncelle",
"Write a description …" : "Bir açıklama yazın …",
"Could not save description" : "Açıklama kaydedilemedi",
"Description" : "Açıklama",
"(Unsaved)" : "(Kaydedilmemiş)",
"(Saving…)" : "(Kaydediliyor…)",

View File

@@ -238,7 +238,6 @@
"Modified" : "Değiştirilme",
"Created" : "Oluşturulma",
"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 bigger view" : "Daha büyük görünümde aç",
"Comments" : "Yorumlar",
@@ -253,7 +252,6 @@
"Reply" : "Yanıtla",
"Update" : "Güncelle",
"Write a description …" : "Bir açıklama yazın …",
"Could not save description" : "Açıklama kaydedilemedi",
"Description" : "Açıklama",
"(Unsaved)" : "(Kaydedilmemiş)",
"(Saving…)" : "(Kaydediliyor…)",

View File

@@ -48,30 +48,8 @@ OC.L10N.register(
"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}",
"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" : "Колода",
"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 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 формі",
@@ -81,66 +59,30 @@ OC.L10N.register(
"Could not write file to disk" : "Неможливо записати файл на диск",
"A PHP extension stopped the file upload" : "Розширення PHP призупинило завантаження файлу",
"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" : "Очікують на виконання",
"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",
"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",
"Deck boards and cards" : "Колода та карти",
"No data was provided to create an attachment." : "Для створення вкладення не було надано жодних даних.",
"Finished" : "Завершено",
"To review" : "На перегляд",
"Action needed" : "Потребує дій",
"Later" : "Пізніше",
"copy" : "копіювати",
"Read more inside" : "Читайте більше всередині",
"Custom lists - click to rename!" : "Користувацькі списки - натисніть, щоб перейменувати!",
"To Do" : "Зробити",
"In Progress" : "В процесі",
"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" : "Вкладення",
"File" : "Файл",
"date" : "дата",
"Card not found" : "Картку не знайдено",
"Path is already shared with this card" : "Шлях вже є спільним з цією карткою",
"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" : "Додати дошку",
"Card details" : "Деталі картки",
"Select the board to link to a project" : "Виберіть дошку для прив'зки до проєкту",
"Search by board title" : "Шукати за назвою дошки",
"Select board" : "Вибрати дошку",
"Move/copy card" : "Картка переміщення/копіювання",
"Select a board" : "Вибрати дошку",
"No lists available" : "Списки відсутні",
"Select a list" : "Виберіть список",
"Move card" : "Пересунути картку",
"Copy card" : "Копіювальна картка",
"Select the card to link to a project" : "Виберіть картку для прив'язки до проєкту",
"Link to card" : "Прив'язати до картки",
"Select a card" : "Вибрати картку",
@@ -161,27 +103,19 @@ OC.L10N.register(
"Filter by tag" : "Відібрати за мітками",
"Filter by assigned user" : "Відібрати за призначеним користувачем",
"Unassigned" : "Скасовано призначення",
"Filter by status" : "Фільтр за статусом",
"Open and completed" : "Відкрито та завершено",
"Open" : "Відкрити",
"Completed" : "Виконано",
"Filter by due date" : "Відібрати за датою завершення",
"Overdue" : "Протерміновано",
"Next 24 hours" : "Наступні 24 години",
"Next 7 days" : "Наступні 7 днів",
"Next 30 days" : "Наступні 30 днів",
"No due date" : "Без дати завершення",
"Clear filter" : "Очистити фільтр",
"View Modes" : "Режими перегляду",
"Toggle View Modes" : "Перемикання режимів перегляду",
"Hide archived cards" : "Приховати архівні картки",
"Show archived cards" : "Показати архівні картки",
"Toggle compact mode" : "Перемкнути компактний вигляд",
"Hide card cover images" : "Приховати зображення обкладинок карток",
"Show card cover images" : "Показати зображення обкладинки картки",
"Open details" : "Показати деталі",
"Details" : "Деталі",
"Currently present people" : "Наразі присутні люди",
"Loading board" : "Завантаження дошки",
"Board not found" : "Дошку не знайдено",
"Create a new list to add cards to this board" : "Створіть список щоб додати картки на цю дошку",
@@ -192,62 +126,35 @@ OC.L10N.register(
"Deleted lists" : "Вилучені списки",
"Undo" : "Скасувати",
"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" : "Передати",
"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" : "Власник дошки",
"(Group)" : "(група)",
"(Team)" : "(Команда)",
"Can edit" : "Може редагувати",
"Can share" : "Can share",
"Can manage" : "Може керувати",
"Owner" : "Власник",
"Delete" : "Вилучити",
"List deleted" : "Список видалено",
"Edit list title" : "Редагувати заголовок списку",
"Archive all cards" : "Архівувати всі картки",
"Unarchive all cards" : "Розархівувати всі картки",
"Delete list" : "Вилучити список",
"Archive all cards in this list" : "Архівуйте всі картки в цьому списку",
"Unarchive all cards in this list" : "Розархівувати всі картки в цьому списку",
"Add a new card" : "Додати нову картку",
"Card name" : "Назва картки",
"title and color value must be provided" : "потрібно зазначити назву та колір",
"Edit" : "Редагувати",
"Add a new tag" : "Додати нову мітку",
"Board name" : "Назва дошки",
"Members" : "Учасники",
"Assign to users/groups/team" : "Призначити користувачам/групам/команді",
"Assign a user to this card…" : "Призначити користувачеві цю картку",
"Select a user to assign to this card…" : "Виберіть користувача, якого слід призначити на цю картку...",
"File to share" : "Виберіть файл для надання доступу",
"Invalid path selected" : "Вибрано неправильний шлях",
"Upload new files" : "Додати файл",
"Share from Files" : "Відкрити Файли",
"Pending share" : "Очікувана акція",
"Add this attachment" : "Долучити вкладення",
"Show in Files" : "Показати в Файлах",
"Download" : "Звантажити",
"Remove attachment" : "Зніміть вкладення",
"Delete Attachment" : "Забрати вкладення",
"Restore Attachment" : "Відновити вкладення",
"Modified" : "Змінено",
"Created" : "Створено",
"The title cannot be empty." : "Заголовок не може бути порожнім.",
"Cannot close unsaved card!" : "Неможливо закрити незбережену картку!",
"Open in sidebar view" : "Відкрити у вигляді бічної панелі",
"Open in bigger view" : "Відкрити в більшому розмірі",
"Comments" : "Коментарі",
"Failed to load comments" : "Не вдалося завантажити коментарі",
"No comments yet. Begin the discussion!" : "Коментарів немає, почніть обговорення!",
"The comment cannot be empty." : "Коментар не може бути порожнім.",
"The comment cannot be longer than 1000 characters." : "Коментар не може бути довшим за 1000 символів.",
"Save" : "Зберегти",
"Created:" : "Створено:",
"In reply to" : "У відповідь",
@@ -255,7 +162,6 @@ OC.L10N.register(
"Reply" : "Відповісти",
"Update" : "Оновлення",
"Write a description …" : "Додайте опис ...",
"Could not save description" : "Не вдалося зберегти опис",
"Description" : "Опис",
"(Unsaved)" : "(Не збережено)",
"(Saving…)" : "(Зберігання...)",
@@ -265,150 +171,73 @@ OC.L10N.register(
"Add Attachment" : "Долучити вкладення",
"Choose attachment" : "Вибрати вкладення",
"Select Date" : "Вкажіть дату",
"Later today {timeLocale}" : "Пізніше сьогодні - {timeLocale}",
"Set due date for later today" : "Встановіть термін сплати на сьогоднішній день",
"Tomorrow {timeLocale}" : "Завтра - {timeLocale}",
"Set due date for tomorrow" : "Встановіть дедлайн на завтра",
"This weekend {timeLocale}" : "На цих вихідних - {timeLocale}",
"Set due date for this weekend" : "Встановіть термін виконання на ці вихідні",
"Next week {timeLocale}" : "Наступного тижня - {timeLocale}",
"Set due date for next week" : "Встановіть термін виконання на наступний тиждень",
"Assign a due date to this card…" : "Призначте цій картці термін оплати...",
"Set a due date" : "Встановити дату завершення",
"Add due date" : "Додати термін сплати",
"Choose a date" : "Виберіть дату",
"Remove due date" : "Вилучити до",
"Mark as done" : "Позначити як виконане",
"Due at:" : "На часі:",
"Not done" : "Ще не все.",
"Unarchive card" : "Розархівувати картку",
"Archive card" : "Архівувати картку",
"Assign a tag to this card…" : "Додати мітку до цієї картки",
"Select or create a tag…" : "Виберіть або створіть тег...",
"Create a new tag:" : "Створіть новий тег:",
"(group)" : "(група)",
"{count} comments, {unread} unread" : "{count} коментарів, {unread} непрочитаних",
"Todo items" : "Пункти завдань",
"Edit card title" : "Редагувати заголовок картки",
"Open link" : "Відкрити посилання",
"Card deleted" : "Картку видалено",
"Edit title" : "Редагувати",
"Assign to me" : "Призначити мені",
"Unassign myself" : "Зняти з себе повноваження.",
"Mark as not done" : "Позначити як не виконано",
"Delete card" : "Вилучити картку",
"seconds ago" : "секунд тому",
"Keyboard shortcuts" : "Скорочення",
"Boost your productivity using Deck with keyboard shortcuts." : "Підвищуйте свою продуктивність, використовуючи Deck за допомогою комбінацій клавіш.",
"Board actions" : "Дії правління",
"Keyboard shortcut" : "Сполучення клавіш",
"Action" : "Дія ",
"Shift" : "Shift",
"Scroll" : "Прокрутка",
"Scroll sideways" : "Прокрутіть вбік",
"Navigate between cards" : "Перехід між картками",
"Esc" : "Esc",
"Close card details" : "Закрити дані картки",
"Ctrl" : "Ctrl",
"Search" : "Пошук",
"Show card filters" : "Показати фільтри карток",
"Clear card filters" : "Очистити фільтри карток",
"Show help dialog" : "Показати діалогове вікно довідки",
"Card actions" : "Дії з карткою",
"The following actions can be triggered on the currently highlighted card" : "На поточній виділеній картці можна виконати такі дії",
"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" : "Усі дошки",
"Archived boards" : "Архівні дошки",
"Shared with you" : "Вам надано доступ",
"Deck settings" : "Налаштування колоди",
"Use bigger card view" : "Режим перегляду зі збільшеними картками",
"Show card ID badge" : "Покажіть бейдж з ідентифікаційною карткою",
"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" : "Скасувати редагування",
"Save board" : "Зберегти дошку",
"Board {0} deleted" : "Дошку {0} вилучено",
"All cards" : "Всі карти",
"Only assigned cards" : "Тільки призначені картки",
"No reminder" : "Відсутні нагадування",
"An error occurred" : "Виникла помилка",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Ви впевнені, що хочете вилучити дошку {title}? Це призведе до видалення всіх даних цієї дошки, включно архівні картки.",
"Delete the board?" : "Вилучити дошку?",
"Exporting board..." : "Експортна дошка...",
"Board details" : "Деталі дошки",
"Edit board" : "Редагувати дошку",
"Clone board" : "Копіювати дошку",
"Unarchive board" : "Розархівувати дошку",
"Archive board" : "Архівувати дошку",
"Export board" : "Дошка експорту",
"Turn on due date reminders" : "Нагадування про термін виконання",
"Turn off due date reminders" : "Вимкнути нагадування про терміни виконання",
"Due date reminders" : "Нагадування про терміни виконання",
"Assigned cards" : "Призначені картки",
"No notifications" : "Немає сповіщень",
"Delete board" : "Вилучити дошку",
"Importing board..." : "Імпортна дошка...",
"Board imported successfully" : "Плату успішно імпортовано",
"Import board" : "Імпортна дошка",
"Clone {boardTitle}" : "Клон {boardTitle}",
"Clone cards" : "Копіювати картки",
"Clone assignments" : "Призначення клонів",
"Clone labels" : "Етикетки клонів",
"Clone due dates" : "Клонувати дві дати",
"Advanced options" : "Розширені налаштування",
"Move all cards to the first list" : "Перемістіть усі картки до першого списку",
"Restore archived cards" : "Відновлення заархівованих карток",
"Clone" : "Копіювати",
"Export {boardTitle}" : "Експорт {boardTitle}",
"Export as JSON" : "Експорт як JSON",
"Export as CSV" : "Експорт у CSV",
"Note: Only the JSON format is supported for importing back into the Deck app." : "Примітка: Для імпорту в додаток Deck підтримується лише формат JSON.",
"Export" : "Експортувати",
"Loading filtered view" : "Завантаження відфільтрованого перегляду",
"Today" : "Сьогодні",
"Tomorrow" : "Завтра",
"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}",
"{stack} in {board}" : "{stack} в {board}",
"Click to expand description" : "Натисніть, щоб розгорнути опис",
"Click to expand comment" : "Натисніть, щоб розгорнути коментар",
"Create card" : "Створити картку",
"Create a new card" : "Створити нову картку",
"Card title" : "Заголовок картки",
"Creating the new card …" : "Створення нової картки ...",
"Card \"{card}\" was added to \"{board}\"" : "Картку \"{card}\" додано до \"{board}\"",
"Open card" : "Відкрити картку",
"Close" : "Закрити",
"No upcoming cards" : "Немає майбутніх завдань",
"upcoming cards today" : "найближчі картки на сьогодні",
"upcoming cards tomorrow" : "найближчі картки завтра",
"upcoming cards" : "очікують на виконання",
"New card" : "Нова картка",
"Link to a board" : "Прив'язати до дошки",
"Link to a card" : "Прив'язати до картки",
"Create a card" : "Створити картку",
"Message from {author} in {conversationName}" : "Повідомлення від {author} у {conversationName}",
"Something went wrong" : "От халепа!",
"Failed to upload {name}" : "Не вдалося завантажити {name}",
"Maximum file size of {size} exceeded" : "Досягнуто максимальний розмір файлу {size}",
"Assigned users" : "Призначені користувачі",
"Due date" : "Дата виконання",
"Error creating the share" : "Помилка створення спільного доступу",
"Share with a Deck card" : "Поділіться з картою з колоди",
"Share {file} with a Deck card" : "Поділіться {file} з картою колоди",
"Share" : "Спільний доступ",
"Personal" : "Особисте",
"To do" : "Заплановано",

View File

@@ -46,30 +46,8 @@
"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}",
"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" : "Колода",
"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 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 формі",
@@ -79,66 +57,30 @@
"Could not write file to disk" : "Неможливо записати файл на диск",
"A PHP extension stopped the file upload" : "Розширення PHP призупинило завантаження файлу",
"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" : "Очікують на виконання",
"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",
"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",
"Deck boards and cards" : "Колода та карти",
"No data was provided to create an attachment." : "Для створення вкладення не було надано жодних даних.",
"Finished" : "Завершено",
"To review" : "На перегляд",
"Action needed" : "Потребує дій",
"Later" : "Пізніше",
"copy" : "копіювати",
"Read more inside" : "Читайте більше всередині",
"Custom lists - click to rename!" : "Користувацькі списки - натисніть, щоб перейменувати!",
"To Do" : "Зробити",
"In Progress" : "В процесі",
"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" : "Вкладення",
"File" : "Файл",
"date" : "дата",
"Card not found" : "Картку не знайдено",
"Path is already shared with this card" : "Шлях вже є спільним з цією карткою",
"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" : "Додати дошку",
"Card details" : "Деталі картки",
"Select the board to link to a project" : "Виберіть дошку для прив'зки до проєкту",
"Search by board title" : "Шукати за назвою дошки",
"Select board" : "Вибрати дошку",
"Move/copy card" : "Картка переміщення/копіювання",
"Select a board" : "Вибрати дошку",
"No lists available" : "Списки відсутні",
"Select a list" : "Виберіть список",
"Move card" : "Пересунути картку",
"Copy card" : "Копіювальна картка",
"Select the card to link to a project" : "Виберіть картку для прив'язки до проєкту",
"Link to card" : "Прив'язати до картки",
"Select a card" : "Вибрати картку",
@@ -159,27 +101,19 @@
"Filter by tag" : "Відібрати за мітками",
"Filter by assigned user" : "Відібрати за призначеним користувачем",
"Unassigned" : "Скасовано призначення",
"Filter by status" : "Фільтр за статусом",
"Open and completed" : "Відкрито та завершено",
"Open" : "Відкрити",
"Completed" : "Виконано",
"Filter by due date" : "Відібрати за датою завершення",
"Overdue" : "Протерміновано",
"Next 24 hours" : "Наступні 24 години",
"Next 7 days" : "Наступні 7 днів",
"Next 30 days" : "Наступні 30 днів",
"No due date" : "Без дати завершення",
"Clear filter" : "Очистити фільтр",
"View Modes" : "Режими перегляду",
"Toggle View Modes" : "Перемикання режимів перегляду",
"Hide archived cards" : "Приховати архівні картки",
"Show archived cards" : "Показати архівні картки",
"Toggle compact mode" : "Перемкнути компактний вигляд",
"Hide card cover images" : "Приховати зображення обкладинок карток",
"Show card cover images" : "Показати зображення обкладинки картки",
"Open details" : "Показати деталі",
"Details" : "Деталі",
"Currently present people" : "Наразі присутні люди",
"Loading board" : "Завантаження дошки",
"Board not found" : "Дошку не знайдено",
"Create a new list to add cards to this board" : "Створіть список щоб додати картки на цю дошку",
@@ -190,62 +124,35 @@
"Deleted lists" : "Вилучені списки",
"Undo" : "Скасувати",
"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" : "Передати",
"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" : "Власник дошки",
"(Group)" : "(група)",
"(Team)" : "(Команда)",
"Can edit" : "Може редагувати",
"Can share" : "Can share",
"Can manage" : "Може керувати",
"Owner" : "Власник",
"Delete" : "Вилучити",
"List deleted" : "Список видалено",
"Edit list title" : "Редагувати заголовок списку",
"Archive all cards" : "Архівувати всі картки",
"Unarchive all cards" : "Розархівувати всі картки",
"Delete list" : "Вилучити список",
"Archive all cards in this list" : "Архівуйте всі картки в цьому списку",
"Unarchive all cards in this list" : "Розархівувати всі картки в цьому списку",
"Add a new card" : "Додати нову картку",
"Card name" : "Назва картки",
"title and color value must be provided" : "потрібно зазначити назву та колір",
"Edit" : "Редагувати",
"Add a new tag" : "Додати нову мітку",
"Board name" : "Назва дошки",
"Members" : "Учасники",
"Assign to users/groups/team" : "Призначити користувачам/групам/команді",
"Assign a user to this card…" : "Призначити користувачеві цю картку",
"Select a user to assign to this card…" : "Виберіть користувача, якого слід призначити на цю картку...",
"File to share" : "Виберіть файл для надання доступу",
"Invalid path selected" : "Вибрано неправильний шлях",
"Upload new files" : "Додати файл",
"Share from Files" : "Відкрити Файли",
"Pending share" : "Очікувана акція",
"Add this attachment" : "Долучити вкладення",
"Show in Files" : "Показати в Файлах",
"Download" : "Звантажити",
"Remove attachment" : "Зніміть вкладення",
"Delete Attachment" : "Забрати вкладення",
"Restore Attachment" : "Відновити вкладення",
"Modified" : "Змінено",
"Created" : "Створено",
"The title cannot be empty." : "Заголовок не може бути порожнім.",
"Cannot close unsaved card!" : "Неможливо закрити незбережену картку!",
"Open in sidebar view" : "Відкрити у вигляді бічної панелі",
"Open in bigger view" : "Відкрити в більшому розмірі",
"Comments" : "Коментарі",
"Failed to load comments" : "Не вдалося завантажити коментарі",
"No comments yet. Begin the discussion!" : "Коментарів немає, почніть обговорення!",
"The comment cannot be empty." : "Коментар не може бути порожнім.",
"The comment cannot be longer than 1000 characters." : "Коментар не може бути довшим за 1000 символів.",
"Save" : "Зберегти",
"Created:" : "Створено:",
"In reply to" : "У відповідь",
@@ -253,7 +160,6 @@
"Reply" : "Відповісти",
"Update" : "Оновлення",
"Write a description …" : "Додайте опис ...",
"Could not save description" : "Не вдалося зберегти опис",
"Description" : "Опис",
"(Unsaved)" : "(Не збережено)",
"(Saving…)" : "(Зберігання...)",
@@ -263,150 +169,73 @@
"Add Attachment" : "Долучити вкладення",
"Choose attachment" : "Вибрати вкладення",
"Select Date" : "Вкажіть дату",
"Later today {timeLocale}" : "Пізніше сьогодні - {timeLocale}",
"Set due date for later today" : "Встановіть термін сплати на сьогоднішній день",
"Tomorrow {timeLocale}" : "Завтра - {timeLocale}",
"Set due date for tomorrow" : "Встановіть дедлайн на завтра",
"This weekend {timeLocale}" : "На цих вихідних - {timeLocale}",
"Set due date for this weekend" : "Встановіть термін виконання на ці вихідні",
"Next week {timeLocale}" : "Наступного тижня - {timeLocale}",
"Set due date for next week" : "Встановіть термін виконання на наступний тиждень",
"Assign a due date to this card…" : "Призначте цій картці термін оплати...",
"Set a due date" : "Встановити дату завершення",
"Add due date" : "Додати термін сплати",
"Choose a date" : "Виберіть дату",
"Remove due date" : "Вилучити до",
"Mark as done" : "Позначити як виконане",
"Due at:" : "На часі:",
"Not done" : "Ще не все.",
"Unarchive card" : "Розархівувати картку",
"Archive card" : "Архівувати картку",
"Assign a tag to this card…" : "Додати мітку до цієї картки",
"Select or create a tag…" : "Виберіть або створіть тег...",
"Create a new tag:" : "Створіть новий тег:",
"(group)" : "(група)",
"{count} comments, {unread} unread" : "{count} коментарів, {unread} непрочитаних",
"Todo items" : "Пункти завдань",
"Edit card title" : "Редагувати заголовок картки",
"Open link" : "Відкрити посилання",
"Card deleted" : "Картку видалено",
"Edit title" : "Редагувати",
"Assign to me" : "Призначити мені",
"Unassign myself" : "Зняти з себе повноваження.",
"Mark as not done" : "Позначити як не виконано",
"Delete card" : "Вилучити картку",
"seconds ago" : "секунд тому",
"Keyboard shortcuts" : "Скорочення",
"Boost your productivity using Deck with keyboard shortcuts." : "Підвищуйте свою продуктивність, використовуючи Deck за допомогою комбінацій клавіш.",
"Board actions" : "Дії правління",
"Keyboard shortcut" : "Сполучення клавіш",
"Action" : "Дія ",
"Shift" : "Shift",
"Scroll" : "Прокрутка",
"Scroll sideways" : "Прокрутіть вбік",
"Navigate between cards" : "Перехід між картками",
"Esc" : "Esc",
"Close card details" : "Закрити дані картки",
"Ctrl" : "Ctrl",
"Search" : "Пошук",
"Show card filters" : "Показати фільтри карток",
"Clear card filters" : "Очистити фільтри карток",
"Show help dialog" : "Показати діалогове вікно довідки",
"Card actions" : "Дії з карткою",
"The following actions can be triggered on the currently highlighted card" : "На поточній виділеній картці можна виконати такі дії",
"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" : "Усі дошки",
"Archived boards" : "Архівні дошки",
"Shared with you" : "Вам надано доступ",
"Deck settings" : "Налаштування колоди",
"Use bigger card view" : "Режим перегляду зі збільшеними картками",
"Show card ID badge" : "Покажіть бейдж з ідентифікаційною карткою",
"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" : "Скасувати редагування",
"Save board" : "Зберегти дошку",
"Board {0} deleted" : "Дошку {0} вилучено",
"All cards" : "Всі карти",
"Only assigned cards" : "Тільки призначені картки",
"No reminder" : "Відсутні нагадування",
"An error occurred" : "Виникла помилка",
"Are you sure you want to delete the board {title}? This will delete all the data of this board including archived cards." : "Ви впевнені, що хочете вилучити дошку {title}? Це призведе до видалення всіх даних цієї дошки, включно архівні картки.",
"Delete the board?" : "Вилучити дошку?",
"Exporting board..." : "Експортна дошка...",
"Board details" : "Деталі дошки",
"Edit board" : "Редагувати дошку",
"Clone board" : "Копіювати дошку",
"Unarchive board" : "Розархівувати дошку",
"Archive board" : "Архівувати дошку",
"Export board" : "Дошка експорту",
"Turn on due date reminders" : "Нагадування про термін виконання",
"Turn off due date reminders" : "Вимкнути нагадування про терміни виконання",
"Due date reminders" : "Нагадування про терміни виконання",
"Assigned cards" : "Призначені картки",
"No notifications" : "Немає сповіщень",
"Delete board" : "Вилучити дошку",
"Importing board..." : "Імпортна дошка...",
"Board imported successfully" : "Плату успішно імпортовано",
"Import board" : "Імпортна дошка",
"Clone {boardTitle}" : "Клон {boardTitle}",
"Clone cards" : "Копіювати картки",
"Clone assignments" : "Призначення клонів",
"Clone labels" : "Етикетки клонів",
"Clone due dates" : "Клонувати дві дати",
"Advanced options" : "Розширені налаштування",
"Move all cards to the first list" : "Перемістіть усі картки до першого списку",
"Restore archived cards" : "Відновлення заархівованих карток",
"Clone" : "Копіювати",
"Export {boardTitle}" : "Експорт {boardTitle}",
"Export as JSON" : "Експорт як JSON",
"Export as CSV" : "Експорт у CSV",
"Note: Only the JSON format is supported for importing back into the Deck app." : "Примітка: Для імпорту в додаток Deck підтримується лише формат JSON.",
"Export" : "Експортувати",
"Loading filtered view" : "Завантаження відфільтрованого перегляду",
"Today" : "Сьогодні",
"Tomorrow" : "Завтра",
"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}",
"{stack} in {board}" : "{stack} в {board}",
"Click to expand description" : "Натисніть, щоб розгорнути опис",
"Click to expand comment" : "Натисніть, щоб розгорнути коментар",
"Create card" : "Створити картку",
"Create a new card" : "Створити нову картку",
"Card title" : "Заголовок картки",
"Creating the new card …" : "Створення нової картки ...",
"Card \"{card}\" was added to \"{board}\"" : "Картку \"{card}\" додано до \"{board}\"",
"Open card" : "Відкрити картку",
"Close" : "Закрити",
"No upcoming cards" : "Немає майбутніх завдань",
"upcoming cards today" : "найближчі картки на сьогодні",
"upcoming cards tomorrow" : "найближчі картки завтра",
"upcoming cards" : "очікують на виконання",
"New card" : "Нова картка",
"Link to a board" : "Прив'язати до дошки",
"Link to a card" : "Прив'язати до картки",
"Create a card" : "Створити картку",
"Message from {author} in {conversationName}" : "Повідомлення від {author} у {conversationName}",
"Something went wrong" : "От халепа!",
"Failed to upload {name}" : "Не вдалося завантажити {name}",
"Maximum file size of {size} exceeded" : "Досягнуто максимальний розмір файлу {size}",
"Assigned users" : "Призначені користувачі",
"Due date" : "Дата виконання",
"Error creating the share" : "Помилка створення спільного доступу",
"Share with a Deck card" : "Поділіться з картою з колоди",
"Share {file} with a Deck card" : "Поділіться {file} з картою колоди",
"Share" : "Спільний доступ",
"Personal" : "Особисте",
"To do" : "Заплановано",

View File

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

View File

@@ -18,12 +18,12 @@
"Card not found" : "Karta topilmadi",
"Add board" : "Doska qo'shing",
"Move card" : "Kartani ko'chirish",
"Cancel" : "Bekor qilish",
"Cancel" : "Cancel",
"Add card" : "Karta qo'shing",
"Archived cards" : "Arxivlangan kartalar",
"Add list" : "Roʻyxat qoʻshish",
"Unassigned" : "Tayinlanmagan",
"Open" : "Ochish",
"Open" : "Open",
"Overdue" : "Muddati o'tgan",
"Next 7 days" : "Keyingi 7 kun",
"Next 30 days" : "Keyingi 30 kun",
@@ -35,13 +35,13 @@
"Undo" : "Bekor qilish",
"Can edit" : "Can edit",
"Owner" : "Owner",
"Delete" : "O'chirish",
"Delete" : "Delete",
"Delete list" : "Roʻyxatni oʻchirish",
"Edit" : "Tahrirlash",
"Download" : "Yuklab olish",
"Download" : "Download",
"Modified" : "Modified",
"Comments" : "Comments",
"Save" : "Saqlash",
"Save" : "Save",
"In reply to" : "ga javoban",
"Reply" : "Javob bering",
"Update" : "Update",
@@ -53,7 +53,7 @@
"Edit title" : "Sarlavhani tahrirlash",
"Delete card" : "Kartani o'chirish",
"seconds ago" : "seconds ago",
"Search" : "Qidirish",
"Search" : "Search",
"Archived boards" : "Arxivlangan taxtalar",
"Shared with you" : "Shared with you",
"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);
foreach ($labels as $label) {
$this->assignLabel($card->getId(), $label);
$this->assignLabel($card->id, $label);
}
foreach ($users as $user) {
$this->assignmentService->assignUser($card->getId(), $user['id'], $user['type']);
$this->assignmentService->assignUser($card->id, $user['id'], $user['type']);
}
return $card;

View File

@@ -45,7 +45,8 @@ class SessionMapper extends QBMapper {
$qb->select('id', 'board_id', 'last_contact', 'user_id', 'token')
->from($this->getTableName())
->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);
}

View File

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

View File

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

View File

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

12727
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -31,19 +31,22 @@
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"@babel/runtime": "^7.27.1",
"@babel/runtime": "^7.27.0",
"@nextcloud/auth": "^2.4.0",
"@nextcloud/axios": "^2.5.1",
"@nextcloud/capabilities": "^1.2.0",
"@nextcloud/dialogs": "^6.0.1",
"@nextcloud/dialogs": "^7.0.0-rc.1",
"@nextcloud/event-bus": "^3.3.2",
"@nextcloud/files": "^3.10.1",
"@nextcloud/initial-state": "^2.2.0",
"@nextcloud/l10n": "^3.1.0",
"@nextcloud/moment": "^1.3.4",
"@nextcloud/moment": "^1.3.2",
"@nextcloud/notify_push": "^1.3.0",
"@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",
"chroma-js": "^3.1.2",
"dompurify": "^3.2.5",
@@ -54,16 +57,14 @@
"moment": "^2.30.1",
"p-queue": "^8.0.1",
"url-search-params-polyfill": "^8.2.5",
"vue": "^2.7.15",
"vue-at": "^2.5.1",
"v3-infinite-loading": "^1.3.2",
"vue": "^3.5.13",
"vue-click-outside": "^1.1.0",
"vue-easymde": "^2.0.0",
"vue-infinite-loading": "^2.4.5",
"vue-material-design-icons": "^5.3.1",
"vue-router": "^3.6.5",
"vue-smooth-dnd": "^0.8.1",
"vuex": "^3.6.2",
"vuex-router-sync": "^5.0.0"
"vue-router": "^4.5.0",
"vue3-smooth-dnd": "^0.0.6",
"vuex": "^4.1.0"
},
"browserslist": [
"extends @nextcloud/browserslist-config"
@@ -75,20 +76,18 @@
"devDependencies": {
"@nextcloud/babel-config": "^1.2.0",
"@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/stylelint-config": "^3.0.1",
"@nextcloud/webpack-vue-config": "^6.3.0",
"@relative-ci/agent": "^4.3.1",
"@nextcloud/webpack-vue-config": "github:nextcloud-libraries/webpack-vue-config#vue3",
"@relative-ci/agent": "^4.2.14",
"@vue/test-utils": "^2.4.6",
"@vue/vue2-jest": "^29.2.6",
"cypress": "^13.17.0",
"eslint-plugin-cypress": "^3.6.0",
"eslint-webpack-plugin": "^5.0.1",
"jest": "^29.7.0",
"jest-serializer-vue": "^3.1.0",
"stylelint-webpack-plugin": "^5.0.1",
"vue-template-compiler": "^2.7.16"
"stylelint-webpack-plugin": "^5.0.1"
},
"jest": {
"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
-->
<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>
<NcContent app-name="deck" :class="{ 'nav-hidden': !navShown, 'sidebar-hidden': !sidebarRouterView }">
<NcContent app-name="deck">
<AppNavigation />
<NcAppContent :allow-swipe-navigation="false">
<router-view />
</NcAppContent>
<div v-if="$route.params.id || $route.params.cardId">
<NcModal v-if="cardDetailsInModal && $route.params.cardId"
:name="t('deck', 'Card details')"
@@ -21,179 +57,10 @@
<router-view name="sidebar" />
</div>
</NcModal>
<router-view name="sidebar" :visible="!cardDetailsInModal || !$route.params.cardId" />
</div>
<KeyboardShortcuts />
<CardMoveDialog />
</NcContent>
</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" />
</div>
<template #actions>
<NcButton :disabled="!isBoardAndStackChoosen" type="secondary" @click="moveCard">
<NcButton :disabled="!isBoardAndStackChoosen" variant="secondary" @click="moveCard">
{{ t('deck', 'Move card') }}
</NcButton>
<NcButton :disabled="!isBoardAndStackChoosen" type="primary" @click="cloneCard">
<NcButton :disabled="!isBoardAndStackChoosen" variant="primary" @click="cloneCard">
{{ t('deck', 'Copy card') }}
</NcButton>
</template>
@@ -72,7 +72,7 @@ export default {
mounted() {
subscribe('deck:card:show-move-dialog', this.openModal)
},
destroyed() {
unmounted() {
unsubscribe('deck:card:show-move-dialog', this.openModal)
},
methods: {

View File

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

View File

@@ -84,7 +84,7 @@
:title="t('deck', 'Apply filter')"
:aria-label="t('deck', 'Apply filter')"
class="filter-button"
:type="isFilterActive ? 'primary' : 'tertiary'">
:variant="isFilterActive ? 'primary' : 'tertiary'">
<template #icon>
<FilterIcon v-if="isFilterActive" :size="20" decorative />
<FilterOffIcon v-else :size="20" decorative />
@@ -231,12 +231,16 @@
</NcActionButton>
<NcActionButton v-if="compactMode"
@click="toggleCompactMode">
<ArrowExpandVerticalIcon slot="icon" :size="20" decorative />
<template #icon>
<ArrowExpandVerticalIcon :size="20" decorative />
</template>
{{ t('deck', 'Toggle compact mode') }}
</NcActionButton>
<NcActionButton v-else
@click="toggleCompactMode">
<ArrowCollapseVerticalIcon slot="icon" :size="20" decorative />
<template #icon>
<ArrowCollapseVerticalIcon :size="20" decorative />
</template>
{{ t('deck', 'Toggle compact mode') }}
</NcActionButton>
<NcActionButton @click="toggleShowCardCover">
@@ -263,10 +267,10 @@ import { mapState, mapGetters } from 'vuex'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import { NcActions, NcActionButton, NcAvatar, NcButton, NcPopover, NcModal } from '@nextcloud/vue'
import labelStyle from '../mixins/labelStyle.js'
import ArchiveIcon from 'vue-material-design-icons/ArchiveOutline.vue'
import ImageIcon from 'vue-material-design-icons/ImageMultipleOutline.vue'
import FilterIcon from 'vue-material-design-icons/FilterOutline.vue'
import FilterOffIcon from 'vue-material-design-icons/FilterOffOutline.vue'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import ImageIcon from 'vue-material-design-icons/ImageMultiple.vue'
import FilterIcon from 'vue-material-design-icons/Filter.vue'
import FilterOffIcon from 'vue-material-design-icons/FilterOff.vue'
import TableColumnPlusAfter from 'vue-material-design-icons/TableColumnPlusAfter.vue'
import ArrowCollapseVerticalIcon from 'vue-material-design-icons/ArrowCollapseVertical.vue'
import ArrowExpandVerticalIcon from 'vue-material-design-icons/ArrowExpandVertical.vue'
@@ -274,6 +278,7 @@ import SessionList from './SessionList.vue'
import { isNotifyPushEnabled } from '../sessions.js'
import CreateNewCardCustomPicker from '../views/CreateNewCardCustomPicker.vue'
import { getCurrentUser } from '@nextcloud/auth'
import { onClickOutside } from '@vueuse/core'
export default {
name: 'Controls',
@@ -359,6 +364,11 @@ export default {
}
},
},
created() {
onClickOutside(() => {
this.hideAddStack()
})
},
beforeMount() {
subscribe('deck:board:show-new-card', this.clickShowAddCardModel)
subscribe('deck:board:toggle-filter-popover', this.triggerOpenFilters)
@@ -366,7 +376,7 @@ export default {
subscribe('deck:board:toggle-filter-by-me', this.triggerFilterByMe)
},
beforeDestroy() {
beforeUnmount() {
unsubscribe('deck:board:show-new-card', this.clickShowAddCardModel)
unsubscribe('deck:board:toggle-filter-popover', this.triggerOpenFilters)
unsubscribe('deck:board:clear-filter', this.triggerClearFilter)
@@ -508,20 +518,6 @@ export default {
#stack-add form {
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}" -->
<div v-if="card && selector"
ref="shortcutModal"
v-click-outside="close"
class="keyboard-shortcuts__modal"
tabindex="0"
@keydown.esc="close">
@@ -18,6 +17,7 @@
</template>
<script>
import DueDateSelector from './card/DueDateSelector.vue'
import { onClickOutside } from '@vueuse/core'
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
import { mapState } from 'vuex'
import TagSelector from './card/TagSelector.vue'
@@ -50,8 +50,9 @@ export default {
subscribe('deck:card:show-assignment-selector', this.handleShowAssignemnt)
subscribe('deck:card:show-due-date-selector', this.handleShowDueDate)
subscribe('deck:card:show-label-selector', this.handleShowLabel)
onClickOutside(this.close)
},
destroyed() {
unmounted() {
document.removeEventListener('keydown', this.onKeydown)
unsubscribe('deck:card:show-assignment-selector', this.handleShowAssignemnt)
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') }}
<form @submit.prevent="addNewStack()">
<NcTextField ref="newStackInput"
v-model="newStackTitle"
:disable="loading"
:value.sync="newStackTitle"
:placeholder="t('deck', 'List name')"
type="text" />
<NcButton type="secondary"
native-type="submit"
<NcButton variant="secondary"
type="submit"
:disabled="loading"
:title="t('deck', 'Add list')">
<template #icon>
@@ -63,7 +63,10 @@
data-click-closes-sidebar="true"
data-dragscroll-enabled
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>
</Container>
</div>
@@ -82,7 +85,7 @@
</template>
<script>
import { Container, Draggable } from 'vue-smooth-dnd'
import { Container, Draggable } from 'vue3-smooth-dnd'
import { mapState, mapGetters } from 'vuex'
import Controls from '../Controls.vue'
import DeckIcon from '../icons/DeckIcon.vue'
@@ -165,14 +168,14 @@ export default {
created() {
this.session = createSession(this.id)
this.fetchData()
this.$root.$on('open-card', (cardId) => {
this.localModal = cardId
})
},
beforeDestroy() {
beforeUnmount() {
this.session.close()
},
methods: {
openCard(cardId) {
},
async fetchData() {
this.loading = true
try {
@@ -253,8 +256,8 @@ export default {
</script>
<style lang="scss" scoped>
@import '../../css/animations';
@import '../../css/variables';
@use '../../css/animations';
@use '../../css/variables';
form {
text-align: center;
@@ -282,7 +285,7 @@ export default {
}
.board {
padding-left: $board-spacing;
padding-left: variables.$board-spacing;
position: relative;
max-height: calc(100% - var(--default-clickable-area));
overflow: hidden;
@@ -313,8 +316,8 @@ export default {
display: flex;
flex-direction: column;
// Margin left instead of padidng to avoid jumps on dropping a card
margin-left: $stack-spacing;
padding-right: $stack-spacing;
margin-left: variables.$stack-spacing;
padding-right: variables.$stack-spacing;
overflow-x: hidden;
overflow-y: auto;
padding-top: 15px;

View File

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

View File

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

View File

@@ -44,7 +44,7 @@
<script>
import { defineComponent } from '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({
name: 'AssignmentSelector',

View File

@@ -3,16 +3,16 @@
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<!-- eslint-disable vue/no-v-model-argument -->
<template>
<NcAppSidebar v-if="currentBoard && currentCard"
ref="cardSidebar"
v-model:name-editable="isEditingTitle"
:active="tabId"
:name="displayTitle"
:subname="subtitle"
:subtitle="subtitleTooltip"
:name-editable.sync="isEditingTitle"
@update:name="(value) => titleEditing = value"
@update:active="(value) => activeTabId = value"
@update:name="value => titleEditing = value"
@dismiss-editing="titleEditing = currentCard.title"
@submit-name="handleSubmitTitle"
@opened="focusHeader"
@@ -25,39 +25,71 @@
{{ t('deck', 'Open in bigger view') }}
</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 #description>
<NcReferenceList v-if="currentCard.referenceData"
:text="currentCard.title"
:interactive="false" />
<NcReferenceList v-if="currentCard.referenceData" :text="currentCard.title" :interactive="false" />
</template>
<NcAppSidebarTab id="details"
:order="0"
:name="t('deck', 'Details')">
<NcAppSidebarTab id="details" :order="0" :name="t('deck', 'Details')">
<CardSidebarTabDetails :card="currentCard" />
<template #icon>
<HomeIcon v-if="activeTabId === 'details'" :size="20" />
<HomeOutlineIcon v-else :size="20" />
<HomeIcon :size="20" />
</template>
</NcAppSidebarTab>
<NcAppSidebarTab id="attachments"
:order="1"
:name="t('deck', 'Attachments')">
<NcAppSidebarTab id="attachments" :order="1" :name="t('deck', 'Attachments')">
<template #icon>
<AttachmentIcon :size="20" />
</template>
<CardSidebarTabAttachments :card="currentCard" />
</NcAppSidebarTab>
<NcAppSidebarTab id="comments"
:order="2"
:name="t('deck', 'Comments')">
<NcAppSidebarTab id="comments" :order="2" :name="t('deck', 'Comments')">
<template #icon>
<CommentIcon v-if="activeTabId === 'comments'" :size="20" />
<CommentOutlineIcon v-else :size="20" />
<CommentIcon :size="20" />
</template>
<CardSidebarTabComments :card="currentCard" :tab-query="tabQuery" />
</NcAppSidebarTab>
@@ -76,7 +108,7 @@
<script>
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 { mapState, mapGetters } from 'vuex'
import CardSidebarTabDetails from './CardSidebarTabDetails.vue'
@@ -87,14 +119,18 @@ import relativeDate from '../../mixins/relativeDate.js'
import moment from '@nextcloud/moment'
import AttachmentIcon from 'vue-material-design-icons/Paperclip.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 CommentOutlineIcon from 'vue-material-design-icons/CommentOutline.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 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()
@@ -112,10 +148,8 @@ export default {
ActivityIcon,
AttachmentIcon,
CommentIcon,
CommentOutlineIcon,
HomeIcon,
HomeOutlineIcon,
CardMenuEntries,
ArchiveIcon,
},
mixins: [relativeDate],
props: {
@@ -140,7 +174,6 @@ export default {
titleEditing: '',
hasActivity: capabilities && capabilities.activity,
locale: getLocale(),
activeTabId: this.tabId || 'details',
}
},
computed: {
@@ -148,8 +181,17 @@ export default {
isFullApp: (state) => state.isFullApp,
currentBoard: (state) => state.currentBoard,
hasCardSaveError: (state) => state.hasCardSaveError,
showArchived: (state) => state.showArchived,
}),
...mapGetters(['canEdit', 'assignables', 'cardActions', 'stackById']),
...mapGetters([
'canEdit',
'assignables',
'cardActions',
'stackById',
'isArchived',
'boards',
'boardById',
]),
currentCard() {
return this.$store.getters.cardById(this.id)
},
@@ -176,6 +218,31 @@ export default {
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: {
currentCard() {
@@ -224,12 +291,46 @@ export default {
formatDate(timestamp) {
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>
<style lang="scss">
section.app-sidebar__tab--active {
min-height: auto;
display: flex;
@@ -281,6 +382,7 @@ section.app-sidebar__tab--active {
z-index: 100;
background-color: var(--color-main-background);
}
.app-sidebar-tabs__nav {
position: sticky;
top: 87px;
@@ -293,10 +395,10 @@ section.app-sidebar__tab--active {
overflow: initial;
}
#emptycontent, .emptycontent {
#emptycontent,
.emptycontent {
margin-top: 88px;
}
}
}
</style>

View File

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

View File

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

View File

@@ -82,7 +82,7 @@ import CommentForm from './CommentForm.vue'
import { getCurrentUser } from '@nextcloud/auth'
import md5 from 'blueimp-md5'
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'
const AtMention = {

View File

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

View File

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

View File

@@ -7,7 +7,7 @@
<div class="selector-wrapper--icon">
<TagMultiple :size="20" />
</div>
<NcSelect :value="assignedLabels"
<NcSelect v-model="assignedLabels"
class="selector-wrapper--selector"
:multiple="true"
:disabled="disabled"
@@ -44,7 +44,7 @@
<script>
import { NcSelect } from '@nextcloud/vue'
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 {
name: 'TagSelector',

View File

@@ -70,7 +70,7 @@
<script>
import { NcAvatar, NcPopover } from '@nextcloud/vue'
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 {
name: 'AvatarList',

View File

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

View File

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

View File

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

View File

@@ -6,40 +6,190 @@
<template>
<div v-if="card" class="card-menu" @click.stop.prevent>
<NcButton v-if="card.referenceData"
type="tertiary"
:title="t('deck','Open link')"
variant="tertiary"
:title="t('deck', 'Open link')"
@click="openLink">
<template #icon>
<LinkIcon :size="20" />
</template>
</NcButton>
<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>
</div>
</template>
<script>
import { NcActions, NcButton } from '@nextcloud/vue'
import { NcActions, NcButton, NcActionButton } from '@nextcloud/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 {
name: 'CardMenu',
components: { NcActions, NcButton, LinkIcon, CardMenuEntries },
components: { NcActions, NcButton, LinkIcon, NcActionButton, PencilIcon, CardBulletedIcon, ArchiveIcon },
props: {
card: {
type: Object,
default: null,
},
hideDetailsEntry: {
type: Boolean,
default: false,
},
},
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: {
openLink() {
window.open(this.card?.referenceData?.openGraphObject?.link)
return false
},
editTitle(id) {
this.$emit('edit-title', id)
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)
},
},
}

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>
<script>
import { NcModal, Tooltip } from '@nextcloud/vue'
import { NcModal } from '@nextcloud/vue'
export default {
name: 'HelpModal',
components: {
NcModal,
},
directives: {
Tooltip,
},
}
</script>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,19 +3,14 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import Vue from 'vue'
import './../css/collections.css'
import FileSharingPicker from './views/FileSharingPicker.js'
import { buildSelector } from './helpers/selector.js'
import './shared-init.js'
Vue.prototype.t = t
Vue.prototype.n = n
Vue.prototype.OC = OC
window.addEventListener('DOMContentLoaded', () => {
export function initCollections() {
window.addEventListener('DOMContentLoaded', () => {
if (OCA.Sharing && OCA.Sharing.ShareSearch) {
OCA.Sharing.ShareSearch.addNewResult(FileSharingPicker)
}
@@ -37,4 +32,5 @@ window.addEventListener('DOMContentLoaded', () => {
typeString: t('deck', 'Link to a card'),
typeIconClass: 'icon-deck',
})
})
})
}

View File

@@ -3,7 +3,7 @@
* 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 './shared-init.js'

View File

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

View File

@@ -26,7 +26,8 @@ export default {
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()
bodyFormData.append('cardId', this.cardId)
bodyFormData.append('type', type)
@@ -39,7 +40,7 @@ export default {
onUploadProgress: (e) => {
const percentCompleted = Math.round((e.loaded * 100) / e.total)
console.debug(percentCompleted)
this.$set(this.uploadQueue[file.name], 'progress', percentCompleted)
this.uploadQueue[file.name].progress = percentCompleted
},
})
} catch (err) {
@@ -50,7 +51,7 @@ export default {
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
*/
import Vue from 'vue'
import Router from 'vue-router'
import { createRouter, createWebHistory } from 'vue-router'
import { generateUrl, getRootUrl } from '@nextcloud/router'
import { BOARD_FILTERS } from './store/main.js'
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 Overview from './components/overview/Overview.vue'
Vue.use(Router)
// We apply a dynamic base URL depending on the URL used in the browser
const baseUrl = generateUrl('/apps/deck/')
const webRootWithIndexPHP = getRootUrl() + '/index.php'
const doesURLContainIndexPHP = window.location.pathname.startsWith(webRootWithIndexPHP)
const currentBaseUrl = doesURLContainIndexPHP ? baseUrl : baseUrl.replace('/index.php/', '/')
const router = new Router({
mode: 'history',
base: currentBaseUrl,
const router = createRouter({
history: createWebHistory(currentBaseUrl),
linkActiveClass: 'active',
routes: [
{

View File

@@ -4,7 +4,6 @@
*/
import { AttachmentApi } from './../services/AttachmentApi.js'
import Vue from 'vue'
const apiClient = new AttachmentApi()
@@ -24,20 +23,20 @@ export default {
mutations: {
createAttachment(state, { cardId, attachment }) {
if (typeof state.attachments[cardId] === 'undefined') {
Vue.set(state.attachments, cardId, [attachment])
state.attachments[cardId] = [attachment]
} else {
state.attachments[cardId].push(attachment)
}
},
createAttachments(state, { cardId, attachments }) {
Vue.set(state.attachments, cardId, attachments)
state.attachments[cardId] = attachments
},
updateAttachment(state, { cardId, attachment }) {
const existingIndex = state.attachments[attachment.cardId].findIndex(a => a.id === attachment.id && a.type === attachment.type)
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 moment from 'moment'
import Vue from 'vue'
const apiClient = new CardApi()
@@ -190,7 +189,7 @@ export default {
const existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) {
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 {
state.cards.push(card)
}
@@ -204,15 +203,15 @@ export default {
updateCard(state, card) {
const existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) {
Vue.set(state.cards, existingIndex, Object.assign({}, state.cards[existingIndex], card))
state.cards[existingIndex] = { ...state.cards[existingIndex], ...card }
}
},
updateCardsReorder(state, cards) {
for (const newCard of cards) {
const existingIndex = state.cards.findIndex(_card => _card.id === newCard.id)
if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], 'order', newCard.order)
Vue.set(state.cards[existingIndex], 'stackId', newCard.stackId)
state.cards[existingIndex].order = newCard.order
state.cards[existingIndex].stackId = newCard.stackId
}
}
},
@@ -234,26 +233,26 @@ export default {
updateCardProperty(state, { card, property }) {
const existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], property, card[property])
Vue.set(state.cards[existingIndex], 'lastModified', Date.now() / 1000)
state.cards[existingIndex][property] = card[property]
state.cards[existingIndex].lastModifiedBy = Date.now() / 1000
}
},
cardSetAttachmentCount(state, { cardId, count }) {
const existingIndex = state.cards.findIndex(_card => _card.id === cardId)
if (existingIndex !== -1) {
Vue.set(state.cards[existingIndex], 'attachmentCount', count)
state.cards[existingIndex].attachmentCount = count
}
},
cardIncreaseAttachmentCount(state, cardId) {
const existingIndex = state.cards.findIndex(_card => _card.id === cardId)
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) {
const existingIndex = state.cards.findIndex(_card => _card.id === cardId)
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) {

View File

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

View File

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

View File

@@ -3,7 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import Vue from 'vue'
import { StackApi } from './../services/StackApi.js'
import applyOrderToArray from './../helpers/applyOrderToArray.js'
@@ -26,7 +25,7 @@ export default {
const existingIndex = state.stacks.findIndex(_stack => _stack.id === stack.id)
if (existingIndex !== -1) {
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 {
state.stacks.push(stack)
}

View File

@@ -33,7 +33,7 @@ import DeckIcon from '../components/icons/DeckIcon.vue'
import { BoardApi } from './../services/BoardApi.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 { generateUrl } from '@nextcloud/router'

View File

@@ -66,7 +66,7 @@
</template>
<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 CardBulletedOutlineIcon from 'vue-material-design-icons/CardBulletedOutline.vue'

View File

@@ -78,7 +78,7 @@
</template>
<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 CardBulletedOutlineIcon from 'vue-material-design-icons/CardBulletedOutline.vue'
import CommentProcessingOutlineIcon from 'vue-material-design-icons/CommentProcessingOutline.vue'

View File

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

View File

@@ -1 +1 @@
81373
81091

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,7 @@ const isDevServer = process.env.WEBPACK_SERVE
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'),
calendar: path.join(__dirname, 'src', 'init-calendar.js'),
talk: path.join(__dirname, 'src', 'init-talk.js'),
@@ -22,6 +22,9 @@ if (isDevServer) {
})
)
} else {
webpackConfig.output.clean = {
keep: /\webpack-stats\.json$/,
}
webpackConfig.stats = {
context: path.resolve(__dirname, 'src'),
assets: true,
@@ -30,7 +33,5 @@ if (isDevServer) {
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