From 4c16ed0af462d72b3920173e1ce67781fd3d49ff Mon Sep 17 00:00:00 2001 From: Cleopatra Enjeck M Date: Wed, 14 Feb 2024 09:41:00 +0100 Subject: [PATCH 1/2] enh: hold multiple tables/views in global store Signed-off-by: Cleopatra Enjeck M --- src/modules/main/sections/MainWrapper.vue | 19 ++- src/modules/modals/CreateColumn.vue | 2 +- src/modules/modals/DeleteColumn.vue | 6 +- src/modules/modals/DeleteRows.vue | 3 +- src/modules/modals/EditColumn.vue | 2 +- src/modules/modals/EditRow.vue | 6 +- src/modules/modals/Import.vue | 2 +- src/store/data.js | 151 ++++++++++++++-------- 8 files changed, 121 insertions(+), 70 deletions(-) diff --git a/src/modules/main/sections/MainWrapper.vue b/src/modules/main/sections/MainWrapper.vue index 40acb4599..a6216c139 100644 --- a/src/modules/main/sections/MainWrapper.vue +++ b/src/modules/main/sections/MainWrapper.vue @@ -68,8 +68,8 @@ export default { computed: { ...mapState(['activeRowId']), ...mapState({ - columns: state => state.data.columns, - rows: state => state.data.rows, + columns(state) { return state.data.columns[this.isView ? 'view-' + (this.element.id).toString() : (this.element.id).toString()] }, + rows(state) { return state.data.rows[this.isView ? 'view-' + (this.element.id).toString() : (this.element.id).toString()] }, }), }, @@ -79,7 +79,7 @@ export default { }, }, - mounted() { + beforeMount() { this.reload(true) }, @@ -107,14 +107,16 @@ export default { return } - if (!this.lastActiveElement || this.element.id !== this.lastActiveElement.id || this.isView !== this.lastActiveElement.isView || force) { + // Used to reload View from backend, in case there are Filter updates + const isLastElementSameAndView = this.element.id === this.lastActiveElement?.id && this.isView === this.lastActiveElement?.isView + if (!this.lastActiveElement || this.element.id !== this.lastActiveElement.id || isLastElementSameAndView || this.isView !== this.lastActiveElement.isView || force) { this.localLoading = true this.viewSetting = {} await this.$store.dispatch('loadColumnsFromBE', { view: this.isView ? this.element : null, - table: !this.isView ? this.element : null, + tableId: !this.isView ? this.element.id : null, }) if (this.canReadData(this.element)) { await this.$store.dispatch('loadRowsFromBE', { @@ -122,9 +124,12 @@ export default { tableId: !this.isView ? this.element.id : null, }) } else { - await this.$store.dispatch('removeRows') + await this.$store.dispatch('removeRows', { + isView: this.isView, + elementId: this.element.id, + }) } - this.lastActiveViewId = { + this.lastActiveElement = { id: this.element.id, isView: this.isView, } diff --git a/src/modules/modals/CreateColumn.vue b/src/modules/modals/CreateColumn.vue index 1c21fa746..1be09fe94 100644 --- a/src/modules/modals/CreateColumn.vue +++ b/src/modules/modals/CreateColumn.vue @@ -281,7 +281,7 @@ export default { data.numberSuffix = this.column.numberSuffix } } - const res = await this.$store.dispatch('insertNewColumn', { data }) + const res = await this.$store.dispatch('insertNewColumn', { isView: this.isView, elementId: this.element.id, data }) if (res) { showSuccess(t('tables', 'The column "{column}" was created.', { column: this.column.title })) } else { diff --git a/src/modules/modals/DeleteColumn.vue b/src/modules/modals/DeleteColumn.vue index fbcd61e63..a44885200 100644 --- a/src/modules/modals/DeleteColumn.vue +++ b/src/modules/modals/DeleteColumn.vue @@ -41,11 +41,13 @@ export default { }, methods: { async deleteColumn() { - const res = await this.$store.dispatch('removeColumn', { id: this.columnToDelete.id }) + const res = await this.$store.dispatch('removeColumn', { id: this.columnToDelete.id, isView: this.isView, elementId: this.elementId }) if (!res) { showError(t('tables', 'Error occurred while deleting column "{column}".', { column: this.columnToDelete.title })) } - await this.$store.dispatch('reloadViewsOfTable', { tableId: this.elementId }) + if (!this.isView) { + await this.$store.dispatch('reloadViewsOfTable', { tableId: this.elementId }) + } this.$emit('cancel') }, }, diff --git a/src/modules/modals/DeleteRows.vue b/src/modules/modals/DeleteRows.vue index dbcb2d176..b90032a9b 100644 --- a/src/modules/modals/DeleteRows.vue +++ b/src/modules/modals/DeleteRows.vue @@ -41,7 +41,8 @@ export default { this.rowsToDelete.forEach(rowId => { const res = this.$store.dispatch('removeRow', { rowId, - viewId: this.isView ? this.elementId : null, + isView: this.isView, + elementId: this.elementId, }) if (!res) { error = true diff --git a/src/modules/modals/EditColumn.vue b/src/modules/modals/EditColumn.vue index e7408f3f7..7337d659c 100644 --- a/src/modules/modals/EditColumn.vue +++ b/src/modules/modals/EditColumn.vue @@ -188,7 +188,7 @@ export default { delete data.lastEditAt delete data.lastEditBy console.debug('this column data will be send', data) - const res = await this.$store.dispatch('updateColumn', { id: this.editColumn.id, data }) + const res = await this.$store.dispatch('updateColumn', { id: this.editColumn.id, isView: this.isView, elementId: this.elementId, data }) if (res) { showSuccess(t('tables', 'The column "{column}" was updated.', { column: this.editColumn.title })) } diff --git a/src/modules/modals/EditRow.vue b/src/modules/modals/EditRow.vue index 6082e1d9f..40fc737bd 100644 --- a/src/modules/modals/EditRow.vue +++ b/src/modules/modals/EditRow.vue @@ -163,7 +163,8 @@ export default { } const res = await this.$store.dispatch('updateRow', { id: this.row.id, - viewId: this.isView ? this.element.id : null, + isView: this.isView, + elementId: this.element.id, data, }) if (!res) { @@ -182,7 +183,8 @@ export default { this.localLoading = true const res = await this.$store.dispatch('removeRow', { rowId, - viewId: this.isView ? this.element.id : null, + isView: this.isView, + elementId: this.element.id, }) if (!res) { showError(t('tables', 'Could not delete row.')) diff --git a/src/modules/modals/Import.vue b/src/modules/modals/Import.vue index 23b6f7da7..3a0b428bb 100644 --- a/src/modules/modals/Import.vue +++ b/src/modules/modals/Import.vue @@ -212,7 +212,7 @@ export default { await this.$store.dispatch('loadViewsSharedWithMeFromBE') await this.$store.dispatch('loadColumnsFromBE', { view: this.isElementView ? this.element : null, - table: !this.isElementView ? this.element : null, + tableId: !this.isElementView ? this.element.id : null, }) if (this.canReadData(this.element)) { await this.$store.dispatch('loadRowsFromBE', { diff --git a/src/store/data.js b/src/store/data.js index 486976ec3..919343781 100644 --- a/src/store/data.js +++ b/src/store/data.js @@ -4,24 +4,40 @@ import displayError from '../shared/utils/displayError.js' import { parseCol } from '../shared/components/ncTable/mixins/columnParser.js' import { MetaColumns } from '../shared/components/ncTable/mixins/metaColumns.js' import { showError } from '@nextcloud/dialogs' +import { set } from 'vue' + +function genStateKey(isView, elementId) { + elementId = elementId.toString() + return isView ? 'view-' + elementId : elementId +} export default { state: { - loading: false, - rows: [], - columns: [], + loading: {}, + rows: {}, + columns: {}, }, mutations: { - setColumns(state, columns) { - state.columns = columns + setColumns(state, { stateId, columns }) { + set(state.columns, stateId, columns) + }, + setRows(state, { stateId, rows }) { + set(state.rows, stateId, rows) + }, + setLoading(state, { stateId, value }) { + set(state.loading, stateId, !!(value)) + }, + clearColumns(state) { + state.columns = {} }, - setRows(state, rows) { - state.rows = rows + clearRows(state) { + state.rows = {} }, - setLoading(state, value) { - state.loading = !!(value) + clearLoading(state) { + state.loading = {} }, + }, getters: { @@ -31,9 +47,15 @@ export default { }, actions: { + clearState({ commit }) { + commit('clearLoading') + commit('clearColumns') + commit('clearRows') + }, // COLUMNS async getColumnsFromBE({ commit }, { tableId, viewId }) { - commit('setLoading', true) + const stateId = genStateKey(!!(viewId), viewId ?? tableId) + commit('setLoading', { stateId, value: true }) let res = null try { @@ -57,22 +79,24 @@ export default { return false } const columns = res.data.map(col => parseCol(col)) - commit('setLoading', false) + commit('setLoading', { stateId, value: false }) return columns }, - async loadColumnsFromBE({ commit, dispatch }, { view, table }) { - let allColumns = await dispatch('getColumnsFromBE', { tableId: table?.id, viewId: view?.id }) + async loadColumnsFromBE({ commit, dispatch }, { view, tableId }) { + let allColumns = await dispatch('getColumnsFromBE', { tableId, viewId: view?.id }) if (view) { allColumns = allColumns.concat(MetaColumns.filter(col => view.columns.includes(col.id))) allColumns = allColumns.sort(function(a, b) { return view.columns.indexOf(a.id) - view.columns.indexOf(b.id) }) } - commit('setColumns', allColumns) + const stateId = genStateKey(!!(view?.id), view?.id ?? tableId) + commit('setColumns', { stateId, columns: allColumns }) return true }, - async insertNewColumn({ commit, state }, { data }) { - commit('setLoading', true) + async insertNewColumn({ commit, state }, { isView, elementId, data }) { + const stateId = genStateKey(isView, elementId) + commit('setLoading', { stateId, value: true }) let res = null try { @@ -81,15 +105,15 @@ export default { displayError(e, t('tables', 'Could not insert column.')) return false } - - const columns = state.columns - columns.push(parseCol(res.data)) - commit('setColumns', columns) - - commit('setLoading', false) + if (stateId) { + const columns = state.columns[stateId] + columns.push(parseCol(res.data)) + commit('setColumns', { stateId, columns }) + commit('setLoading', { stateId, value: false }) + } return true }, - async updateColumn({ state, commit }, { id, data }) { + async updateColumn({ state, commit }, { id, isView, elementId, data }) { data.selectionOptions = JSON.stringify(data.selectionOptions) let res = null @@ -100,15 +124,18 @@ export default { return false } - const col = res.data - const columns = state.columns - const index = columns.findIndex(c => c.id === col.id) - columns[index] = parseCol(col) - commit('setColumns', [...columns]) + const stateId = genStateKey(isView, elementId) + if (stateId) { + const col = res.data + const columns = state.columns[stateId] + const index = columns.findIndex(c => c.id === col.id) + columns[index] = parseCol(col) + commit('setColumns', { stateId, columns: [...columns] }) + } return true }, - async removeColumn({ state, commit }, { id }) { + async removeColumn({ state, commit }, { id, isView, elementId }) { try { await axios.delete(generateUrl('/apps/tables/column/' + id)) } catch (e) { @@ -116,17 +143,21 @@ export default { return false } - const columns = state.columns - const index = columns.findIndex(c => c.id === id) - columns.splice(index, 1) - commit('setColumns', [...columns]) + const stateId = genStateKey(isView, elementId) + if (stateId) { + const columns = state.columns[stateId] + const index = columns.findIndex(c => c.id === id) + columns.splice(index, 1) + commit('setColumns', { stateId, columns: [...columns] }) + } return true }, // ROWS async loadRowsFromBE({ commit }, { tableId, viewId }) { - commit('setLoading', true) + const stateId = genStateKey(!!(viewId), viewId ?? tableId) + commit('setLoading', { stateId, value: true }) let res = null try { @@ -140,16 +171,17 @@ export default { return false } - commit('setRows', res.data) - - commit('setLoading', false) + commit('setRows', { stateId, rows: res.data }) + commit('setLoading', { stateId, value: false }) return true }, - removeRows({ commit }) { - commit('setRows', []) + removeRows({ commit }, { isView, elementId }) { + const stateId = genStateKey(isView, elementId) + commit('setRows', { stateId, rows: [] }) }, - async updateRow({ state, commit, dispatch }, { id, viewId, data }) { + async updateRow({ state, commit, dispatch }, { id, isView, elementId, data }) { let res = null + const viewId = isView ? elementId : null try { res = await axios.put(generateUrl('/apps/tables/row/' + id), { viewId, data }) @@ -164,11 +196,14 @@ export default { return false } - const row = res.data - const rows = state.rows - const index = rows.findIndex(r => r.id === row.id) - rows[index] = row - commit('setRows', [...rows]) + const stateId = genStateKey(isView, elementId) + if (stateId) { + const row = res.data + const rows = state.rows[stateId] + const index = rows.findIndex(r => r.id === row.id) + rows[index] = row + commit('setRows', { stateId, rows: [...rows] }) + } return true }, async insertNewRow({ state, commit, dispatch }, { viewId, tableId, data }) { @@ -181,13 +216,17 @@ export default { return false } - const row = res.data - const rows = state.rows - rows.push(row) - commit('setRows', [...rows]) + const stateId = genStateKey(!!(viewId), viewId ?? tableId) + if (stateId) { + const row = res.data + const rows = state.rows[stateId] + rows.push(row) + commit('setRows', { stateId, rows: [...rows] }) + } return true }, - async removeRow({ state, commit, dispatch }, { rowId, viewId }) { + async removeRow({ state, commit, dispatch }, { rowId, isView, elementId }) { + const viewId = isView ? elementId : null try { if (viewId) await axios.delete(generateUrl('/apps/tables/view/' + viewId + '/row/' + rowId)) else await axios.delete(generateUrl('/apps/tables/row/' + rowId)) @@ -201,11 +240,13 @@ export default { return false } - const rows = state.rows - const index = rows.findIndex(r => r.id === rowId) - rows.splice(index, 1) - commit('setRows', [...rows]) - + const stateId = genStateKey(isView, elementId) + if (stateId) { + const rows = state.rows[stateId] + const index = rows.findIndex(r => r.id === rowId) + rows.splice(index, 1) + commit('setRows', { stateId, rows: [...rows] }) + } return true }, }, From 47ce815bab642d823e48cb743ceae77164931372 Mon Sep 17 00:00:00 2001 From: Cleopatra Enjeck M Date: Mon, 19 Feb 2024 13:18:56 +0100 Subject: [PATCH 2/2] enh: clean up Signed-off-by: Cleopatra Enjeck M --- src/modules/main/sections/MainWrapper.vue | 4 ++++ src/shared/components/ncTable/NcTable.vue | 16 ++++++++-------- .../components/ncTable/sections/CustomTable.vue | 3 --- src/store/data.js | 6 ------ 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/modules/main/sections/MainWrapper.vue b/src/modules/main/sections/MainWrapper.vue index a6216c139..684a204dc 100644 --- a/src/modules/main/sections/MainWrapper.vue +++ b/src/modules/main/sections/MainWrapper.vue @@ -109,9 +109,13 @@ export default { // Used to reload View from backend, in case there are Filter updates const isLastElementSameAndView = this.element.id === this.lastActiveElement?.id && this.isView === this.lastActiveElement?.isView + if (!this.lastActiveElement || this.element.id !== this.lastActiveElement.id || isLastElementSameAndView || this.isView !== this.lastActiveElement.isView || force) { this.localLoading = true + // Since we show one page at a time, no need keep other tables in the store + await this.$store.dispatch('clearState') + this.viewSetting = {} await this.$store.dispatch('loadColumnsFromBE', { diff --git a/src/shared/components/ncTable/NcTable.vue b/src/shared/components/ncTable/NcTable.vue index 973821815..7c7aa88c0 100644 --- a/src/shared/components/ncTable/NcTable.vue +++ b/src/shared/components/ncTable/NcTable.vue @@ -41,19 +41,19 @@ deselect-all-rows -> unselect all rows, e.g. after deleting selected rows
+ @delete-selected-rows="rowIds => $emit('delete-selected-rows', rowIds)" />