Skip to content

Commit

Permalink
feat: Save/create view with frontend config repaired and improved
Browse files Browse the repository at this point in the history
Signed-off-by: Philipp Hempel <Philipp.Hempel1@web.de>
  • Loading branch information
Hephi2 committed Aug 3, 2023
1 parent 04d7e4d commit a01cbd2
Show file tree
Hide file tree
Showing 11 changed files with 420 additions and 144 deletions.
2 changes: 1 addition & 1 deletion lib/Service/TableService.php
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
99 changes: 88 additions & 11 deletions src/modules/main/modals/ViewSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,35 @@
<!--columns & order-->
<NcAppSettingsSection v-if="columns != null" id="columns-and-order" :title="t('tables', 'Columns')">
<SelectedViewColumns
:columns="allColumns"
:selected-columns="selectedColumns" />
: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)" />
</NcAppSettingsSection>
<!--filtering-->
<NcAppSettingsSection v-if="columns != null" id="filter" :title="t('tables', 'Filter')">
<FilterForm :filters="mutableView.filter" :columns="allColumns" />
<NcAppSettingsSection v-if="columns != null && canManageTable(view)" id="filter" :title="t('tables', 'Filter')">
<FilterForm
:filters="mutableView.filter"
:view-filters="view.filter"
:generated-filters="generatedView.filter"
:columns="allColumns" />
</NcAppSettingsSection>
<!--sorting-->
<NcAppSettingsSection v-if="columns != null" id="sort" :title="t('tables', 'Sort')">
<SortForm :sort="mutableView.sort" :columns="allColumns" />
<SortForm
:sort="mutableView.sort"
:view-sort="view.sort"
:generated-sort="generatedView.sort"
:columns="allColumns" />
</NcAppSettingsSection>

<div class="row sticky">
<div class="fix-col-4 space-T end">
<button v-if="!localLoading" class="primary" :aria-label="saveText" @click="actionConfirm()">
<button v-if="!localLoading && type === 'edit-view'" class="primary" :aria-label="createNewViewText" @click="createNewView()">
{{ createNewViewText }}
</button>
<button v-if="!localLoading" class="primary" :aria-label="saveText" @click="saveView()">
{{ saveText }}
</button>
</div>
Expand All @@ -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',
Expand All @@ -65,6 +80,7 @@ export default {
SelectedViewColumns,
SortForm,
},
mixins: [permissionsMixin],
props: {
showModal: {
type: Boolean,
Expand All @@ -79,6 +95,11 @@ export default {
type: Boolean,
default: false,
},
// Local/frontend view settings like filter, sorting, ...
viewSetting: {
type: Object,
default: null,
},
},
data() {
return {
Expand All @@ -93,7 +114,8 @@ export default {
columns: null,
draggedItem: null,
startDragIndex: null,
mutableView: this.view,
mutableView: null,
generatedView: null,
}
},
computed: {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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) {
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down
171 changes: 95 additions & 76 deletions src/modules/main/partials/editViewPartials/SelectedViewColumns.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="selected-columns-wrapper"
@dragenter.prevent
@dragover.prevent>
<div v-for="(column, index) in columns" :key="column.id" :draggable="true"
<div v-for="(column, index) in columns" :key="column.id" :draggable="true" :class="{'locallyRemoved': isLocallyRemoved(column.id)}"
class="column-entry" @dragstart="dragStart(index)"
@dragover="dragOver(index)" @dragend="dragEnd(index)">
<div class="row-elements">
Expand All @@ -15,6 +15,7 @@
</template>
</NcButton>
<NcCheckboxRadioSwitch
v-if="!disableHide"
:checked="selectedColumns.includes(column.id)"
class="display-checkbox"
@update:checked="onToggle(column.id)" />
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
Expand Down Expand Up @@ -121,80 +137,83 @@ export default {

<style lang="scss" scoped>
.column-entry {
display: flex;
justify-content: space-between;
align-items: center;
padding: calc(var(--default-grid-baseline) * 1) 0;
border-radius: var(--border-radius-large);
}
.column-entry:hover {
background-color: var(--color-background-dark);
}
.display-checkbox {
padding-right: calc(var(--default-grid-baseline) * 4);
}
:deep(.modal-container) {
min-width: 60% !important;
}
:deep(.button-vue) {
cursor: move !important;
min-height: auto !important;
min-width: auto !important;
}
:deep(.button-vue__icon) {
height: auto !important;
width: auto !important;
min-height: auto !important;
min-width: auto !important;
}
:deep(.checkbox-radio-switch__label) {
min-height: auto;
padding: 4px;
}
:deep(.checkbox-radio-switch__icon) {
margin-right: 0 !important;
margin-left: 0 !important;
}
.selected-columns-wrapper {
display: flex;
flex-direction: column;
}
.move-button {
padding-right: 10px !important;
cursor: move !important;
}
.move-button:hover {
cursor: move !important;
}
.meta-info {
font-style: italic;
padding-left: calc(var(--default-grid-baseline) * 1);
color: var(--color-info);
}
.row-elements {
display: flex;
align-items: center;
}
.row-elements.move {
display: none;
}
.column-entry:hover .row-elements.move, .column-entry:focus-within .row-elements.move {
display: flex;
}
.column-entry {
display: flex;
justify-content: space-between;
align-items: center;
padding: calc(var(--default-grid-baseline) * 1) 0;
border-radius: var(--border-radius-large);
}
.column-entry:hover {
background-color: var(--color-background-dark);
}
.display-checkbox {
padding-right: calc(var(--default-grid-baseline) * 4);
}
:deep(.modal-container) {
min-width: 60% !important;
}
:deep(.button-vue) {
cursor: move !important;
min-height: auto !important;
min-width: auto !important;
}
:deep(.button-vue__icon) {
height: auto !important;
width: auto !important;
min-height: auto !important;
min-width: auto !important;
}
:deep(.checkbox-radio-switch__label) {
min-height: auto;
padding: 4px;
}
:deep(.checkbox-radio-switch__icon) {
margin-right: 0 !important;
margin-left: 0 !important;
}
.selected-columns-wrapper {
display: flex;
flex-direction: column;
}
.move-button {
padding-right: 10px !important;
cursor: move !important;
}
.move-button:hover {
cursor: move !important;
}
.meta-info {
font-style: italic;
padding-left: calc(var(--default-grid-baseline) * 1);
color: var(--color-info);
}
.row-elements {
display: flex;
align-items: center;
}
.row-elements.move {
display: none;
}
.column-entry:hover .row-elements.move, .column-entry:focus-within .row-elements.move {
display: flex;
}
.locallyRemoved {
background-color: var(--color-error-hover);
}
</style>
Loading

0 comments on commit a01cbd2

Please sign in to comment.