diff options
| author | かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> | 2025-06-03 17:20:11 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-03 17:20:11 +0900 |
| commit | 810a609df4d4037daf77bf6dbf2b38b9457bb0dd (patch) | |
| tree | 10bb63433bc4025d4d0155362702d0136e0254b3 /packages/frontend | |
| parent | fix(frontend): ドライブのファイル選択が不安定な問題を修... (diff) | |
| download | misskey-810a609df4d4037daf77bf6dbf2b38b9457bb0dd.tar.gz misskey-810a609df4d4037daf77bf6dbf2b38b9457bb0dd.tar.bz2 misskey-810a609df4d4037daf77bf6dbf2b38b9457bb0dd.zip | |
fix(frontend): 一部のグリッドのページネーションが正しく表示されない問題を修正 (#16147)
* fix(frontend): 一部のグリッドのページネーションが正しく表示されない問題を修正
* update changelog
* fix
Diffstat (limited to 'packages/frontend')
| -rw-r--r-- | packages/frontend/src/components/MkFileListForAdmin.vue | 156 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/files.vue | 8 | ||||
| -rw-r--r-- | packages/frontend/src/pages/instance-info.vue | 85 |
3 files changed, 126 insertions, 123 deletions
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> |