mirror of
https://github.com/versia-pub/frontend.git
synced 2025-12-06 16:38:20 +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>
|
||||
<ClientOnly>
|
||||
<Component is="style">
|
||||
{{ customCss.value }}
|
||||
</Component>
|
||||
</ClientOnly>
|
||||
<NuxtPwaAssets />
|
||||
<ClientOnly>
|
||||
<NuxtLayout>
|
||||
|
|
@ -13,6 +18,7 @@ import "~/styles/theme.css";
|
|||
import { convert } from "html-to-text";
|
||||
import "iconify-icon";
|
||||
import NotificationsRenderer from "./components/notifications/notifications-renderer.vue";
|
||||
import { SettingIds } from "./settings";
|
||||
// Use SSR-safe IDs for Headless UI
|
||||
provideHeadlessUseId(() => useId());
|
||||
|
||||
|
|
@ -20,6 +26,7 @@ const code = useRequestURL().searchParams.get("code");
|
|||
const appData = useAppData();
|
||||
const instance = useInstance();
|
||||
const description = useExtendedDescription(client);
|
||||
const customCss = useSetting(SettingIds.CustomCSS);
|
||||
|
||||
useSeoMeta({
|
||||
titleTemplate: (titleChunk) => {
|
||||
|
|
|
|||
|
|
@ -1,51 +1,23 @@
|
|||
<template>
|
||||
<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">
|
||||
<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>
|
||||
<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>
|
||||
<SettingBoolean v-if="setting.type === SettingType.Boolean" :id="id" />
|
||||
|
||||
<SettingCode v-else-if="setting.type === SettingType.Code" :id="id" />
|
||||
<SettingOther v-else :id="id" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Switch } from "@ark-ui/vue";
|
||||
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<{
|
||||
id: SettingIds;
|
||||
}>();
|
||||
|
||||
const setting = useSetting(props.id);
|
||||
const checked = ref(setting.value.value as boolean);
|
||||
|
||||
watch(checked, (c) => {
|
||||
setting.value.value = c;
|
||||
});
|
||||
</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