You've already forked obsidian-visualiser
Feature Builder panel progress
This commit is contained in:
@@ -16,7 +16,7 @@ onMounted(() => {
|
||||
|
||||
useShortcuts({
|
||||
"Meta_S": () => builder.save(false),
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Icon } from '@iconify/vue/dist/iconify.js';
|
||||
import characterConfig from '#shared/character-config.json';
|
||||
import type { CharacterConfig } from '~/types/character';
|
||||
|
||||
definePageMeta({
|
||||
guestsGoesTo: '/user/login',
|
||||
@@ -8,6 +10,7 @@ const { add } = useToast();
|
||||
const { user } = useUserSession();
|
||||
|
||||
const { data: characters, error, status } = await useFetch(`/api/character`);
|
||||
const config = characterConfig as CharacterConfig;
|
||||
|
||||
async function deleteCharacter(id: number)
|
||||
{
|
||||
@@ -32,21 +35,48 @@ async function duplicateCharacter(id: number)
|
||||
<Title>d[any] - Mes personnages</Title>
|
||||
</Head>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex align-center justify-center">
|
||||
<NuxtLink v-if="user?.state === 1" :to="{ name: 'character-id-edit', params: { id: 'new' } }"><Button>Nouveau personnage</Button></NuxtLink>
|
||||
<Tooltip v-else side="top" message="Veuillez valider votre email avant de pouvoir créer un personnage."><Button disabled>Nouveau personnage</Button></Tooltip>
|
||||
</div>
|
||||
<div v-if="status === 'pending'" class="flex flex-1 justify-center align-center">
|
||||
<Loading size="large" />
|
||||
</div>
|
||||
<div v-else-if="status === 'success'" class="grid p-6 2xl:grid-cols-3 lg:grid-cols-2 grid-cols-1 gap-4 w-full">
|
||||
<div class="border border-light-30 dark:border-dark-30 p-3 flex flex-row gap-4" v-for="character of characters">
|
||||
<Avatar size="large" icon="radix-icons:person" src="" />
|
||||
<div class="flex flex-1 flex-shrink flex-col truncate">
|
||||
<NuxtLink class="text-xl font-bold hover:text-accent-blue truncate" :to="{ name: 'character-id', params: { id: character.id } }" :title="character.name">{{ character.name }}</NuxtLink>
|
||||
<span class="text-sm truncate">Niveau {{ character.level }}</span>
|
||||
<div class="flex flex-col w-[360px] border border-light-35 dark:border-dark-35" v-for="character of characters">
|
||||
<NuxtLink :to="{ name: 'character-id', params: { id: character.id } }" class="group bg-light-10 dark:bg-dark-10 border-b border-light-35 dark:border-dark-35 p-2 flex flex-col gap-2">
|
||||
<div class="flex flex-row gap-8 ps-4 items-center">
|
||||
<div class="flex flex-1 flex-col gap-2 justify-center">
|
||||
<span class="text-lg font-bold group-hover:text-accent-blue">{{ character.name }}</span>
|
||||
<span class="border-b w-full border-light-50 dark:border-dark-50"></span>
|
||||
<div class="flex flex-row flex-1 items-stretch gap-4">
|
||||
<span class="text-sm">Niveau {{ character.level }}</span>
|
||||
<span class="w-px h-full bg-light-50 dark:bg-dark-50"></span>
|
||||
<span class="text-sm italic">{{ config.peoples[character.people!]?.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-full w-[96px] h-[96px] border border-light-50 dark:border-dark-50 bg-light-100 dark:bg-dark-100 !bg-opacity-10"></div>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
<div class="flex justify-around items-center py-2 px-4 gap-4">
|
||||
<NuxtLink :to="{ name: 'character-id-edit', params: { id: character.id } }" class="text-sm font-bold cursor-pointer hover:text-accent-blue">Editer</NuxtLink>
|
||||
<span class="w-px h-full bg-light-50 dark:bg-dark-50"></span>
|
||||
<NuxtLink @click="duplicateCharacter(character.id)" class="text-sm font-bold cursor-pointer hover:text-accent-blue">Dupliquer</NuxtLink>
|
||||
<span class="w-px h-full bg-light-50 dark:bg-dark-50"></span>
|
||||
<AlertDialogRoot>
|
||||
<AlertDialogTrigger>
|
||||
<span class="text-sm font-bold text-light-red dark:text-dark-red">Supprimer</span>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogPortal>
|
||||
<AlertDialogOverlay class="bg-light-0 dark:bg-dark-0 opacity-70 fixed inset-0 z-40" />
|
||||
<AlertDialogContent
|
||||
class="data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[800px] translate-x-[-50%] translate-y-[-50%] bg-light-10 dark:bg-dark-10 border border-light-30 dark:border-dark-30 p-6 z-50 text-light-100 dark:text-dark-100">
|
||||
<AlertDialogTitle class="text-3xl font-light relative -top-2">Supprimer {{ character.name }} ?</AlertDialogTitle>
|
||||
<div class="flex flex-1 justify-end gap-4">
|
||||
<AlertDialogCancel asChild><Button>Non</Button></AlertDialogCancel>
|
||||
<AlertDialogAction asChild><Button @click="() => deleteCharacter(character.id)" class="border-light-red dark:border-dark-red hover:border-light-red dark:hover:border-dark-red hover:bg-light-redBack dark:hover:bg-dark-redBack text-light-red dark:text-dark-red focus:shadow-light-red dark:focus:shadow-dark-red">Oui</Button></AlertDialogAction>
|
||||
</div>
|
||||
</AlertDialogContent>
|
||||
</AlertDialogPortal>
|
||||
</AlertDialogRoot>
|
||||
</div>
|
||||
<AlertDialogRoot>
|
||||
<!--
|
||||
<DropdownMenuRoot>
|
||||
<DropdownMenuTrigger class="self-start">
|
||||
<Button icon><Icon icon="radix-icons:dots-vertical" /></Button>
|
||||
@@ -84,7 +114,7 @@ async function duplicateCharacter(id: number)
|
||||
</div>
|
||||
</AlertDialogContent>
|
||||
</AlertDialogPortal>
|
||||
</AlertDialogRoot>
|
||||
</AlertDialogRoot> -->
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
|
||||
@@ -1,42 +1,113 @@
|
||||
<script setup lang="ts">
|
||||
import characterConfig from '#shared/character-config.json';
|
||||
import { Icon } from '@iconify/vue/dist/iconify.js';
|
||||
import type { CharacterConfig } from '~/types/character';
|
||||
import { FeatureEditor } from '~/shared/feature.util';
|
||||
import { confirm, fullblocker } from '~/shared/floating.util';
|
||||
import { getID, ID_SIZE } from '~/shared/general.util';
|
||||
import type { CharacterConfig, Feature } from '~/types/character';
|
||||
|
||||
//@ts-ignore
|
||||
const config = ref<CharacterConfig>(characterConfig);
|
||||
const featureEditor = new FeatureEditor();
|
||||
|
||||
function copy()
|
||||
{
|
||||
navigator.clipboard.writeText(JSON.stringify(config.value));
|
||||
}
|
||||
|
||||
function createFeature()
|
||||
{
|
||||
const feature: Feature = { id: getID(ID_SIZE), description: '', effect: [] };
|
||||
|
||||
featureEditor.edit(feature).then(feature => {
|
||||
config.value.features[feature.id] = feature;
|
||||
}).catch(() => {}).finally(() => {
|
||||
setTimeout(popup.close, 150);
|
||||
featureEditor.container.setAttribute('data-state', 'inactive');
|
||||
});
|
||||
|
||||
const popup = fullblocker([featureEditor.container], {
|
||||
priority: true, closeWhenOutside: false,
|
||||
});
|
||||
featureEditor.container.setAttribute('data-state', 'active');
|
||||
}
|
||||
function editFeature(id: string)
|
||||
{
|
||||
config.value.features[id] && featureEditor.edit(config.value.features[id]).then(feature => {
|
||||
config.value.features[id] = feature;
|
||||
}).catch(() => {}).finally(() => {
|
||||
setTimeout(popup.close, 150);
|
||||
featureEditor.container.setAttribute('data-state', 'inactive');
|
||||
});
|
||||
|
||||
const popup = fullblocker([featureEditor.container], {
|
||||
priority: true, closeWhenOutside: false,
|
||||
});
|
||||
featureEditor.container.setAttribute('data-state', 'active');
|
||||
}
|
||||
function deleteFeature(id: string)
|
||||
{
|
||||
confirm("Voulez vous vraiment supprimer cet effet ?").then(e => {
|
||||
if(e)
|
||||
{
|
||||
const value = config.value;
|
||||
delete value.features[id];
|
||||
config.value = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head>
|
||||
<Title>d[any] - Edition de données</Title>
|
||||
</Head>
|
||||
<TabsRoot class="flex flex-1 max-w-full flex-col gap-8 justify-start items-center px-8 w-full" default-value="training">
|
||||
<TabsRoot class="flex flex-1 max-w-full flex-col gap-8 justify-start items-center px-8 w-full" default-value="features">
|
||||
<TabsList class="flex flex-row gap-4 self-center relative px-4">
|
||||
<TabsIndicator class="absolute left-0 h-[3px] bottom-0 w-[--radix-tabs-indicator-size] translate-x-[--radix-tabs-indicator-position] transition-[width,transform] duration-300 bg-accent-blue"></TabsIndicator>
|
||||
<TabsTrigger value="peoples" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Peuples</TabsTrigger>
|
||||
<TabsTrigger value="peoples" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Peuples ({{ config.peoples.length }})</TabsTrigger>
|
||||
<TabsTrigger value="training" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Entrainement</TabsTrigger>
|
||||
<TabsTrigger value="abilities" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Compétences</TabsTrigger>
|
||||
<TabsTrigger value="spells" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Sorts</TabsTrigger>
|
||||
<TabsTrigger value="abilities" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Compétences ({{ Object.keys(config.abilities).length }})</TabsTrigger>
|
||||
<TabsTrigger value="aspects" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Aspects ({{ config.aspects.length }})</TabsTrigger>
|
||||
<TabsTrigger value="spells" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Sorts ({{ config.spells.length }})</TabsTrigger>
|
||||
<TabsTrigger value="features" class="px-2 py-1 border-b border-transparent hover:border-accent-blue">Features ({{ Object.keys(config.features).length }})</TabsTrigger>
|
||||
<Tooltip message="Copier le JSON" side="right"><Button icon @click="copy" class="p-2"><Icon icon="radix-icons:clipboard-copy" /></Button></Tooltip>
|
||||
</TabsList>
|
||||
<div class="flex-1 outline-none max-w-full w-full">
|
||||
<TabsContent value="peoples">
|
||||
</TabsContent>
|
||||
<TabsContent value="training">
|
||||
<TrainingConfigEditor :config="config" />
|
||||
</TabsContent>
|
||||
<TabsContent value="abilities">
|
||||
|
||||
</TabsContent>
|
||||
<TabsContent value="spells">
|
||||
|
||||
</TabsContent>
|
||||
<div class="flex flex-row outline-none max-w-full w-full relative overflow-hidden">
|
||||
<div class="flex flex-1 outline-none max-w-full overflow-hidden">
|
||||
<TabsContent value="peoples" class="outline-none flex gap-4 flex-col overflow-hidden">
|
||||
<div class=""></div>
|
||||
</TabsContent>
|
||||
<TabsContent value="training" class="outline-none flex gap-4 flex-col overflow-hidden">
|
||||
<div class=""></div>
|
||||
</TabsContent>
|
||||
<TabsContent value="abilities" class="outline-none flex gap-4 flex-col overflow-hidden">
|
||||
<div class=""></div>
|
||||
</TabsContent>
|
||||
<TabsContent value="aspects" class="outline-none flex gap-4 flex-col overflow-hidden">
|
||||
<div class=""></div>
|
||||
</TabsContent>
|
||||
<TabsContent value="spells" class="outline-none flex gap-4 flex-col overflow-hidden">
|
||||
<div class=""></div>
|
||||
</TabsContent>
|
||||
<TabsContent value="features" class="outline-none flex gap-4 flex-col overflow-hidden">
|
||||
<div class="flex flex-col w-full gap-2 justify-end items-end relative">
|
||||
<Button icon @click="createFeature"><Icon icon="radix-icons:plus" class="w-6 h-6" /></Button>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 overflow-x-hidden pe-2">
|
||||
<div class="flex flex-row gap-2 w-full border-b border-light-35 dark:border-dark-35 pb-2" v-for="feature of config.features">
|
||||
<div class="w-full flex flex-row px-4 gap-8 items-center">
|
||||
<span class="font-mono">{{ feature.id }}</span>
|
||||
<span class="truncate">{{ feature.description }}</span>
|
||||
</div>
|
||||
<div class="flex flex-row gap-2 items-center">
|
||||
<Button icon @click="editFeature(feature.id)"><Icon icon="radix-icons:pencil-1" /></Button>
|
||||
<Button icon @click="deleteFeature(feature.id)"><Icon icon="radix-icons:trash" /></Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</div>
|
||||
</div>
|
||||
</TabsRoot>
|
||||
</template>
|
||||
Reference in New Issue
Block a user