separate sort order component
This commit is contained in:
parent
47ca0e6689
commit
cb136e635d
|
@ -5,6 +5,26 @@ export type RequestLogItem = {
|
||||||
error?: string;
|
error?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const gridSortOrderKeys = [
|
||||||
|
'name',
|
||||||
|
'category',
|
||||||
|
'aliases',
|
||||||
|
'type',
|
||||||
|
'license',
|
||||||
|
'host',
|
||||||
|
'uri',
|
||||||
|
'publicUrl',
|
||||||
|
'isSensitive',
|
||||||
|
'localOnly',
|
||||||
|
'updatedAt',
|
||||||
|
];
|
||||||
|
export type GridSortOrderKey = typeof gridSortOrderKeys[number];
|
||||||
|
|
||||||
|
export type GridSortOrder = {
|
||||||
|
key: GridSortOrderKey;
|
||||||
|
direction: 'ASC' | 'DESC';
|
||||||
|
}
|
||||||
|
|
||||||
export function emptyStrToUndefined(value: string | null) {
|
export function emptyStrToUndefined(value: string | null) {
|
||||||
return value ? value : undefined;
|
return value ? value : undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,26 +118,7 @@
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MkFolder :spacerMax="8" :spacerMin="8">
|
<XSortOrderFolder :sortOrders="sortOrders" @update="onSortOrderUpdate"/>
|
||||||
<template #icon><i class="ti ti-arrows-sort"></i></template>
|
|
||||||
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.sortOrder }}</template>
|
|
||||||
<div :class="$style.sortOrderArea">
|
|
||||||
<div :class="$style.sortOrderAreaTags">
|
|
||||||
<MkTagItem
|
|
||||||
v-for="order in sortOrders"
|
|
||||||
:key="order.key"
|
|
||||||
:iconClass="order.direction === 'ASC' ? 'ti ti-arrow-up' : 'ti ti-arrow-down'"
|
|
||||||
:exButtonIconClass="'ti ti-x'"
|
|
||||||
:content="order.key"
|
|
||||||
@click="onToggleSortOrderButtonClicked(order)"
|
|
||||||
@exButtonClick="onRemoveSortOrderButtonClicked(order.key)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<MkButton :class="$style.sortOrderAddButton" @click="onAddSortOrderButtonClicked">
|
|
||||||
<span class="ti ti-plus"/>
|
|
||||||
</MkButton>
|
|
||||||
</div>
|
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<div :class="[[spMode ? $style.searchButtonsSp : $style.searchButtons]]">
|
<div :class="[[spMode ? $style.searchButtonsSp : $style.searchButtons]]">
|
||||||
<MkButton primary @click="onSearchRequest">
|
<MkButton primary @click="onSearchRequest">
|
||||||
|
@ -150,15 +131,7 @@
|
||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder>
|
<XRegisterLogsFolder :logs="requestLogs"/>
|
||||||
<template #icon><i class="ti ti-notes"></i></template>
|
|
||||||
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.registrationLogs }}</template>
|
|
||||||
<template #caption>
|
|
||||||
{{ i18n.ts._customEmojisManager._gridCommon.registrationLogsCaption }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<XRegisterLogs :logs="requestLogs"/>
|
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<div :class="$style.gridArea">
|
<div :class="$style.gridArea">
|
||||||
<MkGrid :data="gridItems" :settings="setupGrid()" @event="onGridEvent"/>
|
<MkGrid :data="gridItems" :settings="setupGrid()" @event="onGridEvent"/>
|
||||||
|
@ -188,7 +161,7 @@ import * as os from '@/os.js';
|
||||||
import {
|
import {
|
||||||
emptyStrToEmptyArray,
|
emptyStrToEmptyArray,
|
||||||
emptyStrToNull,
|
emptyStrToNull,
|
||||||
emptyStrToUndefined,
|
emptyStrToUndefined, GridSortOrder,
|
||||||
RequestLogItem,
|
RequestLogItem,
|
||||||
roleIdsParser,
|
roleIdsParser,
|
||||||
} from '@/pages/admin/custom-emojis-manager.impl.js';
|
} from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||||
|
@ -200,13 +173,12 @@ import { validators } from '@/components/grid/cell-validators.js';
|
||||||
import { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
import { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||||
import { misskeyApi } from '@/scripts/misskey-api.js';
|
import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||||
import MkPagingButtons from '@/components/MkPagingButtons.vue';
|
import MkPagingButtons from '@/components/MkPagingButtons.vue';
|
||||||
import XRegisterLogs from '@/pages/admin/custom-emojis-manager.logs.vue';
|
import XRegisterLogsFolder from '@/pages/admin/custom-emojis-manager.logs-folder.vue';
|
||||||
|
import XSortOrderFolder from '@/pages/admin/custom-emojis-manager.sort-order-folder.vue';
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
import MkSelect from '@/components/MkSelect.vue';
|
import MkSelect from '@/components/MkSelect.vue';
|
||||||
import { deviceKind } from '@/scripts/device-kind.js';
|
import { deviceKind } from '@/scripts/device-kind.js';
|
||||||
import { GridSetting } from '@/components/grid/grid.js';
|
import { GridSetting } from '@/components/grid/grid.js';
|
||||||
import MkTagItem from '@/components/MkTagItem.vue';
|
|
||||||
import { MenuItem } from '@/types/menu.js';
|
|
||||||
import { selectFile } from '@/scripts/select-file.js';
|
import { selectFile } from '@/scripts/select-file.js';
|
||||||
import { copyGridDataToClipboard, removeDataFromGrid } from '@/components/grid/grid-utils.js';
|
import { copyGridDataToClipboard, removeDataFromGrid } from '@/components/grid/grid-utils.js';
|
||||||
|
|
||||||
|
@ -228,23 +200,6 @@ type GridItem = {
|
||||||
originalUrl?: string | null;
|
originalUrl?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gridSortOrderKeys = [
|
|
||||||
'name',
|
|
||||||
'category',
|
|
||||||
'aliases',
|
|
||||||
'type',
|
|
||||||
'license',
|
|
||||||
'isSensitive',
|
|
||||||
'localOnly',
|
|
||||||
'updatedAt',
|
|
||||||
];
|
|
||||||
type GridSortOrderKey = typeof gridSortOrderKeys[number];
|
|
||||||
|
|
||||||
type GridSortOrder = {
|
|
||||||
key: GridSortOrderKey;
|
|
||||||
direction: 'ASC' | 'DESC';
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupGrid(): GridSetting {
|
function setupGrid(): GridSetting {
|
||||||
const required = validators.required();
|
const required = validators.required();
|
||||||
const regex = validators.regex(/^[a-zA-Z0-9_]+$/);
|
const regex = validators.regex(/^[a-zA-Z0-9_]+$/);
|
||||||
|
@ -538,33 +493,8 @@ async function onQueryRolesEditClicked() {
|
||||||
queryRoles.value = result.result;
|
queryRoles.value = result.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onToggleSortOrderButtonClicked(order: GridSortOrder) {
|
function onSortOrderUpdate(_sortOrders: GridSortOrder[]) {
|
||||||
switch (order.direction) {
|
sortOrders.value = _sortOrders;
|
||||||
case 'ASC':
|
|
||||||
order.direction = 'DESC';
|
|
||||||
break;
|
|
||||||
case 'DESC':
|
|
||||||
order.direction = 'ASC';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRemoveSortOrderButtonClicked(key: GridSortOrderKey) {
|
|
||||||
sortOrders.value = sortOrders.value.filter(it => it.key !== key);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAddSortOrderButtonClicked(ev: MouseEvent) {
|
|
||||||
const menuItems: MenuItem[] = gridSortOrderKeys
|
|
||||||
.filter(key => !sortOrders.value.map(it => it.key).includes(key))
|
|
||||||
.map(it => {
|
|
||||||
return {
|
|
||||||
text: it,
|
|
||||||
action: () => {
|
|
||||||
sortOrders.value.push({ key: it, direction: 'ASC' });
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
os.contextMenu(menuItems, ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSearchRequest() {
|
async function onSearchRequest() {
|
||||||
|
@ -751,37 +681,6 @@ onMounted(async () => {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sortOrderArea {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sortOrderAreaTags {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sortOrderAddButton {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
min-width: 2.0em;
|
|
||||||
min-height: 2.0em;
|
|
||||||
max-width: 2.0em;
|
|
||||||
max-height: 2.0em;
|
|
||||||
padding: 8px;
|
|
||||||
margin-left: auto;
|
|
||||||
border-radius: 9999px;
|
|
||||||
background-color: var(--buttonBg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gridArea {
|
.gridArea {
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
|
|
|
@ -25,15 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder>
|
<XRegisterLogsFolder :logs="requestLogs"/>
|
||||||
<template #icon><i class="ti ti-notes"></i></template>
|
|
||||||
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.registrationLogs }}</template>
|
|
||||||
<template #caption>
|
|
||||||
{{ i18n.ts._customEmojisManager._gridCommon.registrationLogsCaption }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<XRegisterLogs :logs="requestLogs"/>
|
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
:class="[$style.uploadBox, [isDragOver ? $style.dragOver : {}]]"
|
:class="[$style.uploadBox, [isDragOver ? $style.dragOver : {}]]"
|
||||||
|
@ -94,7 +86,7 @@ import { chooseFileFromDrive, chooseFileFromPc } from '@/scripts/select-file.js'
|
||||||
import { uploadFile } from '@/scripts/upload.js';
|
import { uploadFile } from '@/scripts/upload.js';
|
||||||
import { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
import { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||||
import { DroppedFile, extractDroppedItems, flattenDroppedFiles } from '@/scripts/file-drop.js';
|
import { DroppedFile, extractDroppedItems, flattenDroppedFiles } from '@/scripts/file-drop.js';
|
||||||
import XRegisterLogs from '@/pages/admin/custom-emojis-manager.logs.vue';
|
import XRegisterLogsFolder from '@/pages/admin/custom-emojis-manager.logs-folder.vue';
|
||||||
import { GridSetting } from '@/components/grid/grid.js';
|
import { GridSetting } from '@/components/grid/grid.js';
|
||||||
import { copyGridDataToClipboard } from '@/components/grid/grid-utils.js';
|
import { copyGridDataToClipboard } from '@/components/grid/grid-utils.js';
|
||||||
import { GridRow } from '@/components/grid/row.js';
|
import { GridRow } from '@/components/grid/row.js';
|
||||||
|
|
|
@ -1,25 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<MkFolder>
|
||||||
<div v-if="logs.length > 0" style="display:flex; flex-direction: column; overflow-y: scroll; gap: 16px;">
|
<template #icon><i class="ti ti-notes"></i></template>
|
||||||
<MkSwitch v-model="showingSuccessLogs">
|
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.registrationLogs }}</template>
|
||||||
<template #label>{{ i18n.ts._customEmojisManager._logs.showSuccessLogSwitch }}</template>
|
<template #caption>
|
||||||
</MkSwitch>
|
{{ i18n.ts._customEmojisManager._gridCommon.registrationLogsCaption }}
|
||||||
<div>
|
</template>
|
||||||
<div v-if="filteredLogs.length > 0">
|
|
||||||
<MkGrid
|
<div>
|
||||||
:data="filteredLogs"
|
<div v-if="logs.length > 0" style="display:flex; flex-direction: column; overflow-y: scroll; gap: 16px;">
|
||||||
:settings="setupGrid()"
|
<MkSwitch v-model="showingSuccessLogs">
|
||||||
/>
|
<template #label>{{ i18n.ts._customEmojisManager._logs.showSuccessLogSwitch }}</template>
|
||||||
</div>
|
</MkSwitch>
|
||||||
<div v-else>
|
<div>
|
||||||
{{ i18n.ts._customEmojisManager._logs.failureLogNothing }}
|
<div v-if="filteredLogs.length > 0">
|
||||||
|
<MkGrid
|
||||||
|
:data="filteredLogs"
|
||||||
|
:settings="setupGrid()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
{{ i18n.ts._customEmojisManager._logs.failureLogNothing }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
{{ i18n.ts._customEmojisManager._logs.logNothing }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
</MkFolder>
|
||||||
{{ i18n.ts._customEmojisManager._logs.logNothing }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -31,6 +39,7 @@ import MkGrid from '@/components/grid/MkGrid.vue';
|
||||||
import MkSwitch from '@/components/MkSwitch.vue';
|
import MkSwitch from '@/components/MkSwitch.vue';
|
||||||
import { GridSetting } from '@/components/grid/grid.js';
|
import { GridSetting } from '@/components/grid/grid.js';
|
||||||
import { copyGridDataToClipboard } from '@/components/grid/grid-utils.js';
|
import { copyGridDataToClipboard } from '@/components/grid/grid-utils.js';
|
||||||
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
|
|
||||||
function setupGrid(): GridSetting {
|
function setupGrid(): GridSetting {
|
||||||
return {
|
return {
|
|
@ -52,26 +52,7 @@
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MkFolder :spacerMax="8" :spacerMin="8">
|
<XSortOrderFolder :sortOrders="sortOrders" @update="onSortOrderChanged"/>
|
||||||
<template #icon><i class="ti ti-arrows-sort"></i></template>
|
|
||||||
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.sortOrder }}</template>
|
|
||||||
<div :class="$style.sortOrderArea">
|
|
||||||
<div :class="$style.sortOrderAreaTags">
|
|
||||||
<MkTagItem
|
|
||||||
v-for="order in sortOrders"
|
|
||||||
:key="order.key"
|
|
||||||
:iconClass="order.direction === 'ASC' ? 'ti ti-arrow-up' : 'ti ti-arrow-down'"
|
|
||||||
:exButtonIconClass="'ti ti-x'"
|
|
||||||
:content="order.key"
|
|
||||||
@click="onToggleSortOrderButtonClicked(order)"
|
|
||||||
@exButtonClick="onRemoveSortOrderButtonClicked(order.key)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<MkButton :class="$style.sortOrderAddButton" @click="onAddSortOrderButtonClicked">
|
|
||||||
<span class="ti ti-plus"/>
|
|
||||||
</MkButton>
|
|
||||||
</div>
|
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<div :class="[[spMode ? $style.searchButtonsSp : $style.searchButtons]]">
|
<div :class="[[spMode ? $style.searchButtonsSp : $style.searchButtons]]">
|
||||||
<MkButton primary @click="onSearchRequest">
|
<MkButton primary @click="onSearchRequest">
|
||||||
|
@ -84,15 +65,7 @@
|
||||||
</div>
|
</div>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder>
|
<XRegisterLogsFolder :logs="requestLogs"/>
|
||||||
<template #icon><i class="ti ti-notes"></i></template>
|
|
||||||
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.registrationLogs }}</template>
|
|
||||||
<template #caption>
|
|
||||||
{{ i18n.ts._customEmojisManager._gridCommon.registrationLogsCaption }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<XRegisterLogs :logs="requestLogs"/>
|
|
||||||
</MkFolder>
|
|
||||||
|
|
||||||
<div v-if="gridItems.length > 0" :class="$style.gridArea">
|
<div v-if="gridItems.length > 0" :class="$style.gridArea">
|
||||||
<MkGrid :data="gridItems" :settings="setupGrid()" @event="onGridEvent"/>
|
<MkGrid :data="gridItems" :settings="setupGrid()" @event="onGridEvent"/>
|
||||||
|
@ -115,15 +88,14 @@ import { i18n } from '@/i18n.js';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import MkGrid from '@/components/grid/MkGrid.vue';
|
import MkGrid from '@/components/grid/MkGrid.vue';
|
||||||
import { emptyStrToUndefined, RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
import { emptyStrToUndefined, GridSortOrder, RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||||
import { GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
import { GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.js';
|
||||||
import MkFolder from '@/components/MkFolder.vue';
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
import XRegisterLogs from '@/pages/admin/custom-emojis-manager.logs.vue';
|
import XRegisterLogsFolder from '@/pages/admin/custom-emojis-manager.logs-folder.vue';
|
||||||
|
import XSortOrderFolder from '@/pages/admin/custom-emojis-manager.sort-order-folder.vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
import { GridSetting } from '@/components/grid/grid.js';
|
import { GridSetting } from '@/components/grid/grid.js';
|
||||||
import MkTagItem from '@/components/MkTagItem.vue';
|
|
||||||
import { deviceKind } from '@/scripts/device-kind.js';
|
import { deviceKind } from '@/scripts/device-kind.js';
|
||||||
import { MenuItem } from '@/types/menu.js';
|
|
||||||
import MkPagingButtons from '@/components/MkPagingButtons.vue';
|
import MkPagingButtons from '@/components/MkPagingButtons.vue';
|
||||||
|
|
||||||
type GridItem = {
|
type GridItem = {
|
||||||
|
@ -134,19 +106,6 @@ type GridItem = {
|
||||||
host: string;
|
host: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gridSortOrderKeys = [
|
|
||||||
'name',
|
|
||||||
'host',
|
|
||||||
'uri',
|
|
||||||
'publicUrl',
|
|
||||||
];
|
|
||||||
type GridSortOrderKey = typeof gridSortOrderKeys[number];
|
|
||||||
|
|
||||||
type GridSortOrder = {
|
|
||||||
key: GridSortOrderKey;
|
|
||||||
direction: 'ASC' | 'DESC';
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupGrid(): GridSetting {
|
function setupGrid(): GridSetting {
|
||||||
return {
|
return {
|
||||||
row: {
|
row: {
|
||||||
|
@ -206,33 +165,8 @@ const gridItems = ref<GridItem[]>([]);
|
||||||
|
|
||||||
const spMode = computed(() => ['smartphone', 'tablet'].includes(deviceKind));
|
const spMode = computed(() => ['smartphone', 'tablet'].includes(deviceKind));
|
||||||
|
|
||||||
function onToggleSortOrderButtonClicked(order: GridSortOrder) {
|
function onSortOrderChanged(_sortOrders: GridSortOrder[]) {
|
||||||
switch (order.direction) {
|
sortOrders.value = _sortOrders;
|
||||||
case 'ASC':
|
|
||||||
order.direction = 'DESC';
|
|
||||||
break;
|
|
||||||
case 'DESC':
|
|
||||||
order.direction = 'ASC';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRemoveSortOrderButtonClicked(key: GridSortOrderKey) {
|
|
||||||
sortOrders.value = sortOrders.value.filter(it => it.key !== key);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onAddSortOrderButtonClicked(ev: MouseEvent) {
|
|
||||||
const menuItems: MenuItem[] = gridSortOrderKeys
|
|
||||||
.filter(key => !sortOrders.value.map(it => it.key).includes(key))
|
|
||||||
.map(it => {
|
|
||||||
return {
|
|
||||||
text: it,
|
|
||||||
action: () => {
|
|
||||||
sortOrders.value.push({ key: it, direction: 'ASC' });
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
os.contextMenu(menuItems, ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onSearchRequest() {
|
async function onSearchRequest() {
|
||||||
|
@ -412,37 +346,6 @@ onMounted(async () => {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sortOrderArea {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sortOrderAreaTags {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sortOrderAddButton {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
min-width: 2.0em;
|
|
||||||
min-height: 2.0em;
|
|
||||||
max-width: 2.0em;
|
|
||||||
max-height: 2.0em;
|
|
||||||
padding: 8px;
|
|
||||||
margin-left: auto;
|
|
||||||
border-radius: 9999px;
|
|
||||||
background-color: var(--buttonBg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gridArea {
|
.gridArea {
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
<template>
|
||||||
|
<MkFolder :spacerMax="8" :spacerMin="8">
|
||||||
|
<template #icon><i class="ti ti-arrows-sort"></i></template>
|
||||||
|
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.sortOrder }}</template>
|
||||||
|
<div :class="$style.sortOrderArea">
|
||||||
|
<div :class="$style.sortOrderAreaTags">
|
||||||
|
<MkTagItem
|
||||||
|
v-for="order in sortOrders"
|
||||||
|
:key="order.key"
|
||||||
|
:iconClass="order.direction === 'ASC' ? 'ti ti-arrow-up' : 'ti ti-arrow-down'"
|
||||||
|
:exButtonIconClass="'ti ti-x'"
|
||||||
|
:content="order.key"
|
||||||
|
@click="onToggleSortOrderButtonClicked(order)"
|
||||||
|
@exButtonClick="onRemoveSortOrderButtonClicked(order.key)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<MkButton :class="$style.sortOrderAddButton" @click="onAddSortOrderButtonClicked">
|
||||||
|
<span class="ti ti-plus"/>
|
||||||
|
</MkButton>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { toRefs } from 'vue';
|
||||||
|
import { i18n } from '@/i18n.js';
|
||||||
|
import MkFolder from '@/components/MkFolder.vue';
|
||||||
|
import MkTagItem from '@/components/MkTagItem.vue';
|
||||||
|
import MkButton from '@/components/MkButton.vue';
|
||||||
|
import { GridSortOrder, GridSortOrderKey, gridSortOrderKeys } from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||||
|
import { MenuItem } from '@/types/menu.js';
|
||||||
|
import * as os from '@/os.js';
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(ev: 'update', sortOrders: GridSortOrder[]): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
sortOrders: GridSortOrder[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const { sortOrders } = toRefs(props);
|
||||||
|
|
||||||
|
function onToggleSortOrderButtonClicked(order: GridSortOrder) {
|
||||||
|
switch (order.direction) {
|
||||||
|
case 'ASC':
|
||||||
|
order.direction = 'DESC';
|
||||||
|
break;
|
||||||
|
case 'DESC':
|
||||||
|
order.direction = 'ASC';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
emitOrder(sortOrders.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAddSortOrderButtonClicked(ev: MouseEvent) {
|
||||||
|
const menuItems: MenuItem[] = gridSortOrderKeys
|
||||||
|
.filter(key => !sortOrders.value.map(it => it.key).includes(key))
|
||||||
|
.map(it => {
|
||||||
|
return {
|
||||||
|
text: it,
|
||||||
|
action: () => {
|
||||||
|
emitOrder([...sortOrders.value, { key: it, direction: 'ASC' }]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
os.contextMenu(menuItems, ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRemoveSortOrderButtonClicked(key: GridSortOrderKey) {
|
||||||
|
emitOrder(sortOrders.value.filter(it => it.key !== key));
|
||||||
|
}
|
||||||
|
|
||||||
|
function emitOrder(sortOrders: GridSortOrder[]) {
|
||||||
|
emit('update', sortOrders);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style module lang="scss">
|
||||||
|
.sortOrderArea {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortOrderAreaTags {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortOrderAddButton {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
min-width: 2.0em;
|
||||||
|
min-height: 2.0em;
|
||||||
|
max-width: 2.0em;
|
||||||
|
max-height: 2.0em;
|
||||||
|
padding: 8px;
|
||||||
|
margin-left: auto;
|
||||||
|
border-radius: 9999px;
|
||||||
|
background-color: var(--buttonBg);
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue