From 3f39605e53e5deb9ccf69f3b994e0cfd35a11708 Mon Sep 17 00:00:00 2001 From: Luka Trovic Date: Wed, 18 Jun 2025 17:17:11 +0200 Subject: [PATCH] fix: add retry and show warning on description saving error Signed-off-by: Luka Trovic [skip ci] --- src/components/card/CardSidebar.vue | 6 +++++- src/components/card/Description.vue | 31 ++++++++++++++++++++++++----- src/store/main.js | 4 ++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/components/card/CardSidebar.vue b/src/components/card/CardSidebar.vue index d2b24a5cd..83a3024f0 100644 --- a/src/components/card/CardSidebar.vue +++ b/src/components/card/CardSidebar.vue @@ -96,7 +96,7 @@ import HomeIcon from 'vue-material-design-icons/Home.vue' import CommentIcon from 'vue-material-design-icons/Comment.vue' import ActivityIcon from 'vue-material-design-icons/LightningBolt.vue' -import { showError } from '@nextcloud/dialogs' +import { showError, showWarning } from '@nextcloud/dialogs' import { getLocale } from '@nextcloud/l10n' import CardMenuEntries from '../cards/CardMenuEntries.vue' @@ -190,6 +190,10 @@ export default { }, closeSidebar() { + if (this.hasCardSaveError) { + showWarning(t('deck', 'Cannot close unsaved card!')) + return + } this.$router?.push({ name: 'board' }) this.$emit('close') }, diff --git a/src/components/card/Description.vue b/src/components/card/Description.vue index 0e3cb0949..188ccb79d 100644 --- a/src/components/card/Description.vue +++ b/src/components/card/Description.vue @@ -90,7 +90,9 @@ import AttachmentList from './AttachmentList.vue' import { NcActions, NcActionButton, NcModal } from '@nextcloud/vue' import { formatFileSize } from '@nextcloud/files' import { generateUrl } from '@nextcloud/router' +import { showWarning } from '@nextcloud/dialogs' import PaperclipIcon from 'vue-material-design-icons/Paperclip.vue' +import { mapState } from 'vuex' const markdownIt = new MarkdownIt({ linkify: true, @@ -152,6 +154,9 @@ export default { } }, computed: { + ...mapState({ + hasCardSaveError: (state) => state.hasCardSaveError, + }), mimetypeForAttachment() { return (mimetype) => { const url = OC.MimeType.getIconUrl(mimetype) @@ -302,15 +307,31 @@ export default { return } this.descriptionSaving = true - if (this.card.id !== undefined) { - await this.$store.dispatch('updateCardDesc', { ...this.card, description: this.description }) + try { + if (this.card.id !== undefined) { + await this.$store.dispatch('updateCardDesc', { ...this.card, description: this.description }) + } + this.$emit('change', this.description) + this.descriptionLastEdit = 0 + this.$store.commit('setHasCardSaveError', false) + } catch (e) { + this.$store.commit('setHasCardSaveError', true) + showWarning(t('deck', 'Could not save description'), { timeout: 2500 }) + console.error(e) + + // Retry of network error + if (['ERR_NETWORK', 'ETIMEDOUT'].includes(e.code)) { + this.setSaveTimeout() + } + } finally { + this.descriptionSaving = false } - this.$emit('change', this.description) - this.descriptionLastEdit = 0 - this.descriptionSaving = false }, updateDescription() { this.descriptionLastEdit = Date.now() + this.setSaveTimeout() + }, + setSaveTimeout() { clearTimeout(this.descriptionSaveTimeout) this.descriptionSaveTimeout = setTimeout(async () => { await this.saveDescription() diff --git a/src/store/main.js b/src/store/main.js index 5f9d7d054..87b2aab2b 100644 --- a/src/store/main.js +++ b/src/store/main.js @@ -67,6 +67,7 @@ export default new Vuex.Store({ sidebarShown: false, currentBoard: null, currentCard: null, + hasCardSaveError: false, boards: loadState('deck', 'initialBoards', []), sharees: [], assignableUsers: [], @@ -148,6 +149,9 @@ export default new Vuex.Store({ setFullApp(state, isFullApp) { Vue.set(state, 'isFullApp', isFullApp) }, + setHasCardSaveError(state, hasCardSaveError) { + Vue.set(state, 'hasCardSaveError', hasCardSaveError) + }, SET_CONFIG(state, { key, value }) { const [scope, id, configKey] = key.split(':', 3) let indexExisting = -1