From ad123b3cce0a8691681561984fb8c056db23a816 Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Wed, 22 Jun 2022 00:10:34 +0900 Subject: [PATCH] tweak client --- packages/client/src/pages/admin-file.vue | 85 ++++++++++++++------- packages/client/src/pages/instance-info.vue | 6 +- packages/client/src/pages/user-info.vue | 63 +++++++++++++-- 3 files changed, 118 insertions(+), 36 deletions(-) diff --git a/packages/client/src/pages/admin-file.vue b/packages/client/src/pages/admin-file.vue index 2cbe8890a1..7273ddce6a 100644 --- a/packages/client/src/pages/admin-file.vue +++ b/packages/client/src/pages/admin-file.vue @@ -1,30 +1,46 @@ <template> <MkStickyContainer> <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> - <MkSpacer :content-max="500" :margin-min="16" :margin-max="32"> - <div v-if="file" class="cxqhhsmd _formRoot"> - <div class="_formBlock"> + <MkSpacer v-if="file" :content-max="500" :margin-min="16" :margin-max="32"> + <div v-if="tab === 'overview'" class="cxqhhsmd _formRoot"> + <a class="_formBlock thumbnail" :href="file.url" target="_blank"> <MkDriveFileThumbnail class="thumbnail" :file="file" fit="contain"/> - <div class="info"> - <span style="margin-right: 1em;">{{ file.type }}</span> - <span>{{ bytes(file.size) }}</span> - <MkTime :time="file.createdAt" mode="detail" style="display: block;"/> - </div> + </a> + <div class="_formBlock"> + <MkKeyValue :copy="file.type" oneline style="margin: 1em 0;"> + <template #key>MIME Type</template> + <template #value><span class="_monospace">{{ file.type }}</span></template> + </MkKeyValue> + <MkKeyValue oneline style="margin: 1em 0;"> + <template #key>Size</template> + <template #value><span class="_monospace">{{ bytes(file.size) }}</span></template> + </MkKeyValue> + <MkKeyValue :copy="file.id" oneline style="margin: 1em 0;"> + <template #key>ID</template> + <template #value><span class="_monospace">{{ file.id }}</span></template> + </MkKeyValue> + <MkKeyValue :copy="file.md5" oneline style="margin: 1em 0;"> + <template #key>MD5</template> + <template #value><span class="_monospace">{{ file.md5 }}</span></template> + </MkKeyValue> + <MkKeyValue oneline style="margin: 1em 0;"> + <template #key>{{ i18n.ts.createdAt }}</template> + <template #value><span class="_monospace"><MkTime :time="file.createdAt" mode="detail" style="display: block;"/></span></template> + </MkKeyValue> </div> <div class="_formBlock"> <MkSwitch v-model="isSensitive" @update:modelValue="toggleIsSensitive">NSFW</MkSwitch> </div> <FormLink class="_formBlock" :to="file.url" :external="true">Open</FormLink> - <FormLink class="_formBlock" :to="`/user-info/${file.userId}`">{{ $ts.user }}</FormLink> + <FormLink class="_formBlock" :to="`/user-info/${file.userId}`">{{ $ts.user }} ({{ acct(file.user) }})</FormLink> <div class="_formBlock"> <MkButton full danger @click="del"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</MkButton> </div> - <div v-if="info" class="_formBlock"> - <details class="_content rawdata"> - <pre><code>{{ JSON.stringify(info, null, 2) }}</code></pre> - </details> - </div> + </div> + <div v-else-if="tab === 'raw'" class="_formRoot"> + <MkObjectView v-if="info" tall :value="info"> + </MkObjectView> </div> </MkSpacer> </MkStickyContainer> @@ -34,13 +50,17 @@ import { computed } from 'vue'; import MkButton from '@/components/ui/button.vue'; import MkSwitch from '@/components/form/switch.vue'; +import MkObjectView from '@/components/object-view.vue'; import MkDriveFileThumbnail from '@/components/drive-file-thumbnail.vue'; +import MkKeyValue from '@/components/key-value.vue'; import FormLink from '@/components/form/link.vue'; import bytes from '@/filters/bytes'; import * as os from '@/os'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; +import { acct } from '@/filters/user'; +let tab = $ref('overview'); let file: any = $ref(null); let info: any = $ref(null); let isSensitive: boolean = $ref(false); @@ -74,9 +94,25 @@ async function toggleIsSensitive(v) { isSensitive = v; } -const headerActions = $computed(() => []); +const headerActions = $computed(() => [{ + text: i18n.ts.openInNewTab, + icon: 'fas fa-external-link-alt', + handler: () => { + window.open(file.url, '_blank'); + }, +}]); -const headerTabs = $computed(() => []); +const headerTabs = $computed(() => [{ + active: tab === 'overview', + title: i18n.ts.overview, + icon: 'fas fa-info-circle', + onClick: () => { tab = 'overview'; }, +}, { + active: tab === 'raw', + title: 'Raw data', + icon: 'fas fa-code', + onClick: () => { tab = 'raw'; }, +}]); definePageMetadata(computed(() => ({ title: file ? i18n.ts.file + ': ' + file.name : i18n.ts.file, @@ -87,19 +123,12 @@ definePageMetadata(computed(() => ({ <style lang="scss" scoped> .cxqhhsmd { - > ._section { - > .thumbnail { - height: 150px; - max-width: 100%; - } + > .thumbnail { + display: block; - > .info { - text-align: center; - margin-top: 8px; - } - - > .rawdata { - overflow: auto; + > .thumbnail { + height: 300px; + max-width: 100%; } } } diff --git a/packages/client/src/pages/instance-info.vue b/packages/client/src/pages/instance-info.vue index afee31b44a..cca04aca93 100644 --- a/packages/client/src/pages/instance-info.vue +++ b/packages/client/src/pages/instance-info.vue @@ -73,7 +73,7 @@ <FormLink :to="`https://${host}/manifest.json`" external style="margin-bottom: 8px;">manifest.json</FormLink> </FormSection> </div> - <div v-if="tab === 'chart'" class="_formRoot"> + <div v-else-if="tab === 'chart'" class="_formRoot"> <div class="cmhjzshl"> <div class="selects"> <MkSelect v-model="chartSrc" style="margin: 0 10px 0 0; flex: 1;"> @@ -98,7 +98,7 @@ </div> </div> </div> - <div v-if="tab === 'raw'" class="_formRoot"> + <div v-else-if="tab === 'raw'" class="_formRoot"> <MkObjectView tall :value="instance"> </MkObjectView> </div> @@ -130,11 +130,11 @@ const props = defineProps<{ }>(); let tab = $ref('overview'); +let chartSrc = $ref('instance-requests'); let meta = $ref<misskey.entities.DetailedInstanceMetadata | null>(null); let instance = $ref<misskey.entities.Instance | null>(null); let suspended = $ref(false); let isBlocked = $ref(false); -let chartSrc = $ref('instance-requests'); async function fetch() { if (iAmModerator) { diff --git a/packages/client/src/pages/user-info.vue b/packages/client/src/pages/user-info.vue index 996c018dd9..233a8857fc 100644 --- a/packages/client/src/pages/user-info.vue +++ b/packages/client/src/pages/user-info.vue @@ -3,14 +3,18 @@ <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> <MkSpacer :content-max="500" :margin-min="16" :margin-max="32"> <FormSuspense :p="init"> - <div class="_formRoot"> + <div v-if="tab === 'overview'" class="_formRoot"> <div class="_formBlock aeakzknw"> <MkAvatar class="avatar" :user="user" :show-indicator="true"/> </div> - <FormLink class="_formBlock" :to="userPage(user)">Profile</FormLink> + <div v-if="user.url" class="_formLinksGrid _formBlock"> + <FormLink :to="userPage(user)">Profile</FormLink> + <FormLink :to="user.url" :external="true">Profile (remote)</FormLink> + </div> + <FormLink v-else class="_formBlock" :to="userPage(user)">Profile</FormLink> - <FormLink v-if="user.url" class="_formBlock" :to="user.url" :external="true">Profile (remote)</FormLink> + <FormLink v-if="user.host" class="_formBlock" :to="`/instance-info/${user.host}`">{{ i18n.ts.instanceInfo }}</FormLink> <div class="_formBlock"> <MkKeyValue :copy="acct(user)" oneline style="margin: 1em 0;"> @@ -57,7 +61,23 @@ <FormButton v-if="user.host != null" class="_formBlock" @click="updateRemoteUser"><i class="fas fa-sync"></i> {{ $ts.updateRemoteUser }}</FormButton> </FormSection> - + </div> + <div v-else-if="tab === 'chart'" class="_formRoot"> + <div class="cmhjzshm"> + <div class="selects"> + <MkSelect v-model="chartSrc" style="margin: 0 10px 0 0; flex: 1;"> + <option value="per-user-notes">{{ $ts.notes }}</option> + </MkSelect> + </div> + <div class="charts"> + <div class="label">{{ i18n.t('recentNHours', { n: 90 }) }}</div> + <MkChart class="chart" :src="chartSrc" span="hour" :limit="90" :args="{ user, withoutAll: true }" :detailed="true"></MkChart> + <div class="label">{{ i18n.t('recentNDays', { n: 90 }) }}</div> + <MkChart class="chart" :src="chartSrc" span="day" :limit="90" :args="{ user, withoutAll: true }" :detailed="true"></MkChart> + </div> + </div> + </div> + <div v-else-if="tab === 'raw'" class="_formRoot"> <MkObjectView v-if="info && $i.isAdmin" tall :value="info"> </MkObjectView> @@ -72,6 +92,7 @@ <script lang="ts" setup> import { computed, defineAsyncComponent, defineComponent, watch } from 'vue'; import * as misskey from 'misskey-js'; +import MkChart from '@/components/chart.vue'; import MkObjectView from '@/components/object-view.vue'; import FormTextarea from '@/components/form/textarea.vue'; import FormSwitch from '@/components/form/switch.vue'; @@ -79,6 +100,7 @@ import FormLink from '@/components/form/link.vue'; import FormSection from '@/components/form/section.vue'; import FormButton from '@/components/ui/button.vue'; import MkKeyValue from '@/components/key-value.vue'; +import MkSelect from '@/components/form/select.vue'; import FormSuspense from '@/components/form/suspense.vue'; import * as os from '@/os'; import number from '@/filters/number'; @@ -93,6 +115,8 @@ const props = defineProps<{ userId: string; }>(); +let tab = $ref('overview'); +let chartSrc = $ref('per-user-notes'); let user = $ref<null | misskey.entities.UserDetailed>(); let init = $ref(); let info = $ref(); @@ -209,7 +233,22 @@ watch(() => user, () => { const headerActions = $computed(() => []); -const headerTabs = $computed(() => []); +const headerTabs = $computed(() => [{ + active: tab === 'overview', + title: i18n.ts.overview, + icon: 'fas fa-info-circle', + onClick: () => { tab = 'overview'; }, +}, { + active: tab === 'chart', + title: i18n.ts.charts, + icon: 'fas fa-chart-simple', + onClick: () => { tab = 'chart'; }, +}, { + active: tab === 'raw', + title: 'Raw data', + icon: 'fas fa-code', + onClick: () => { tab = 'raw'; }, +}]); definePageMetadata(computed(() => ({ title: user ? acct(user) : i18n.ts.userInfo, @@ -226,4 +265,18 @@ definePageMetadata(computed(() => ({ height: 64px; } } + +.cmhjzshm { + > .selects { + display: flex; + margin: 0 0 16px 0; + } + + > .charts { + > .label { + margin-bottom: 12px; + font-weight: bold; + } + } +} </style>