Update columns manage modal [SCI-10090]

This commit is contained in:
Anton 2024-01-31 15:05:16 +01:00
parent 72b40a63a0
commit f43718ea6d
4 changed files with 168 additions and 33 deletions

View file

@ -11,31 +11,51 @@
</h4>
</div>
<div class="modal-body">
<p class='modal-description'>
{{ i18n.t("experiments.table.column_display_modal.description") }}
</p>
<div class="max-h-90 overflow-y-auto">
<div
v-for="column in columnDefs"
:key="column.field"
@click="toggleColumn(column, columnVisbile(column))"
class="flex items-center gap-4 py-2.5 px-3"
:class="{
'cursor-pointer': column.field !== 'name',
'hover:bg-sn-super-light-grey': column.field !== 'name'
}"
<Draggable
v-model="columnsList"
:forceFallback="true"
:handle="'.element-grip'"
item-key="field"
@end="endReorder"
>
<div v-if="column.field === 'name'" class="w-6 h-6"></div>
<template v-else>
<i v-if="columnVisbile(column)"
class="sn-icon sn-icon-visibility-show"></i>
<i v-else
class="sn-icon sn-icon-visibility-hide"></i>
</template>
<div class="truncate">{{ column.headerName }}</div>
</div>
<template #item="{element}">
<div
class="flex items-center gap-4 py-2.5 px-3 group/column"
:class="{
'hover:bg-sn-super-light-grey': element.field !== 'pinnedSeparator',
'!py-2.5': element.field === 'pinnedSeparator',
'text-sn-grey': (element.field !== 'pinnedSeparator' && !columnVisbile(element))
}"
>
<div v-if="element.field == 'pinnedSeparator'" class="h-[1px] w-full bg-sn-sleepy-grey"></div>
<template v-else>
<div class="opacity-0 group-hover/column:!opacity-100 element-grip cursor-pointer">
<i class="sn-icon sn-icon-drag"></i>
</div>
<div v-if="element.field === 'name'" class="w-6 h-6"></div>
<template v-else>
<i v-if="columnVisbile(element)" @click="toggleColumn(element, true)"
class="sn-icon sn-icon-visibility-show cursor-pointer"></i>
<i v-else @click="toggleColumn(element, false)"
class="sn-icon sn-icon-visibility-hide cursor-pointer"></i>
</template>
<div class="truncate">{{ element.headerName }}</div>
<div class="ml-auto cursor-pointer">
<i v-if="columnPinned(element)" @click="unPinColumn(element)" class="sn-icon sn-icon-pinned"></i>
<i v-else @click="pinColumn(element)" class="sn-icon sn-icon-pin"></i>
</div>
</template>
</div>
</template>
</Draggable>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary mr-auto" @click="resetToDefault">
{{ i18n.t('experiments.table.column_display_modal.reset_to_default') }}
</button>
</div>
</div>
</div>
</div>
@ -43,6 +63,7 @@
<script>
import modalMixin from '../../modal_mixin';
import Draggable from 'vuedraggable';
export default {
name: 'NewModal',
@ -50,28 +71,93 @@ export default {
columnDefs: { type: Array, required: true },
tableState: { type: Object }
},
components: {
Draggable
},
data() {
return {
currentTableState: {}
currentTableState: {},
columnsList: []
};
},
created() {
this.currentTableState = this.tableState;
this.syncColumns();
},
watch: {
tableState: {
handler() {
this.syncColumns();
},
deep: true
}
},
mixins: [modalMixin],
methods: {
resetToDefault() {
this.$emit('resetToDefault');
this.close();
},
columnVisbile(column) {
return !this.currentTableState.columnsState?.find((col) => col.colId === column.field).hide;
},
columnPinned(column) {
return this.currentTableState.columnsState?.find((col) => col.colId === column.field).pinned;
},
toggleColumn(column, visible) {
if (column.field === 'name') return;
this.currentTableState.columnsState.find((col) => col.colId === column.field).hide = visible;
if (visible) {
this.$emit('hideColumn', column);
} else {
this.$emit('showColumn', column);
}
},
pinColumn(column) {
this.$emit('pinColumn', column);
},
unPinColumn(column) {
this.$emit('unPinColumn', column);
},
syncColumns() {
this.currentTableState = this.tableState;
this.currentTableState.columnsState.forEach((col, index) => {
col.position = index;
});
let columns = this.currentTableState.columnsState
.sort((a, b) => {
if (a.pinned === b.pinned) {
return a.position - b.position;
}
return a.pinned ? -1 : 1;
});
const pinnedAmount = columns.filter((col) => col.pinned).length;
columns = columns
.map((col) => this.columnDefs.find((c) => c.field === col.colId))
.filter((col) => col);
this.columnsList = [
...columns.slice(0, pinnedAmount - 1),
{ field: 'pinnedSeparator' },
...columns.slice(pinnedAmount - 1)
];
},
endReorder(event) {
this.$nextTick(() => {
const { newIndex } = event;
const columnName = this.columnsList[newIndex].field;
const separatorIndex = this.columnsList.findIndex((col) => col.field === 'pinnedSeparator');
const reordedColumns = this.columnsList.filter((col) => col.field !== 'pinnedSeparator');
const columnsOrdered = reordedColumns.map((col) => col.field);
this.$emit('reorderColumns', columnsOrdered);
if (newIndex <= separatorIndex) {
this.pinColumn(this.columnDefs.find((col) => col.field === columnName));
} else {
this.unPinColumn(this.columnDefs.find((col) => col.field === columnName));
}
});
}
}
};

View file

@ -21,6 +21,10 @@
@sort="applyOrder"
@hideColumn="hideColumn"
@showColumn="showColumn"
@pinColumn="pinColumn"
@unPinColumn="unPinColumn"
@reorderColumns="reorderColumns"
@resetColumnsToDefault="resetColumnsToDefault"
/>
<div v-if="currentViewRender === 'cards'" ref="cardsContainer" @scroll="handleScroll"
class="flex-grow basis-64 overflow-y-auto overflow-x-visible p-2 -ml-2">
@ -168,7 +172,8 @@ export default {
currentViewRender: 'table',
cardCheckboxes: [],
dataLoading: true,
lastPage: false
lastPage: false,
tableState: null
};
},
components: {
@ -185,11 +190,6 @@ export default {
perPageOptions() {
return [10, 20, 50, 100].map((value) => ([value, `${value} ${this.i18n.t('datatable.rows')}`]));
},
tableState() {
if (!localStorage.getItem(`datatable:${this.tableId}_columns_state`)) return null;
return JSON.parse(localStorage.getItem(`datatable:${this.tableId}_columns_state`));
},
actionsParams() {
return {
items: JSON.stringify(this.selectedRows.map((row) => ({ id: row.id, type: row.type })))
@ -219,7 +219,8 @@ export default {
suppressMovable: true,
width: 48,
minWidth: 48,
resizable: false,
maxWidth: 48,
resizable: true,
pinned: 'left',
lockPosition: 'left'
});
@ -267,6 +268,10 @@ export default {
}
},
created() {
if (localStorage.getItem(`datatable:${this.tableId}_columns_state`)) {
this.tableState = JSON.parse(localStorage.getItem(`datatable:${this.tableId}_columns_state`));
}
if (this.tableState) {
this.currentViewRender = this.tableState.currentViewRender || 'table';
this.perPage = this.tableState.perPage || 20;
@ -431,6 +436,7 @@ export default {
perPage: this.perPage
};
localStorage.setItem(`datatable:${this.tableId}_columns_state`, JSON.stringify(tableState));
this.tableState = tableState;
},
setSelectedRows() {
this.selectedRows = this.gridApi.getSelectedRows();
@ -466,6 +472,23 @@ export default {
this.columnApi.setColumnVisible(column.field, true);
this.saveTableState();
},
pinColumn(column) {
this.columnApi.setColumnPinned(column.field, 'left');
this.saveTableState();
},
unPinColumn(column) {
this.columnApi.setColumnPinned(column.field, null);
this.saveTableState();
},
reorderColumns(columns) {
this.columnApi.moveColumns(columns, 1);
this.saveTableState();
},
resetColumnsToDefault() {
this.columnApi.resetColumnState();
this.columnApi.autoSizeAllColumns();
this.saveTableState();
},
getOrder(columnsState) {
if (!columnsState) return null;

View file

@ -105,9 +105,22 @@
:columnDefs="columnDefs"
@hideColumn="(column) => $emit('hideColumn', column)"
@showColumn="(column) => $emit('showColumn', column)"
@unPinColumn="(column) => $emit('unPinColumn', column)"
@pinColumn="(column) => $emit('pinColumn', column)"
@reorderColumns="(columns) => $emit('reorderColumns', columns)"
@resetToDefault="resetToDefault"
v-if="showColumnsModal"
@close="showColumnsModal = false" />
</teleport>
<teleport to="body">
<ConfirmationModal
:title="i18n.t('experiments.table.column_display_modal.confirmation.title')"
:description="i18n.t('experiments.table.column_display_modal.confirmation.description_html')"
confirmClass="btn btn-primary"
:confirmText="i18n.t('experiments.table.column_display_modal.confirmation.confirm')"
ref="resetColumnModal"
></ConfirmationModal>
</teleport>
</div>
</template>
@ -116,6 +129,7 @@ import MenuDropdown from '../menu_dropdown.vue';
import GeneralDropdown from '../general_dropdown.vue';
import FilterDropdown from '../filters/filter_dropdown.vue';
import ColumnsModal from './modals/columns.vue';
import ConfirmationModal from '../confirmation_modal.vue';
export default {
name: 'Toolbar',
@ -163,7 +177,8 @@ export default {
MenuDropdown,
FilterDropdown,
ColumnsModal,
GeneralDropdown
GeneralDropdown,
ConfirmationModal
},
computed: {
viewModesMenu() {
@ -230,6 +245,12 @@ export default {
},
handleEvent(event) {
this.$emit('toolbar:action', { name: event });
},
async resetToDefault() {
const ok = await this.$refs.resetColumnModal.show();
if (ok) {
this.$emit('resetColumnsToDefault');
}
}
}
};

View file

@ -1551,8 +1551,13 @@ en:
success_flash: "Successfully moved task(s) to experiment %{experiment}."
error_flash: "Failed to move task(s) to experiment %{experiment}."
column_display_modal:
title: 'Columns display'
title: 'Manage columns'
description: 'Click the eye buttons to hide or show columns in the table'
reset_to_default: 'Reset to default'
confirmation:
title: 'Reset to defaults'
description_html: 'With confirmation the order, width and visibility of columns will be set to the default values.<br><br><b>Are you sure you want to to reset to default?</b>'
confirm: 'Reset'
id: 'ID'
task_name: 'Task name'
due_date: 'Due date'