From a01cbd26bae2f05075b0268345678d7f802cd5b5 Mon Sep 17 00:00:00 2001 From: Philipp Hempel Date: Thu, 3 Aug 2023 12:27:48 +0200 Subject: [PATCH] feat: Save/create view with frontend config repaired and improved Signed-off-by: Philipp Hempel --- lib/Service/TableService.php | 2 +- src/modules/main/modals/ViewSettings.vue | 99 ++++++++-- .../editViewPartials/SelectedViewColumns.vue | 171 ++++++++++-------- .../editViewPartials/filter/FilterForm.vue | 10 + .../editViewPartials/filter/FilterGroup.vue | 19 ++ .../sort/DeletedSortEntry.vue | 150 +++++++++++++++ .../editViewPartials/sort/SortEntry.vue | 4 + .../editViewPartials/sort/SortForm.vue | 50 ++++- src/pages/DefaultMainView.vue | 1 + .../ncTable/partials/TableHeader.vue | 55 +----- src/store/data.js | 3 + 11 files changed, 420 insertions(+), 144 deletions(-) create mode 100644 src/modules/main/partials/editViewPartials/sort/DeletedSortEntry.vue diff --git a/lib/Service/TableService.php b/lib/Service/TableService.php index bc655800f..5ce155065 100644 --- a/lib/Service/TableService.php +++ b/lib/Service/TableService.php @@ -174,7 +174,7 @@ private function enhanceTable(Table $table, string $userId): void { } catch (NotFoundError $e) { } } - if ($userId === '' || $table->getOnSharePermissions()['manage']) { + if (!$table->getIsShared() || $table->getOnSharePermissions()['manage']) { // add the corresponding views if it is an own table, or you have table manage rights $table->setViews($this->viewService->findAll($table)); } diff --git a/src/modules/main/modals/ViewSettings.vue b/src/modules/main/modals/ViewSettings.vue index 23b6b8fc6..4e28fe1bc 100644 --- a/src/modules/main/modals/ViewSettings.vue +++ b/src/modules/main/modals/ViewSettings.vue @@ -23,21 +23,35 @@ + :columns="canManageTable(view) ? allColumns : columns.map(id => allColumns.find(col => col.id === id))" + :selected-columns="selectedColumns" + :view-column-ids="view.columns" + :generated-column-ids="generatedView.columns" + :disable-hide="!canManageTable(view)" /> - - + + - +
- +
@@ -53,6 +67,7 @@ import FilterForm from '../partials/editViewPartials/filter/FilterForm.vue' import SortForm from '../partials/editViewPartials/sort/SortForm.vue' import SelectedViewColumns from '../partials/editViewPartials/SelectedViewColumns.vue' import { MetaColumns } from '../../../shared/components/ncTable/mixins/metaColumns.js' +import permissionsMixin from '../../../shared/components/ncTable/mixins/permissionsMixin.js' export default { name: 'ViewSettings', @@ -65,6 +80,7 @@ export default { SelectedViewColumns, SortForm, }, + mixins: [permissionsMixin], props: { showModal: { type: Boolean, @@ -79,6 +95,11 @@ export default { type: Boolean, default: false, }, + // Local/frontend view settings like filter, sorting, ... + viewSetting: { + type: Object, + default: null, + }, }, data() { return { @@ -93,7 +114,8 @@ export default { columns: null, draggedItem: null, startDragIndex: null, - mutableView: this.view, + mutableView: null, + generatedView: null, } }, computed: { @@ -127,16 +149,54 @@ export default { saveText() { switch (this.type) { case 'edit-table': return t('tables', 'Save Table') - case 'edit-view': return t('tables', 'Save View') + case 'edit-view': + if (this.viewSettings) return t('tables', 'Save modified View') + else return t('tables', 'Save View') case 'create-view': return t('tables', 'Create View') default: throw Error('The type ' + this.type + ' is not valid for this modal') } }, + createNewViewText() { + return t('tables', 'Create new view') + }, type() { if (!this.showModal) return 'create-view' if (this.createView) return 'create-view' else return 'edit-view' }, + generateViewConfigData() { + if (!this.viewSetting) return this.view + const mergedViewSettings = JSON.parse(JSON.stringify(this.view)) + if (this.viewSetting.hiddenColumns && this.viewSetting.hiddenColumns.length !== 0) { + mergedViewSettings.columns = this.view.columns.filter(id => !this.viewSetting.hiddenColumns.includes(id)) + } else { + mergedViewSettings.columns = this.view.columns + } + if (this.viewSetting.sorting) { + mergedViewSettings.sort = [this.viewSetting.sorting[0]] + } else { + mergedViewSettings.sort = this.view.sort + } + if (this.viewSetting.filter && this.viewSetting.filter.length !== 0) { + const filteringRules = this.viewSetting.filter.map(fil => ({ + columnId: fil.columnId, + operator: fil.operator.id, + value: fil.value, + })) + const newFilter = [] + if (this.view.filter && this.view.filter.length !== 0) { + this.view.filter.forEach(filterGroup => { + newFilter.push([...filterGroup, ...filteringRules]) + }) + } else { + newFilter[0] = filteringRules + } + mergedViewSettings.filter = newFilter + } else { + mergedViewSettings.filter = this.view.filter + } + return mergedViewSettings + }, }, watch: { title() { @@ -172,9 +232,9 @@ export default { if (this.selectedColumns === null) this.selectedColumns = this.columns.map(col => col.id) // Show columns of view first this.allColumns = this.columns.concat(this.getMetaColumns) - this.allColumns = (this.mutableView.columns ?? this.selectedColumns).map(id => this.allColumns.find(col => col.id === id)).concat(this.allColumns.filter(col => !(this.mutableView.columns ?? this.selectedColumns).includes(col.id))) + this.allColumns = (this.view.columns ?? this.selectedColumns).map(id => this.allColumns.find(col => col.id === id)).concat(this.allColumns.filter(col => !(this.view.columns ?? this.selectedColumns).includes(col.id))) }, - async actionConfirm() { + async saveView() { if (this.title === '') { let titleErrorText switch (this.type) { @@ -199,6 +259,21 @@ export default { } } }, + async createNewView() { + if (this.title === '') { + showError(t('tables', 'Cannot create view.') + ' ' + t('tables', 'Title is missing.')) + this.errorTitle = true + } else { + this.localLoading = true + this.mutableView.id = await this.sendNewViewToBE() + const success = await this.updateViewToBE(this.mutableView.id) + this.localLoading = false + if (success) { + await this.$router.push('/view/' + this.mutableView.id).catch(err => err) + this.actionCancel() + } + } + }, async sendNewViewToBE() { const data = { tableId: this.mutableView.tableId, @@ -235,7 +310,9 @@ export default { } }, reset() { - this.mutableView = this.view + // Deep copy of generated view config data + this.mutableView = JSON.parse(JSON.stringify(this.generateViewConfigData)) + this.generatedView = JSON.parse(JSON.stringify(this.generateViewConfigData)) this.title = this.mutableView.title ?? '' this.icon = this.mutableView.emoji ?? this.loadEmoji() this.errorTitle = false diff --git a/src/modules/main/partials/editViewPartials/SelectedViewColumns.vue b/src/modules/main/partials/editViewPartials/SelectedViewColumns.vue index ff0707aad..c21fa0836 100644 --- a/src/modules/main/partials/editViewPartials/SelectedViewColumns.vue +++ b/src/modules/main/partials/editViewPartials/SelectedViewColumns.vue @@ -2,7 +2,7 @@
-
@@ -15,6 +15,7 @@ @@ -71,6 +72,18 @@ export default { type: Array, default: null, }, + viewColumnIds: { + type: Array, + default: null, + }, + generatedColumnIds: { + type: Array, + default: null, + }, + disableHide: { + type: Boolean, + default: true, + }, }, data() { return { @@ -81,6 +94,9 @@ export default { } }, methods: { + isLocallyRemoved(columnId) { + return !this.selectedColumns.includes(columnId) && !this.generatedColumnIds.includes(columnId) && this.viewColumnIds.includes(columnId) + }, onToggle(columnId) { if (this.mutableSelectedColumns.includes(columnId)) { this.mutableSelectedColumns.splice(this.mutableSelectedColumns.indexOf(columnId), 1) @@ -121,80 +137,83 @@ export default { diff --git a/src/modules/main/partials/editViewPartials/filter/FilterForm.vue b/src/modules/main/partials/editViewPartials/filter/FilterForm.vue index c306f0539..a7bef97f9 100644 --- a/src/modules/main/partials/editViewPartials/filter/FilterForm.vue +++ b/src/modules/main/partials/editViewPartials/filter/FilterForm.vue @@ -6,6 +6,8 @@
@@ -45,6 +47,14 @@ export default { type: Array, default: null, }, + viewFilters: { + type: Array, + default: null, + }, + generatedFilters: { + type: Array, + default: null, + }, columns: { type: Array, default: null, diff --git a/src/modules/main/partials/editViewPartials/filter/FilterGroup.vue b/src/modules/main/partials/editViewPartials/filter/FilterGroup.vue index 78e8d584b..961f25bba 100644 --- a/src/modules/main/partials/editViewPartials/filter/FilterGroup.vue +++ b/src/modules/main/partials/editViewPartials/filter/FilterGroup.vue @@ -8,6 +8,7 @@
object[key] === searchObject[key]) + }, + isLocallyAdded(filter) { + return this.generatedFilterGroup.some(e => this.isSameEntry(e, filter)) && !this.viewFilterGroup.some(e => this.isSameEntry(e, filter)) + }, addFilter() { this.mutableFilterGroup.push({ columnId: null, operator: null, value: '' }) }, @@ -79,4 +94,8 @@ export default { border-left: 6px solid var(--color-primary) !important; padding-left: calc(var(--default-grid-baseline) * 2); } + +.locallyAdded { + background-color: var(--color-success-hover); +} diff --git a/src/modules/main/partials/editViewPartials/sort/DeletedSortEntry.vue b/src/modules/main/partials/editViewPartials/sort/DeletedSortEntry.vue new file mode 100644 index 000000000..6570927e3 --- /dev/null +++ b/src/modules/main/partials/editViewPartials/sort/DeletedSortEntry.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/src/modules/main/partials/editViewPartials/sort/SortEntry.vue b/src/modules/main/partials/editViewPartials/sort/SortEntry.vue index 1f7bf6473..0e851dfd7 100644 --- a/src/modules/main/partials/editViewPartials/sort/SortEntry.vue +++ b/src/modules/main/partials/editViewPartials/sort/SortEntry.vue @@ -78,6 +78,10 @@ export default { } }, watch: { + sortEntry() { + console.debug("Resetting!!!!") + this.reset() + }, selectedColumn() { this.mutableSortEntry.columnId = this.selectedColumn?.id }, diff --git a/src/modules/main/partials/editViewPartials/sort/SortForm.vue b/src/modules/main/partials/editViewPartials/sort/SortForm.vue index 64a2a84e4..a04666f17 100644 --- a/src/modules/main/partials/editViewPartials/sort/SortForm.vue +++ b/src/modules/main/partials/editViewPartials/sort/SortForm.vue @@ -1,7 +1,17 @@