mirror of
https://github.com/misskey-dev/misskey.git
synced 2025-01-01 04:56:19 +01:00
support sort
This commit is contained in:
parent
9189117ef1
commit
089682c08d
5 changed files with 71 additions and 25 deletions
|
@ -64,7 +64,7 @@ export type FetchEmojisParams = {
|
||||||
page?: number;
|
page?: number;
|
||||||
sort?: {
|
sort?: {
|
||||||
key : FetchEmojisSortKeys;
|
key : FetchEmojisSortKeys;
|
||||||
order : 'ASC' | 'DESC';
|
direction : 'ASC' | 'DESC';
|
||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,7 +508,7 @@ export class CustomEmojiService implements OnApplicationShutdown {
|
||||||
|
|
||||||
if (params?.sort) {
|
if (params?.sort) {
|
||||||
for (const sort of params.sort) {
|
for (const sort of params.sort) {
|
||||||
builder.addOrderBy(`emoji.${sort.key}`, sort.order);
|
builder.addOrderBy(`emoji.${sort.key}`, sort.direction);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
builder.addOrderBy('emoji.id', 'DESC');
|
builder.addOrderBy('emoji.id', 'DESC');
|
||||||
|
|
|
@ -82,13 +82,13 @@ export const paramDef = {
|
||||||
],
|
],
|
||||||
default: 'id',
|
default: 'id',
|
||||||
},
|
},
|
||||||
order: {
|
direction: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
enum: ['ASC', 'DESC'],
|
enum: ['ASC', 'DESC'],
|
||||||
default: 'DESC',
|
default: 'DESC',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ['key', 'order'],
|
required: ['key', 'direction'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -128,7 +128,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
params.page = ps.page;
|
params.page = ps.page;
|
||||||
params.sort = ps.sort?.map(it => ({
|
params.sort = ps.sort?.map(it => ({
|
||||||
key: it.key,
|
key: it.key,
|
||||||
order: it.order,
|
direction: it.direction,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const result = await this.customEmojiService.fetchEmojis(params);
|
const result = await this.customEmojiService.fetchEmojis(params);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<span v-if="iconClass" :class="[$style.icon, iconClass]"/>
|
<span v-if="iconClass" :class="[$style.icon, iconClass]"/>
|
||||||
<span :class="$style.content">{{ content }}</span>
|
<span :class="$style.content">{{ content }}</span>
|
||||||
<MkButton v-if="exButtonIconClass" :class="$style.exButton" @click="(ev) => emit('exButtonClick', ev)">
|
<MkButton v-if="exButtonIconClass" :class="$style.exButton" @click="(ev) => emit('exButtonClick', ev)">
|
||||||
<span :class="exButtonIconClass"/>
|
<span :class="[$style.exButtonIcon, exButtonIconClass]"/>
|
||||||
</MkButton>
|
</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -24,15 +24,15 @@ defineProps<{
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style module lang="scss">
|
<style module lang="scss">
|
||||||
$buttonSize : 2em;
|
$buttonSize : 1.8em;
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
padding: 4px 4px;
|
padding: 4px 6px;
|
||||||
gap: 4px;
|
gap: 3px;
|
||||||
|
|
||||||
background-color: var(--buttonBg);
|
background-color: var(--buttonBg);
|
||||||
|
|
||||||
|
@ -42,7 +42,10 @@ $buttonSize : 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
font-size: 0.80em;
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 0.70em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.exButton {
|
.exButton {
|
||||||
|
@ -58,4 +61,11 @@ $buttonSize : 2em;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 0.65em;
|
font-size: 0.65em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.exButtonIcon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 0.80em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -65,13 +65,15 @@
|
||||||
<div :class="$style.sortOrderAreaTags">
|
<div :class="$style.sortOrderAreaTags">
|
||||||
<MkTagItem
|
<MkTagItem
|
||||||
v-for="order in sortOrders"
|
v-for="order in sortOrders"
|
||||||
:key="order.column"
|
:key="order.key"
|
||||||
:iconClass="order.direction === 'ASC' ? 'ti ti-arrow-up' : 'ti ti-arrow-down'"
|
:iconClass="order.direction === 'ASC' ? 'ti ti-arrow-up' : 'ti ti-arrow-down'"
|
||||||
:exButtonIconClass="'ti ti-x'"
|
:exButtonIconClass="'ti ti-x'"
|
||||||
:content="order.column"
|
:content="order.key"
|
||||||
|
@click="onToggleSortOrderButtonClicked(order)"
|
||||||
|
@exButtonClick="onRemoveSortOrderButtonClicked(order.key)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<MkButton :class="$style.sortOrderAddButton">
|
<MkButton :class="$style.sortOrderAddButton" @click="onAddSortOrderButtonClicked">
|
||||||
<span class="ti ti-plus"/>
|
<span class="ti ti-plus"/>
|
||||||
</MkButton>
|
</MkButton>
|
||||||
</div>
|
</div>
|
||||||
|
@ -152,6 +154,7 @@ 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 MkTagItem from '@/components/MkTagItem.vue';
|
||||||
|
import { MenuItem } from '@/types/menu.js';
|
||||||
|
|
||||||
type GridItem = {
|
type GridItem = {
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
|
@ -171,18 +174,20 @@ type GridItem = {
|
||||||
originalUrl?: string | null;
|
originalUrl?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
type GridSortOrderKey =
|
const gridSortOrderKeys = [
|
||||||
'name' |
|
'name',
|
||||||
'category' |
|
'category',
|
||||||
'aliases' |
|
'aliases',
|
||||||
'type' |
|
'type',
|
||||||
'license' |
|
'license',
|
||||||
'isSensitive' |
|
'isSensitive',
|
||||||
'localOnly' |
|
'localOnly',
|
||||||
'updatedAt';
|
'updatedAt',
|
||||||
|
];
|
||||||
|
type GridSortOrderKey = typeof gridSortOrderKeys[number];
|
||||||
|
|
||||||
type GridSortOrder = {
|
type GridSortOrder = {
|
||||||
column: GridSortOrderKey;
|
key: GridSortOrderKey;
|
||||||
direction: 'ASC' | 'DESC';
|
direction: 'ASC' | 'DESC';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +242,6 @@ const querySensitive = ref<string | null>(null);
|
||||||
const queryLocalOnly = ref<string | null>(null);
|
const queryLocalOnly = ref<string | null>(null);
|
||||||
const previousQuery = ref<string | undefined>(undefined);
|
const previousQuery = ref<string | undefined>(undefined);
|
||||||
const sortOrders = ref<GridSortOrder[]>([]);
|
const sortOrders = ref<GridSortOrder[]>([]);
|
||||||
sortOrders.value.push({ column: 'updatedAt', direction: 'DESC' }, { column: 'name', direction: 'ASC' });
|
|
||||||
const requestLogs = ref<RequestLogItem[]>([]);
|
const requestLogs = ref<RequestLogItem[]>([]);
|
||||||
|
|
||||||
const gridItems = ref<GridItem[]>([]);
|
const gridItems = ref<GridItem[]>([]);
|
||||||
|
@ -352,6 +356,36 @@ function onGridResetButtonClicked() {
|
||||||
refreshGridItems();
|
refreshGridItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onToggleSortOrderButtonClicked(order: GridSortOrder) {
|
||||||
|
console.log(order);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
async function onSearchButtonClicked() {
|
async function onSearchButtonClicked() {
|
||||||
await refreshCustomEmojis();
|
await refreshCustomEmojis();
|
||||||
}
|
}
|
||||||
|
@ -529,6 +563,7 @@ async function refreshCustomEmojis() {
|
||||||
query: query,
|
query: query,
|
||||||
limit: limit,
|
limit: limit,
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
|
sort: sortOrders.value.map(({ key, direction }) => ({ key: key as any, direction })),
|
||||||
}),
|
}),
|
||||||
() => {
|
() => {
|
||||||
},
|
},
|
||||||
|
@ -654,6 +689,7 @@ onMounted(async () => {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
flex-wrap: wrap;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6981,7 +6981,7 @@ export type operations = {
|
||||||
* @default DESC
|
* @default DESC
|
||||||
* @enum {string}
|
* @enum {string}
|
||||||
*/
|
*/
|
||||||
order: 'ASC' | 'DESC';
|
direction: 'ASC' | 'DESC';
|
||||||
})[];
|
})[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue