Several fixes to CSS, better responsive overall, improved security and error page

This commit is contained in:
2024-11-10 17:44:42 +01:00
parent 721e7ff3db
commit 057efb848c
20 changed files with 135 additions and 66 deletions

View File

@@ -46,7 +46,7 @@ async function fetch()
<ProseH2>Administration</ProseH2>
<Select label="Job" v-model="job">
<SelectItem label="Synchroniser" value="sync" />
<SelectItem label="Nettoyer la base" value="clear" />
<SelectItem label="Nettoyer la base" value="clear" disabled />
<SelectItem label="Reconstruire" value="rebuild" disabled />
</Select>
<Button class="self-center" @click="() => !!job && fetch()" :loading="status === 'pending'">

View File

@@ -1,22 +1,39 @@
<template>
<div v-if="status === 'pending'" class="flex"><Loading /></div>
<div class="flex flex-1 justify-start items-start" v-if="page">
<div v-if="status === 'pending'" class="flex">
<Head>
<Title>d[any] - Chargement</Title>
</Head>
<Loading />
</div>
<div class="flex flex-1 justify-start items-start" v-else-if="page">
<Head>
<Title>d[any] - {{ page.title }}</Title>
</Head>
<template v-if="page.type === 'markdown'">
<div class="flex flex-1 justify-start items-start flex-col px-24 py-6">
<div class="flex flex-1 justify-start items-start flex-col xl:px-24 md:px-8 px-4 py-6">
<div class="flex flex-1 flex-row justify-between items-center">
<ProseH1>{{ page.title }}</ProseH1>
<Button v-if="isOwner"><NuxtLink :href="{ name: 'explore-edit-path', params: { path: path } }">Modifier</NuxtLink></Button>
<NuxtLink :href="{ name: 'explore-edit-path', params: { path: path } }"><Button v-if="isOwner">Modifier</Button></NuxtLink>
</div>
<Markdown :content="page.content" />
</div>
</template>
<template v-else>
<span>Contenu non traitable</span>
<span>En cours de développement</span>
</template>
</div>
<div v-else-if="status === 'pending'"><Loading /></div>
<div v-else-if="status === 'error'">{{ error?.message }}</div>
<div v-else>Impossible de retrouver le contenu demandé</div>
<div v-else-if="status === 'error'">
<Head>
<Title>d[any] - Erreur</Title>
</Head>
<span>{{ error?.message }}</span>
</div>
<div v-else>
<Head>
<Title>d[any] - Erreur</Title>
</Head>
<div><ProseH2>Impossible d'afficher le contenu demandé</ProseH2></div>
</div>
</template>
<script setup lang="ts">

View File

@@ -1,32 +1,35 @@
<template>
<div v-if="page" class="p-12 flex flex-1 flex-col items-start justify-start">
<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>Modification de {{ page.title }}</Title>
</Head>
<div class="flex justify-between items-center w-full px-4 max-h-full">
<div class="flex gap-16 items-center justify-start">
<input type="text" v-model="page.title" placeholder="Titre" class="mx-4 h-16 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>
<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>
<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>
</div>
</div>
<div class="border-t border-light-35 dark:border-dark-35 mt-4 flex-1 w-full max-h-full flex pt-4">
<template v-if="page.type === 'markdown'">
<textarea v-model="page.content" class="flex-1 bg-transparent appearance-none outline-none max-h-full resize-none"></textarea>
<div class="flex-1 border-s border-light-35 dark:border-dark-35 ms-4 pt-4 ps-4 max-h-full">
<Markdown class="max-h-full overflow-auto" :content="page.content" />
</div>
</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 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 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">
<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>
<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>
</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>
<textarea v-model="page.content" class="flex-1 bg-transparent appearance-none outline-none max-h-full resize-none !overflow-y-auto"></textarea>
</SplitterPanel>
<SplitterResizeHandle class="bg-light-35 dark:bg-dark-35 w-px xl!mx-4 mx-2" />
<SplitterPanel asChild>
<div class="flex-1 max-h-full !overflow-y-auto"><Markdown :content="page.content" /></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>
@@ -40,12 +43,18 @@
<script setup lang="ts">
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 ]});
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';

View File

@@ -11,26 +11,11 @@ watch(loading, (value) => {
<template>
<Head>
<Title>Accueil</Title>
<Title>d[any] - Accueil</Title>
</Head>
<div class="h-full w-full flex flex-1 flex-col justify-center items-center">
<div class="w-1/2 flex flex-1 flex-col justify-center items-center gap-2">
<Collapsible label="Options">
<div class="flex flex-col justify-start items-start">
<div class="w-full flex flex-row justify-center">
<Switch v-model="disabled" onIcon="radix-icons:lock-closed" offIcon="radix-icons:lock-open-2" />
<ThemeSwitch />
</div>
<SliderInput :disabled="disabled" :label="`Prix: ${price.toFixed(2)}€`" :min="0" :max="1500" :step="0.25"
v-model="price" />
<TextInput label="Saisir un pseudonyme" :disabled="disabled" v-model="username" />
<NumberPicker label="Age" :disabled="disabled" />
</div>
</Collapsible>
<Button :loading="loading" @click="() => loading = true">
<span v-if="!loading">Load data</span>
</Button>
</div>
<Avatar src="/logo.dark.svg" class="dark:block hidden w-48 h-48" />
<Avatar src="/logo.light.svg" class="block dark:hidden w-48 h-48" />
<h1 class="text-5xl font-thin font-mono">Bienvenue</h1>
</div>
</template>

View File

@@ -11,7 +11,7 @@
<TextInput type="text" label="Utilisateur ou email" autocomplete="username" v-model="state.usernameOrEmail"/>
<TextInput type="password" label="Mot de passe" autocomplete="current-password" v-model="state.password"/>
<Button class="border border-light-35 dark:border-dark-35 self-center" :loading="status === 'pending'">Se connecter</Button>
<NuxtLink class="mt-4 text-center block text-sm font-semibold tracking-wide hover:text-accent-blue" :to="{ path: `/user/register`, force: true }">Pas de compte ?</NuxtLink>
<NuxtLink class="mt-4 text-center block text-sm font-semibold tracking-wide hover:text-accent-blue" :to="{ name: 'user-register' }">Pas de compte ?</NuxtLink>
</form>
</div>
</template>

View File

@@ -57,7 +57,7 @@ const deleting = ref(false);
</AlertDialogContent>
</AlertDialogPortal>
</AlertDialogRoot>
<Button v-if="hasPermissions(user.permissions, ['admin'])"><NuxtLink :href="{ name: 'admin' }">Administration</NuxtLink></Button>
<NuxtLink v-if="hasPermissions(user.permissions, ['admin'])" :href="{ name: 'admin' }"><Button>Administration</Button></NuxtLink>
</div>
<div class="flex" v-if="user.permissions">
<ProseTable class="!m-0">

View File

@@ -27,7 +27,7 @@
</div>
<TextInput type="password" label="Confirmation du mot de passe" autocomplete="new-password" v-model="confirmPassword" class="w-full md:w-auto"/>
<Button class="border border-light-35 dark:border-dark-35 max-w-48 w-full order-9 col-span-2 md:col-span-1 m-auto" :loading="status === 'pending'">S'inscrire</Button>
<span class="mt-4 order-10 flex justify-center items-center gap-4 col-span-2 md:col-span-1 m-auto">Vous avez déjà un compte ?<NuxtLink class="text-center block text-sm font-semibold tracking-wide hover:text-accent-blue" :to="{ path: `/user/login`, force: true }">Se connecter</NuxtLink></span>
<span class="mt-4 order-10 flex justify-center items-center gap-4 col-span-2 md:col-span-1 m-auto">Vous avez déjà un compte ?<NuxtLink class="text-center block text-sm font-semibold tracking-wide hover:text-accent-blue" :to="{ name: 'user-login' }">Se connecter</NuxtLink></span>
</form>
</div>
</template>