Feat: 絵文字申請中のやつのテーブルを分けた
Signed-off-by: mattyatea <mattyacocacora0@gmail.com>
This commit is contained in:
parent
97590f2567
commit
fe938bf8e6
29 changed files with 666 additions and 189 deletions
|
|
@ -45,18 +45,19 @@ const emojisDraftPaginationComponent = shallowRef<InstanceType<typeof MkPaginati
|
|||
const query = ref(null);
|
||||
|
||||
const paginationDraft = {
|
||||
endpoint: 'admin/emoji/list' as const,
|
||||
endpoint: 'emoji-drafts' as const,
|
||||
limit: 30,
|
||||
params: computed(() => ({
|
||||
query: (query.value && query.value !== '') ? query.value : null,
|
||||
draft: true,
|
||||
})),
|
||||
};
|
||||
|
||||
const editDraft = (emoji) => {
|
||||
emoji.isDraft = true;
|
||||
os.popup(defineAsyncComponent(() => import('@/components/MkEmojiEditDialog.vue')), {
|
||||
emoji: emoji,
|
||||
isRequest: false,
|
||||
isDraftEdit: true,
|
||||
}, {
|
||||
done: result => {
|
||||
if (result.updated) {
|
||||
|
|
@ -80,16 +81,16 @@ async function undrafted(emoji) {
|
|||
});
|
||||
if (canceled) return;
|
||||
|
||||
await os.api('admin/emoji/update', {
|
||||
await os.api('admin/emoji/draft-update', {
|
||||
id: emoji.id,
|
||||
fileId: emoji.fileId,
|
||||
name: emoji.name,
|
||||
category: emoji.category,
|
||||
aliases: emoji.aliases,
|
||||
license: emoji.license,
|
||||
draft: false,
|
||||
isSensitive: emoji.isSensitive,
|
||||
localOnly: emoji.localOnly,
|
||||
roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction,
|
||||
isDraft: false,
|
||||
});
|
||||
|
||||
emojisDraftPaginationComponent.value.removeItem((item) => item.id === emoji.id);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkInput v-model="license">
|
||||
<template #label>{{ i18n.ts.license }}</template>
|
||||
</MkInput>
|
||||
<MkFolder v-if="!isRequest">
|
||||
<MkFolder v-if="!isRequest && !isDraftEdit">
|
||||
<template #label>{{ i18n.ts.rolesThatCanBeUsedThisEmojiAsReaction }}</template>
|
||||
<template #suffix>{{ rolesThatCanBeUsedThisEmojiAsReaction.length === 0 ? i18n.ts.all : rolesThatCanBeUsedThisEmojiAsReaction.length }}</template>
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</MkFolder>
|
||||
<MkSwitch v-model="isSensitive">isSensitive</MkSwitch>
|
||||
<MkSwitch v-model="localOnly">{{ i18n.ts.localOnly }}</MkSwitch>
|
||||
<MkSwitch v-if="!isRequest" v-model="draft" :disabled="isRequest">
|
||||
<MkSwitch v-if="!isRequest" v-model="isDraft" :disabled="isRequest">
|
||||
{{ i18n.ts.draft }}
|
||||
</MkSwitch>
|
||||
</div>
|
||||
|
|
@ -100,6 +100,7 @@ import MkRolePreview from '@/components/MkRolePreview.vue';
|
|||
const props = defineProps<{
|
||||
emoji?: any,
|
||||
isRequest: boolean,
|
||||
isDraftEdit?: boolean,
|
||||
}>();
|
||||
|
||||
let dialog = $ref(null);
|
||||
|
|
@ -109,18 +110,18 @@ let aliases: string = $ref(props.emoji ? props.emoji.aliases.join(' ') : '');
|
|||
let license: string = $ref(props.emoji ? (props.emoji.license ?? '') : '');
|
||||
let isSensitive = $ref(props.emoji ? props.emoji.isSensitive : false);
|
||||
let localOnly = $ref(props.emoji ? props.emoji.localOnly : false);
|
||||
let roleIdsThatCanBeUsedThisEmojiAsReaction = $ref(props.emoji ? props.emoji.roleIdsThatCanBeUsedThisEmojiAsReaction : []);
|
||||
let roleIdsThatCanBeUsedThisEmojiAsReaction = $ref((props.emoji && props.emoji.roleIdsThatCanBeUsedThisEmojiAsReaction) ? props.emoji.roleIdsThatCanBeUsedThisEmojiAsReaction : []);
|
||||
let rolesThatCanBeUsedThisEmojiAsReaction = $ref([]);
|
||||
let file = $ref<Misskey.entities.DriveFile>();
|
||||
let chooseFile: DriveFile|null = $ref(null);
|
||||
let draft = $ref(props.emoji ? props.emoji.draft : false);
|
||||
let isRequest = $ref(props.isRequest);
|
||||
|
||||
let isDraftEdit = $ref(props.isDraftEdit ?? false);
|
||||
let isDraft = $ref(!!(isDraftEdit || props.isRequest));
|
||||
watch($$(roleIdsThatCanBeUsedThisEmojiAsReaction), async () => {
|
||||
rolesThatCanBeUsedThisEmojiAsReaction = (await Promise.all(roleIdsThatCanBeUsedThisEmojiAsReaction.map((id) => os.api('admin/roles/show', { roleId: id }).catch(() => null)))).filter(x => x != null);
|
||||
}, { immediate: true });
|
||||
|
||||
const imgUrl = computed(() => file ? file.url : props.emoji ? `/emoji/${props.emoji.name}.webp` : null);
|
||||
const imgUrl = computed(() => file ? file.url : props.emoji && !isDraftEdit ? `/emoji/${props.emoji.name}.webp` : props.emoji && props.emoji.url ? props.emoji.url : null);
|
||||
const validation = computed(() => {
|
||||
return name.match(/^[a-zA-Z0-9_]+$/) && imgUrl.value != null;
|
||||
});
|
||||
|
|
@ -129,28 +130,6 @@ const emit = defineEmits<{
|
|||
(ev: 'closed'): void
|
||||
}>();
|
||||
|
||||
async function add() {
|
||||
const ret = await os.api('admin/emoji/add-draft', {
|
||||
name: name,
|
||||
category: category,
|
||||
aliases: aliases.split(' '),
|
||||
license: license === '' ? null : license,
|
||||
fileId: chooseFile.id,
|
||||
});
|
||||
|
||||
emit('done', {
|
||||
updated: {
|
||||
id: ret.id,
|
||||
name,
|
||||
category,
|
||||
aliases: aliases.split(' '),
|
||||
license: license === '' ? null : license,
|
||||
draft: true,
|
||||
},
|
||||
});
|
||||
|
||||
dialog.close();
|
||||
}
|
||||
async function changeImage(ev) {
|
||||
file = await selectFile(ev.currentTarget ?? ev.target, null);
|
||||
const candidate = file.name.replace(/\.(.+)$/, '');
|
||||
|
|
@ -174,37 +153,13 @@ async function addRole() {
|
|||
async function removeRole(role, ev) {
|
||||
rolesThatCanBeUsedThisEmojiAsReaction = rolesThatCanBeUsedThisEmojiAsReaction.filter(x => x.id !== role.id);
|
||||
}
|
||||
async function update() {
|
||||
await os.apiWithDialog('admin/emoji/update', {
|
||||
id: props.emoji.id,
|
||||
name,
|
||||
category,
|
||||
aliases: aliases.split(' '),
|
||||
license: license === '' ? null : license,
|
||||
fileId: chooseFile?.id,
|
||||
draft: draft,
|
||||
});
|
||||
|
||||
emit('done', {
|
||||
updated: {
|
||||
id: props.emoji.id,
|
||||
name,
|
||||
category,
|
||||
aliases: aliases.split(' '),
|
||||
license: license === '' ? null : license,
|
||||
draft: draft,
|
||||
},
|
||||
});
|
||||
|
||||
dialog.close();
|
||||
}
|
||||
async function done() {
|
||||
const params = {
|
||||
name,
|
||||
category: category === '' ? null : category,
|
||||
aliases: aliases.replace(' ', ' ').split(' ').filter(x => x !== ''),
|
||||
license: license === '' ? null : license,
|
||||
draft: draft,
|
||||
draft: isDraft,
|
||||
isSensitive,
|
||||
localOnly,
|
||||
roleIdsThatCanBeUsedThisEmojiAsReaction: rolesThatCanBeUsedThisEmojiAsReaction.map(x => x.id),
|
||||
|
|
@ -213,12 +168,19 @@ async function done() {
|
|||
if (file) {
|
||||
params.fileId = file.id;
|
||||
}
|
||||
console.log(props.emoji);
|
||||
|
||||
if (props.emoji) {
|
||||
await os.apiWithDialog('admin/emoji/update', {
|
||||
id: props.emoji.id,
|
||||
...params,
|
||||
});
|
||||
if (isDraftEdit) {
|
||||
await os.apiWithDialog('admin/emoji/draft-update', {
|
||||
id: props.emoji.id,
|
||||
...params,
|
||||
});
|
||||
} else {
|
||||
await os.apiWithDialog('admin/emoji/update', {
|
||||
id: props.emoji.id,
|
||||
...params,
|
||||
});
|
||||
}
|
||||
|
||||
emit('done', {
|
||||
updated: {
|
||||
|
|
|
|||
|
|
@ -201,11 +201,13 @@ async function init(): Promise<void> {
|
|||
...params,
|
||||
limit: props.pagination.limit ?? 10,
|
||||
}).then(res => {
|
||||
if (props.pagination.endpoint === 'emoji-drafts') {
|
||||
res = res.emojis;
|
||||
}
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
const item = res[i];
|
||||
if (i === 3) item._shouldInsertAd_ = true;
|
||||
}
|
||||
|
||||
if (res.length === 0 || props.pagination.noPaging) {
|
||||
concatItems(res);
|
||||
more.value = false;
|
||||
|
|
@ -214,7 +216,6 @@ async function init(): Promise<void> {
|
|||
concatItems(res);
|
||||
more.value = true;
|
||||
}
|
||||
|
||||
offset.value = res.length;
|
||||
error.value = false;
|
||||
fetching.value = false;
|
||||
|
|
@ -241,6 +242,9 @@ const fetchMore = async (): Promise<void> => {
|
|||
untilId: Array.from(items.value.keys()).at(-1),
|
||||
}),
|
||||
}).then(res => {
|
||||
if (props.pagination.endpoint === 'emoji-drafts') {
|
||||
res = res.emojis;
|
||||
}
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
const item = res[i];
|
||||
if (i === 10) item._shouldInsertAd_ = true;
|
||||
|
|
@ -305,6 +309,9 @@ const fetchMoreAhead = async (): Promise<void> => {
|
|||
sinceId: Array.from(items.value.keys()).at(-1),
|
||||
}),
|
||||
}).then(res => {
|
||||
if (props.pagination.endpoint === 'emoji-drafts') {
|
||||
res = res.emojis;
|
||||
}
|
||||
if (res.length === 0) {
|
||||
items.value = concatMapWithArray(items.value, res);
|
||||
more.value = false;
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkFoldableSection v-for="category in customEmojiCategories" v-once :key="category">
|
||||
<template #header>{{ category || i18n.ts.other }}</template>
|
||||
<div :class="$style.emojis">
|
||||
<XEmoji v-for="emoji in customEmojis.filter(e => e.category === category && !e.draft)" :key="emoji.name" :emoji="emoji" :draft="emoji.draft"/>
|
||||
<XEmoji v-for="emoji in customEmojis.filter(e => e.category === category)" :key="emoji.name" :emoji="emoji"/>
|
||||
</div>
|
||||
</MkFoldableSection>
|
||||
</MkSpacer>
|
||||
<MkSpacer v-if="tab === 'draft'" :contentMax="1000" :marginMin="20">
|
||||
<div :class="$style.emojis">
|
||||
<XEmoji v-for="emoji in draftEmojis" :key="emoji.name" :emoji="emoji" :draft="emoji.draft"/>
|
||||
<XEmoji v-for="emoji in draftEmojis.emojis" :key="emoji.name" :emoji="emoji" :draft="true"/>
|
||||
</div>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
|
|
@ -73,8 +73,7 @@ definePageMetadata(ref({}));
|
|||
let q = $ref('');
|
||||
let searchEmojis = $ref<Misskey.entities.CustomEmoji[]>(null);
|
||||
let selectedTags = $ref(new Set());
|
||||
const draftEmojis = customEmojis.value.filter(emoji => emoji.draft);
|
||||
|
||||
const draftEmojis = await os.apiGet('emoji-drafts');
|
||||
function search() {
|
||||
if ((q === '' || q == null) && selectedTags.size === 0) {
|
||||
searchEmojis = null;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
-->
|
||||
|
||||
<template>
|
||||
<button v-if="emoji.draft" class="zuvgdzyu _button emoji-draft" @click="menu">
|
||||
<img :src="emoji.url" class="img" loading="lazy"/>
|
||||
<button v-if="draft" class="_button emoji-draft" :class="$style.root" @click="menu">
|
||||
<img :src="emoji.url" :class="$style.img" loading="lazy"/>
|
||||
<div class="body">
|
||||
<div class="name _monospace">{{ emoji.name + ' (draft)' }}</div>
|
||||
<div class="info">{{ emoji.aliases.join(' ') }}</div>
|
||||
|
|
@ -14,8 +14,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<button v-else class="_button" :class="$style.root" @click="menu">
|
||||
<img :src="emoji.url" :class="$style.img" loading="lazy"/>
|
||||
<div :class="$style.body">
|
||||
<div :class="$style.name" class="_monospace">{{ emoji.name }}</div>
|
||||
<div :class="$style.info">{{ emoji.aliases.join(' ') }}</div>
|
||||
<div class="name _monospace">{{ emoji.name }}</div>
|
||||
<div class="info">{{ emoji.aliases.join(' ') }}</div>
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
|
|
@ -26,13 +26,13 @@ import copyToClipboard from '@/scripts/copy-to-clipboard.js';
|
|||
import { i18n } from '@/i18n.js';
|
||||
|
||||
const props = defineProps<{
|
||||
emoji: {
|
||||
name: string;
|
||||
aliases: string[];
|
||||
category: string;
|
||||
url: string;
|
||||
draft: boolean;
|
||||
};
|
||||
emoji: {
|
||||
name: string;
|
||||
aliases: string[];
|
||||
category: string;
|
||||
url: string;
|
||||
};
|
||||
draft?: boolean;
|
||||
}>();
|
||||
|
||||
function menu(ev) {
|
||||
|
|
@ -50,7 +50,7 @@ function menu(ev) {
|
|||
text: i18n.ts.info,
|
||||
icon: 'ti ti-info-circle',
|
||||
action: () => {
|
||||
os.apiGet('emoji', { name: props.emoji.name }).then(res => {
|
||||
os.apiGet('emoji-drafts', { name: props.emoji.name }).then(res => {
|
||||
os.alert({
|
||||
type: 'info',
|
||||
text: `License: ${res.license}`,
|
||||
|
|
@ -63,45 +63,45 @@ function menu(ev) {
|
|||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
background: var(--panel);
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
background: var(--panel);
|
||||
border-radius: 8px;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
&:hover {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
object-fit: contain;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.body {
|
||||
padding: 0 0 0 8px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
padding: 0 0 0 8px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.name {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.info {
|
||||
opacity: 0.5;
|
||||
font-size: 0.9em;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
opacity: 0.5;
|
||||
font-size: 0.9em;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.emoji-draft {
|
||||
--c: rgb(255 196 0 / 15%);;
|
||||
background-image: linear-gradient(45deg,var(--c) 16.67%,transparent 16.67%,transparent 50%,var(--c) 50%,var(--c) 66.67%,transparent 66.67%,transparent 100%);
|
||||
background-size: 16px 16px;
|
||||
--c: rgb(255 196 0 / 15%);;
|
||||
background-image: linear-gradient(45deg,var(--c) 16.67%,transparent 16.67%,transparent 50%,var(--c) 50%,var(--c) 66.67%,transparent 66.67%,transparent 100%);
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue