feat: add help and about pages with sidebar navigation buttons
This commit is contained in:
parent
eeb957cf17
commit
698bfef3d8
@ -29,6 +29,7 @@
|
||||
(searchOptionsChange)="onHeaderSearchOptionsChange($event)"
|
||||
(markdownPlaygroundSelected)="setView('markdown-playground')"
|
||||
(parametersOpened)="setView('parameters')"
|
||||
(helpPageRequested)="openHelpPage()"
|
||||
></app-shell-nimbus-layout>
|
||||
} @else {
|
||||
<main class="relative flex min-h-screen flex-col bg-bg-main text-text-main lg:flex-row lg:h-screen lg:overflow-hidden">
|
||||
|
||||
@ -878,6 +878,19 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
async openHelpPage(): Promise<void> {
|
||||
// Load the help.md file from the vault
|
||||
const helpPath = 'help.md';
|
||||
await this.vaultService.ensureNoteLoadedByPath(helpPath);
|
||||
const helpNoteId = this.vaultService.buildSlugIdFromPath(helpPath);
|
||||
const helpNote = this.vaultService.getNoteById(helpNoteId);
|
||||
|
||||
if (helpNote) {
|
||||
this.selectNote(helpNote.id);
|
||||
this.logService.log('HELP_PAGE_OPEN');
|
||||
}
|
||||
}
|
||||
|
||||
async selectNote(noteId: string): Promise<void> {
|
||||
let note = this.vaultService.getNoteById(noteId);
|
||||
if (!note) {
|
||||
|
||||
131
src/app/features/about/about-panel.component.ts
Normal file
131
src/app/features/about/about-panel.component.ts
Normal file
@ -0,0 +1,131 @@
|
||||
import { Component, EventEmitter, Output, ChangeDetectionStrategy, HostListener } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { trigger, transition, style, animate } from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
selector: 'app-about-panel',
|
||||
standalone: true,
|
||||
imports: [CommonModule],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
animations: [
|
||||
trigger('fadeInOut', [
|
||||
transition(':enter', [
|
||||
style({ opacity: 0 }),
|
||||
animate('200ms ease-in', style({ opacity: 1 }))
|
||||
]),
|
||||
transition(':leave', [
|
||||
animate('200ms ease-out', style({ opacity: 0 }))
|
||||
])
|
||||
]),
|
||||
trigger('scaleIn', [
|
||||
transition(':enter', [
|
||||
style({ opacity: 0, transform: 'scale(0.95)' }),
|
||||
animate('200ms ease-out', style({ opacity: 1, transform: 'scale(1)' }))
|
||||
]),
|
||||
transition(':leave', [
|
||||
animate('150ms ease-in', style({ opacity: 0, transform: 'scale(0.95)' }))
|
||||
])
|
||||
])
|
||||
],
|
||||
template: `
|
||||
<!-- Backdrop -->
|
||||
<div
|
||||
@fadeInOut
|
||||
class="fixed inset-0 bg-black/60 backdrop-blur-sm z-50 flex items-center justify-center p-4"
|
||||
(click)="onBackdropClick()">
|
||||
|
||||
<!-- Panel -->
|
||||
<div
|
||||
@scaleIn
|
||||
class="bg-card dark:bg-main border border-border dark:border-gray-700 rounded-2xl shadow-2xl max-w-lg w-full p-8 relative"
|
||||
(click)="$event.stopPropagation()">
|
||||
|
||||
<!-- Close button -->
|
||||
<button
|
||||
type="button"
|
||||
class="absolute top-4 right-4 w-8 h-8 rounded-full hover:bg-surface1 dark:hover:bg-card transition-colors flex items-center justify-center text-muted hover:text-main"
|
||||
(click)="close.emit()"
|
||||
aria-label="Fermer">
|
||||
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M18 6 6 18" />
|
||||
<path d="m6 6 12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="text-center space-y-6">
|
||||
<!-- Logo/Icon -->
|
||||
<div class="flex justify-center">
|
||||
<div class="w-20 h-20 rounded-2xl bg-gradient-to-br from-nimbus-400 to-nimbus-600 flex items-center justify-center text-4xl shadow-lg">
|
||||
📖
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- App Name -->
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-main dark:text-white mb-2">ObsiViewer</h1>
|
||||
<p class="text-sm text-muted">Version {{ version }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Description -->
|
||||
<p class="text-base text-main dark:text-gray-300 leading-relaxed">
|
||||
Visualiseur moderne et élégant pour vos notes Obsidian.
|
||||
Explorez, éditez et organisez vos connaissances avec une interface intuitive.
|
||||
</p>
|
||||
|
||||
<!-- Author -->
|
||||
<div class="pt-4 border-t border-border dark:border-gray-700">
|
||||
<p class="text-sm text-muted">
|
||||
Créé par <span class="font-semibold text-main dark:text-white">Bruno Charest</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Credits -->
|
||||
<div class="text-xs text-muted space-y-1">
|
||||
<p class="font-semibold text-main dark:text-gray-300 mb-2">Technologies utilisées</p>
|
||||
<div class="flex flex-wrap justify-center gap-2">
|
||||
<span class="px-3 py-1 bg-surface1 dark:bg-card rounded-full">Angular 20</span>
|
||||
<span class="px-3 py-1 bg-surface1 dark:bg-card rounded-full">TailwindCSS</span>
|
||||
<span class="px-3 py-1 bg-surface1 dark:bg-card rounded-full">CodeMirror 6</span>
|
||||
<span class="px-3 py-1 bg-surface1 dark:bg-card rounded-full">Markdown-it</span>
|
||||
<span class="px-3 py-1 bg-surface1 dark:bg-card rounded-full">Lucide Icons</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- GitHub Link (optional) -->
|
||||
<div class="pt-4">
|
||||
<a
|
||||
href="https://github.com/brunoCharest/ObsiViewer"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-flex items-center gap-2 text-sm text-nimbus-600 dark:text-nimbus-400 hover:text-nimbus-700 dark:hover:text-nimbus-300 transition-colors">
|
||||
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
||||
</svg>
|
||||
Voir sur GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
styles: [`
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class AboutPanelComponent {
|
||||
@Output() close = new EventEmitter<void>();
|
||||
|
||||
readonly version = '1.0.0';
|
||||
|
||||
@HostListener('document:keydown.escape')
|
||||
onEscapeKey(): void {
|
||||
this.close.emit();
|
||||
}
|
||||
|
||||
onBackdropClick(): void {
|
||||
this.close.emit();
|
||||
}
|
||||
}
|
||||
@ -105,6 +105,24 @@ import { TrashExplorerComponent } from '../../layout/sidebar/trash/trash-explore
|
||||
</ng-template>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Help & About section -->
|
||||
<section class="border-b border-border dark:border-gray-800">
|
||||
<div class="px-2 py-2 space-y-1">
|
||||
<button
|
||||
(click)="onHelpPageClick()"
|
||||
class="w-full text-left flex items-center gap-2 px-3 py-2 text-sm rounded-lg hover:bg-surface1 dark:hover:bg-card active:bg-surface2 dark:active:bg-gray-700 transition-all active:scale-[0.98] transform">
|
||||
<span>🆘</span>
|
||||
<span>Help Page</span>
|
||||
</button>
|
||||
<button
|
||||
(click)="onAboutClick()"
|
||||
class="w-full text-left flex items-center gap-2 px-3 py-2 text-sm rounded-lg hover:bg-surface1 dark:hover:bg-card active:bg-surface2 dark:active:bg-gray-700 transition-all active:scale-[0.98] transform">
|
||||
<span>ℹ️</span>
|
||||
<span>About</span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
@ -136,6 +154,8 @@ export class AppSidebarDrawerComponent {
|
||||
@Output() tagSelected = new EventEmitter<string>();
|
||||
@Output() quickLinkSelected = new EventEmitter<string>();
|
||||
@Output() markdownPlaygroundSelected = new EventEmitter<void>();
|
||||
@Output() helpPageSelected = new EventEmitter<void>();
|
||||
@Output() aboutSelected = new EventEmitter<void>();
|
||||
|
||||
open = { quick: true, folders: true, tags: false, trash: false, tests: true };
|
||||
|
||||
@ -165,6 +185,16 @@ export class AppSidebarDrawerComponent {
|
||||
this.mobileNav.sidebarOpen.set(false);
|
||||
}
|
||||
|
||||
onHelpPageClick(): void {
|
||||
this.helpPageSelected.emit();
|
||||
this.mobileNav.sidebarOpen.set(false);
|
||||
}
|
||||
|
||||
onAboutClick(): void {
|
||||
this.aboutSelected.emit();
|
||||
this.mobileNav.sidebarOpen.set(false);
|
||||
}
|
||||
|
||||
trashNotes = () => this.vault.trashNotes();
|
||||
trashCount = () => this.vault.counts().trash;
|
||||
trashHasContent = () => (this.vault.trashTree() || []).length > 0;
|
||||
|
||||
@ -112,6 +112,24 @@ import { VaultService } from '../../../services/vault.service';
|
||||
</ng-template>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Help & About section -->
|
||||
<section class="border-b border-border dark:border-gray-800">
|
||||
<div class="px-2 py-2 space-y-1">
|
||||
<button
|
||||
(click)="helpPageSelected.emit()"
|
||||
class="w-full text-left flex items-center gap-2 px-3 py-2 text-sm rounded-lg hover:bg-surface1 dark:hover:bg-card transition-colors">
|
||||
<span>🆘</span>
|
||||
<span>Help Page</span>
|
||||
</button>
|
||||
<button
|
||||
(click)="aboutSelected.emit()"
|
||||
class="w-full text-left flex items-center gap-2 px-3 py-2 text-sm rounded-lg hover:bg-surface1 dark:hover:bg-card transition-colors">
|
||||
<span>ℹ️</span>
|
||||
<span>About</span>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Footer placeholder -->
|
||||
@ -131,6 +149,8 @@ export class NimbusSidebarComponent {
|
||||
@Output() tagSelected = new EventEmitter<string>();
|
||||
@Output() quickLinkSelected = new EventEmitter<string>();
|
||||
@Output() markdownPlaygroundSelected = new EventEmitter<void>();
|
||||
@Output() helpPageSelected = new EventEmitter<void>();
|
||||
@Output() aboutSelected = new EventEmitter<void>();
|
||||
|
||||
env = environment;
|
||||
open = { quick: true, folders: true, tags: false, trash: false, tests: true };
|
||||
|
||||
@ -17,11 +17,12 @@ import { QuickLinksComponent } from '../../features/quick-links/quick-links.comp
|
||||
import { ScrollableOverlayDirective } from '../../shared/overlay-scrollbar/scrollable-overlay.directive';
|
||||
import { MarkdownPlaygroundComponent } from '../../features/tests/markdown-playground/markdown-playground.component';
|
||||
import { ParametersPage } from '../../features/parameters/parameters.page';
|
||||
import { AboutPanelComponent } from '../../features/about/about-panel.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shell-nimbus-layout',
|
||||
standalone: true,
|
||||
imports: [CommonModule, FileExplorerComponent, NoteViewerComponent, AppBottomNavigationComponent, AppSidebarDrawerComponent, AppTocOverlayComponent, SwipeNavDirective, NotesListComponent, NimbusSidebarComponent, QuickLinksComponent, ScrollableOverlayDirective, MarkdownPlaygroundComponent, ParametersPage],
|
||||
imports: [CommonModule, FileExplorerComponent, NoteViewerComponent, AppBottomNavigationComponent, AppSidebarDrawerComponent, AppTocOverlayComponent, SwipeNavDirective, NotesListComponent, NimbusSidebarComponent, QuickLinksComponent, ScrollableOverlayDirective, MarkdownPlaygroundComponent, ParametersPage, AboutPanelComponent],
|
||||
template: `
|
||||
<div class="relative h-screen flex flex-col bg-card dark:bg-main text-main dark:text-gray-100">
|
||||
|
||||
@ -62,6 +63,8 @@ import { ParametersPage } from '../../features/parameters/parameters.page';
|
||||
(tagSelected)="onTagSelected($event)"
|
||||
(quickLinkSelected)="onQuickLink($event)"
|
||||
(markdownPlaygroundSelected)="onMarkdownPlaygroundSelected()"
|
||||
(helpPageSelected)="onHelpPageSelected()"
|
||||
(aboutSelected)="onAboutSelected()"
|
||||
/>
|
||||
</aside>
|
||||
</ng-container>
|
||||
@ -209,6 +212,8 @@ import { ParametersPage } from '../../features/parameters/parameters.page';
|
||||
(tagSelected)="onTagSelected($event)"
|
||||
(quickLinkSelected)="onQuickLink($event)"
|
||||
(markdownPlaygroundSelected)="onMarkdownPlaygroundSelected()"
|
||||
(helpPageSelected)="onHelpPageSelected()"
|
||||
(aboutSelected)="onAboutSelected()"
|
||||
></app-sidebar-drawer>
|
||||
|
||||
@if (mobileNav.activeTab() === 'list') {
|
||||
@ -244,6 +249,9 @@ import { ParametersPage } from '../../features/parameters/parameters.page';
|
||||
|
||||
<app-bottom-navigation></app-bottom-navigation>
|
||||
</div>
|
||||
|
||||
<!-- About Panel Overlay -->
|
||||
<app-about-panel *ngIf="showAboutPanel" (close)="showAboutPanel = false"></app-about-panel>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
@ -254,6 +262,7 @@ export class AppShellNimbusLayoutComponent {
|
||||
mobileNav = inject(MobileNavService);
|
||||
|
||||
noteFullScreen = false;
|
||||
showAboutPanel = false;
|
||||
|
||||
@Input() vaultName = '';
|
||||
@Input() effectiveFileTree: VaultNode[] = [];
|
||||
@ -283,6 +292,7 @@ export class AppShellNimbusLayoutComponent {
|
||||
@Output() searchOptionsChange = new EventEmitter<any>();
|
||||
@Output() markdownPlaygroundSelected = new EventEmitter<void>();
|
||||
@Output() parametersOpened = new EventEmitter<void>();
|
||||
@Output() helpPageRequested = new EventEmitter<void>();
|
||||
|
||||
folderFilter: string | null = null;
|
||||
listQuery: string = '';
|
||||
@ -489,4 +499,12 @@ export class AppShellNimbusLayoutComponent {
|
||||
this.navigateHeading.emit(headingId);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
onHelpPageSelected(): void {
|
||||
this.helpPageRequested.emit();
|
||||
}
|
||||
|
||||
onAboutSelected(): void {
|
||||
this.showAboutPanel = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,7 +14,8 @@ export type LogEvent =
|
||||
| 'CALENDAR_SEARCH_EXECUTED'
|
||||
| 'THEME_CHANGE'
|
||||
| 'THEME_MODE_CHANGE'
|
||||
| 'LANGUAGE_CHANGE';
|
||||
| 'LANGUAGE_CHANGE'
|
||||
| 'HELP_PAGE_OPEN';
|
||||
|
||||
export interface LogContext {
|
||||
route?: string;
|
||||
|
||||
43
vault/help.md
Normal file
43
vault/help.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
titre: Guide d'utilisateur
|
||||
auteur: Bruno Charest
|
||||
creation_date: 2025-10-21
|
||||
modification_date: 2025-10-21T22:42:09-04:00
|
||||
catégorie: documentation
|
||||
tags:
|
||||
- aide
|
||||
- guide
|
||||
aliases: []
|
||||
status: publié
|
||||
publish: false
|
||||
favoris: false
|
||||
template: false
|
||||
task: false
|
||||
archive: false
|
||||
draft: false
|
||||
private: false
|
||||
---
|
||||
# 🧭 Guide d'utilisateur ObsiViewer
|
||||
|
||||
Bienvenue dans **ObsiViewer** !
|
||||
|
||||
Ce guide vous aidera à comprendre les principales fonctionnalités :
|
||||
|
||||
## 📂 Navigation
|
||||
- La barre latérale permet d'accéder aux notes, favoris, tags et modèles.
|
||||
- Les boutons en haut à droite donnent accès au mode édition, plein écran, et propriétés.
|
||||
|
||||
## ✏️ Édition
|
||||
- Le bouton ✏️ ouvre le **mode édition** basé sur CodeMirror 6.
|
||||
- Toutes les modifications sont sauvegardées automatiquement.
|
||||
|
||||
## 🏷️ Tags
|
||||
- Cliquez sur un tag pour voir toutes les notes qui le contiennent.
|
||||
- Utilisez l'icône 🏷️ à gauche pour modifier ou ajouter des tags.
|
||||
|
||||
## ⚙️ Paramètres
|
||||
- Les thèmes, langues et préférences sont gérés depuis le menu principal.
|
||||
|
||||
---
|
||||
|
||||
💡 **Astuce :** vous pouvez mettre à jour ce guide directement depuis votre voute Markdown.
|
||||
36
vault/help.md.bak
Normal file
36
vault/help.md.bak
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
titre: Guide d'utilisateur
|
||||
auteur: Bruno Charest
|
||||
creation_date: 2025-10-21
|
||||
modification_date: 2025-10-21
|
||||
catégorie: documentation
|
||||
tags:
|
||||
- aide
|
||||
- guide
|
||||
status: publié
|
||||
---
|
||||
|
||||
# 🧭 Guide d'utilisateur ObsiViewer
|
||||
|
||||
Bienvenue dans **ObsiViewer** !
|
||||
|
||||
Ce guide vous aidera à comprendre les principales fonctionnalités :
|
||||
|
||||
## 📂 Navigation
|
||||
- La barre latérale permet d'accéder aux notes, favoris, tags et modèles.
|
||||
- Les boutons en haut à droite donnent accès au mode édition, plein écran, et propriétés.
|
||||
|
||||
## ✏️ Édition
|
||||
- Le bouton ✏️ ouvre le **mode édition** basé sur CodeMirror 6.
|
||||
- Toutes les modifications sont sauvegardées automatiquement.
|
||||
|
||||
## 🏷️ Tags
|
||||
- Cliquez sur un tag pour voir toutes les notes qui le contiennent.
|
||||
- Utilisez l'icône 🏷️ à gauche pour modifier ou ajouter des tags.
|
||||
|
||||
## ⚙️ Paramètres
|
||||
- Les thèmes, langues et préférences sont gérés depuis le menu principal.
|
||||
|
||||
---
|
||||
|
||||
💡 **Astuce :** vous pouvez mettre à jour ce guide directement depuis votre voute Markdown.
|
||||
Loading…
x
Reference in New Issue
Block a user