mirror of
https://github.com/versia-pub/frontend.git
synced 2025-12-08 09:18:21 +01:00
feat: ✨ Add support for settings of type "code"
This commit is contained in:
parent
ee8372592c
commit
4f2c1901d1
7
app.vue
7
app.vue
|
|
@ -1,4 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
|
<ClientOnly>
|
||||||
|
<Component is="style">
|
||||||
|
{{ customCss.value }}
|
||||||
|
</Component>
|
||||||
|
</ClientOnly>
|
||||||
<NuxtPwaAssets />
|
<NuxtPwaAssets />
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<NuxtLayout>
|
<NuxtLayout>
|
||||||
|
|
@ -13,6 +18,7 @@ import "~/styles/theme.css";
|
||||||
import { convert } from "html-to-text";
|
import { convert } from "html-to-text";
|
||||||
import "iconify-icon";
|
import "iconify-icon";
|
||||||
import NotificationsRenderer from "./components/notifications/notifications-renderer.vue";
|
import NotificationsRenderer from "./components/notifications/notifications-renderer.vue";
|
||||||
|
import { SettingIds } from "./settings";
|
||||||
// Use SSR-safe IDs for Headless UI
|
// Use SSR-safe IDs for Headless UI
|
||||||
provideHeadlessUseId(() => useId());
|
provideHeadlessUseId(() => useId());
|
||||||
|
|
||||||
|
|
@ -20,6 +26,7 @@ const code = useRequestURL().searchParams.get("code");
|
||||||
const appData = useAppData();
|
const appData = useAppData();
|
||||||
const instance = useInstance();
|
const instance = useInstance();
|
||||||
const description = useExtendedDescription(client);
|
const description = useExtendedDescription(client);
|
||||||
|
const customCss = useSetting(SettingIds.CustomCSS);
|
||||||
|
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
titleTemplate: (titleChunk) => {
|
titleTemplate: (titleChunk) => {
|
||||||
|
|
|
||||||
|
|
@ -1,51 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="w-full px-8 py-4 bg-dark-700 hover:bg-dark-500 duration-100 h-full">
|
<div class="w-full px-8 py-4 bg-dark-700 hover:bg-dark-500 duration-100 h-full">
|
||||||
<div class="max-w-7xl mx-auto h-full">
|
<div class="max-w-7xl mx-auto h-full">
|
||||||
<Switch.Root v-model:checked="checked" class="grid grid-cols-[1fr_auto] gap-x-4"
|
<SettingBoolean v-if="setting.type === SettingType.Boolean" :id="id" />
|
||||||
@click="setting.notImplemented ? $event.preventDefault() : undefined"
|
|
||||||
v-if="setting.type === SettingType.Boolean" @update:checked="c => checked = c">
|
<SettingCode v-else-if="setting.type === SettingType.Code" :id="id" />
|
||||||
<Switch.Label :data-disabled="setting.notImplemented ? '' : undefined"
|
<SettingOther v-else :id="id" />
|
||||||
class="row-start-1 select-none text-base/6 data-[disabled]:opacity-50 sm:text-sm/6 text-white font-semibold">
|
|
||||||
{{
|
|
||||||
setting.title
|
|
||||||
}}</Switch.Label>
|
|
||||||
<p v-if="setting.notImplemented" class="text-xs mt-1 row-start-3 text-red-300 font-semibold">Not
|
|
||||||
implemented
|
|
||||||
</p>
|
|
||||||
<p v-else :data-disabled="setting.notImplemented ? '' : undefined"
|
|
||||||
class="text-base/6 row-start-2 data-[disabled]:opacity-50 sm:text-sm/6 text-gray-300">{{
|
|
||||||
setting.description }}
|
|
||||||
</p>
|
|
||||||
<Switch.Control :data-disabled="setting.notImplemented ? '' : undefined"
|
|
||||||
:data-checked="checked ? '' : undefined"
|
|
||||||
class="group col-start-2 relative isolate inline-flex h-6 w-10 cursor-default rounded-full p-[3px] sm:h-5 sm:w-8 transition duration-0 ease-in-out data-[changing]:duration-200 forced-colors:outline forced-colors:[--switch-bg:Highlight] ring-1 ring-inset bg-white/5 ring-white/15 data-[checked]:bg-[--switch-bg] data-[checked]:ring-[--switch-bg-ring] focus:outline-none focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-blue-500 hover:data-[checked]:ring-[--switch-bg-ring] hover:ring-white/25 data-[disabled]:bg-zinc-200 data-[disabled]:data-[checked]:bg-zinc-200 data-[disabled]:opacity-50 data-[disabled]:bg-white/15 data-[disabled]:data-[checked]:bg-white/15 data-[disabled]:data-[checked]:ring-white/15 [--switch-bg-ring:transparent] [--switch-bg:theme(colors.primary.600/25%)] [--switch-shadow:theme(colors.black/10%)] [--switch:white] [--switch-ring:theme(colors.white/10%)]">
|
|
||||||
<Switch.Thumb
|
|
||||||
class="pointer-events-none relative inline-block size-[1.125rem] rounded-full sm:size-3.5 translate-x-0 transition duration-200 ease-in-out border border-transparent bg-white shadow ring-1 ring-black/5 group-data-[checked]:bg-[--switch] group-data-[checked]:shadow-[--switch-shadow] group-data-[checked]:ring-[--switch-ring] group-data-[checked]:translate-x-4 sm:group-data-[checked]:translate-x-3 group-data-[disabled]:group-data-[checked]:bg-white group-data-[disabled]:group-data-[checked]:shadow group-data-[disabled]:group-data-[checked]:ring-black/5" />
|
|
||||||
</Switch.Control>
|
|
||||||
<Switch.HiddenInput />
|
|
||||||
</Switch.Root>
|
|
||||||
<div v-else class="grid grid-cols-[1fr_auto] gap-x-4">
|
|
||||||
<h4 class="row-start-1 select-none text-base/6 sm:text-sm/6 text-white font-semibold">{{ setting.title
|
|
||||||
}}
|
|
||||||
</h4>
|
|
||||||
<p class="text-xs mt-1 row-start-3 text-red-300 font-semibold">Not implemented</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Switch } from "@ark-ui/vue";
|
|
||||||
import { type SettingIds, SettingType } from "~/settings";
|
import { type SettingIds, SettingType } from "~/settings";
|
||||||
|
import SettingBoolean from "./types/Boolean.vue";
|
||||||
|
import SettingCode from "./types/Code.vue";
|
||||||
|
import SettingOther from "./types/Other.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
id: SettingIds;
|
id: SettingIds;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const setting = useSetting(props.id);
|
const setting = useSetting(props.id);
|
||||||
const checked = ref(setting.value.value as boolean);
|
|
||||||
|
|
||||||
watch(checked, (c) => {
|
|
||||||
setting.value.value = c;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
41
components/settings/types/Boolean.vue
Normal file
41
components/settings/types/Boolean.vue
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<Switch.Root v-model:checked="checked" class="grid grid-cols-[1fr_auto] gap-x-4"
|
||||||
|
@click="setting.notImplemented ? $event.preventDefault() : undefined"
|
||||||
|
v-if="setting.type === SettingType.Boolean" @update:checked="c => checked = c">
|
||||||
|
<Switch.Label :data-disabled="setting.notImplemented ? '' : undefined"
|
||||||
|
class="row-start-1 select-none text-base/6 data-[disabled]:opacity-50 sm:text-sm/6 text-white font-semibold">
|
||||||
|
{{
|
||||||
|
setting.title
|
||||||
|
}}</Switch.Label>
|
||||||
|
<p v-if="setting.notImplemented" class="text-xs mt-1 row-start-3 text-red-300 font-semibold">Not
|
||||||
|
implemented
|
||||||
|
</p>
|
||||||
|
<p v-else :data-disabled="setting.notImplemented ? '' : undefined"
|
||||||
|
class="text-base/6 row-start-2 data-[disabled]:opacity-50 sm:text-sm/6 text-gray-300">{{
|
||||||
|
setting.description }}
|
||||||
|
</p>
|
||||||
|
<Switch.Control :data-disabled="setting.notImplemented ? '' : undefined"
|
||||||
|
:data-checked="checked ? '' : undefined"
|
||||||
|
class="group col-start-2 relative isolate inline-flex h-6 w-10 cursor-default rounded-full p-[3px] sm:h-5 sm:w-8 transition duration-0 ease-in-out data-[changing]:duration-200 forced-colors:outline forced-colors:[--switch-bg:Highlight] ring-1 ring-inset bg-white/5 ring-white/15 data-[checked]:bg-[--switch-bg] data-[checked]:ring-[--switch-bg-ring] focus:outline-none focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-blue-500 hover:data-[checked]:ring-[--switch-bg-ring] hover:ring-white/25 data-[disabled]:bg-zinc-200 data-[disabled]:data-[checked]:bg-zinc-200 data-[disabled]:opacity-50 data-[disabled]:bg-white/15 data-[disabled]:data-[checked]:bg-white/15 data-[disabled]:data-[checked]:ring-white/15 [--switch-bg-ring:transparent] [--switch-bg:theme(colors.primary.600/25%)] [--switch-shadow:theme(colors.black/10%)] [--switch:white] [--switch-ring:theme(colors.white/10%)]">
|
||||||
|
<Switch.Thumb
|
||||||
|
class="pointer-events-none relative inline-block size-[1.125rem] rounded-full sm:size-3.5 translate-x-0 transition duration-200 ease-in-out border border-transparent bg-white shadow ring-1 ring-black/5 group-data-[checked]:bg-[--switch] group-data-[checked]:shadow-[--switch-shadow] group-data-[checked]:ring-[--switch-ring] group-data-[checked]:translate-x-4 sm:group-data-[checked]:translate-x-3 group-data-[disabled]:group-data-[checked]:bg-white group-data-[disabled]:group-data-[checked]:shadow group-data-[disabled]:group-data-[checked]:ring-black/5" />
|
||||||
|
</Switch.Control>
|
||||||
|
<Switch.HiddenInput />
|
||||||
|
</Switch.Root>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Switch } from "@ark-ui/vue";
|
||||||
|
import { type SettingIds, SettingType } from "~/settings";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id: SettingIds;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const setting = useSetting(props.id);
|
||||||
|
const checked = ref(setting.value.value as boolean);
|
||||||
|
|
||||||
|
watch(checked, (c) => {
|
||||||
|
setting.value.value = c;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
25
components/settings/types/Code.vue
Normal file
25
components/settings/types/Code.vue
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-y-1">
|
||||||
|
<h4 class="row-start-1 select-none text-base/6 sm:text-sm/6 text-white font-semibold">{{ setting.title
|
||||||
|
}}
|
||||||
|
</h4>
|
||||||
|
<textarea v-model="content"
|
||||||
|
class="resize-none min-h-48 mt-1 prose prose-invert max-w-full ring-1 ring-white/20 font-mono placeholder:text-zinc-500 bg-transparent rounded appearance-none disabled:cursor-not-allowed"
|
||||||
|
aria-label="Start typing here..."></textarea>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { SettingIds } from "~/settings";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id: SettingIds;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const setting = useSetting(props.id);
|
||||||
|
const content = ref(setting.value.value as string);
|
||||||
|
|
||||||
|
watch(content, (c) => {
|
||||||
|
setting.value.value = c;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
18
components/settings/types/Other.vue
Normal file
18
components/settings/types/Other.vue
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<template>
|
||||||
|
<div class="grid grid-cols-[1fr_auto] gap-x-4">
|
||||||
|
<h4 class="row-start-1 select-none text-base/6 sm:text-sm/6 text-white font-semibold">{{ setting.title
|
||||||
|
}}
|
||||||
|
</h4>
|
||||||
|
<p class="text-xs mt-1 row-start-3 text-red-300 font-semibold">Not implemented</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { SettingIds } from "~/settings";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id: SettingIds;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const setting = useSetting(props.id);
|
||||||
|
</script>
|
||||||
Loading…
Reference in a new issue