Add sorting to global search [SCI-10528]

This commit is contained in:
Anton 2024-04-08 12:54:46 +02:00
parent 1e7bb69763
commit c2da52a6bb
14 changed files with 186 additions and 98 deletions

View file

@ -1,10 +1,13 @@
<template>
<div v-if="total" class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-files"></i>
{{ i18n.t('search.index.files') }}
[{{ total }}]
</h2>
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-files"></i>
{{ i18n.t('search.index.files') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div>
<div class="grid grid-cols-[auto_auto_auto_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">

View file

@ -1,10 +1,13 @@
<template>
<div v-if="total" class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-experiment"></i>
{{ i18n.t('search.index.experiments') }}
[{{ total }}]
</h2>
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-experiment"></i>
{{ i18n.t('search.index.experiments') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div>
<div class="grid grid-cols-[auto_80px_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">

View file

@ -1,10 +1,13 @@
<template>
<div v-if="total" class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-folder"></i>
{{ i18n.t('search.index.folders') }}
[{{ total }}]
</h2>
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-folder"></i>
{{ i18n.t('search.index.folders') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div>
<div class="grid grid-cols-[auto_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id" class="hover:bg-sn-super-light-grey">

View file

@ -1,10 +1,13 @@
<template>
<div class="bg-white rounded p-4 mb-4" v-if="!disabled">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-label-templates"></i>
{{ i18n.t('search.index.label_templates') }}
[{{ total }}]
</h2>
<div class="bg-white rounded p-4 mb-4" v-if="total">
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-label-templates"></i>
{{ i18n.t('search.index.label_templates') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div>
<div class="grid grid-cols-[auto_110px_auto_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">

View file

@ -1,10 +1,13 @@
<template>
<div v-if="total" class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-protocols-templates"></i>
{{ i18n.t('search.index.task_protocols') }}
[{{ total }}]
</h2>
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-protocols-templates"></i>
{{ i18n.t('search.index.task_protocols') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div>
<div class="grid grid-cols-[auto_80px_auto_auto_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">

View file

@ -1,10 +1,13 @@
<template>
<div v-if="total" class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-task"></i>
{{ i18n.t('search.index.tasks') }}
[{{ total }}]
</h2>
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-task"></i>
{{ i18n.t('search.index.tasks') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div>
<div class="grid grid-cols-[auto_80px_auto_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">

View file

@ -1,10 +1,13 @@
<template>
<div v-if="total" class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-projects"></i>
{{ i18n.t('search.index.projects') }}
[{{ total }}]
</h2>
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-projects"></i>
{{ i18n.t('search.index.projects') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div>
<div class="grid grid-cols-[auto_80px_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">

View file

@ -1,10 +1,13 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-protocols-templates"></i>
{{ i18n.t('search.index.protocol_templates') }}
[{{ total }}]
</h2>
<div v-if="total" class="bg-white rounded p-4 mb-4">
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-protocols-templates"></i>
{{ i18n.t('search.index.protocol_templates') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div>
<div class="grid grid-cols-[auto_110px_auto_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">

View file

@ -1,10 +1,13 @@
<template>
<div v-if="total" class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-reports"></i>
{{ i18n.t('search.index.reports') }}
[{{ total }}]
</h2>
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-reports"></i>
{{ i18n.t('search.index.reports') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div>
<div class="grid grid-cols-[auto_110px_auto_auto_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">

View file

@ -1,10 +1,13 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-inventory"></i>
{{ i18n.t('search.index.inventory_items') }}
[{{ total }}]
</h2>
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-inventory"></i>
{{ i18n.t('search.index.inventory_items') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div>
<div class="grid grid-cols-[auto_110px_auto_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">

View file

@ -1,51 +1,52 @@
<template>
<div v-if="total" class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-results"></i>
{{ i18n.t('search.index.task_results') }}
[{{ total }}]
</h2>
</div>
<div>
<div class="grid grid-cols-[auto_auto_auto_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">
<a :href="row.attributes.url" target="_blank" class="h-full py-2 px-4 overflow-hidden font-bold border-0 border-b border-solid border-sn-light-grey">
<StringWithEllipsis class="w-full" :text="row.attributes.name"></StringWithEllipsis>
</a>
<div class="h-full py-2 px-4 flex items-center gap-1 text-xs border-0 border-b border-solid border-sn-light-grey max-w-[200px]">
<b class="shrink-0">{{ i18n.t('search.index.created_at') }}:</b>
<span class="truncate">{{ row.attributes.created_at }}</span>
</div>
<div class="h-full py-2 px-4 flex items-center gap-1 text-xs border-0 border-b border-solid border-sn-light-grey max-w-[200px]">
<b class="shrink-0">{{ i18n.t('search.index.updated_at') }}:</b>
<span class="truncate">{{ row.attributes.updated_at }}</span>
</div>
<div class="h-full py-2 px-4 grid grid-cols-[auto_1fr] items-center gap-1 text-xs border-0 border-b border-solid border-sn-light-grey">
<b class="shrink-0">{{ i18n.t('search.index.team') }}:</b>
<a :href="row.attributes.team.url" class="shrink-0 overflow-hidden" target="_blank">
<StringWithEllipsis class="w-full" :text="row.attributes.team.name"></StringWithEllipsis>
</a>
</div>
<div class="h-full py-2 px-4 grid grid-cols-[auto_1fr] items-center gap-1 text-xs border-0 border-b border-solid border-sn-light-grey">
<b class="shrink-0">{{ i18n.t('search.index.task') }}:</b>
<a :href="row.attributes.my_module.url" class="shrink-0 overflow-hidden" target="_blank">
<StringWithEllipsis class="w-full" :text="row.attributes.my_module.name"></StringWithEllipsis>
</a>
</div>
<div class="h-full py-2 px-4 border-0 border-b border-solid border-sn-light-grey">
<div class="grid grid-cols-[auto_1fr] items-center gap-1 text-xs w-full">
<b class="shrink-0">{{ i18n.t('search.index.experiment') }}:</b>
<a :href="row.attributes.experiment.url" class="shrink-0 overflow-hidden" target="_blank">
<StringWithEllipsis class="w-full" :text="row.attributes.experiment.name"></StringWithEllipsis>
</a>
</div>
</div>
</template>
</div>
<div v-if="viewAll" class="mt-4">
<button class="btn btn-light" @click="$emit('selectGroup', 'ResultsComponent')">View all</button>
</div>
<div class="flex items-center">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-results"></i>
{{ i18n.t('search.index.task_results') }}
[{{ total }}]
</h2>
<SortFlyout v-if="selected" :sort="sort" @changeSort="changeSort"></SortFlyout>
</div>
<div class="grid grid-cols-[auto_auto_auto_auto_auto_auto] items-center">
<template v-for="row in preparedResults" :key="row.id">
<a :href="row.attributes.url" target="_blank" class="h-full py-2 px-4 overflow-hidden font-bold border-0 border-b border-solid border-sn-light-grey">
<StringWithEllipsis class="w-full" :text="row.attributes.name"></StringWithEllipsis>
</a>
<div class="h-full py-2 px-4 flex items-center gap-1 text-xs border-0 border-b border-solid border-sn-light-grey max-w-[200px]">
<b class="shrink-0">{{ i18n.t('search.index.created_at') }}:</b>
<span class="truncate">{{ row.attributes.created_at }}</span>
</div>
<div class="h-full py-2 px-4 flex items-center gap-1 text-xs border-0 border-b border-solid border-sn-light-grey max-w-[200px]">
<b class="shrink-0">{{ i18n.t('search.index.updated_at') }}:</b>
<span class="truncate">{{ row.attributes.updated_at }}</span>
</div>
<div class="h-full py-2 px-4 grid grid-cols-[auto_1fr] items-center gap-1 text-xs border-0 border-b border-solid border-sn-light-grey">
<b class="shrink-0">{{ i18n.t('search.index.team') }}:</b>
<a :href="row.attributes.team.url" class="shrink-0 overflow-hidden" target="_blank">
<StringWithEllipsis class="w-full" :text="row.attributes.team.name"></StringWithEllipsis>
</a>
</div>
<div class="h-full py-2 px-4 grid grid-cols-[auto_1fr] items-center gap-1 text-xs border-0 border-b border-solid border-sn-light-grey">
<b class="shrink-0">{{ i18n.t('search.index.task') }}:</b>
<a :href="row.attributes.my_module.url" class="shrink-0 overflow-hidden" target="_blank">
<StringWithEllipsis class="w-full" :text="row.attributes.my_module.name"></StringWithEllipsis>
</a>
</div>
<div class="h-full py-2 px-4 border-0 border-b border-solid border-sn-light-grey">
<div class="grid grid-cols-[auto_1fr] items-center gap-1 text-xs w-full">
<b class="shrink-0">{{ i18n.t('search.index.experiment') }}:</b>
<a :href="row.attributes.experiment.url" class="shrink-0 overflow-hidden" target="_blank">
<StringWithEllipsis class="w-full" :text="row.attributes.experiment.name"></StringWithEllipsis>
</a>
</div>
</div>
</template>
</div>
<div v-if="viewAll" class="mt-4">
<button class="btn btn-light" @click="$emit('selectGroup', 'ResultsComponent')">View all</button>
</div>
</div>
</template>
<script>

View file

@ -1,5 +1,6 @@
import axios from '../../../packs/custom_axios.js';
import StringWithEllipsis from '../../shared/string_with_ellipsis.vue';
import SortFlyout from './sort_flyout.vue';
/* global GLOBAL_CONSTANTS */
export default {
@ -10,10 +11,12 @@ export default {
filters: Object
},
components: {
StringWithEllipsis
StringWithEllipsis,
SortFlyout
},
data() {
return {
sort: 'created_desc',
results: [],
total: 0,
loading: false,
@ -66,6 +69,12 @@ export default {
}
}
},
changeSort(sort) {
this.sort = sort;
this.results = [];
this.page = 1;
this.loadData();
},
loadData() {
if (this.loading && this.page) return;
@ -73,6 +82,7 @@ export default {
axios.get(this.searchUrl, {
params: {
q: this.query,
sort: this.sort,
filters: this.filters,
group: this.group,
preview: !this.selected,

View file

@ -0,0 +1,43 @@
<template>
<MenuDropdown
class="ml-auto"
:listItems="sortOptions"
btnClasses="btn btn-light icon-btn btn-black"
position="right"
@dtEvent="changeSort"
btnIcon="sn-icon sn-icon-sort-down"
></MenuDropdown>
</template>
<script>
import MenuDropdown from '../../shared/menu_dropdown.vue';
export default {
name: 'SortFlyout',
props: {
sort: {
type: String,
default: 'created_desc'
}
},
components: {
MenuDropdown
},
computed: {
sortOptions() {
return ['created_desc', 'created_asc', 'atoz', 'ztoa'].map((sort) => (
{
emit: sort,
text: this.i18n.t(`search.index.${sort}`),
active: this.sort === sort
}
));
}
},
methods: {
changeSort(value) {
this.$emit('changeSort', value);
}
}
};
</script>

View file

@ -481,6 +481,10 @@ en:
untitled_protocol: 'Untitled protocol'
protocol_template: "Protocol template"
inventory_item: "Inventory item"
created_desc: "Created last"
created_asc: "Created first"
atoz: "Name A to Z"
ztoa: "Name Z to A"
comments:
save_changes: "Save changes"
empty_state: