diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2023-07-21 20:36:07 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-21 20:36:07 +0900 |
| commit | e64a81aa1d2801516e8eac8dc69aac540489f20b (patch) | |
| tree | 56accbc0f5f71db864e1e975920135fb0a957291 /packages/frontend/src/pages/admin | |
| parent | Merge pull request #10990 from misskey-dev/develop (diff) | |
| parent | New Crowdin updates (#11336) (diff) | |
| download | misskey-e64a81aa1d2801516e8eac8dc69aac540489f20b.tar.gz misskey-e64a81aa1d2801516e8eac8dc69aac540489f20b.tar.bz2 misskey-e64a81aa1d2801516e8eac8dc69aac540489f20b.zip | |
Merge pull request #11301 from misskey-dev/develop
Release: 13.14.0
Diffstat (limited to 'packages/frontend/src/pages/admin')
| -rw-r--r-- | packages/frontend/src/pages/admin/abuses.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/ads.vue | 19 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/index.vue | 13 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/invites.vue | 126 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/moderation.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/other-settings.vue | 40 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/overview.ap-requests.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/overview.federation.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/overview.queue.vue | 4 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/overview.stats.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/overview.vue | 4 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/queue.chart.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/roles.editor.vue | 65 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/roles.role.vue | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/roles.vue | 23 | ||||
| -rw-r--r-- | packages/frontend/src/pages/admin/settings.vue | 15 |
16 files changed, 297 insertions, 26 deletions
diff --git a/packages/frontend/src/pages/admin/abuses.vue b/packages/frontend/src/pages/admin/abuses.vue index 3bc5ee9723..9cf96d3d04 100644 --- a/packages/frontend/src/pages/admin/abuses.vue +++ b/packages/frontend/src/pages/admin/abuses.vue @@ -75,7 +75,7 @@ const pagination = { }; function resolved(reportId) { - reports.removeItem(item => item.id === reportId); + reports.removeItem(reportId); } const headerActions = $computed(() => []); diff --git a/packages/frontend/src/pages/admin/ads.vue b/packages/frontend/src/pages/admin/ads.vue index 2c9e18b0bf..9a5bd88b2e 100644 --- a/packages/frontend/src/pages/admin/ads.vue +++ b/packages/frontend/src/pages/admin/ads.vue @@ -36,6 +36,16 @@ <template #label>{{ i18n.ts.expiration }}</template> </MkInput> </FormSplit> + <MkFolder> + <template #label>{{ i18n.ts.advancedSettings }}</template> + <span> + {{ i18n.ts._ad.timezoneinfo }} + <div v-for="(day, index) in daysOfWeek" :key="index"> + <input :id="`ad${ad.id}-${index}`" type="checkbox" :checked="(ad.dayOfWeek & (1 << index)) !== 0" @change="toggleDayOfWeek(ad, index)"> + <label :for="`ad${ad.id}-${index}`">{{ day }}</label> + </div> + </span> + </MkFolder> <MkTextarea v-model="ad.memo"> <template #label>{{ i18n.ts.memo }}</template> </MkTextarea> @@ -59,6 +69,7 @@ import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; import MkTextarea from '@/components/MkTextarea.vue'; import MkRadios from '@/components/MkRadios.vue'; +import MkFolder from '@/components/MkFolder.vue'; import FormSplit from '@/components/form/split.vue'; import * as os from '@/os'; import { i18n } from '@/i18n'; @@ -69,6 +80,7 @@ let ads: any[] = $ref([]); // ISO形式はTZがUTCになってしまうので、TZ分ずらして時間を初期化 const localTime = new Date(); const localTimeDiff = localTime.getTimezoneOffset() * 60 * 1000; +const daysOfWeek: string[] = [i18n.ts._weekday.sunday, i18n.ts._weekday.monday, i18n.ts._weekday.tuesday, i18n.ts._weekday.wednesday, i18n.ts._weekday.thursday, i18n.ts._weekday.friday, i18n.ts._weekday.saturday]; os.api('admin/ad/list').then(adsResponse => { ads = adsResponse.map(r => { @@ -84,6 +96,11 @@ os.api('admin/ad/list').then(adsResponse => { }); }); +// 選択された曜日(index)のビットフラグを操作する +function toggleDayOfWeek(ad, index) { + ad.dayOfWeek ^= 1 << index; +} + function add() { ads.unshift({ id: null, @@ -95,6 +112,7 @@ function add() { imageUrl: null, expiresAt: null, startsAt: null, + dayOfWeek: 0, }); } @@ -105,6 +123,7 @@ function remove(ad) { }).then(({ canceled }) => { if (canceled) return; ads = ads.filter(x => x !== ad); + if (ad.id == null) return; os.apiWithDialog('admin/ad/delete', { id: ad.id, }); diff --git a/packages/frontend/src/pages/admin/index.vue b/packages/frontend/src/pages/admin/index.vue index 8b083bc896..e91f65b5d5 100644 --- a/packages/frontend/src/pages/admin/index.vue +++ b/packages/frontend/src/pages/admin/index.vue @@ -1,6 +1,6 @@ <template> <div ref="el" class="hiyeyicy" :class="{ wide: !narrow }"> - <div v-if="!narrow || currentPage?.route.name == null" class="nav"> + <div v-if="!narrow || currentPage?.route.name == null" class="nav"> <MkSpacer :contentMax="700" :marginMin="16"> <div class="lxpfedzu"> <div class="banner"> @@ -80,7 +80,7 @@ const menuDef = $computed(() => [{ }, ...(instance.disableRegistration ? [{ type: 'button', icon: 'ti ti-user-plus', - text: i18n.ts.invite, + text: i18n.ts.createInviteCode, action: invite, }] : [])], }, { @@ -96,6 +96,11 @@ const menuDef = $computed(() => [{ to: '/admin/users', active: currentPage?.route.name === 'users', }, { + icon: 'ti ti-user-plus', + text: i18n.ts.invite, + to: '/admin/invites', + active: currentPage?.route.name === 'invites', + }, { icon: 'ti ti-badges', text: i18n.ts.roles, to: '/admin/roles', @@ -240,10 +245,10 @@ provideMetadataReceiver((info) => { }); const invite = () => { - os.api('invite').then(x => { + os.api('admin/invite/create').then(x => { os.alert({ type: 'info', - text: x.code, + text: x?.[0].code, }); }).catch(err => { os.alert({ diff --git a/packages/frontend/src/pages/admin/invites.vue b/packages/frontend/src/pages/admin/invites.vue new file mode 100644 index 0000000000..70a9c93713 --- /dev/null +++ b/packages/frontend/src/pages/admin/invites.vue @@ -0,0 +1,126 @@ +<template> +<MkStickyContainer> + <template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template> + <MkSpacer :contentMax="800"> + <div class="_gaps_m"> + <MkFolder :expanded="false"> + <template #icon><i class="ti ti-plus"></i></template> + <template #label>{{ i18n.ts.createInviteCode }}</template> + + <div class="_gaps_m"> + <MkSwitch v-model="noExpirationDate"> + <template #label>{{ i18n.ts.noExpirationDate }}</template> + </MkSwitch> + <MkInput v-if="!noExpirationDate" v-model="expiresAt" type="datetime-local"> + <template #label>{{ i18n.ts.expirationDate }}</template> + </MkInput> + <MkInput v-model="createCount" type="number"> + <template #label>{{ i18n.ts.createCount }}</template> + </MkInput> + <MkButton primary rounded @click="createWithOptions">{{ i18n.ts.create }}</MkButton> + </div> + </MkFolder> + + <div :class="$style.inputs"> + <MkSelect v-model="type" :class="$style.input"> + <template #label>{{ i18n.ts.state }}</template> + <option value="all">{{ i18n.ts.all }}</option> + <option value="unused">{{ i18n.ts.unused }}</option> + <option value="used">{{ i18n.ts.used }}</option> + <option value="expired">{{ i18n.ts.expired }}</option> + </MkSelect> + <MkSelect v-model="sort" :class="$style.input"> + <template #label>{{ i18n.ts.sort }}</template> + <option value="+createdAt">{{ i18n.ts.createdAt }} ({{ i18n.ts.ascendingOrder }})</option> + <option value="-createdAt">{{ i18n.ts.createdAt }} ({{ i18n.ts.descendingOrder }})</option> + <option value="+usedAt">{{ i18n.ts.usedAt }} ({{ i18n.ts.ascendingOrder }})</option> + <option value="-usedAt">{{ i18n.ts.usedAt }} ({{ i18n.ts.descendingOrder }})</option> + </MkSelect> + </div> + <MkPagination ref="pagingComponent" :pagination="pagination"> + <template #default="{ items }"> + <div class="_gaps_s"> + <MkInviteCode v-for="item in items" :key="item.id" :invite="(item as any)" :onDeleted="deleted" moderator/> + </div> + </template> + </MkPagination> + </div> + </MkSpacer> +</MkStickyContainer> +</template> + +<script lang="ts" setup> +import { computed, ref, shallowRef } from 'vue'; +import XHeader from './_header_.vue'; +import { i18n } from '@/i18n'; +import * as os from '@/os'; +import MkButton from '@/components/MkButton.vue'; +import MkFolder from '@/components/MkFolder.vue'; +import MkSelect from '@/components/MkSelect.vue'; +import MkInput from '@/components/MkInput.vue'; +import MkSwitch from '@/components/MkSwitch.vue'; +import MkPagination, { Paging } from '@/components/MkPagination.vue'; +import MkInviteCode from '@/components/MkInviteCode.vue'; +import { definePageMetadata } from '@/scripts/page-metadata'; + +const pagingComponent = shallowRef<InstanceType<typeof MkPagination>>(); + +let type = ref('all'); +let sort = ref('+createdAt'); + +const pagination: Paging = { + endpoint: 'admin/invite/list' as const, + limit: 10, + params: computed(() => ({ + type: type.value, + sort: sort.value, + })), + offsetMode: true, +}; + +const expiresAt = ref(''); +const noExpirationDate = ref(true); +const createCount = ref(1); + +async function createWithOptions() { + const options = { + expiresAt: noExpirationDate.value ? null : expiresAt.value, + count: createCount.value, + }; + + const tickets = await os.api('admin/invite/create', options); + os.alert({ + type: 'success', + title: i18n.ts.inviteCodeCreated, + text: tickets?.map(x => x.code).join('\n'), + }); + + tickets?.forEach(ticket => pagingComponent.value?.prepend(ticket)); +} + +function deleted(id: string) { + if (pagingComponent.value) { + pagingComponent.value.items.delete(id); + } +} + +const headerActions = $computed(() => []); +const headerTabs = $computed(() => []); + +definePageMetadata({ + title: i18n.ts.invite, + icon: 'ti ti-user-plus', +}); +</script> + +<style lang="scss" module> +.inputs { + display: flex; + gap: 8px; + flex-wrap: wrap; +} + +.input { + flex: 1; +} +</style> diff --git a/packages/frontend/src/pages/admin/moderation.vue b/packages/frontend/src/pages/admin/moderation.vue index e36c9ac91d..13789820a0 100644 --- a/packages/frontend/src/pages/admin/moderation.vue +++ b/packages/frontend/src/pages/admin/moderation.vue @@ -24,7 +24,7 @@ <template #label>{{ i18n.ts.preservedUsernames }}</template> <template #caption>{{ i18n.ts.preservedUsernamesDescription }}</template> </MkTextarea> - + <MkTextarea v-model="sensitiveWords"> <template #label>{{ i18n.ts.sensitiveWords }}</template> <template #caption>{{ i18n.ts.sensitiveWordsDescription }}<br>{{ i18n.ts.sensitiveWordsDescription2 }}</template> diff --git a/packages/frontend/src/pages/admin/other-settings.vue b/packages/frontend/src/pages/admin/other-settings.vue index 15d720a070..13e3588740 100644 --- a/packages/frontend/src/pages/admin/other-settings.vue +++ b/packages/frontend/src/pages/admin/other-settings.vue @@ -3,14 +3,34 @@ <template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template> <MkSpacer :contentMax="700" :marginMin="16" :marginMax="32"> <FormSuspense :p="init"> - <div class="_gaps_s"> - <MkSwitch v-model="enableChartsForRemoteUser"> - <template #label>{{ i18n.ts.enableChartsForRemoteUser }}</template> - </MkSwitch> + <div class="_gaps"> + <div class="_panel" style="padding: 16px;"> + <MkSwitch v-model="enableServerMachineStats"> + <template #label>{{ i18n.ts.enableServerMachineStats }}</template> + <template #caption>{{ i18n.ts.turnOffToImprovePerformance }}</template> + </MkSwitch> + </div> - <MkSwitch v-model="enableChartsForFederatedInstances"> - <template #label>{{ i18n.ts.enableChartsForFederatedInstances }}</template> - </MkSwitch> + <div class="_panel" style="padding: 16px;"> + <MkSwitch v-model="enableIdenticonGeneration"> + <template #label>{{ i18n.ts.enableIdenticonGeneration }}</template> + <template #caption>{{ i18n.ts.turnOffToImprovePerformance }}</template> + </MkSwitch> + </div> + + <div class="_panel" style="padding: 16px;"> + <MkSwitch v-model="enableChartsForRemoteUser"> + <template #label>{{ i18n.ts.enableChartsForRemoteUser }}</template> + <template #caption>{{ i18n.ts.turnOffToImprovePerformance }}</template> + </MkSwitch> + </div> + + <div class="_panel" style="padding: 16px;"> + <MkSwitch v-model="enableChartsForFederatedInstances"> + <template #label>{{ i18n.ts.enableChartsForFederatedInstances }}</template> + <template #caption>{{ i18n.ts.turnOffToImprovePerformance }}</template> + </MkSwitch> + </div> </div> </FormSuspense> </MkSpacer> @@ -27,17 +47,23 @@ import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; import MkSwitch from '@/components/MkSwitch.vue'; +let enableServerMachineStats: boolean = $ref(false); +let enableIdenticonGeneration: boolean = $ref(false); let enableChartsForRemoteUser: boolean = $ref(false); let enableChartsForFederatedInstances: boolean = $ref(false); async function init() { const meta = await os.api('admin/meta'); + enableServerMachineStats = meta.enableServerMachineStats; + enableIdenticonGeneration = meta.enableIdenticonGeneration; enableChartsForRemoteUser = meta.enableChartsForRemoteUser; enableChartsForFederatedInstances = meta.enableChartsForFederatedInstances; } function save() { os.apiWithDialog('admin/update-meta', { + enableServerMachineStats, + enableIdenticonGeneration, enableChartsForRemoteUser, enableChartsForFederatedInstances, }).then(() => { diff --git a/packages/frontend/src/pages/admin/overview.ap-requests.vue b/packages/frontend/src/pages/admin/overview.ap-requests.vue index ad8e623415..bde5580366 100644 --- a/packages/frontend/src/pages/admin/overview.ap-requests.vue +++ b/packages/frontend/src/pages/admin/overview.ap-requests.vue @@ -259,7 +259,7 @@ onMounted(async () => { }, plugins: [chartVLine(vLineColor)], }); - + fetching = false; }); </script> diff --git a/packages/frontend/src/pages/admin/overview.federation.vue b/packages/frontend/src/pages/admin/overview.federation.vue index ab78c4c393..469d2e6927 100644 --- a/packages/frontend/src/pages/admin/overview.federation.vue +++ b/packages/frontend/src/pages/admin/overview.federation.vue @@ -58,7 +58,7 @@ let federationSubActiveDiff = $ref<number | null>(null); let fetching = $ref(true); const { handler: externalTooltipHandler } = useChartTooltip(); - + onMounted(async () => { const chart = await os.apiGet('charts/federation', { limit: 2, span: 'day' }); federationPubActive = chart.pubActive[0]; diff --git a/packages/frontend/src/pages/admin/overview.queue.vue b/packages/frontend/src/pages/admin/overview.queue.vue index 69ca89e226..7d8d468512 100644 --- a/packages/frontend/src/pages/admin/overview.queue.vue +++ b/packages/frontend/src/pages/admin/overview.queue.vue @@ -85,7 +85,7 @@ onMounted(() => { connection.on('stats', onStats); connection.on('statsLog', onStatsLog); connection.send('requestLog', { - id: Math.random().toString().substr(2, 8), + id: Math.random().toString().substring(2, 10), length: 100, }); }); @@ -122,4 +122,4 @@ onUnmounted(() => { } } } -</style> +</style> diff --git a/packages/frontend/src/pages/admin/overview.stats.vue b/packages/frontend/src/pages/admin/overview.stats.vue index 142e70c698..f746ad14b9 100644 --- a/packages/frontend/src/pages/admin/overview.stats.vue +++ b/packages/frontend/src/pages/admin/overview.stats.vue @@ -73,7 +73,7 @@ let fetching = $ref(true); onMounted(async () => { const [_stats, _onlineUsersCount] = await Promise.all([ os.api('stats', {}), - os.api('get-online-users-count').then(res => res.count), + os.apiGet('get-online-users-count').then(res => res.count), ]); stats = _stats; onlineUsersCount = _onlineUsersCount; diff --git a/packages/frontend/src/pages/admin/overview.vue b/packages/frontend/src/pages/admin/overview.vue index e8295c81b5..41a6d4f5b7 100644 --- a/packages/frontend/src/pages/admin/overview.vue +++ b/packages/frontend/src/pages/admin/overview.vue @@ -30,7 +30,7 @@ <template #header>Federation</template> <XFederation/> </MkFoldableSection> - + <MkFoldableSection class="item"> <template #header>Instances</template> <XInstances/> @@ -156,7 +156,7 @@ onMounted(async () => { nextTick(() => { queueStatsConnection.send('requestLog', { - id: Math.random().toString().substr(2, 8), + id: Math.random().toString().substring(2, 10), length: 100, }); }); diff --git a/packages/frontend/src/pages/admin/queue.chart.vue b/packages/frontend/src/pages/admin/queue.chart.vue index 8e6856fddd..83ca9639e7 100644 --- a/packages/frontend/src/pages/admin/queue.chart.vue +++ b/packages/frontend/src/pages/admin/queue.chart.vue @@ -106,7 +106,7 @@ onMounted(() => { connection.on('stats', onStats); connection.on('statsLog', onStatsLog); connection.send('requestLog', { - id: Math.random().toString().substr(2, 8), + id: Math.random().toString().substring(2, 10), length: 200, }); }); diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index a1fa9d2932..1ba502ff86 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -1,5 +1,9 @@ <template> <div class="_gaps"> + <MkInput v-if="readonly" :modelValue="role.id" :readonly="true"> + <template #label>ID</template> + </MkInput> + <MkInput v-model="role.name" :readonly="readonly"> <template #label>{{ i18n.ts._role.name }}</template> </MkInput> @@ -171,6 +175,65 @@ </div> </MkFolder> + <MkFolder v-if="matchQuery([i18n.ts._role._options.inviteLimit, 'inviteLimit'])"> + <template #label>{{ i18n.ts._role._options.inviteLimit }}</template> + <template #suffix> + <span v-if="role.policies.inviteLimit.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span> + <span v-else>{{ role.policies.inviteLimit.value }}</span> + <span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.inviteLimit)"></i></span> + </template> + <div class="_gaps"> + <MkSwitch v-model="role.policies.inviteLimit.useDefault" :readonly="readonly"> + <template #label>{{ i18n.ts._role.useBaseValue }}</template> + </MkSwitch> + <MkInput v-model="role.policies.inviteLimit.value" :disabled="role.policies.inviteLimit.useDefault" type="number" :readonly="readonly"> + </MkInput> + <MkRange v-model="role.policies.inviteLimit.priority" :min="0" :max="2" :step="1" easing :textConverter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''"> + <template #label>{{ i18n.ts._role.priority }}</template> + </MkRange> + </div> + </MkFolder> + + <MkFolder v-if="matchQuery([i18n.ts._role._options.inviteLimitCycle, 'inviteLimitCycle'])"> + <template #label>{{ i18n.ts._role._options.inviteLimitCycle }}</template> + <template #suffix> + <span v-if="role.policies.inviteLimitCycle.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span> + <span v-else>{{ role.policies.inviteLimitCycle.value + i18n.ts._time.minute }}</span> + <span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.inviteLimitCycle)"></i></span> + </template> + <div class="_gaps"> + <MkSwitch v-model="role.policies.inviteLimitCycle.useDefault" :readonly="readonly"> + <template #label>{{ i18n.ts._role.useBaseValue }}</template> + </MkSwitch> + <MkInput v-model="role.policies.inviteLimitCycle.value" :disabled="role.policies.inviteLimitCycle.useDefault" type="number" :readonly="readonly"> + <template #suffix>{{ i18n.ts._time.minute }}</template> + </MkInput> + <MkRange v-model="role.policies.inviteLimitCycle.priority" :min="0" :max="2" :step="1" easing :textConverter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''"> + <template #label>{{ i18n.ts._role.priority }}</template> + </MkRange> + </div> + </MkFolder> + + <MkFolder v-if="matchQuery([i18n.ts._role._options.inviteExpirationTime, 'inviteExpirationTime'])"> + <template #label>{{ i18n.ts._role._options.inviteExpirationTime }}</template> + <template #suffix> + <span v-if="role.policies.inviteExpirationTime.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span> + <span v-else>{{ role.policies.inviteExpirationTime.value + i18n.ts._time.minute }}</span> + <span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.inviteExpirationTime)"></i></span> + </template> + <div class="_gaps"> + <MkSwitch v-model="role.policies.inviteExpirationTime.useDefault" :readonly="readonly"> + <template #label>{{ i18n.ts._role.useBaseValue }}</template> + </MkSwitch> + <MkInput v-model="role.policies.inviteExpirationTime.value" :disabled="role.policies.inviteExpirationTime.useDefault" type="number" :readonly="readonly"> + <template #suffix>{{ i18n.ts._time.minute }}</template> + </MkInput> + <MkRange v-model="role.policies.inviteExpirationTime.priority" :min="0" :max="2" :step="1" easing :textConverter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''"> + <template #label>{{ i18n.ts._role.priority }}</template> + </MkRange> + </div> + </MkFolder> + <MkFolder v-if="matchQuery([i18n.ts._role._options.canManageCustomEmojis, 'canManageCustomEmojis'])"> <template #label>{{ i18n.ts._role._options.canManageCustomEmojis }}</template> <template #suffix> @@ -210,7 +273,7 @@ </MkRange> </div> </MkFolder> - + <MkFolder v-if="matchQuery([i18n.ts._role._options.driveCapacity, 'driveCapacityMb'])"> <template #label>{{ i18n.ts._role._options.driveCapacity }}</template> <template #suffix> diff --git a/packages/frontend/src/pages/admin/roles.role.vue b/packages/frontend/src/pages/admin/roles.role.vue index 6cbe7ae658..789c9da277 100644 --- a/packages/frontend/src/pages/admin/roles.role.vue +++ b/packages/frontend/src/pages/admin/roles.role.vue @@ -40,7 +40,7 @@ </div> <div v-if="expandedItems.includes(item.id)" :class="$style.userItemSub"> <div>Assigned: <MkTime :time="item.createdAt" mode="detail"/></div> - <div v-if="item.expiresAt">Period: {{ item.expiresAt.toLocaleString() }}</div> + <div v-if="item.expiresAt">Period: {{ new Date(item.expiresAt).toLocaleString() }}</div> <div v-else>Period: {{ i18n.ts.indefinitely }}</div> </div> </div> diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue index 6634d9cba9..cdb6e90505 100644 --- a/packages/frontend/src/pages/admin/roles.vue +++ b/packages/frontend/src/pages/admin/roles.vue @@ -51,6 +51,29 @@ </MkSwitch> </MkFolder> + <MkFolder v-if="matchQuery([i18n.ts._role._options.inviteLimit, 'inviteLimit'])"> + <template #label>{{ i18n.ts._role._options.inviteLimit }}</template> + <template #suffix>{{ policies.inviteLimit }}</template> + <MkInput v-model="policies.inviteLimit" type="number"> + </MkInput> + </MkFolder> + + <MkFolder v-if="matchQuery([i18n.ts._role._options.inviteLimitCycle, 'inviteLimitCycle'])"> + <template #label>{{ i18n.ts._role._options.inviteLimitCycle }}</template> + <template #suffix>{{ policies.inviteLimitCycle + i18n.ts._time.minute }}</template> + <MkInput v-model="policies.inviteLimitCycle" type="number"> + <template #suffix>{{ i18n.ts._time.minute }}</template> + </MkInput> + </MkFolder> + + <MkFolder v-if="matchQuery([i18n.ts._role._options.inviteExpirationTime, 'inviteExpirationTime'])"> + <template #label>{{ i18n.ts._role._options.inviteExpirationTime }}</template> + <template #suffix>{{ policies.inviteExpirationTime + i18n.ts._time.minute }}</template> + <MkInput v-model="policies.inviteExpirationTime" type="number"> + <template #suffix>{{ i18n.ts._time.minute }}</template> + </MkInput> + </MkFolder> + <MkFolder v-if="matchQuery([i18n.ts._role._options.canManageCustomEmojis, 'canManageCustomEmojis'])"> <template #label>{{ i18n.ts._role._options.canManageCustomEmojis }}</template> <template #suffix>{{ policies.canManageCustomEmojis ? i18n.ts.yes : i18n.ts.no }}</template> diff --git a/packages/frontend/src/pages/admin/settings.vue b/packages/frontend/src/pages/admin/settings.vue index 4c2fe46f28..bd57c06181 100644 --- a/packages/frontend/src/pages/admin/settings.vue +++ b/packages/frontend/src/pages/admin/settings.vue @@ -37,6 +37,13 @@ <template #label>{{ i18n.ts.cacheRemoteFiles }}</template> <template #caption>{{ i18n.ts.cacheRemoteFilesDescription }}</template> </MkSwitch> + + <template v-if="cacheRemoteFiles"> + <MkSwitch v-model="cacheRemoteSensitiveFiles"> + <template #label>{{ i18n.ts.cacheRemoteSensitiveFiles }}</template> + <template #caption>{{ i18n.ts.cacheRemoteSensitiveFilesDescription }}</template> + </MkSwitch> + </template> </div> </FormSection> @@ -104,7 +111,6 @@ import { fetchInstance } from '@/instance'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; import MkButton from '@/components/MkButton.vue'; -import MkColorInput from '@/components/MkColorInput.vue'; let name: string | null = $ref(null); let description: string | null = $ref(null); @@ -112,13 +118,14 @@ let maintainerName: string | null = $ref(null); let maintainerEmail: string | null = $ref(null); let pinnedUsers: string = $ref(''); let cacheRemoteFiles: boolean = $ref(false); +let cacheRemoteSensitiveFiles: boolean = $ref(false); let enableServiceWorker: boolean = $ref(false); let swPublicKey: any = $ref(null); let swPrivateKey: any = $ref(null); let deeplAuthKey: string = $ref(''); let deeplIsPro: boolean = $ref(false); -async function init() { +async function init(): Promise<void> { const meta = await os.api('admin/meta'); name = meta.name; description = meta.description; @@ -126,6 +133,7 @@ async function init() { maintainerEmail = meta.maintainerEmail; pinnedUsers = meta.pinnedUsers.join('\n'); cacheRemoteFiles = meta.cacheRemoteFiles; + cacheRemoteSensitiveFiles = meta.cacheRemoteSensitiveFiles; enableServiceWorker = meta.enableServiceWorker; swPublicKey = meta.swPublickey; swPrivateKey = meta.swPrivateKey; @@ -133,7 +141,7 @@ async function init() { deeplIsPro = meta.deeplIsPro; } -function save() { +function save(): void { os.apiWithDialog('admin/update-meta', { name, description, @@ -141,6 +149,7 @@ function save() { maintainerEmail, pinnedUsers: pinnedUsers.split('\n'), cacheRemoteFiles, + cacheRemoteSensitiveFiles, enableServiceWorker, swPublicKey, swPrivateKey, |