93 lines
4.7 KiB
Vue
93 lines
4.7 KiB
Vue
<template>
|
|
<div v-if="page" class="xl:p-12 lg:p-8 py-4 flex flex-1 flex-col items-start justify-start max-h-full">
|
|
<Head>
|
|
<Title>d[any] - Modification de {{ page.title }}</Title>
|
|
</Head>
|
|
<div class="flex flex-col xl:flex-row xl:justify-between justify-center items-center w-full px-4 pb-4 border-b border-light-35 dark:border-dark-35 bg-light-0 dark:bg-dark-0">
|
|
<input type="text" v-model="page.title" placeholder="Titre" class="flex-1 mx-4 h-16 w-full caret-light-50 dark:caret-dark-50 text-light-100 dark:text-dark-100 placeholder:text-light-50 dark:placeholder:text-dark-50 appearance-none outline-none px-3 py-1 text-5xl font-thin bg-transparent" />
|
|
<div class="flex gap-4 self-end xl:self-auto flex-wrap">
|
|
<div class="flex gap-4">
|
|
<Tooltip message="Consultable uniquement par le propriétaire" side="bottom"><Switch label="Privé" v-model="page.private" /></Tooltip>
|
|
<Tooltip message="Afficher dans le menu de navigation" side="bottom"><Switch label="Navigable" v-model="page.navigable" /></Tooltip>
|
|
</div>
|
|
<div class="flex gap-4">
|
|
<Button @click="() => save()" :loading="saveStatus === 'pending'" class="border-light-blue dark:border-dark-blue hover:border-light-blue dark:hover:border-dark-blue focus:shadow-light-blue dark:focus:shadow-dark-blue">Enregistrer</Button>
|
|
<NuxtLink :href="{ name: 'explore-path', params: { path: path } }"><Button>Annuler</Button></NuxtLink>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="my-4 flex-1 w-full max-h-full flex">
|
|
<template v-if="page.type === 'markdown'">
|
|
<SplitterGroup direction="horizontal" class="flex-1 w-full flex" >
|
|
<SplitterPanel asChild collapsible :collapsedSize="0" :minSize="20" v-slot="{ isCollapsed }" :defaultSize="50">
|
|
<textarea v-model="page.content" class="flex-1 bg-transparent appearance-none outline-none max-h-full resize-none !overflow-y-auto" :class="{ 'hidden': isCollapsed }"></textarea>
|
|
</SplitterPanel>
|
|
<SplitterResizeHandle class="bg-light-35 dark:bg-dark-35 w-px xl!mx-4 mx-2" />
|
|
<SplitterPanel asChild collapsible :collapsedSize="0" :minSize="20" v-slot="{ isCollapsed }">
|
|
<div class="flex-1 max-h-full !overflow-y-auto px-8" :class="{ 'hidden': isCollapsed }"><Markdown :content="debounced" :proses="{ 'a': FakeA }" /></div>
|
|
</SplitterPanel>
|
|
</SplitterGroup>
|
|
</template>
|
|
<template v-else-if="page.type === 'canvas'">
|
|
<span class="flex-1 items-center"><ProseH1>Editeur de graphe en cours de développement</ProseH1></span>
|
|
</template>
|
|
<template v-else-if="page.type === 'file'">
|
|
<span>Modifier le contenu :</span><input type="file" @change="(e) => console.log(e)" />
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<div v-else-if="status === 'pending'" class="flex">
|
|
<Head>
|
|
<Title>d[any] - Chargement</Title>
|
|
</Head>
|
|
<Loading />
|
|
</div>
|
|
<div v-else-if="status === 'error'">{{ error?.message }}</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import FakeA from '~/components/prose/FakeA.vue';
|
|
|
|
const route = useRouter().currentRoute;
|
|
const path = computed(() => Array.isArray(route.value.params.path) ? route.value.params.path[0] : route.value.params.path);
|
|
const { user, loggedIn } = useUserSession();
|
|
|
|
const toaster = useToast();
|
|
const saveStatus = ref<'idle' | 'pending' | 'success' | 'error'>('idle');
|
|
|
|
const { data: page, status, error } = await useLazyFetch(`/api/file/${encodeURIComponent(path.value)}`, { watch: [ route, path ]});
|
|
const content = computed(() => page.value?.content);
|
|
const debounced = useDebounce(content, 250);
|
|
|
|
if(!loggedIn || (page.value && page.value.owner !== user.value?.id))
|
|
{
|
|
useRouter().replace({ name: 'explore-path', params: { path: path.value } });
|
|
}
|
|
|
|
async function save(): Promise<void>
|
|
{
|
|
saveStatus.value = 'pending';
|
|
try {
|
|
await $fetch(`/api/file`, {
|
|
method: 'post',
|
|
body: page.value,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
saveStatus.value = 'success';
|
|
|
|
toaster.clear('error');
|
|
toaster.add({
|
|
type: 'success', content: 'Contenu enregistré', timer: true, duration: 10000
|
|
});
|
|
|
|
useRouter().push({ name: 'explore-path', params: { path: path.value } });
|
|
} catch(e: any) {
|
|
toaster.add({
|
|
type: 'error', content: e.message, timer: true, duration: 10000
|
|
})
|
|
saveStatus.value = 'error';
|
|
}
|
|
}
|
|
</script> |