diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2023-10-21 18:38:07 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-21 18:38:07 +0900 |
| commit | 2c0a139da60ddf33e82353acbb985230c71c78da (patch) | |
| tree | b12d2762b332b7c885c5b210954053869618b62a /packages/frontend/src/pages/admin | |
| parent | Update CHANGELOG.md (diff) | |
| download | misskey-2c0a139da60ddf33e82353acbb985230c71c78da.tar.gz misskey-2c0a139da60ddf33e82353acbb985230c71c78da.tar.bz2 misskey-2c0a139da60ddf33e82353acbb985230c71c78da.zip | |
feat: Avatar decoration (#12096)
* wip
* Update ja-JP.yml
* Update profile.vue
* .js
* Update home.test.ts
Diffstat (limited to 'packages/frontend/src/pages/admin')
| -rw-r--r-- | packages/frontend/src/pages/admin/avatar-decorations.vue | 103 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/index.vue | 5 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/modlog.ModLog.vue | 12 |
3 files changed, 118 insertions, 2 deletions
diff --git a/packages/frontend/src/pages/admin/avatar-decorations.vue b/packages/frontend/src/pages/admin/avatar-decorations.vue new file mode 100644 index 0000000000..b4007e6d20 --- /dev/null +++ b/packages/frontend/src/pages/admin/avatar-decorations.vue @@ -0,0 +1,103 @@ +<!-- +SPDX-FileCopyrightText: syuilo and other misskey contributors +SPDX-License-Identifier: AGPL-3.0-only +--> + +<template> +<MkStickyContainer> + <template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template> + <MkSpacer :contentMax="900"> + <div class="_gaps"> + <MkFolder v-for="avatarDecoration in avatarDecorations" :key="avatarDecoration.id ?? avatarDecoration._id" :defaultOpen="avatarDecoration.id == null"> + <template #label>{{ avatarDecoration.name }}</template> + <template #caption>{{ avatarDecoration.description }}</template> + + <div class="_gaps_m"> + <MkInput v-model="avatarDecoration.name"> + <template #label>{{ i18n.ts.name }}</template> + </MkInput> + <MkTextarea v-model="avatarDecoration.description"> + <template #label>{{ i18n.ts.description }}</template> + </MkTextarea> + <MkInput v-model="avatarDecoration.url"> + <template #label>{{ i18n.ts.imageUrl }}</template> + </MkInput> + <div class="buttons _buttons"> + <MkButton class="button" inline primary @click="save(avatarDecoration)"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton> + <MkButton v-if="avatarDecoration.id != null" class="button" inline danger @click="del(avatarDecoration)"><i class="ti ti-trash"></i> {{ i18n.ts.delete }}</MkButton> + </div> + </div> + </MkFolder> + </div> + </MkSpacer> +</MkStickyContainer> +</template> + +<script lang="ts" setup> +import { } from 'vue'; +import XHeader from './_header_.vue'; +import MkButton from '@/components/MkButton.vue'; +import MkInput from '@/components/MkInput.vue'; +import MkTextarea from '@/components/MkTextarea.vue'; +import MkSwitch from '@/components/MkSwitch.vue'; +import MkRadios from '@/components/MkRadios.vue'; +import MkInfo from '@/components/MkInfo.vue'; +import * as os from '@/os.js'; +import { i18n } from '@/i18n.js'; +import { definePageMetadata } from '@/scripts/page-metadata.js'; +import MkFolder from '@/components/MkFolder.vue'; + +let avatarDecorations: any[] = $ref([]); + +function add() { + avatarDecorations.unshift({ + _id: Math.random().toString(36), + id: null, + name: '', + description: '', + url: '', + }); +} + +function del(avatarDecoration) { + os.confirm({ + type: 'warning', + text: i18n.t('deleteAreYouSure', { x: avatarDecoration.name }), + }).then(({ canceled }) => { + if (canceled) return; + avatarDecorations = avatarDecorations.filter(x => x !== avatarDecoration); + os.api('admin/avatar-decorations/delete', avatarDecoration); + }); +} + +async function save(avatarDecoration) { + if (avatarDecoration.id == null) { + await os.apiWithDialog('admin/avatar-decorations/create', avatarDecoration); + load(); + } else { + os.apiWithDialog('admin/avatar-decorations/update', avatarDecoration); + } +} + +function load() { + os.api('admin/avatar-decorations/list').then(_avatarDecorations => { + avatarDecorations = _avatarDecorations; + }); +} + +load(); + +const headerActions = $computed(() => [{ + asFullButton: true, + icon: 'ti ti-plus', + text: i18n.ts.add, + handler: add, +}]); + +const headerTabs = $computed(() => []); + +definePageMetadata({ + title: i18n.ts.avatarDecorations, + icon: 'ti ti-sparkles', +}); +</script> diff --git a/packages/frontend/src/pages/admin/index.vue b/packages/frontend/src/pages/admin/index.vue index a508c20cf3..b304edbf57 100644 --- a/packages/frontend/src/pages/admin/index.vue +++ b/packages/frontend/src/pages/admin/index.vue @@ -116,6 +116,11 @@ const menuDef = $computed(() => [{ to: '/admin/emojis', active: currentPage?.route.name === 'emojis', }, { + icon: 'ti ti-sparkles', + text: i18n.ts.avatarDecorations, + to: '/admin/avatar-decorations', + active: currentPage?.route.name === 'avatarDecorations', + }, { icon: 'ti ti-whirl', text: i18n.ts.federation, to: '/admin/federation', diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue index 0af226f02e..bceefcf6c8 100644 --- a/packages/frontend/src/pages/admin/modlog.ModLog.vue +++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue @@ -8,9 +8,9 @@ SPDX-License-Identifier: AGPL-3.0-only <template #label> <b :class="{ - [$style.logGreen]: ['createRole', 'addCustomEmoji', 'createGlobalAnnouncement', 'createUserAnnouncement', 'createAd', 'createInvitation'].includes(log.type), + [$style.logGreen]: ['createRole', 'addCustomEmoji', 'createGlobalAnnouncement', 'createUserAnnouncement', 'createAd', 'createInvitation', 'createAvatarDecoration'].includes(log.type), [$style.logYellow]: ['markSensitiveDriveFile', 'resetPassword'].includes(log.type), - [$style.logRed]: ['suspend', 'deleteRole', 'suspendRemoteInstance', 'deleteGlobalAnnouncement', 'deleteUserAnnouncement', 'deleteCustomEmoji', 'deleteNote', 'deleteDriveFile', 'deleteAd'].includes(log.type) + [$style.logRed]: ['suspend', 'deleteRole', 'suspendRemoteInstance', 'deleteGlobalAnnouncement', 'deleteUserAnnouncement', 'deleteCustomEmoji', 'deleteNote', 'deleteDriveFile', 'deleteAd', 'deleteAvatarDecoration'].includes(log.type) }" >{{ i18n.ts._moderationLogTypes[log.type] }}</b> <span v-if="log.type === 'updateUserNote'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span> @@ -37,6 +37,9 @@ SPDX-License-Identifier: AGPL-3.0-only <span v-else-if="log.type === 'deleteUserAnnouncement'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span> <span v-else-if="log.type === 'deleteNote'">: @{{ log.info.noteUserUsername }}{{ log.info.noteUserHost ? '@' + log.info.noteUserHost : '' }}</span> <span v-else-if="log.type === 'deleteDriveFile'">: @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }}</span> + <span v-else-if="log.type === 'createAvatarDecoration'">: {{ log.info.avatarDecoration.name }}</span> + <span v-else-if="log.type === 'updateAvatarDecoration'">: {{ log.info.before.name }}</span> + <span v-else-if="log.type === 'deleteAvatarDecoration'">: {{ log.info.avatarDecoration.name }}</span> </template> <template #icon> <MkAvatar :user="log.user" :class="$style.avatar"/> @@ -102,6 +105,11 @@ SPDX-License-Identifier: AGPL-3.0-only <CodeDiff :context="5" :hideHeader="true" :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/> </div> </template> + <template v-else-if="log.type === 'updateAvatarDecoration'"> + <div :class="$style.diff"> + <CodeDiff :context="5" :hideHeader="true" :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/> + </div> + </template> <details> <summary>raw</summary> |