enhance(frontend): tweak control panel
This commit is contained in:
parent
01ec708020
commit
d435d04eaf
2 changed files with 151 additions and 77 deletions
|
@ -41,6 +41,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkSpacer :marginMin="14" :marginMax="22">
|
<MkSpacer :marginMin="14" :marginMax="22">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
|
<div :class="$style.footer" v-if="withFooter">
|
||||||
|
<slot name="footer"></slot>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
@ -56,9 +59,11 @@ import { defaultStore } from '@/store.js';
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
defaultOpen?: boolean;
|
defaultOpen?: boolean;
|
||||||
maxHeight?: number | null;
|
maxHeight?: number | null;
|
||||||
|
withFooter?: boolean;
|
||||||
}>(), {
|
}>(), {
|
||||||
defaultOpen: false,
|
defaultOpen: false,
|
||||||
maxHeight: null,
|
maxHeight: null,
|
||||||
|
withFooter: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const getBgColor = (el: HTMLElement) => {
|
const getBgColor = (el: HTMLElement) => {
|
||||||
|
@ -224,4 +229,17 @@ onMounted(() => {
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
position: sticky !important;
|
||||||
|
z-index: 1;
|
||||||
|
bottom: var(--stickyBottom, 0px);
|
||||||
|
left: 0;
|
||||||
|
padding: 9px 12px;
|
||||||
|
border-top: solid 0.5px var(--divider);
|
||||||
|
background: var(--acrylicBg);
|
||||||
|
-webkit-backdrop-filter: var(--blur, blur(15px));
|
||||||
|
backdrop-filter: var(--blur, blur(15px));
|
||||||
|
border-radius: 0 0 6px 6px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -10,6 +10,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
|
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="32">
|
||||||
<FormSuspense :p="init">
|
<FormSuspense :p="init">
|
||||||
<div class="_gaps_m">
|
<div class="_gaps_m">
|
||||||
|
<MkFolder :defaultOpen="true" :withFooter="true">
|
||||||
|
<template #icon><i class="ti ti-info-circle"></i></template>
|
||||||
|
<template #label>{{ i18n.ts.info }}</template>
|
||||||
|
<template #footer>
|
||||||
|
<MkButton primary rounded @click="saveInfo">{{ i18n.ts.save }}</MkButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div class="_gaps">
|
||||||
<MkInput v-model="name">
|
<MkInput v-model="name">
|
||||||
<template #label>{{ i18n.ts.instanceName }}</template>
|
<template #label>{{ i18n.ts.instanceName }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
|
@ -65,16 +73,30 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template #prefix><i class="ti ti-link"></i></template>
|
<template #prefix><i class="ti ti-link"></i></template>
|
||||||
<template #caption>{{ i18n.ts.impressumDescription }}</template>
|
<template #caption>{{ i18n.ts.impressumDescription }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
|
<MkFolder :withFooter="true">
|
||||||
|
<template #icon><i class="ti ti-user-star"></i></template>
|
||||||
|
<template #label>{{ i18n.ts.pinnedUsers }}</template>
|
||||||
|
<template #footer>
|
||||||
|
<MkButton primary rounded @click="save_pinnedUsers">{{ i18n.ts.save }}</MkButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
<MkTextarea v-model="pinnedUsers">
|
<MkTextarea v-model="pinnedUsers">
|
||||||
<template #label>{{ i18n.ts.pinnedUsers }}</template>
|
<template #label>{{ i18n.ts.pinnedUsers }}</template>
|
||||||
<template #caption>{{ i18n.ts.pinnedUsersDescription }}</template>
|
<template #caption>{{ i18n.ts.pinnedUsersDescription }}</template>
|
||||||
</MkTextarea>
|
</MkTextarea>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
<FormSection>
|
<MkFolder :withFooter="true">
|
||||||
|
<template #icon><i class="ti ti-cloud"></i></template>
|
||||||
<template #label>{{ i18n.ts.files }}</template>
|
<template #label>{{ i18n.ts.files }}</template>
|
||||||
|
<template #footer>
|
||||||
|
<MkButton primary rounded @click="saveFiles">{{ i18n.ts.save }}</MkButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div class="_gaps_m">
|
<div class="_gaps">
|
||||||
<MkSwitch v-model="cacheRemoteFiles">
|
<MkSwitch v-model="cacheRemoteFiles">
|
||||||
<template #label>{{ i18n.ts.cacheRemoteFiles }}</template>
|
<template #label>{{ i18n.ts.cacheRemoteFiles }}</template>
|
||||||
<template #caption>{{ i18n.ts.cacheRemoteFilesDescription }}{{ i18n.ts.youCanCleanRemoteFilesCache }}</template>
|
<template #caption>{{ i18n.ts.cacheRemoteFilesDescription }}{{ i18n.ts.youCanCleanRemoteFilesCache }}</template>
|
||||||
|
@ -87,12 +109,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</FormSection>
|
</MkFolder>
|
||||||
|
|
||||||
<FormSection>
|
<MkFolder :withFooter="true">
|
||||||
|
<template #icon><i class="ti ti-world-cog"></i></template>
|
||||||
<template #label>ServiceWorker</template>
|
<template #label>ServiceWorker</template>
|
||||||
|
<template #footer>
|
||||||
|
<MkButton primary rounded @click="saveServiceWorker">{{ i18n.ts.save }}</MkButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div class="_gaps_m">
|
<div class="_gaps">
|
||||||
<MkSwitch v-model="enableServiceWorker">
|
<MkSwitch v-model="enableServiceWorker">
|
||||||
<template #label>{{ i18n.ts.enableServiceworker }}</template>
|
<template #label>{{ i18n.ts.enableServiceworker }}</template>
|
||||||
<template #caption>{{ i18n.ts.serviceworkerInfo }}</template>
|
<template #caption>{{ i18n.ts.serviceworkerInfo }}</template>
|
||||||
|
@ -110,12 +136,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkInput>
|
</MkInput>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</FormSection>
|
</MkFolder>
|
||||||
|
|
||||||
<FormSection>
|
<MkFolder :withFooter="true">
|
||||||
|
<template #icon><i class="ti ti-ad"></i></template>
|
||||||
<template #label>{{ i18n.ts._ad.adsSettings }}</template>
|
<template #label>{{ i18n.ts._ad.adsSettings }}</template>
|
||||||
|
<template #footer>
|
||||||
|
<MkButton primary rounded @click="saveAd">{{ i18n.ts.save }}</MkButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div class="_gaps_m">
|
<div class="_gaps">
|
||||||
<div class="_gaps_s">
|
<div class="_gaps_s">
|
||||||
<MkInput v-model="notesPerOneAd" :min="0" type="number">
|
<MkInput v-model="notesPerOneAd" :min="0" type="number">
|
||||||
<template #label>{{ i18n.ts._ad.notesPerOneAd }}</template>
|
<template #label>{{ i18n.ts._ad.notesPerOneAd }}</template>
|
||||||
|
@ -126,12 +156,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</MkInfo>
|
</MkInfo>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</FormSection>
|
</MkFolder>
|
||||||
|
|
||||||
<FormSection>
|
<MkFolder :withFooter="true">
|
||||||
|
<template #icon><i class="ti ti-world-search"></i></template>
|
||||||
<template #label>{{ i18n.ts._urlPreviewSetting.title }}</template>
|
<template #label>{{ i18n.ts._urlPreviewSetting.title }}</template>
|
||||||
|
<template #footer>
|
||||||
|
<MkButton primary rounded @click="saveUrlPreview">{{ i18n.ts.save }}</MkButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div class="_gaps_m">
|
<div class="_gaps">
|
||||||
<MkSwitch v-model="urlPreviewEnabled">
|
<MkSwitch v-model="urlPreviewEnabled">
|
||||||
<template #label>{{ i18n.ts._urlPreviewSetting.enable }}</template>
|
<template #label>{{ i18n.ts._urlPreviewSetting.enable }}</template>
|
||||||
</MkSwitch>
|
</MkSwitch>
|
||||||
|
@ -173,17 +207,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</FormSection>
|
</MkFolder>
|
||||||
</div>
|
</div>
|
||||||
</FormSuspense>
|
</FormSuspense>
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
<template #footer>
|
|
||||||
<div :class="$style.footer">
|
|
||||||
<MkSpacer :contentMax="700" :marginMin="16" :marginMax="16">
|
|
||||||
<MkButton primary rounded @click="save"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
|
|
||||||
</MkSpacer>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</MkStickyContainer>
|
</MkStickyContainer>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -195,7 +222,6 @@ import MkSwitch from '@/components/MkSwitch.vue';
|
||||||
import MkInput from '@/components/MkInput.vue';
|
import MkInput from '@/components/MkInput.vue';
|
||||||
import MkTextarea from '@/components/MkTextarea.vue';
|
import MkTextarea from '@/components/MkTextarea.vue';
|
||||||
import MkInfo from '@/components/MkInfo.vue';
|
import MkInfo from '@/components/MkInfo.vue';
|
||||||
import FormSection from '@/components/form/section.vue';
|
|
||||||
import FormSplit from '@/components/form/split.vue';
|
import FormSplit from '@/components/form/split.vue';
|
||||||
import FormSuspense from '@/components/form/suspense.vue';
|
import FormSuspense from '@/components/form/suspense.vue';
|
||||||
import * as os from '@/os.js';
|
import * as os from '@/os.js';
|
||||||
|
@ -258,8 +284,8 @@ async function init(): Promise<void> {
|
||||||
urlPreviewSummaryProxyUrl.value = meta.urlPreviewSummaryProxyUrl;
|
urlPreviewSummaryProxyUrl.value = meta.urlPreviewSummaryProxyUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function save() {
|
function saveInfo() {
|
||||||
await os.apiWithDialog('admin/update-meta', {
|
os.apiWithDialog('admin/update-meta', {
|
||||||
name: name.value,
|
name: name.value,
|
||||||
shortName: shortName.value === '' ? null : shortName.value,
|
shortName: shortName.value === '' ? null : shortName.value,
|
||||||
description: description.value,
|
description: description.value,
|
||||||
|
@ -270,22 +296,57 @@ async function save() {
|
||||||
inquiryUrl: inquiryUrl.value,
|
inquiryUrl: inquiryUrl.value,
|
||||||
repositoryUrl: repositoryUrl.value,
|
repositoryUrl: repositoryUrl.value,
|
||||||
impressumUrl: impressumUrl.value,
|
impressumUrl: impressumUrl.value,
|
||||||
|
}).then(() => {
|
||||||
|
fetchInstance(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function save_pinnedUsers() {
|
||||||
|
os.apiWithDialog('admin/update-meta', {
|
||||||
pinnedUsers: pinnedUsers.value.split('\n'),
|
pinnedUsers: pinnedUsers.value.split('\n'),
|
||||||
|
}).then(() => {
|
||||||
|
fetchInstance(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveFiles() {
|
||||||
|
os.apiWithDialog('admin/update-meta', {
|
||||||
cacheRemoteFiles: cacheRemoteFiles.value,
|
cacheRemoteFiles: cacheRemoteFiles.value,
|
||||||
cacheRemoteSensitiveFiles: cacheRemoteSensitiveFiles.value,
|
cacheRemoteSensitiveFiles: cacheRemoteSensitiveFiles.value,
|
||||||
|
}).then(() => {
|
||||||
|
fetchInstance(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveServiceWorker() {
|
||||||
|
os.apiWithDialog('admin/update-meta', {
|
||||||
enableServiceWorker: enableServiceWorker.value,
|
enableServiceWorker: enableServiceWorker.value,
|
||||||
swPublicKey: swPublicKey.value,
|
swPublicKey: swPublicKey.value,
|
||||||
swPrivateKey: swPrivateKey.value,
|
swPrivateKey: swPrivateKey.value,
|
||||||
|
}).then(() => {
|
||||||
|
fetchInstance(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveAd() {
|
||||||
|
os.apiWithDialog('admin/update-meta', {
|
||||||
notesPerOneAd: notesPerOneAd.value,
|
notesPerOneAd: notesPerOneAd.value,
|
||||||
|
}).then(() => {
|
||||||
|
fetchInstance(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveUrlPreview() {
|
||||||
|
os.apiWithDialog('admin/update-meta', {
|
||||||
urlPreviewEnabled: urlPreviewEnabled.value,
|
urlPreviewEnabled: urlPreviewEnabled.value,
|
||||||
urlPreviewTimeout: urlPreviewTimeout.value,
|
urlPreviewTimeout: urlPreviewTimeout.value,
|
||||||
urlPreviewMaximumContentLength: urlPreviewMaximumContentLength.value,
|
urlPreviewMaximumContentLength: urlPreviewMaximumContentLength.value,
|
||||||
urlPreviewRequireContentLength: urlPreviewRequireContentLength.value,
|
urlPreviewRequireContentLength: urlPreviewRequireContentLength.value,
|
||||||
urlPreviewUserAgent: urlPreviewUserAgent.value,
|
urlPreviewUserAgent: urlPreviewUserAgent.value,
|
||||||
urlPreviewSummaryProxyUrl: urlPreviewSummaryProxyUrl.value,
|
urlPreviewSummaryProxyUrl: urlPreviewSummaryProxyUrl.value,
|
||||||
});
|
}).then(() => {
|
||||||
|
|
||||||
fetchInstance(true);
|
fetchInstance(true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerTabs = computed(() => []);
|
const headerTabs = computed(() => []);
|
||||||
|
@ -297,11 +358,6 @@ definePageMetadata(() => ({
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
.footer {
|
|
||||||
-webkit-backdrop-filter: var(--blur, blur(15px));
|
|
||||||
backdrop-filter: var(--blur, blur(15px));
|
|
||||||
}
|
|
||||||
|
|
||||||
.subCaption {
|
.subCaption {
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
color: var(--fgTransparentWeak);
|
color: var(--fgTransparentWeak);
|
||||||
|
|
Loading…
Reference in a new issue