Move visualiser to explorer folder and start working on account

This commit is contained in:
Peaceultime 2024-07-25 13:24:44 +02:00
parent a4729b8d84
commit 39299a268c
23 changed files with 242 additions and 12574 deletions

37
app.vue
View File

@ -1,14 +1,45 @@
<script lang="ts">
let icon: HTMLDivElement | null;
function toggleLeftPanel(_: Event): void {
document.querySelector('.published-container')?.classList.toggle('is-left-column-open');
}
</script>
<script setup lang="ts">
const { data: tags } = await useAsyncData('descriptions', queryContent('/tags').findOne);
provide('tags/descriptions', tags);
onMounted(() => {
icon = document.querySelector('.site-nav-bar .clickable-icon');
icon?.removeEventListener('click', toggleLeftPanel);
icon?.addEventListener('click', toggleLeftPanel);
})
</script>
<template>
<div class="published-container print has-navigation has-outline" style="">
<div class="published-container print has-navigation has-outline">
<div class="site-nav-bar">
<div>
<div class="clickable-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-menu">
<line x1="4" y1="12" x2="20" y2="12"></line>
<line x1="4" y1="6" x2="20" y2="6"></line>
<line x1="4" y1="18" x2="20" y2="18"></line>
</svg>
</div>
<NuxtLink class="site-name" aria-label="Accueil" :href="'/explorer'">Système Aspect</NuxtLink>
</div>
<div>
<SearchView />
</div>
<div class="ps-1">
<ThemeSwitch />
<Icon name="material-symbols:account-circle-outline" mode="svg" size="1.5em"/>
</div>
</div>
<div class="site-body">
<LeftComponent />
<MainComponent />
<NuxtPage />
</div>
</div>
</template>

50
assets/common.css Normal file
View File

@ -0,0 +1,50 @@
.ps-1
{
padding-left: 1em;
}
.pe-1
{
padding-right: 1em;
}
.pt-1
{
padding-top: 1em;
}
.pb-1
{
padding-bottom: 1em;
}
.ps-2
{
padding-left: 2em;
}
.pe-2
{
padding-right: 2em;
}
.pt-2
{
padding-top: 2em;
}
.pb-2
{
padding-bottom: 2em;
}
.ps-3
{
padding-left: 3em;
}
.pe-3
{
padding-right: 3em;
}
.pt-3
{
padding-top: 3em;
}
.pb-3
{
padding-bottom: 3em;
}

View File

@ -3316,9 +3316,8 @@ input[type='number'] {
height: 18px;
}
.site-header .search-view-outer {
width: 50%;
max-width: 240px;
.site-nav-bar .search-view-outer {
flex: 1 1 0;
order: 1;
}
@ -3332,7 +3331,7 @@ input[type='number'] {
margin: 0;
width: 0;
flex-grow: 1;
padding-left: 30px;
padding-left: 14px;
}
.search-view-container .search-bar.has-no-results {
@ -3463,7 +3462,6 @@ input[type='number'] {
}
.site-body-left-column-site-theme-toggle {
padding: 0 0 12px 0;
display: flex;
position: relative;
}
@ -3800,10 +3798,6 @@ body {
-webkit-user-select: none;
}
.published-container.has-navigation .site-header {
display: none;
}
.published-container .markdown-preview-view {
user-select: text;
}
@ -3852,11 +3846,11 @@ body {
}
@media screen and (min-width: 750px) {
.published-container.is-readable-line-width:not(.has-navigation).published-container.is-readable-line-width:not(.has-graph).published-container.is-readable-line-width:not(.has-outline) .site-header {
.published-container.is-readable-line-width:not(.has-navigation).published-container.is-readable-line-width:not(.has-graph).published-container.is-readable-line-width:not(.has-outline) .site-nav-bar {
width: var(--page-width);
margin: 0 auto;
border-bottom: 0;
padding: 24px 48px;
padding: .5em 3em;
}
.published-container.is-readable-line-width:not(.has-navigation).published-container.is-readable-line-width:not(.has-graph).published-container.is-readable-line-width:not(.has-outline) .site-body-center-column {
@ -3926,8 +3920,7 @@ body {
/* Nav view */
.nav-view-outer {
overflow: auto;
padding-bottom: 32px;
padding-top: 10px;
padding: 12px 18px 0 36px;
scrollbar-gutter: stable;
}
@ -4147,7 +4140,6 @@ body {
width: var(--sidebar-left-width);
flex: 0 0 var(--sidebar-left-width);
min-width: var(--sidebar-left-width);
padding: 32px 18px 0 36px;
position: relative;
display: flex;
background-color: var(--sidebar-left-background);
@ -4192,19 +4184,18 @@ body {
object-fit: contain;
}
.site-body-left-column-site-name {
.site-name {
color: var(--site-name-color);
font-size: var(--site-name-size);
font-weight: var(--site-name-weight);
z-index: 1;
cursor: pointer;
line-height: 1.2;
padding: 4px 32px 32px 0;
text-decoration: none;
}
@media (hover: hover) {
.site-body-left-column-site-name:hover {
.site-name:hover {
color: var(--site-name-color-hover);
text-decoration: none;
}
@ -4277,26 +4268,15 @@ body {
}
}
.site-header {
display: flex;
font-size: var(--site-name-size);
line-height: 1.3;
height: var(--header-height);
padding: 12px 18px;
border-bottom: 1px solid var(--background-modifier-border);
align-items: center;
flex: 0 0 auto;
}
.site-header .clickable-icon {
.site-nav-bar .clickable-icon {
display: none;
}
.site-header .clickable-icon svg {
.site-nav-bar .clickable-icon svg {
vertical-align: middle;
}
.site-header-logo img {
.site-nav-bar-logo img {
border-radius: var(--logo-radius);
max-height: calc(var(--header-height) - 10px);
width: var(--logo-width);
@ -4306,7 +4286,7 @@ body {
object-fit: contain;
}
.site-header-text {
.site-nav-bar-text {
color: var(--site-name-color);
cursor: pointer;
font-size: var(--site-name-size);
@ -4315,7 +4295,7 @@ body {
text-decoration: none;
}
.site-header-text:hover {
.site-nav-bar-text:hover {
color: var(--site-name-color-hover);
}
@ -4780,7 +4760,7 @@ body {
z-index: -1;
}
.published-container.has-navigation .site-header {
.published-container.has-navigation .site-nav-bar {
display: flex;
z-index: 90;
background-color: var(--header-background);
@ -4789,7 +4769,7 @@ body {
/* Hamburger menu icon */
}
.published-container.has-navigation .site-header .clickable-icon {
.published-container.has-navigation .site-nav-bar .clickable-icon {
display: flex;
align-items: center;
color: var(--site-menu-icon-color);
@ -4798,7 +4778,7 @@ body {
margin-right: 6px;
}
.published-container.has-navigation .site-header .clickable-icon svg {
.published-container.has-navigation .site-nav-bar .clickable-icon svg {
width: var(--site-menu-icon-size);
height: var(--site-menu-icon-size);
stroke-width: 1.2px;
@ -4985,3 +4965,21 @@ body {
.callout.is-collapsed .fold {
transform: rotate(-90deg);
}
.site-nav-bar {
border-bottom: 1px solid var(--background-modifier-border);
display: flex;
justify-content: space-between;
align-items: center;
padding: .5em 3em;
}
.site-nav-bar > div {
flex: 1 1 0;
display: flex;
flex-direction: row;
}
.site-nav-bar > div:last-child {
justify-content: end;
}

View File

@ -1,15 +1,9 @@
<template>
<div class="site-body-left-column">
<div class="site-body-left-column-inner">
<NuxtLink class="site-body-left-column-site-name" aria-label="Accueil" :href="'/'">Système Aspect</NuxtLink>
<ThemeSwitch />
<SearchView />
<div class="nav-view-outer">
<div class="nav-view">
<div class="tree-item">
<div class="tree-item-self mod-root is-clickable" data-path="">
<div class="tree-item-inner"></div>
</div>
<div class="tree-item-children">
<ContentNavigation v-slot="{ navigation }">
<NavigationLink v-if="!!navigation" v-for="link of navigation.filter(e => !['/tags', '/'].includes(e?._path ?? ''))" :link="link" />

View File

@ -1,16 +0,0 @@
<template>
<div class="site-body-center-column">
<div class="site-header">
<div class="clickable-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-menu">
<line x1="4" y1="12" x2="20" y2="12"></line>
<line x1="4" y1="6" x2="20" y2="6"></line>
<line x1="4" y1="18" x2="20" y2="18"></line>
</svg>
</div>
</div>
<div class="render-container">
<NuxtPage />
</div>
</div>
</template>

View File

@ -30,8 +30,8 @@ const results = computed(() => {
</div>
</div>
<Teleport to="body" v-if="input !== ''">
<div class="search-results" :style="{top: (pos.bottom + 4) + 'px', left: pos.left + 'px'}">
<div class="suggestion-item" v-if="results.length > 0" v-for="result of results" :key="result._path" @mouseenter="(e) => (e.target as HTMLElement).classList.add('is-selected')" @mouseleave="(e) => (e.target as HTMLElement).classList.remove('is-selected')" @mousedown="navigateTo(result._path); input = ''">
<div class="search-results" :style="{top: (pos.bottom + 4) + 'px', left: pos.left + 'px', width: pos.width + 'px'}">
<div class="suggestion-item" v-if="results.length > 0" v-for="result of results" :key="result._path" @mouseenter="(e) => (e.target as HTMLElement).classList.add('is-selected')" @mouseleave="(e) => (e.target as HTMLElement).classList.remove('is-selected')" @mousedown="navigateTo('/explorer' + result._path); input = ''">
<div class="suggestion-content">
<div class="suggestion-title">
{{ result.title.substring(0, clear(result.title).indexOf(clear(input))) }}<span class="suggestion-highlight">{{ result.title.substring(clear(result.title).indexOf(clear(input)), clear(result.title).indexOf(clear(input)) + clear(input).length + 1) }}</span>{{ result.title.substring(clear(result.title).indexOf(clear(input)) + clear(input).length + 1) }}

View File

@ -2,6 +2,8 @@
import type { MarkdownRoot, ParsedContent, TocLink } from '@nuxt/content/dist/runtime/types';
import type { Canvas, CanvasContent } from '~/types/canvas';
import { stringifyParsedURL, type ParsedURL } from 'ufo';
interface ParsedContentExtended extends Omit<ParsedContent, 'body'> {
body: MarkdownRoot | CanvasContent | null;
}
@ -31,6 +33,7 @@ function flatten(val: TocLink[]): TocLink[] {
return val.flatMap ? val?.flatMap((e: TocLink) => e.children ? [e, ...flatten(e.children)] : e) : val;
}
function handleResult(result: ParsedContentExtended, tag: boolean = false) {
console.log();
loading.value = false;
let body: MarkdownRoot | CanvasContent | null = JSON.parse(JSON.stringify(result.body));
@ -120,9 +123,9 @@ function hidePreview(e: Event) {
<template >
<template v-if="href !== ''">
<NuxtLink custom no-prefetch v-slot="{ href: hrefSlot, navigate }" :href="isTag ? { path: '/tags/' + anchor.substring(1) } : { path: content?._path ?? link, hash: anchor }" :target="target">
<a :href="hrefSlot" @click="navigate" @mouseenter="(e) => showPreview(e, true)" @mouseleave="hidePreview" v-bind="$attrs"><slot></slot></a>
</NuxtLink>
<a @mouseenter="(e) => showPreview(e, true)" @mouseleave="hidePreview" v-bind="$attrs" :href="stringifyParsedURL({ host: '/explorer', pathname: content?._path ?? href, hash: anchor, search: '' })" :target="target">
<slot></slot>
</a>
<Teleport to="body" v-if="hovered && (loading || !!content)">
<div class="popover hover-popover is-loaded" :style="pos" @mouseenter="(e) => showPreview(e, false)" @mouseleave="hidePreview">
<template v-if="!!content">

View File

@ -5,8 +5,6 @@ interface NavItem {
_id?: string
_draft?: boolean
children?: NavItem[]
[key: string]: any
}
interface Props {
link: NavItem;
@ -29,6 +27,11 @@ if(hasChildren.value)
}
const collapsed = ref(!useRoute().path.startsWith(props.link._path));
function hideLeftPanel(_: Event)
{
document?.querySelector('.published-container')?.classList.remove('is-left-column-open');
}
</script>
<template>
@ -48,8 +51,8 @@ const collapsed = ref(!useRoute().path.startsWith(props.link._path));
<NavigationLink v-if="hasChildren" v-for="l of link.children" :link="l"/>
</div>
</template>
<NuxtLink v-else class="tree-item-self" :to="link._path" :active-class="'mod-active'">
<div class="tree-item-inner">{{ link.title }}<span v-if="link"></span></div>
<NuxtLink @click="hideLeftPanel" v-else class="tree-item-self" :to="'/explorer' + link._path" :active-class="'mod-active'">
<div class="tree-item-inner">{{ link.title }}</div>
</NuxtLink>
</div>
</template>

View File

@ -1,5 +1,9 @@
<script setup lang="ts">
const { toc } = useContent()
interface Props
{
toc: Toc;
}
const props = defineProps<Props>();
</script>
<template>

View File

@ -3,11 +3,17 @@ import CanvasModule from './transformer/canvas/module'
export default defineNuxtConfig({
modules: [CanvasModule, "@nuxt/content", "@nuxtjs/color-mode"],
css: ['~/assets/global.css'],
content: {
documentDriven: {
injectPage: true,
components: [
{
path: '~/components',
pathPrefix: false,
},
],
css: ['~/assets/common.css', '~/assets/global.css'],
content: {
ignores: [
'98.Privé'
],
@ -43,5 +49,13 @@ export default defineNuxtConfig({
cdnURL: "https://git.peaceultime.com/",
}
}
}
},
vite: {
vue: {
customElement: ['Line', 'Circle', 'Path']
}
},
compatibilityDate: '2024-07-25'
})

12414
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
{
"name": "nuxt-app",
"private": true,
"type": "module",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"devDependencies": {
"@nuxt/content": "^2.10.0",
"@nuxtjs/color-mode": "^3.3.2",
"nuxt": "^3.9.0",
"three": "^0.160.0",
"vue": "^3.4.3",
"vue-router": "^4.2.5"
},
"dependencies": {
"hast-util-to-html": "^9.0.0",
"remark-breaks": "^4.0.0",
"remark-ofm": "file:../remark-ofm"
}
}

View File

@ -1,63 +1,11 @@
<script lang="ts">
let icon: HTMLDivElement | null;
function toggleLeftPanel(_: Event) {
icon!.parentElement!.parentElement!.parentElement!.parentElement!.classList.toggle('is-left-column-open');
}
</script>
<script setup lang="ts">
const { page } = useContent()
useContentHead(page);
onMounted(() => {
document.querySelectorAll('.callout.is-collapsible .callout-title').forEach(e => {
e.addEventListener('click', (_) => {
e.parentElement!.classList.toggle('is-collapsed');
})
})
icon = document.querySelector('.site-header .clickable-icon');
icon?.removeEventListener('click', toggleLeftPanel);
icon?.addEventListener('click', toggleLeftPanel);
document.querySelector(".published-container")?.classList.toggle('is-readable-line-width', !page.value || page.value._type !== 'canvas');
})
</script>
<template>
<template v-if="!!page && page._type == 'markdown' && page.body.children.length > 0">
<div class="render-container-inner">
<div class="publish-renderer">
<div class="markdown-preview-view markdown-rendered node-insert-event hide-title">
<div class="markdown-preview-sizer markdown-preview-section" style="padding-bottom: 0px;">
<h1 v-if="!(page as MarkdownParsedContent).body.children.find((e: MarkdownNode) => e.tag === 'h1')">{{(page as MarkdownParsedContent).title}}</h1>
<ContentRenderer :key="page._id" :value="page" />
</div>
</div>
<div class="extra-title">
<span class="extra-title-text">Home</span>
<span aria-label="Close page" role="button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-x">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</span>
</div>
<div class="site-body-center-column">
<div class="render-container">
<div class="not-found-container">
<div class="not-found-image"></div>
<div class="not-found-title">Introuvable</div>
<div class="not-found-description">Cette page n'existe pas</div>
</div>
</div>
<RightComponent />
</template>
<CanvasRenderer v-else-if="!!page && page._type == 'canvas'" :key="page._id" :canvas="page" />
<div v-else-if="!!page">
<div class="not-found-container">
<div class="not-found-image"></div>
<div class="not-found-title">Impossible d'afficher (ou vide)</div>
<div class="not-found-description">Cette page est actuellement vide ou impossible à traiter</div>
</div>
</div>
<div v-else class="not-found-container">
<div class="not-found-image"></div>
<div class="not-found-title">Introuvable</div>
<div class="not-found-description">Cette page n'existe pas</div>
</div>
</template>

View File

@ -0,0 +1,74 @@
<script lang="ts">
let icon: HTMLDivElement | null;
function toggleLeftPanel(_: Event) {
icon!.parentElement!.parentElement!.parentElement!.parentElement!.classList.toggle('is-left-column-open');
}
</script>
<script setup lang="ts">
const { hash, path } = useRoute();
const { data: page } = await useAsyncData('home', queryContent(path.substring(path.indexOf('/explorer') + '/explorer'.length)).findOne);
if(page.value)
useContentHead(page.value!);
if(hash)
{
console.log(document.getElementById(hash.substring(1)));
document.getElementById(hash.substring(1))?.scrollTo({ behavior: 'smooth', top: 100 });
}
onMounted(() => {
document.querySelectorAll('.callout.is-collapsible .callout-title').forEach(e => {
e.addEventListener('click', (_) => {
e.parentElement!.classList.toggle('is-collapsed');
})
})
document.querySelector(".published-container")?.classList.toggle('is-readable-line-width', !page.value || page.value._type !== 'canvas');
})
</script>
<template>
<LeftComponent />
<div class="site-body-center-column">
<div class="render-container">
<template v-if="!!page && page._type == 'markdown' && page.body.children.length > 0">
<div class="render-container-inner">
<div class="publish-renderer">
<div class="markdown-preview-view markdown-rendered node-insert-event hide-title">
<div class="markdown-preview-sizer markdown-preview-section" style="padding-bottom: 0px;">
<h1 v-if="!(page as MarkdownParsedContent).body.children.find((e: MarkdownNode) => e.tag === 'h1')">{{(page as MarkdownParsedContent).title}}</h1>
<ContentRenderer :key="page._id" :value="page" />
</div>
</div>
<div class="extra-title">
<span class="extra-title-text">Home</span>
<span aria-label="Close page" role="button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-x">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</span>
</div>
</div>
</div>
<RightComponent v-if="page.body?.toc" :toc="page?.body?.toc" />
</template>
<CanvasRenderer v-else-if="!!page && page._type == 'canvas'" :key="page._id" :canvas="page" />
<div v-else-if="!!page">
<div class="not-found-container">
<div class="not-found-image"></div>
<div class="not-found-title">Impossible d'afficher (ou vide)</div>
<div class="not-found-description">Cette page est actuellement vide ou impossible à traiter</div>
</div>
</div>
<div v-else class="not-found-container">
<div class="not-found-image"></div>
<div class="not-found-title">Introuvable</div>
<div class="not-found-description">Cette page n'existe pas</div>
</div>
</div>
</div>
</template>

View File

@ -68,7 +68,7 @@ onMounted(() => {
<ContentRenderer :value="getContent(descriptions)" />
<h2>Pages contenant le tag</h2>
<div class="card-container">
<NuxtLink :key="item._id" :href="item._path" v-for="item of list" class="tag"> {{ item.title }} </NuxtLink>
<NuxtLink :key="item._id" :href="'/explorer' + item._path" v-for="item of list" class="tag"> {{ item.title }} </NuxtLink>
</div>
</div>
</div>

1
pages/user/login.vue Normal file
View File

@ -0,0 +1 @@
<template></template>

1
pages/user/logout.vue Normal file
View File

@ -0,0 +1 @@
<template></template>

1
pages/user/profile.vue Normal file
View File

@ -0,0 +1 @@
<template></template>

1
pages/user/signin.vue Normal file
View File

@ -0,0 +1 @@
<template></template>