ソートキーの指定方法を他と合わせた
This commit is contained in:
parent
fdf20a6605
commit
ca2da9d296
|
@ -27,47 +27,34 @@ export const fetchEmojisHostTypes = [
|
|||
] as const;
|
||||
export type FetchEmojisHostTypes = typeof fetchEmojisHostTypes[number];
|
||||
export const fetchEmojisSortKeys = [
|
||||
'id',
|
||||
'updatedAt',
|
||||
'name',
|
||||
'host',
|
||||
'uri',
|
||||
'publicUrl',
|
||||
'type',
|
||||
'aliases',
|
||||
'category',
|
||||
'license',
|
||||
'isSensitive',
|
||||
'localOnly',
|
||||
'roleIdsThatCanBeUsedThisEmojiAsReaction',
|
||||
'+id',
|
||||
'-id',
|
||||
'+updatedAt',
|
||||
'-updatedAt',
|
||||
'+name',
|
||||
'-name',
|
||||
'+host',
|
||||
'-host',
|
||||
'+uri',
|
||||
'-uri',
|
||||
'+publicUrl',
|
||||
'-publicUrl',
|
||||
'+type',
|
||||
'-type',
|
||||
'+aliases',
|
||||
'-aliases',
|
||||
'+category',
|
||||
'-category',
|
||||
'+license',
|
||||
'-license',
|
||||
'+isSensitive',
|
||||
'-isSensitive',
|
||||
'+localOnly',
|
||||
'-localOnly',
|
||||
'+roleIdsThatCanBeUsedThisEmojiAsReaction',
|
||||
'-roleIdsThatCanBeUsedThisEmojiAsReaction',
|
||||
] as const;
|
||||
export type FetchEmojisSortKeys = typeof fetchEmojisSortKeys[number];
|
||||
export type FetchEmojisParams = {
|
||||
query?: {
|
||||
updatedAtFrom?: string;
|
||||
updatedAtTo?: string;
|
||||
name?: string;
|
||||
host?: string;
|
||||
uri?: string;
|
||||
publicUrl?: string;
|
||||
type?: string;
|
||||
aliases?: string;
|
||||
category?: string;
|
||||
license?: string;
|
||||
isSensitive?: boolean;
|
||||
localOnly?: boolean;
|
||||
hostType?: FetchEmojisHostTypes;
|
||||
roleIds?: string[];
|
||||
},
|
||||
sinceId?: string;
|
||||
untilId?: string;
|
||||
limit?: number;
|
||||
page?: number;
|
||||
sort?: {
|
||||
key: FetchEmojisSortKeys;
|
||||
direction: 'ASC' | 'DESC';
|
||||
}[]
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class CustomEmojiService implements OnApplicationShutdown {
|
||||
|
@ -449,7 +436,33 @@ export class CustomEmojiService implements OnApplicationShutdown {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async fetchEmojis(params?: FetchEmojisParams) {
|
||||
public async fetchEmojis(
|
||||
params?: {
|
||||
query?: {
|
||||
updatedAtFrom?: string;
|
||||
updatedAtTo?: string;
|
||||
name?: string;
|
||||
host?: string;
|
||||
uri?: string;
|
||||
publicUrl?: string;
|
||||
type?: string;
|
||||
aliases?: string;
|
||||
category?: string;
|
||||
license?: string;
|
||||
isSensitive?: boolean;
|
||||
localOnly?: boolean;
|
||||
hostType?: FetchEmojisHostTypes;
|
||||
roleIds?: string[];
|
||||
},
|
||||
sinceId?: string;
|
||||
untilId?: string;
|
||||
},
|
||||
opts?: {
|
||||
limit?: number;
|
||||
page?: number;
|
||||
sortKeys?: FetchEmojisSortKeys[]
|
||||
},
|
||||
) {
|
||||
function multipleWordsToQuery<T extends ObjectLiteral>(
|
||||
query: string,
|
||||
builder: SelectQueryBuilder<T>,
|
||||
|
@ -565,17 +578,19 @@ export class CustomEmojiService implements OnApplicationShutdown {
|
|||
builder.andWhere('emoji.id < :untilId', { untilId: params.untilId });
|
||||
}
|
||||
|
||||
if (params?.sort && params.sort.length > 0) {
|
||||
for (const sort of params.sort) {
|
||||
builder.addOrderBy(`emoji.${sort.key}`, sort.direction);
|
||||
if (opts?.sortKeys && opts.sortKeys.length > 0) {
|
||||
for (const sortKey of opts.sortKeys) {
|
||||
const direction = sortKey.startsWith('-') ? 'DESC' : 'ASC';
|
||||
const key = sortKey.replace(/^[+-]/, '');
|
||||
builder.addOrderBy(`emoji.${key}`, direction);
|
||||
}
|
||||
} else {
|
||||
builder.addOrderBy('emoji.id', 'DESC');
|
||||
}
|
||||
|
||||
const limit = params?.limit ?? 10;
|
||||
if (params?.page) {
|
||||
builder.skip((params.page - 1) * limit);
|
||||
const limit = opts?.limit ?? 10;
|
||||
if (opts?.page) {
|
||||
builder.skip((opts.page - 1) * limit);
|
||||
}
|
||||
|
||||
builder.take(limit);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
|
||||
import { CustomEmojiService, FetchEmojisParams } from '@/core/CustomEmojiService.js';
|
||||
import { CustomEmojiService, fetchEmojisHostTypes, fetchEmojisSortKeys } from '@/core/CustomEmojiService.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
|
@ -52,7 +52,11 @@ export const paramDef = {
|
|||
license: { type: 'string' },
|
||||
isSensitive: { type: 'boolean' },
|
||||
localOnly: { type: 'boolean' },
|
||||
hostType: { type: 'string', enum: ['local', 'remote', 'all'], default: 'all' },
|
||||
hostType: {
|
||||
type: 'string',
|
||||
enum: fetchEmojisHostTypes,
|
||||
default: 'all',
|
||||
},
|
||||
roleIds: {
|
||||
type: 'array',
|
||||
items: { type: 'string', format: 'misskey:id' },
|
||||
|
@ -63,37 +67,12 @@ export const paramDef = {
|
|||
untilId: { type: 'string', format: 'misskey:id' },
|
||||
limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 },
|
||||
page: { type: 'integer' },
|
||||
sort: {
|
||||
sortKeys: {
|
||||
type: 'array',
|
||||
default: ['-id'],
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
key: {
|
||||
type: 'string',
|
||||
enum: [
|
||||
'id',
|
||||
'updatedAt',
|
||||
'name',
|
||||
'host',
|
||||
'uri',
|
||||
'publicUrl',
|
||||
'type',
|
||||
'aliases',
|
||||
'category',
|
||||
'license',
|
||||
'isSensitive',
|
||||
'localOnly',
|
||||
'roleIdsThatCanBeUsedThisEmojiAsReaction',
|
||||
],
|
||||
default: 'id',
|
||||
},
|
||||
direction: {
|
||||
type: 'string',
|
||||
enum: ['ASC', 'DESC'],
|
||||
default: 'DESC',
|
||||
},
|
||||
},
|
||||
required: ['key', 'direction'],
|
||||
type: 'string',
|
||||
enum: fetchEmojisSortKeys,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -107,37 +86,34 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
private emojiEntityService: EmojiEntityService,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const params: FetchEmojisParams = {};
|
||||
|
||||
if (ps.query) {
|
||||
params.query = {
|
||||
updatedAtFrom: ps.query.updatedAtFrom,
|
||||
updatedAtTo: ps.query.updatedAtTo,
|
||||
name: ps.query.name,
|
||||
host: ps.query.host,
|
||||
uri: ps.query.uri,
|
||||
publicUrl: ps.query.publicUrl,
|
||||
type: ps.query.type,
|
||||
aliases: ps.query.aliases,
|
||||
category: ps.query.category,
|
||||
license: ps.query.license,
|
||||
isSensitive: ps.query.isSensitive,
|
||||
localOnly: ps.query.localOnly,
|
||||
hostType: ps.query.hostType,
|
||||
roleIds: ps.query.roleIds,
|
||||
};
|
||||
}
|
||||
|
||||
params.sinceId = ps.sinceId;
|
||||
params.untilId = ps.untilId;
|
||||
params.limit = ps.limit;
|
||||
params.page = ps.page;
|
||||
params.sort = ps.sort?.map(it => ({
|
||||
key: it.key,
|
||||
direction: it.direction,
|
||||
}));
|
||||
|
||||
const result = await this.customEmojiService.fetchEmojis(params);
|
||||
const q = ps.query;
|
||||
const result = await this.customEmojiService.fetchEmojis(
|
||||
{
|
||||
query: {
|
||||
updatedAtFrom: q?.updatedAtFrom,
|
||||
updatedAtTo: q?.updatedAtTo,
|
||||
name: q?.name,
|
||||
host: q?.host,
|
||||
uri: q?.uri,
|
||||
publicUrl: q?.publicUrl,
|
||||
type: q?.type,
|
||||
aliases: q?.aliases,
|
||||
category: q?.category,
|
||||
license: q?.license,
|
||||
isSensitive: q?.isSensitive,
|
||||
localOnly: q?.localOnly,
|
||||
hostType: q?.hostType,
|
||||
roleIds: q?.roleIds,
|
||||
},
|
||||
sinceId: ps.sinceId,
|
||||
untilId: ps.untilId,
|
||||
},
|
||||
{
|
||||
limit: ps.limit,
|
||||
page: ps.page,
|
||||
sortKeys: ps.sortKeys,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
emojis: await this.emojiEntityService.packDetailedAdminMany(result.emojis),
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export type SortOrderDirection = '+' | '-'
|
||||
|
||||
export type SortOrder<T extends string> = {
|
||||
key: T;
|
||||
direction: SortOrderDirection;
|
||||
}
|
|
@ -7,13 +7,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.sortOrderArea">
|
||||
<div :class="$style.sortOrderAreaTags">
|
||||
<MkTagItem
|
||||
v-for="order in sortOrders"
|
||||
v-for="order in currentOrders"
|
||||
:key="order.key"
|
||||
:iconClass="order.direction === 'ASC' ? 'ti ti-arrow-up' : 'ti ti-arrow-down'"
|
||||
:iconClass="order.direction === '+' ? 'ti ti-arrow-up' : 'ti ti-arrow-down'"
|
||||
:exButtonIconClass="'ti ti-x'"
|
||||
:content="order.key"
|
||||
@click="onToggleSortOrderButtonClicked(order)"
|
||||
@exButtonClick="onRemoveSortOrderButtonClicked(order.key)"
|
||||
@exButtonClick="onRemoveSortOrderButtonClicked(order)"
|
||||
/>
|
||||
</div>
|
||||
<MkButton :class="$style.sortOrderAddButton" @click="onAddSortOrderButtonClicked">
|
||||
|
@ -22,58 +22,57 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup lang="ts" generic="T extends string">
|
||||
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';
|
||||
import { SortOrder } from '@/components/MkSortOrderEditor.define.js';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'update', sortOrders: GridSortOrder[]): void;
|
||||
(ev: 'update', sortOrders: SortOrder<T>[]): void;
|
||||
}>();
|
||||
|
||||
const props = defineProps<{
|
||||
sortOrders: GridSortOrder[];
|
||||
baseOrderKeyNames: T[];
|
||||
currentOrders: SortOrder<T>[];
|
||||
}>();
|
||||
|
||||
const { sortOrders } = toRefs(props);
|
||||
const { currentOrders } = toRefs(props);
|
||||
|
||||
function onToggleSortOrderButtonClicked(order: GridSortOrder) {
|
||||
function onToggleSortOrderButtonClicked(order: SortOrder<T>) {
|
||||
switch (order.direction) {
|
||||
case 'ASC':
|
||||
order.direction = 'DESC';
|
||||
case '+':
|
||||
order.direction = '-';
|
||||
break;
|
||||
case 'DESC':
|
||||
order.direction = 'ASC';
|
||||
case '-':
|
||||
order.direction = '+';
|
||||
break;
|
||||
}
|
||||
|
||||
emitOrder(sortOrders.value);
|
||||
emitOrder(currentOrders.value);
|
||||
}
|
||||
|
||||
function onAddSortOrderButtonClicked(ev: MouseEvent) {
|
||||
const menuItems: MenuItem[] = gridSortOrderKeys
|
||||
.filter(key => !sortOrders.value.map(it => it.key).includes(key))
|
||||
const menuItems: MenuItem[] = props.baseOrderKeyNames
|
||||
.filter(baseKey => !currentOrders.value.map(it => it.key).includes(baseKey))
|
||||
.map(it => {
|
||||
return {
|
||||
text: it,
|
||||
action: () => {
|
||||
emitOrder([...sortOrders.value, { key: it, direction: 'ASC' }]);
|
||||
emitOrder([...currentOrders.value, { key: it, direction: '+' }]);
|
||||
},
|
||||
};
|
||||
});
|
||||
os.contextMenu(menuItems, ev);
|
||||
}
|
||||
|
||||
function onRemoveSortOrderButtonClicked(key: GridSortOrderKey) {
|
||||
emitOrder(sortOrders.value.filter(it => it.key !== key));
|
||||
function onRemoveSortOrderButtonClicked(order: SortOrder<T>) {
|
||||
emitOrder(currentOrders.value.filter(it => it.key !== order.key));
|
||||
}
|
||||
|
||||
function emitOrder(sortOrders: GridSortOrder[]) {
|
||||
function emitOrder(sortOrders: SortOrder<T>[]) {
|
||||
emit('update', sortOrders);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,11 +25,6 @@ export const gridSortOrderKeys = [
|
|||
];
|
||||
export type GridSortOrderKey = typeof gridSortOrderKeys[number];
|
||||
|
||||
export type GridSortOrder = {
|
||||
key: GridSortOrderKey;
|
||||
direction: 'ASC' | 'DESC';
|
||||
}
|
||||
|
||||
export function emptyStrToUndefined(value: string | null) {
|
||||
return value ? value : undefined;
|
||||
}
|
||||
|
|
|
@ -120,7 +120,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkFolder :spacerMax="8" :spacerMin="8">
|
||||
<template #icon><i class="ti ti-arrows-sort"></i></template>
|
||||
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.sortOrder }}</template>
|
||||
<MkSortOrderEditor :sortOrders="sortOrders" @update="onSortOrderUpdate"/>
|
||||
<MkSortOrderEditor
|
||||
:baseOrderKeyNames="gridSortOrderKeys"
|
||||
:currentOrders="sortOrders"
|
||||
@update="onSortOrderUpdate"
|
||||
/>
|
||||
</MkFolder>
|
||||
|
||||
<div :class="[[spMode ? $style.searchButtonsSp : $style.searchButtons]]">
|
||||
|
@ -163,7 +167,9 @@ import * as os from '@/os.js';
|
|||
import {
|
||||
emptyStrToEmptyArray,
|
||||
emptyStrToNull,
|
||||
emptyStrToUndefined, GridSortOrder,
|
||||
emptyStrToUndefined,
|
||||
GridSortOrderKey,
|
||||
gridSortOrderKeys,
|
||||
RequestLogItem,
|
||||
roleIdsParser,
|
||||
} from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||
|
@ -183,6 +189,7 @@ import { GridSetting } from '@/components/grid/grid.js';
|
|||
import { selectFile } from '@/scripts/select-file.js';
|
||||
import { copyGridDataToClipboard, removeDataFromGrid } from '@/components/grid/grid-utils.js';
|
||||
import MkSortOrderEditor from '@/components/MkSortOrderEditor.vue';
|
||||
import { SortOrder } from '@/components/MkSortOrderEditor.define.js';
|
||||
|
||||
type GridItem = {
|
||||
checked: boolean;
|
||||
|
@ -370,7 +377,7 @@ const querySensitive = ref<string | null>(null);
|
|||
const queryLocalOnly = ref<string | null>(null);
|
||||
const queryRoles = ref<{ id: string, name: string }[]>([]);
|
||||
const previousQuery = ref<string | undefined>(undefined);
|
||||
const sortOrders = ref<GridSortOrder[]>([]);
|
||||
const sortOrders = ref<SortOrder<GridSortOrderKey>[]>([]);
|
||||
const requestLogs = ref<RequestLogItem[]>([]);
|
||||
|
||||
const gridItems = ref<GridItem[]>([]);
|
||||
|
@ -499,7 +506,7 @@ async function onQueryRolesEditClicked() {
|
|||
queryRoles.value = result.result;
|
||||
}
|
||||
|
||||
function onSortOrderUpdate(_sortOrders: GridSortOrder[]) {
|
||||
function onSortOrderUpdate(_sortOrders: SortOrder<GridSortOrderKey>[]) {
|
||||
sortOrders.value = _sortOrders;
|
||||
}
|
||||
|
||||
|
@ -573,7 +580,7 @@ async function refreshCustomEmojis() {
|
|||
query: query,
|
||||
limit: limit,
|
||||
page: currentPage.value,
|
||||
sort: sortOrders.value.map(({ key, direction }) => ({ key: key as any, direction })),
|
||||
sortKeys: sortOrders.value.map(({ key, direction }) => `${direction}${key}`),
|
||||
}),
|
||||
() => {
|
||||
},
|
||||
|
|
|
@ -56,7 +56,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkFolder :spacerMax="8" :spacerMin="8">
|
||||
<template #icon><i class="ti ti-arrows-sort"></i></template>
|
||||
<template #label>{{ i18n.ts._customEmojisManager._gridCommon.sortOrder }}</template>
|
||||
<MkSortOrderEditor :sortOrders="sortOrders" @update="onSortOrderChanged"/>
|
||||
<MkSortOrderEditor
|
||||
:baseOrderKeyNames="gridSortOrderKeys"
|
||||
:currentOrders="sortOrders"
|
||||
@update="onSortOrderUpdate"
|
||||
/>
|
||||
</MkFolder>
|
||||
|
||||
<div :class="[[spMode ? $style.searchButtonsSp : $style.searchButtons]]">
|
||||
|
@ -79,7 +83,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkPagingButtons :current="currentPage" :max="allPages" :buttonCount="5" @pageChanged="onPageChanged"/>
|
||||
|
||||
<div v-if="gridItems.length > 0" class="_gaps" :class="$style.buttons">
|
||||
<MkButton primary @click="onImportClicked">{{ i18n.ts._customEmojisManager._remote.importEmojisButton }}</MkButton>
|
||||
<MkButton primary @click="onImportClicked">
|
||||
{{
|
||||
i18n.ts._customEmojisManager._remote.importEmojisButton
|
||||
}}
|
||||
</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -93,7 +101,12 @@ 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, GridSortOrder, RequestLogItem } from '@/pages/admin/custom-emojis-manager.impl.js';
|
||||
import {
|
||||
emptyStrToUndefined,
|
||||
GridSortOrderKey,
|
||||
gridSortOrderKeys,
|
||||
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 XRegisterLogsFolder from '@/pages/admin/custom-emojis-manager.logs-folder.vue';
|
||||
|
@ -102,6 +115,7 @@ import { GridSetting } from '@/components/grid/grid.js';
|
|||
import { deviceKind } from '@/scripts/device-kind.js';
|
||||
import MkPagingButtons from '@/components/MkPagingButtons.vue';
|
||||
import MkSortOrderEditor from '@/components/MkSortOrderEditor.vue';
|
||||
import { SortOrder } from '@/components/MkSortOrderEditor.define.js';
|
||||
|
||||
type GridItem = {
|
||||
checked: boolean;
|
||||
|
@ -163,14 +177,14 @@ const queryHost = ref<string | null>(null);
|
|||
const queryUri = ref<string | null>(null);
|
||||
const queryPublicUrl = ref<string | null>(null);
|
||||
const previousQuery = ref<string | undefined>(undefined);
|
||||
const sortOrders = ref<GridSortOrder[]>([]);
|
||||
const sortOrders = ref<SortOrder<GridSortOrderKey>[]>([]);
|
||||
const requestLogs = ref<RequestLogItem[]>([]);
|
||||
|
||||
const gridItems = ref<GridItem[]>([]);
|
||||
|
||||
const spMode = computed(() => ['smartphone', 'tablet'].includes(deviceKind));
|
||||
|
||||
function onSortOrderChanged(_sortOrders: GridSortOrder[]) {
|
||||
function onSortOrderUpdate(_sortOrders: SortOrder<GridSortOrderKey>[]) {
|
||||
sortOrders.value = _sortOrders;
|
||||
}
|
||||
|
||||
|
@ -272,7 +286,7 @@ async function refreshCustomEmojis() {
|
|||
limit: 100,
|
||||
query: query,
|
||||
page: currentPage.value,
|
||||
sort: sortOrders.value.map(({ key, direction }) => ({ key: key as any, direction })),
|
||||
sortKeys: sortOrders.value.map(({ key, direction }) => `${direction}${key}`),
|
||||
}),
|
||||
() => {
|
||||
},
|
||||
|
|
|
@ -7681,18 +7681,12 @@ export type operations = {
|
|||
/** @default 10 */
|
||||
limit?: number;
|
||||
page?: number;
|
||||
sort?: ({
|
||||
/**
|
||||
* @default id
|
||||
* @enum {string}
|
||||
*/
|
||||
key: 'id' | 'updatedAt' | 'name' | 'host' | 'uri' | 'publicUrl' | 'type' | 'aliases' | 'category' | 'license' | 'isSensitive' | 'localOnly' | 'roleIdsThatCanBeUsedThisEmojiAsReaction';
|
||||
/**
|
||||
* @default DESC
|
||||
* @enum {string}
|
||||
*/
|
||||
direction: 'ASC' | 'DESC';
|
||||
})[];
|
||||
/**
|
||||
* @default [
|
||||
* "-id"
|
||||
* ]
|
||||
*/
|
||||
sortKeys?: ('+id' | '-id' | '+updatedAt' | '-updatedAt' | '+name' | '-name' | '+host' | '-host' | '+uri' | '-uri' | '+publicUrl' | '-publicUrl' | '+type' | '-type' | '+aliases' | '-aliases' | '+category' | '-category' | '+license' | '-license' | '+isSensitive' | '-isSensitive' | '+localOnly' | '-localOnly' | '+roleIdsThatCanBeUsedThisEmojiAsReaction' | '-roleIdsThatCanBeUsedThisEmojiAsReaction')[];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue