separate sort order component

This commit is contained in:
samunohito 2024-02-27 21:00:03 +09:00
parent 47ca0e6689
commit cb136e635d
6 changed files with 175 additions and 240 deletions

View File

@ -5,6 +5,26 @@ export type RequestLogItem = {
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) {
return value ? value : undefined;
}

View File

@ -118,26 +118,7 @@
</MkInput>
</div>
<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>
<XSortOrderFolder :sortOrders="sortOrders" @update="onSortOrderUpdate"/>
<div :class="[[spMode ? $style.searchButtonsSp : $style.searchButtons]]">
<MkButton primary @click="onSearchRequest">
@ -150,15 +131,7 @@
</div>
</MkFolder>
<MkFolder>
<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>
<XRegisterLogsFolder :logs="requestLogs"/>
<div :class="$style.gridArea">
<MkGrid :data="gridItems" :settings="setupGrid()" @event="onGridEvent"/>
@ -188,7 +161,7 @@ import * as os from '@/os.js';
import {
emptyStrToEmptyArray,
emptyStrToNull,
emptyStrToUndefined,
emptyStrToUndefined, GridSortOrder,
RequestLogItem,
roleIdsParser,
} 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 { misskeyApi } from '@/scripts/misskey-api.js';
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 MkSelect from '@/components/MkSelect.vue';
import { deviceKind } from '@/scripts/device-kind.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 { copyGridDataToClipboard, removeDataFromGrid } from '@/components/grid/grid-utils.js';
@ -228,23 +200,6 @@ type GridItem = {
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 {
const required = validators.required();
const regex = validators.regex(/^[a-zA-Z0-9_]+$/);
@ -538,33 +493,8 @@ async function onQueryRolesEditClicked() {
queryRoles.value = result.result;
}
function onToggleSortOrderButtonClicked(order: GridSortOrder) {
switch (order.direction) {
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);
function onSortOrderUpdate(_sortOrders: GridSortOrder[]) {
sortOrders.value = _sortOrders;
}
async function onSearchRequest() {
@ -751,37 +681,6 @@ onMounted(async () => {
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 {
overflow: scroll;
padding-top: 8px;

View File

@ -25,15 +25,7 @@
</div>
</MkFolder>
<MkFolder>
<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>
<XRegisterLogsFolder :logs="requestLogs"/>
<div
: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 { GridCellValidationEvent, GridCellValueChangeEvent, GridEvent } from '@/components/grid/grid-event.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 { copyGridDataToClipboard } from '@/components/grid/grid-utils.js';
import { GridRow } from '@/components/grid/row.js';

View File

@ -1,5 +1,12 @@
<template>
<div>
<MkFolder>
<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>
<div>
<div v-if="logs.length > 0" style="display:flex; flex-direction: column; overflow-y: scroll; gap: 16px;">
<MkSwitch v-model="showingSuccessLogs">
<template #label>{{ i18n.ts._customEmojisManager._logs.showSuccessLogSwitch }}</template>
@ -19,7 +26,8 @@
<div v-else>
{{ i18n.ts._customEmojisManager._logs.logNothing }}
</div>
</div>
</div>
</MkFolder>
</template>
<script setup lang="ts">
@ -31,6 +39,7 @@ import MkGrid from '@/components/grid/MkGrid.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import { GridSetting } from '@/components/grid/grid.js';
import { copyGridDataToClipboard } from '@/components/grid/grid-utils.js';
import MkFolder from '@/components/MkFolder.vue';
function setupGrid(): GridSetting {
return {

View File

@ -52,26 +52,7 @@
</MkInput>
</div>
<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>
<XSortOrderFolder :sortOrders="sortOrders" @update="onSortOrderChanged"/>
<div :class="[[spMode ? $style.searchButtonsSp : $style.searchButtons]]">
<MkButton primary @click="onSearchRequest">
@ -84,15 +65,7 @@
</div>
</MkFolder>
<MkFolder>
<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>
<XRegisterLogsFolder :logs="requestLogs"/>
<div v-if="gridItems.length > 0" :class="$style.gridArea">
<MkGrid :data="gridItems" :settings="setupGrid()" @event="onGridEvent"/>
@ -115,15 +88,14 @@ import { i18n } from '@/i18n.js';
import MkButton from '@/components/MkButton.vue';
import MkInput from '@/components/MkInput.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 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 { GridSetting } from '@/components/grid/grid.js';
import MkTagItem from '@/components/MkTagItem.vue';
import { deviceKind } from '@/scripts/device-kind.js';
import { MenuItem } from '@/types/menu.js';
import MkPagingButtons from '@/components/MkPagingButtons.vue';
type GridItem = {
@ -134,19 +106,6 @@ type GridItem = {
host: string;
}
const gridSortOrderKeys = [
'name',
'host',
'uri',
'publicUrl',
];
type GridSortOrderKey = typeof gridSortOrderKeys[number];
type GridSortOrder = {
key: GridSortOrderKey;
direction: 'ASC' | 'DESC';
}
function setupGrid(): GridSetting {
return {
row: {
@ -206,33 +165,8 @@ const gridItems = ref<GridItem[]>([]);
const spMode = computed(() => ['smartphone', 'tablet'].includes(deviceKind));
function onToggleSortOrderButtonClicked(order: GridSortOrder) {
switch (order.direction) {
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);
function onSortOrderChanged(_sortOrders: GridSortOrder[]) {
sortOrders.value = _sortOrders;
}
async function onSearchRequest() {
@ -412,37 +346,6 @@ onMounted(async () => {
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 {
overflow: scroll;
padding-top: 8px;

View File

@ -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>