summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2025-06-03 17:20:11 +0900
committerGitHub <noreply@github.com>2025-06-03 17:20:11 +0900
commit810a609df4d4037daf77bf6dbf2b38b9457bb0dd (patch)
tree10bb63433bc4025d4d0155362702d0136e0254b3
parentfix(frontend): ドライブのファイル選択が不安定な問題を修... (diff)
downloadmisskey-810a609df4d4037daf77bf6dbf2b38b9457bb0dd.tar.gz
misskey-810a609df4d4037daf77bf6dbf2b38b9457bb0dd.tar.bz2
misskey-810a609df4d4037daf77bf6dbf2b38b9457bb0dd.zip
fix(frontend): 一部のグリッドのページネーションが正しく表示されない問題を修正 (#16147)
* fix(frontend): 一部のグリッドのページネーションが正しく表示されない問題を修正 * update changelog * fix
-rw-r--r--CHANGELOG.md1
-rw-r--r--packages/frontend/src/components/MkFileListForAdmin.vue156
-rw-r--r--packages/frontend/src/pages/admin/files.vue8
-rw-r--r--packages/frontend/src/pages/instance-info.vue85
4 files changed, 127 insertions, 123 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c2533b7232..6f99b946d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
### Client
- Fix: ドライブファイルの選択が不安定な問題を修正
+- Fix: コントロールパネルのファイル欄などのデザインが崩れている問題を修正
### Server
-
diff --git a/packages/frontend/src/components/MkFileListForAdmin.vue b/packages/frontend/src/components/MkFileListForAdmin.vue
index d5d32ebb28..3b495c2807 100644
--- a/packages/frontend/src/components/MkFileListForAdmin.vue
+++ b/packages/frontend/src/components/MkFileListForAdmin.vue
@@ -5,33 +5,35 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<div>
- <MkPagination v-slot="{items}" :pagination="pagination" class="urempief" :class="{ grid: viewMode === 'grid' }">
- <MkA
- v-for="file in (items as Misskey.entities.DriveFile[])"
- :key="file.id"
- v-tooltip.mfm="`${file.type}\n${bytes(file.size)}\n${dateString(file.createdAt)}\nby ${file.user ? '@' + Misskey.acct.toString(file.user) : 'system'}`"
- :to="`/admin/file/${file.id}`"
- class="file _button"
- >
- <div v-if="file.isSensitive" class="sensitive-label">{{ i18n.ts.sensitive }}</div>
- <MkDriveFileThumbnail class="thumbnail" :file="file" fit="contain" :highlightWhenSensitive="true"/>
- <div v-if="viewMode === 'list'" class="body">
- <div>
- <small style="opacity: 0.7;">{{ file.name }}</small>
+ <MkPagination v-slot="{ items }" :pagination="pagination">
+ <div :class="[$style.fileList, { [$style.grid]: viewMode === 'grid', [$style.list]: viewMode === 'list', '_gaps_s': viewMode === 'list' }]">
+ <MkA
+ v-for="file in items"
+ :key="file.id"
+ v-tooltip.mfm="`${file.type}\n${bytes(file.size)}\n${dateString(file.createdAt)}\nby ${file.user ? '@' + Misskey.acct.toString(file.user) : 'system'}`"
+ :to="`/admin/file/${file.id}`"
+ :class="[$style.file, '_button']"
+ >
+ <div v-if="file.isSensitive" :class="$style.sensitiveLabel">{{ i18n.ts.sensitive }}</div>
+ <MkDriveFileThumbnail :class="$style.thumbnail" :file="file" fit="contain" :highlightWhenSensitive="true"/>
+ <div v-if="viewMode === 'list'" :class="$style.body">
+ <div>
+ <small style="opacity: 0.7;">{{ file.name }}</small>
+ </div>
+ <div>
+ <MkAcct v-if="file.user" :user="file.user"/>
+ <div v-else>{{ i18n.ts.system }}</div>
+ </div>
+ <div>
+ <span style="margin-right: 1em;">{{ file.type }}</span>
+ <span>{{ bytes(file.size) }}</span>
+ </div>
+ <div>
+ <span>{{ i18n.ts.registeredDate }}: <MkTime :time="file.createdAt" mode="detail"/></span>
+ </div>
</div>
- <div>
- <MkAcct v-if="file.user" :user="file.user"/>
- <div v-else>{{ i18n.ts.system }}</div>
- </div>
- <div>
- <span style="margin-right: 1em;">{{ file.type }}</span>
- <span>{{ bytes(file.size) }}</span>
- </div>
- <div>
- <span>{{ i18n.ts.registeredDate }}: <MkTime :time="file.createdAt" mode="detail"/></span>
- </div>
- </div>
- </MkA>
+ </MkA>
+ </div>
</MkPagination>
</div>
</template>
@@ -43,76 +45,76 @@ import MkDriveFileThumbnail from '@/components/MkDriveFileThumbnail.vue';
import bytes from '@/filters/bytes.js';
import { i18n } from '@/i18n.js';
import { dateString } from '@/filters/date.js';
+import type { PagingCtx } from '@/composables/use-pagination.js';
-const props = defineProps<{
- pagination: any;
+defineProps<{
+ pagination: PagingCtx<'admin/drive/files'>;
viewMode: 'grid' | 'list';
}>();
</script>
-<style lang="scss" scoped>
+<style lang="scss" module>
@keyframes sensitive-blink {
0% { opacity: 1; }
50% { opacity: 0; }
}
-.urempief {
- &.list {
- > .file {
- display: flex;
- width: 100%;
- box-sizing: border-box;
- text-align: left;
- align-items: center;
+.list {
+ > .file {
+ display: flex;
+ width: 100%;
+ height: auto;
+ box-sizing: border-box;
+ text-align: left;
+ align-items: center;
+ }
- &:hover {
- color: var(--MI_THEME-accent);
- }
+ > .file:hover {
+ color: var(--MI_THEME-accent);
+ }
- > .thumbnail {
- width: 128px;
- height: 128px;
- }
+ > .file > .thumbnail {
+ width: 128px;
+ height: 128px;
+ }
- > .body {
- margin-left: 0.3em;
- padding: 8px;
- flex: 1;
+ > .file > .body {
+ margin-left: 0.3em;
+ padding: 8px;
+ flex: 1;
- @media (max-width: 500px) {
- font-size: 14px;
- }
- }
+ @media (max-width: 500px) {
+ font-size: 14px;
}
}
+}
- &.grid {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
- grid-gap: 12px;
-
- > .file {
- position: relative;
- aspect-ratio: 1;
+.grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
+ grid-gap: 12px;
- > .thumbnail {
- width: 100%;
- height: 100%;
- }
+ > .file {
+ position: relative;
+ aspect-ratio: 1;
+ }
- > .sensitive-label {
- position: absolute;
- z-index: 10;
- top: 8px;
- left: 8px;
- padding: 2px 4px;
- background: #ff0000bf;
- color: #fff;
- border-radius: 4px;
- font-size: 85%;
- animation: sensitive-blink 1s infinite;
- }
- }
+ .thumbnail {
+ width: 100%;
+ height: 100%;
}
}
+
+.sensitiveLabel {
+ position: absolute;
+ z-index: 10;
+ top: 8px;
+ left: 8px;
+ padding: 2px 4px;
+ background: #ff0000bf;
+ color: #fff;
+ border-radius: 4px;
+ font-size: 85%;
+ animation: sensitive-blink 1s infinite;
+}
</style>
diff --git a/packages/frontend/src/pages/admin/files.vue b/packages/frontend/src/pages/admin/files.vue
index 87595a820b..4ea5756284 100644
--- a/packages/frontend/src/pages/admin/files.vue
+++ b/packages/frontend/src/pages/admin/files.vue
@@ -34,6 +34,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { computed, ref } from 'vue';
+import * as Misskey from 'misskey-js';
import MkInput from '@/components/MkInput.vue';
import MkSelect from '@/components/MkSelect.vue';
import MkFileListForAdmin from '@/components/MkFileListForAdmin.vue';
@@ -41,12 +42,13 @@ import * as os from '@/os.js';
import { lookupFile } from '@/utility/admin-lookup.js';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
+import type { PagingCtx } from '@/composables/use-pagination.js';
-const origin = ref('local');
+const origin = ref<Misskey.entities.AdminDriveFilesRequest['origin']>('local');
const type = ref<string | null>(null);
const searchHost = ref('');
const userId = ref('');
-const viewMode = ref('grid');
+const viewMode = ref<'grid' | 'list'>('grid');
const pagination = {
endpoint: 'admin/drive/files' as const,
limit: 10,
@@ -56,7 +58,7 @@ const pagination = {
origin: origin.value,
hostname: (searchHost.value && searchHost.value !== '') ? searchHost.value : null,
})),
-};
+} satisfies PagingCtx<'admin/drive/files'>;
function clear() {
os.confirm({
diff --git a/packages/frontend/src/pages/instance-info.vue b/packages/frontend/src/pages/instance-info.vue
index 0057106411..7c5191276d 100644
--- a/packages/frontend/src/pages/instance-info.vue
+++ b/packages/frontend/src/pages/instance-info.vue
@@ -7,9 +7,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs" :swipable="true">
<div v-if="instance" class="_spacer" style="--MI_SPACER-w: 600px; --MI_SPACER-min: 16px; --MI_SPACER-max: 32px;">
<div v-if="tab === 'overview'" class="_gaps_m">
- <div class="fnfelxur">
- <img :src="faviconUrl" alt="" class="icon"/>
- <span class="name">{{ instance.name || `(${i18n.ts.unknown})` }}</span>
+ <div :class="$style.faviconAndName">
+ <img :src="faviconUrl" alt="" :class="$style.icon"/>
+ <span :class="$style.name">{{ instance.name || `(${i18n.ts.unknown})` }}</span>
</div>
<div style="display: flex; flex-direction: column; gap: 1em;">
<MkKeyValue :copy="host" oneline>
@@ -90,8 +90,8 @@ SPDX-License-Identifier: AGPL-3.0-only
</FormSection>
</div>
<div v-else-if="tab === 'chart'" class="_gaps_m">
- <div class="cmhjzshl">
- <div class="selects">
+ <div>
+ <div :class="$style.selects">
<MkSelect v-model="chartSrc" style="margin: 0 10px 0 0; flex: 1;">
<option value="instance-requests">{{ i18n.ts._instanceCharts.requests }}</option>
<option value="instance-users">{{ i18n.ts._instanceCharts.users }}</option>
@@ -106,19 +106,21 @@ SPDX-License-Identifier: AGPL-3.0-only
<option value="instance-drive-files-total">{{ i18n.ts._instanceCharts.filesTotal }}</option>
</MkSelect>
</div>
- <div class="charts">
- <div class="label">{{ i18n.tsx.recentNHours({ n: 90 }) }}</div>
- <MkChart class="chart" :src="chartSrc" span="hour" :limit="90" :args="{ host: host }" :detailed="true"></MkChart>
- <div class="label">{{ i18n.tsx.recentNDays({ n: 90 }) }}</div>
- <MkChart class="chart" :src="chartSrc" span="day" :limit="90" :args="{ host: host }" :detailed="true"></MkChart>
+ <div>
+ <div :class="$style.label">{{ i18n.tsx.recentNHours({ n: 90 }) }}</div>
+ <MkChart :src="chartSrc" span="hour" :limit="90" :args="{ host: host }" :detailed="true"></MkChart>
+ <div :class="$style.label">{{ i18n.tsx.recentNDays({ n: 90 }) }}</div>
+ <MkChart :src="chartSrc" span="day" :limit="90" :args="{ host: host }" :detailed="true"></MkChart>
</div>
</div>
</div>
<div v-else-if="tab === 'users'" class="_gaps_m">
- <MkPagination v-slot="{items}" :pagination="usersPagination" style="display: grid; grid-template-columns: repeat(auto-fill,minmax(270px,1fr)); grid-gap: 12px;">
- <MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${dateString(user.updatedAt)}`" class="user" :to="`/admin/user/${user.id}`">
- <MkUserCardMini :user="user"/>
- </MkA>
+ <MkPagination v-slot="{ items }" :pagination="usersPagination">
+ <div :class="$style.users">
+ <MkA v-for="user in items" :key="user.id" v-tooltip.mfm="`Last posted: ${user.updatedAt ? dateString(user.updatedAt) : 'unknown'}`" :to="`/admin/user/${user.id}`">
+ <MkUserCardMini :user="user"/>
+ </MkA>
+ </div>
</MkPagination>
</div>
<div v-else-if="tab === 'raw'" class="_gaps_m">
@@ -180,7 +182,7 @@ const usersPagination = {
hostname: props.host,
},
offsetMode: true,
-} satisfies PagingCtx;
+} satisfies PagingCtx<'admin/show-users' | 'users'>;
if (iAmModerator) {
watch(moderationNote, async () => {
@@ -281,7 +283,7 @@ const headerTabs = computed(() => [{
key: 'overview',
title: i18n.ts.overview,
icon: 'ti ti-info-circle',
-}, {
+}, ...(iAmModerator ? [{
key: 'chart',
title: i18n.ts.charts,
icon: 'ti ti-chart-line',
@@ -289,7 +291,7 @@ const headerTabs = computed(() => [{
key: 'users',
title: i18n.ts.users,
icon: 'ti ti-users',
-}, {
+}] : []), {
key: 'raw',
title: 'Raw',
icon: 'ti ti-code',
@@ -301,34 +303,31 @@ definePage(() => ({
}));
</script>
-<style lang="scss" scoped>
-.fnfelxur {
+<style lang="scss" module>
+.faviconAndName {
display: flex;
align-items: center;
-
- > .icon {
- display: block;
- margin: 0 16px 0 0;
- height: 64px;
- border-radius: 8px;
- }
-
- > .name {
- word-break: break-all;
- }
}
-
-.cmhjzshl {
- > .selects {
- display: flex;
- margin: 0 0 16px 0;
- }
-
- > .charts {
- > .label {
- margin-bottom: 12px;
- font-weight: bold;
- }
- }
+.icon {
+ display: block;
+ margin: 0 16px 0 0;
+ height: 64px;
+ border-radius: 8px;
+}
+.name {
+ word-break: break-all;
+}
+.selects {
+ display: flex;
+ margin: 0 0 16px 0;
+}
+.label {
+ margin-bottom: 12px;
+ font-weight: bold;
+}
+.users {
+ display: grid;
+ grid-template-columns: repeat(auto-fill,minmax(270px,1fr));
+ grid-gap: 12px;
}
</style>