Merge pull request #6930 from aignatov-bio/ai-sci-9985-add-sorting-to-cards

Add sorting to cards view [SCI-9985]
This commit is contained in:
aignatov-bio 2024-01-12 14:53:49 +01:00 committed by GitHub
commit 0fe7c040a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 6 deletions

View file

@ -14,9 +14,11 @@
:filters="filters" :filters="filters"
:columnDefs="columnDefs" :columnDefs="columnDefs"
:tableState="tableState" :tableState="tableState"
:order="order"
@applyFilters="applyFilters" @applyFilters="applyFilters"
@setTableView="switchViewRender('table')" @setTableView="switchViewRender('table')"
@setCardsView="switchViewRender('cards')" @setCardsView="switchViewRender('cards')"
@sort="applyOrder"
@hideColumn="hideColumn" @hideColumn="hideColumn"
@showColumn="showColumn" @showColumn="showColumn"
/> />
@ -248,6 +250,8 @@ export default {
} }
}, },
currentViewRender() { currentViewRender() {
this.columnApi = null;
this.gridApi = null;
this.saveTableState(); this.saveTableState();
}, },
perPage() { perPage() {
@ -258,7 +262,7 @@ export default {
if (this.tableState) { if (this.tableState) {
this.currentViewRender = this.tableState.currentViewRender || 'table'; this.currentViewRender = this.tableState.currentViewRender || 'table';
this.perPage = this.tableState.perPage || 20; this.perPage = this.tableState.perPage || 20;
[this.order] = this.getOrder(this.tableState.columnsState); this.order = this.tableState.order;
} }
}, },
mounted() { mounted() {
@ -328,6 +332,13 @@ export default {
this.columnApi = params.columnApi; this.columnApi = params.columnApi;
if (this.tableState) { if (this.tableState) {
if (this.order) {
this.tableState.columnsState.forEach((column) => {
const updatedColumn = column;
updatedColumn.sort = this.order.column === column.colId ? this.order.dir : null;
return updatedColumn;
});
}
this.columnApi.applyColumnState({ this.columnApi.applyColumnState({
state: this.tableState.columnsState, state: this.tableState.columnsState,
applyOrder: true applyOrder: true
@ -363,6 +374,7 @@ export default {
} }
const tableState = { const tableState = {
columnsState: columnsState || [], columnsState: columnsState || [],
order: this.order,
currentViewRender: this.currentViewRender, currentViewRender: this.currentViewRender,
perPage: this.perPage perPage: this.perPage
}; };
@ -410,6 +422,14 @@ export default {
column: column.colId, column: column.colId,
dir: column.sort dir: column.sort
})); }));
},
applyOrder(column, dir) {
this.order = {
column,
dir
};
this.saveTableState();
this.reloadTable();
} }
} }
}; };

View file

@ -76,6 +76,28 @@
@click="$emit('search:change', '')"></i> @click="$emit('search:change', '')"></i>
</div> </div>
<FilterDropdown v-else :filters="filters" @applyFilters="applyFilters" /> <FilterDropdown v-else :filters="filters" @applyFilters="applyFilters" />
<GeneralDropdown v-if="currentViewRender === 'cards'" ref="dropdown" position="right">
<template v-slot:field>
<button class="btn btn-light icon-btn">
<i class="sn-icon sn-icon-sort-down"></i>
</button>
</template>
<template v-slot:flyout >
<div class="min-w-[12rem]">
<div v-for="col in sortableColumns"
class="flex whitespace-nowrap rounded px-3 py-2.5 hover:!text-sn-blue items-center h-11
hover:no-underline cursor-pointer hover:bg-sn-super-light-grey leading-5"
:key="col.field"
@click="$emit('sort', col.field, (order?.dir === 'asc' ? 'desc' : 'asc'))">
<span>{{ col.headerName }}</span>
<div v-if="order && order.column === col.field" class="ml-auto">
<i v-if="order.dir === 'asc'" class="sn-icon sn-icon-sort-up"></i>
<i v-else class="sn-icon sn-icon-sort-down"></i>
</div>
</div>
</div>
</template>
</GeneralDropdown>
</div> </div>
<teleport to="body"> <teleport to="body">
<ColumnsModal <ColumnsModal
@ -91,6 +113,7 @@
<script> <script>
import MenuDropdown from '../menu_dropdown.vue'; import MenuDropdown from '../menu_dropdown.vue';
import GeneralDropdown from '../general_dropdown.vue';
import FilterDropdown from '../filters/filter_dropdown.vue'; import FilterDropdown from '../filters/filter_dropdown.vue';
import ColumnsModal from './modals/columns.vue'; import ColumnsModal from './modals/columns.vue';
@ -131,12 +154,16 @@ export default {
}, },
tableState: { tableState: {
type: Object type: Object
},
order: {
type: Object
} }
}, },
components: { components: {
MenuDropdown, MenuDropdown,
FilterDropdown, FilterDropdown,
ColumnsModal ColumnsModal,
GeneralDropdown
}, },
computed: { computed: {
viewModesMenu() { viewModesMenu() {
@ -159,6 +186,9 @@ export default {
return view; return view;
} }
}); });
},
sortableColumns() {
return this.columnDefs.filter((column) => column.sortable);
} }
}, },
data() { data() {

View file

@ -58,9 +58,7 @@ export default {
}, },
methods: { methods: {
closeMenu(e) { closeMenu(e) {
if (e && e.target.closest('.sn-dropdown, .sn-select-dropdown, .dp__instance_calendar')) return; if (e && e.target.closest('.sn-dropdown, .sn-select-dropdown, .dp__instance_calendar')) return;
this.isOpen = false; this.isOpen = false;
} }
} }

View file

@ -8,12 +8,12 @@
</button> </button>
<teleport to="body"> <teleport to="body">
<div ref="flyout" <div ref="flyout"
v-if="isOpen"
class="fixed z-[3000] bg-sn-white inline-block rounded p-2.5 sn-shadow-menu-sm flex flex-col gap-[1px]" class="fixed z-[3000] bg-sn-white inline-block rounded p-2.5 sn-shadow-menu-sm flex flex-col gap-[1px]"
:class="{ :class="{
'right-0': position === 'right', 'right-0': position === 'right',
'left-0': position === 'left', 'left-0': position === 'left',
}" }"
v-if="isOpen"
> >
<span v-for="(item, i) in listItems" :key="i" class="contents"> <span v-for="(item, i) in listItems" :key="i" class="contents">
<div v-if="item.dividerBefore" class="border-0 border-t border-solid border-sn-light-grey"></div> <div v-if="item.dividerBefore" class="border-0 border-t border-solid border-sn-light-grey"></div>

View file

@ -9,14 +9,16 @@ export default {
isOpen() { isOpen() {
if (this.isOpen) { if (this.isOpen) {
this.$nextTick(() => { this.$nextTick(() => {
this.setPosition();
this.overflowContainerListener(); this.overflowContainerListener();
}); });
} }
}, }
}, },
methods: { methods: {
overflowContainerListener() { overflowContainerListener() {
const { field, flyout } = this.$refs; const { field, flyout } = this.$refs;
if (!field || !flyout) return; if (!field || !flyout) return;
const fieldRect = field.getBoundingClientRect(); const fieldRect = field.getBoundingClientRect();