diff options
Diffstat (limited to 'packages/frontend/src/pages/admin/settings.vue')
| -rw-r--r-- | packages/frontend/src/pages/admin/settings.vue | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/packages/frontend/src/pages/admin/settings.vue b/packages/frontend/src/pages/admin/settings.vue new file mode 100644 index 0000000000..460eb92694 --- /dev/null +++ b/packages/frontend/src/pages/admin/settings.vue @@ -0,0 +1,262 @@ +<template> +<div> + <MkStickyContainer> + <template #header><XHeader :actions="headerActions" :tabs="headerTabs"/></template> + <MkSpacer :content-max="700" :margin-min="16" :margin-max="32"> + <FormSuspense :p="init"> + <div class="_formRoot"> + <FormInput v-model="name" class="_formBlock"> + <template #label>{{ i18n.ts.instanceName }}</template> + </FormInput> + + <FormTextarea v-model="description" class="_formBlock"> + <template #label>{{ i18n.ts.instanceDescription }}</template> + </FormTextarea> + + <FormInput v-model="tosUrl" class="_formBlock"> + <template #prefix><i class="ti ti-link"></i></template> + <template #label>{{ i18n.ts.tosUrl }}</template> + </FormInput> + + <FormSplit :min-width="300"> + <FormInput v-model="maintainerName" class="_formBlock"> + <template #label>{{ i18n.ts.maintainerName }}</template> + </FormInput> + + <FormInput v-model="maintainerEmail" type="email" class="_formBlock"> + <template #prefix><i class="ti ti-mail"></i></template> + <template #label>{{ i18n.ts.maintainerEmail }}</template> + </FormInput> + </FormSplit> + + <FormTextarea v-model="pinnedUsers" class="_formBlock"> + <template #label>{{ i18n.ts.pinnedUsers }}</template> + <template #caption>{{ i18n.ts.pinnedUsersDescription }}</template> + </FormTextarea> + + <FormSection> + <FormSwitch v-model="enableRegistration" class="_formBlock"> + <template #label>{{ i18n.ts.enableRegistration }}</template> + </FormSwitch> + + <FormSwitch v-model="emailRequiredForSignup" class="_formBlock"> + <template #label>{{ i18n.ts.emailRequiredForSignup }}</template> + </FormSwitch> + </FormSection> + + <FormSection> + <FormSwitch v-model="enableLocalTimeline" class="_formBlock">{{ i18n.ts.enableLocalTimeline }}</FormSwitch> + <FormSwitch v-model="enableGlobalTimeline" class="_formBlock">{{ i18n.ts.enableGlobalTimeline }}</FormSwitch> + <FormInfo class="_formBlock">{{ i18n.ts.disablingTimelinesInfo }}</FormInfo> + </FormSection> + + <FormSection> + <template #label>{{ i18n.ts.theme }}</template> + + <FormInput v-model="iconUrl" class="_formBlock"> + <template #prefix><i class="ti ti-link"></i></template> + <template #label>{{ i18n.ts.iconUrl }}</template> + </FormInput> + + <FormInput v-model="bannerUrl" class="_formBlock"> + <template #prefix><i class="ti ti-link"></i></template> + <template #label>{{ i18n.ts.bannerUrl }}</template> + </FormInput> + + <FormInput v-model="backgroundImageUrl" class="_formBlock"> + <template #prefix><i class="ti ti-link"></i></template> + <template #label>{{ i18n.ts.backgroundImageUrl }}</template> + </FormInput> + + <FormInput v-model="themeColor" class="_formBlock"> + <template #prefix><i class="ti ti-palette"></i></template> + <template #label>{{ i18n.ts.themeColor }}</template> + <template #caption>#RRGGBB</template> + </FormInput> + + <FormTextarea v-model="defaultLightTheme" class="_formBlock"> + <template #label>{{ i18n.ts.instanceDefaultLightTheme }}</template> + <template #caption>{{ i18n.ts.instanceDefaultThemeDescription }}</template> + </FormTextarea> + + <FormTextarea v-model="defaultDarkTheme" class="_formBlock"> + <template #label>{{ i18n.ts.instanceDefaultDarkTheme }}</template> + <template #caption>{{ i18n.ts.instanceDefaultThemeDescription }}</template> + </FormTextarea> + </FormSection> + + <FormSection> + <template #label>{{ i18n.ts.files }}</template> + + <FormSwitch v-model="cacheRemoteFiles" class="_formBlock"> + <template #label>{{ i18n.ts.cacheRemoteFiles }}</template> + <template #caption>{{ i18n.ts.cacheRemoteFilesDescription }}</template> + </FormSwitch> + + <FormSplit :min-width="280"> + <FormInput v-model="localDriveCapacityMb" type="number" class="_formBlock"> + <template #label>{{ i18n.ts.driveCapacityPerLocalAccount }}</template> + <template #suffix>MB</template> + <template #caption>{{ i18n.ts.inMb }}</template> + </FormInput> + + <FormInput v-model="remoteDriveCapacityMb" type="number" :disabled="!cacheRemoteFiles" class="_formBlock"> + <template #label>{{ i18n.ts.driveCapacityPerRemoteAccount }}</template> + <template #suffix>MB</template> + <template #caption>{{ i18n.ts.inMb }}</template> + </FormInput> + </FormSplit> + </FormSection> + + <FormSection> + <template #label>ServiceWorker</template> + + <FormSwitch v-model="enableServiceWorker" class="_formBlock"> + <template #label>{{ i18n.ts.enableServiceworker }}</template> + <template #caption>{{ i18n.ts.serviceworkerInfo }}</template> + </FormSwitch> + + <template v-if="enableServiceWorker"> + <FormInput v-model="swPublicKey" class="_formBlock"> + <template #prefix><i class="ti ti-key"></i></template> + <template #label>Public key</template> + </FormInput> + + <FormInput v-model="swPrivateKey" class="_formBlock"> + <template #prefix><i class="ti ti-key"></i></template> + <template #label>Private key</template> + </FormInput> + </template> + </FormSection> + + <FormSection> + <template #label>DeepL Translation</template> + + <FormInput v-model="deeplAuthKey" class="_formBlock"> + <template #prefix><i class="ti ti-key"></i></template> + <template #label>DeepL Auth Key</template> + </FormInput> + <FormSwitch v-model="deeplIsPro" class="_formBlock"> + <template #label>Pro account</template> + </FormSwitch> + </FormSection> + </div> + </FormSuspense> + </MkSpacer> + </MkStickyContainer> +</div> +</template> + +<script lang="ts" setup> +import { } from 'vue'; +import XHeader from './_header_.vue'; +import FormSwitch from '@/components/form/switch.vue'; +import FormInput from '@/components/form/input.vue'; +import FormTextarea from '@/components/form/textarea.vue'; +import FormInfo from '@/components/MkInfo.vue'; +import FormSection from '@/components/form/section.vue'; +import FormSplit from '@/components/form/split.vue'; +import FormSuspense from '@/components/form/suspense.vue'; +import * as os from '@/os'; +import { fetchInstance } from '@/instance'; +import { i18n } from '@/i18n'; +import { definePageMetadata } from '@/scripts/page-metadata'; + +let name: string | null = $ref(null); +let description: string | null = $ref(null); +let tosUrl: string | null = $ref(null); +let maintainerName: string | null = $ref(null); +let maintainerEmail: string | null = $ref(null); +let iconUrl: string | null = $ref(null); +let bannerUrl: string | null = $ref(null); +let backgroundImageUrl: string | null = $ref(null); +let themeColor: any = $ref(null); +let defaultLightTheme: any = $ref(null); +let defaultDarkTheme: any = $ref(null); +let enableLocalTimeline: boolean = $ref(false); +let enableGlobalTimeline: boolean = $ref(false); +let pinnedUsers: string = $ref(''); +let cacheRemoteFiles: boolean = $ref(false); +let localDriveCapacityMb: any = $ref(0); +let remoteDriveCapacityMb: any = $ref(0); +let enableRegistration: boolean = $ref(false); +let emailRequiredForSignup: 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() { + const meta = await os.api('admin/meta'); + name = meta.name; + description = meta.description; + tosUrl = meta.tosUrl; + iconUrl = meta.iconUrl; + bannerUrl = meta.bannerUrl; + backgroundImageUrl = meta.backgroundImageUrl; + themeColor = meta.themeColor; + defaultLightTheme = meta.defaultLightTheme; + defaultDarkTheme = meta.defaultDarkTheme; + maintainerName = meta.maintainerName; + maintainerEmail = meta.maintainerEmail; + enableLocalTimeline = !meta.disableLocalTimeline; + enableGlobalTimeline = !meta.disableGlobalTimeline; + pinnedUsers = meta.pinnedUsers.join('\n'); + cacheRemoteFiles = meta.cacheRemoteFiles; + localDriveCapacityMb = meta.driveCapacityPerLocalUserMb; + remoteDriveCapacityMb = meta.driveCapacityPerRemoteUserMb; + enableRegistration = !meta.disableRegistration; + emailRequiredForSignup = meta.emailRequiredForSignup; + enableServiceWorker = meta.enableServiceWorker; + swPublicKey = meta.swPublickey; + swPrivateKey = meta.swPrivateKey; + deeplAuthKey = meta.deeplAuthKey; + deeplIsPro = meta.deeplIsPro; +} + +function save() { + os.apiWithDialog('admin/update-meta', { + name, + description, + tosUrl, + iconUrl, + bannerUrl, + backgroundImageUrl, + themeColor: themeColor === '' ? null : themeColor, + defaultLightTheme: defaultLightTheme === '' ? null : defaultLightTheme, + defaultDarkTheme: defaultDarkTheme === '' ? null : defaultDarkTheme, + maintainerName, + maintainerEmail, + disableLocalTimeline: !enableLocalTimeline, + disableGlobalTimeline: !enableGlobalTimeline, + pinnedUsers: pinnedUsers.split('\n'), + cacheRemoteFiles, + localDriveCapacityMb: parseInt(localDriveCapacityMb, 10), + remoteDriveCapacityMb: parseInt(remoteDriveCapacityMb, 10), + disableRegistration: !enableRegistration, + emailRequiredForSignup, + enableServiceWorker, + swPublicKey, + swPrivateKey, + deeplAuthKey, + deeplIsPro, + }).then(() => { + fetchInstance(); + }); +} + +const headerActions = $computed(() => [{ + asFullButton: true, + icon: 'ti ti-check', + text: i18n.ts.save, + handler: save, +}]); + +const headerTabs = $computed(() => []); + +definePageMetadata({ + title: i18n.ts.general, + icon: 'ti ti-settings', +}); +</script> |