2023-09-24 20:10:53 +08:00
|
|
|
<template>
|
2023-11-24 18:08:28 +08:00
|
|
|
<div class="flex py-4 items-center justify-between">
|
2023-09-24 20:10:53 +08:00
|
|
|
<div class="flex items-center gap-4">
|
2023-12-28 03:09:36 +08:00
|
|
|
<template v-for="action in toolbarActions.left" :key="action.label">
|
2024-01-11 02:56:01 +08:00
|
|
|
<a v-if="action.type === 'emit' || action.type === 'link'"
|
2023-12-28 03:09:36 +08:00
|
|
|
:class="action.buttonStyle"
|
|
|
|
:href="action.path"
|
|
|
|
@click="doAction(action, $event)">
|
|
|
|
<i :class="action.icon"></i>
|
|
|
|
{{ action.label }}
|
|
|
|
</a>
|
|
|
|
<MenuDropdown
|
|
|
|
v-if="action.type === 'menu'"
|
|
|
|
:listItems="action.menuItems"
|
|
|
|
:btnClasses="action.buttonStyle"
|
|
|
|
:btnText="action.label"
|
|
|
|
:btnIcon="action.icon"
|
|
|
|
:caret="true"
|
|
|
|
:position="'right'"
|
|
|
|
@dtEvent="handleEvent"
|
|
|
|
></MenuDropdown>
|
|
|
|
</template>
|
2023-09-24 20:10:53 +08:00
|
|
|
</div>
|
2023-11-24 18:08:28 +08:00
|
|
|
<div>
|
2023-12-12 19:17:38 +08:00
|
|
|
<div class="flex items-center gap-2">
|
2023-11-24 18:08:28 +08:00
|
|
|
<MenuDropdown
|
2023-12-28 03:09:36 +08:00
|
|
|
v-if="viewRenders"
|
2023-12-01 07:01:08 +08:00
|
|
|
:listItems="this.viewRendersMenu"
|
|
|
|
:btnClasses="'btn btn-light icon-btn'"
|
|
|
|
:btnText="i18n.t(`toolbar.${currentViewRender}_view`)"
|
|
|
|
:caret="true"
|
|
|
|
:position="'right'"
|
|
|
|
@setCardsView="$emit('setCardsView')"
|
|
|
|
@setTableView="$emit('setTableView')"
|
|
|
|
></MenuDropdown>
|
|
|
|
<MenuDropdown
|
|
|
|
v-if="archivedPageUrl"
|
|
|
|
:listItems="this.viewModesMenu"
|
2023-11-24 18:08:28 +08:00
|
|
|
:btnClasses="'btn btn-light icon-btn'"
|
|
|
|
:btnText="i18n.t(`projects.index.${currentViewMode}`)"
|
|
|
|
:caret="true"
|
|
|
|
:position="'right'"
|
|
|
|
></MenuDropdown>
|
|
|
|
</div>
|
|
|
|
</div>
|
2023-12-12 19:17:38 +08:00
|
|
|
<div class="flex items-center gap-2">
|
2023-09-24 20:10:53 +08:00
|
|
|
<a v-for="action in toolbarActions.right" :key="action.label"
|
|
|
|
:class="action.buttonStyle"
|
|
|
|
:href="action.path"
|
|
|
|
@click="doAction(action, $event)">
|
|
|
|
<i :class="action.icon"></i>
|
|
|
|
{{ action.label }}
|
|
|
|
</a>
|
2023-12-12 19:17:38 +08:00
|
|
|
<button
|
|
|
|
v-if="currentViewRender === 'table'"
|
|
|
|
@click="showColumnsModal = true"
|
2024-01-24 21:06:26 +08:00
|
|
|
:title="i18n.t('experiments.table.column_display_modal.title')"
|
2023-12-12 19:17:38 +08:00
|
|
|
class="btn btn-light icon-btn"
|
|
|
|
>
|
|
|
|
<i class="sn-icon sn-icon-reports"></i>
|
|
|
|
</button>
|
2023-12-11 16:18:22 +08:00
|
|
|
<div v-if="filters.length == 0"
|
|
|
|
class="sci-input-container-v2"
|
|
|
|
:class="{'w-48': showSearch, 'w-11': !showSearch}">
|
2023-09-24 20:10:53 +08:00
|
|
|
<input
|
|
|
|
ref="searchInput"
|
|
|
|
class="sci-input-field !pr-8"
|
|
|
|
type="text"
|
|
|
|
@focus="openSearch"
|
|
|
|
@blur="hideSearch"
|
|
|
|
:value="searchValue"
|
|
|
|
:placeholder="'Search...'"
|
|
|
|
@change="$emit('search:change', $event.target.value)"
|
|
|
|
/>
|
2023-12-28 03:09:36 +08:00
|
|
|
<i v-if="searchValue.length === 0" class="sn-icon sn-icon-search !m-2.5 !ml-auto right-0"></i>
|
|
|
|
<i v-else class="sn-icon sn-icon-close !m-2.5 !ml-auto right-0 cursor-pointer z-10"
|
|
|
|
@click="$emit('search:change', '')"></i>
|
2023-09-24 20:10:53 +08:00
|
|
|
</div>
|
2023-11-24 18:08:28 +08:00
|
|
|
<FilterDropdown v-else :filters="filters" @applyFilters="applyFilters" />
|
2024-01-12 00:42:17 +08:00
|
|
|
<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>
|
2023-09-24 20:10:53 +08:00
|
|
|
</div>
|
2023-12-12 19:17:38 +08:00
|
|
|
<teleport to="body">
|
|
|
|
<ColumnsModal
|
|
|
|
:tableState="tableState"
|
|
|
|
:columnDefs="columnDefs"
|
|
|
|
@hideColumn="(column) => $emit('hideColumn', column)"
|
|
|
|
@showColumn="(column) => $emit('showColumn', column)"
|
|
|
|
v-if="showColumnsModal"
|
|
|
|
@close="showColumnsModal = false" />
|
|
|
|
</teleport>
|
2023-09-24 20:10:53 +08:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
2023-12-11 16:18:22 +08:00
|
|
|
import MenuDropdown from '../menu_dropdown.vue';
|
2024-01-12 00:42:17 +08:00
|
|
|
import GeneralDropdown from '../general_dropdown.vue';
|
2023-11-24 18:08:28 +08:00
|
|
|
import FilterDropdown from '../filters/filter_dropdown.vue';
|
2023-12-12 19:17:38 +08:00
|
|
|
import ColumnsModal from './modals/columns.vue';
|
2023-11-24 18:08:28 +08:00
|
|
|
|
2023-09-24 20:10:53 +08:00
|
|
|
export default {
|
|
|
|
name: 'Toolbar',
|
|
|
|
props: {
|
|
|
|
toolbarActions: {
|
|
|
|
type: Object,
|
2023-12-12 19:17:38 +08:00
|
|
|
required: true
|
2023-09-24 20:10:53 +08:00
|
|
|
},
|
|
|
|
searchValue: {
|
2023-12-12 19:17:38 +08:00
|
|
|
type: String
|
2023-11-24 18:08:28 +08:00
|
|
|
},
|
|
|
|
activePageUrl: {
|
2023-12-12 19:17:38 +08:00
|
|
|
type: String
|
2023-11-24 18:08:28 +08:00
|
|
|
},
|
|
|
|
archivedPageUrl: {
|
2023-12-12 19:17:38 +08:00
|
|
|
type: String
|
2023-11-24 18:08:28 +08:00
|
|
|
},
|
|
|
|
currentViewMode: {
|
|
|
|
type: String,
|
2023-12-12 19:17:38 +08:00
|
|
|
default: 'active'
|
2023-11-24 18:08:28 +08:00
|
|
|
},
|
|
|
|
filters: {
|
|
|
|
type: Array,
|
2023-12-12 19:17:38 +08:00
|
|
|
default: () => []
|
2023-12-01 07:01:08 +08:00
|
|
|
},
|
|
|
|
viewRenders: {
|
2023-12-12 19:17:38 +08:00
|
|
|
required: true
|
2023-12-01 07:01:08 +08:00
|
|
|
},
|
|
|
|
currentViewRender: {
|
|
|
|
type: String,
|
2023-12-12 19:17:38 +08:00
|
|
|
required: true
|
|
|
|
},
|
|
|
|
columnDefs: {
|
|
|
|
type: Array,
|
|
|
|
required: true
|
2023-12-11 16:18:22 +08:00
|
|
|
},
|
2023-12-12 19:17:38 +08:00
|
|
|
tableState: {
|
|
|
|
type: Object
|
2024-01-12 00:42:17 +08:00
|
|
|
},
|
|
|
|
order: {
|
|
|
|
type: Object
|
2023-12-12 19:17:38 +08:00
|
|
|
}
|
2023-11-24 18:08:28 +08:00
|
|
|
},
|
|
|
|
components: {
|
|
|
|
MenuDropdown,
|
2023-12-11 16:18:22 +08:00
|
|
|
FilterDropdown,
|
2024-01-12 00:42:17 +08:00
|
|
|
ColumnsModal,
|
|
|
|
GeneralDropdown
|
2023-11-24 18:08:28 +08:00
|
|
|
},
|
|
|
|
computed: {
|
2023-12-01 07:01:08 +08:00
|
|
|
viewModesMenu() {
|
2023-11-24 18:08:28 +08:00
|
|
|
return [
|
2023-12-11 16:18:22 +08:00
|
|
|
{ text: this.i18n.t('projects.index.active'), url: this.activePageUrl },
|
2023-12-12 19:17:38 +08:00
|
|
|
{ text: this.i18n.t('projects.index.archived'), url: this.archivedPageUrl }
|
2023-12-11 16:18:22 +08:00
|
|
|
];
|
2023-12-01 07:01:08 +08:00
|
|
|
},
|
|
|
|
viewRendersMenu() {
|
|
|
|
return this.viewRenders.map((view) => {
|
2023-12-11 16:18:22 +08:00
|
|
|
const { type } = view;
|
2023-12-01 07:01:08 +08:00
|
|
|
switch (type) {
|
|
|
|
case 'cards':
|
2023-12-11 16:18:22 +08:00
|
|
|
return { text: this.i18n.t('toolbar.cards_view'), emit: 'setCardsView' };
|
2023-12-01 07:01:08 +08:00
|
|
|
case 'table':
|
2023-12-11 16:18:22 +08:00
|
|
|
return { text: this.i18n.t('toolbar.table_view'), emit: 'setTableView' };
|
2023-12-12 19:17:38 +08:00
|
|
|
case 'custom':
|
|
|
|
return { text: view.name, url: view.url };
|
2023-12-01 07:01:08 +08:00
|
|
|
default:
|
|
|
|
return view;
|
|
|
|
}
|
2023-12-11 16:18:22 +08:00
|
|
|
});
|
2024-01-12 00:42:17 +08:00
|
|
|
},
|
|
|
|
sortableColumns() {
|
|
|
|
return this.columnDefs.filter((column) => column.sortable);
|
2023-12-12 19:17:38 +08:00
|
|
|
}
|
2023-09-24 20:10:53 +08:00
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
2023-12-11 16:18:22 +08:00
|
|
|
showSearch: false,
|
2023-12-12 19:17:38 +08:00
|
|
|
showColumnsModal: false
|
2023-12-11 16:18:22 +08:00
|
|
|
};
|
2023-09-24 20:10:53 +08:00
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
searchValue() {
|
|
|
|
if (this.searchValue.length > 0) {
|
|
|
|
this.openSearch();
|
|
|
|
}
|
2023-12-12 19:17:38 +08:00
|
|
|
}
|
2023-09-24 20:10:53 +08:00
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
openSearch() {
|
|
|
|
this.showSearch = true;
|
|
|
|
},
|
|
|
|
hideSearch() {
|
|
|
|
if (this.searchValue.length === 0) {
|
|
|
|
this.showSearch = false;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
doAction(action, event) {
|
2023-12-11 16:18:22 +08:00
|
|
|
switch (action.type) {
|
2023-09-24 20:10:53 +08:00
|
|
|
case 'emit':
|
|
|
|
event.preventDefault();
|
|
|
|
this.$emit('toolbar:action', action);
|
|
|
|
break;
|
|
|
|
case 'link':
|
|
|
|
break;
|
2023-12-11 16:18:22 +08:00
|
|
|
default:
|
|
|
|
break;
|
2023-09-24 20:10:53 +08:00
|
|
|
}
|
2023-11-24 18:08:28 +08:00
|
|
|
},
|
|
|
|
applyFilters(filters) {
|
|
|
|
this.$emit('applyFilters', filters);
|
2023-12-28 03:09:36 +08:00
|
|
|
},
|
|
|
|
handleEvent(event) {
|
|
|
|
this.$emit('toolbar:action', { name: event });
|
2023-12-12 19:17:38 +08:00
|
|
|
}
|
|
|
|
}
|
2023-12-11 16:18:22 +08:00
|
|
|
};
|
2023-09-24 20:10:53 +08:00
|
|
|
</script>
|