4410 lines
208 KiB
HTML
4410 lines
208 KiB
HTML
<!doctype html>
|
||
<html lang="fr" data-theme="dark">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>ObsiGate</title>
|
||
|
||
<!-- PWA Meta Tags -->
|
||
<meta
|
||
name="description"
|
||
content="Porte d'entrée web pour vos vaults Obsidian - Accédez, naviguez et recherchez dans toutes vos notes"
|
||
/>
|
||
<meta name="theme-color" content="#2563eb" />
|
||
<meta name="mobile-web-app-capable" content="yes" />
|
||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||
<meta
|
||
name="apple-mobile-web-app-status-bar-style"
|
||
content="black-translucent"
|
||
/>
|
||
<meta name="apple-mobile-web-app-title" content="ObsiGate" />
|
||
|
||
<!-- PWA Manifest -->
|
||
<link rel="manifest" href="/static/manifest.json" />
|
||
|
||
<!-- Apple Touch Icons -->
|
||
<link
|
||
rel="apple-touch-icon"
|
||
sizes="152x152"
|
||
href="/static/icons/icon-152x152.svg"
|
||
/>
|
||
<link
|
||
rel="apple-touch-icon"
|
||
sizes="192x192"
|
||
href="/static/icons/icon-192x192.svg"
|
||
/>
|
||
|
||
<!-- Favicon -->
|
||
<link
|
||
rel="icon"
|
||
type="image/svg+xml"
|
||
href="/static/icons/icon-72x72.svg"
|
||
/>
|
||
<link
|
||
rel="icon"
|
||
type="image/svg+xml"
|
||
sizes="192x192"
|
||
href="/static/icons/icon-192x192.svg"
|
||
/>
|
||
|
||
<link rel="stylesheet" href="/static/style.css" />
|
||
<link
|
||
rel="stylesheet"
|
||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css"
|
||
id="hljs-theme-dark"
|
||
/>
|
||
<link
|
||
rel="stylesheet"
|
||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css"
|
||
id="hljs-theme-light"
|
||
disabled
|
||
/>
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
||
<script src="https://unpkg.com/[email protected]/dist/umd/lucide.min.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
|
||
<script type="importmap">
|
||
{
|
||
"imports": {
|
||
"@codemirror/state": "https://esm.sh/@codemirror/[email protected]"
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<!-- CodeMirror 6 -->
|
||
<script type="module">
|
||
import {
|
||
EditorView,
|
||
keymap,
|
||
lineNumbers,
|
||
highlightActiveLineGutter,
|
||
highlightSpecialChars,
|
||
drawSelection,
|
||
dropCursor,
|
||
rectangularSelection,
|
||
crosshairCursor,
|
||
highlightActiveLine,
|
||
} from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { EditorState } from "@codemirror/state";
|
||
import {
|
||
defaultHighlightStyle,
|
||
syntaxHighlighting,
|
||
indentOnInput,
|
||
bracketMatching,
|
||
foldGutter,
|
||
foldKeymap,
|
||
} from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import {
|
||
defaultKeymap,
|
||
history,
|
||
historyKeymap,
|
||
} from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import {
|
||
searchKeymap,
|
||
highlightSelectionMatches,
|
||
} from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import {
|
||
autocompletion,
|
||
completionKeymap,
|
||
closeBrackets,
|
||
closeBracketsKeymap,
|
||
} from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { markdown } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { python } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { javascript } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { html } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { css } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { json } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { xml } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { sql } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { php } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { cpp } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { java } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { rust } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
import { oneDark } from "https://esm.sh/@codemirror/[email protected]?external=@codemirror/state";
|
||
|
||
const basicSetup = [
|
||
lineNumbers(),
|
||
highlightActiveLineGutter(),
|
||
highlightSpecialChars(),
|
||
history(),
|
||
foldGutter(),
|
||
drawSelection(),
|
||
dropCursor(),
|
||
EditorState.allowMultipleSelections.of(true),
|
||
indentOnInput(),
|
||
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
||
bracketMatching(),
|
||
closeBrackets(),
|
||
autocompletion(),
|
||
rectangularSelection(),
|
||
crosshairCursor(),
|
||
highlightActiveLine(),
|
||
highlightSelectionMatches(),
|
||
keymap.of([
|
||
...closeBracketsKeymap,
|
||
...defaultKeymap,
|
||
...searchKeymap,
|
||
...historyKeymap,
|
||
...foldKeymap,
|
||
...completionKeymap,
|
||
]),
|
||
];
|
||
|
||
window.CodeMirror = {
|
||
EditorView,
|
||
EditorState,
|
||
basicSetup,
|
||
markdown,
|
||
python,
|
||
javascript,
|
||
html,
|
||
css,
|
||
json,
|
||
xml,
|
||
sql,
|
||
php,
|
||
cpp,
|
||
java,
|
||
rust,
|
||
oneDark,
|
||
keymap,
|
||
};
|
||
</script>
|
||
</head>
|
||
<body>
|
||
<div class="search-progress-bar" id="search-progress-bar">
|
||
<div class="search-progress-bar__fill"></div>
|
||
</div>
|
||
|
||
<!-- Login Screen (hidden by default, shown when auth is required) -->
|
||
<div id="login-screen" class="login-screen hidden">
|
||
<div class="login-card">
|
||
<div class="login-header">
|
||
<div class="login-logo">
|
||
<span class="login-logo-icon">📖</span>
|
||
<span class="login-logo-text">ObsiGate</span>
|
||
</div>
|
||
<p class="login-subtitle">Accès sécurisé à vos vaults</p>
|
||
</div>
|
||
<form id="login-form" class="login-form" autocomplete="on">
|
||
<div class="form-group">
|
||
<label for="login-username">Nom d'utilisateur</label>
|
||
<input
|
||
type="text"
|
||
id="login-username"
|
||
name="username"
|
||
autocomplete="username"
|
||
placeholder="utilisateur"
|
||
required
|
||
autofocus
|
||
/>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="login-password">Mot de passe</label>
|
||
<div class="password-input-wrapper">
|
||
<input
|
||
type="password"
|
||
id="login-password"
|
||
name="password"
|
||
autocomplete="current-password"
|
||
placeholder="••••••••"
|
||
required
|
||
/>
|
||
<button
|
||
type="button"
|
||
id="toggle-password"
|
||
class="password-toggle"
|
||
aria-label="Afficher le mot de passe"
|
||
>
|
||
👁
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="form-group form-group--inline">
|
||
<label class="checkbox-label">
|
||
<input
|
||
type="checkbox"
|
||
id="remember-me"
|
||
name="remember_me"
|
||
/>
|
||
<span>Se souvenir de moi (30 jours)</span>
|
||
</label>
|
||
</div>
|
||
<div id="login-error" class="login-error hidden"></div>
|
||
<button type="submit" id="login-btn" class="btn-login">
|
||
<span class="btn-text">Se connecter</span>
|
||
<span class="btn-spinner hidden">⏳</span>
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Main Application (wrapped for show/hide) -->
|
||
<div id="app" class="app-container">
|
||
<!-- Header -->
|
||
<header class="header">
|
||
<div class="header-left">
|
||
<button
|
||
class="hamburger-btn"
|
||
id="hamburger-btn"
|
||
title="Menu"
|
||
>
|
||
<i
|
||
data-lucide="menu"
|
||
style="width: 20px; height: 20px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="sidebar-toggle-btn"
|
||
id="sidebar-toggle-btn"
|
||
title="Afficher/Masquer la sidebar"
|
||
>
|
||
<i
|
||
data-lucide="sidebar"
|
||
style="width: 20px; height: 20px"
|
||
></i>
|
||
</button>
|
||
|
||
<div class="header-logo" id="header-logo">
|
||
<i
|
||
data-lucide="book-open"
|
||
style="width: 20px; height: 20px"
|
||
></i>
|
||
ObsiGate
|
||
</div>
|
||
<span
|
||
class="sync-badge sync-badge--disconnected"
|
||
id="sync-badge"
|
||
title="Synchronisation"
|
||
></span>
|
||
</div>
|
||
|
||
<div class="header-center">
|
||
<div class="search-wrapper">
|
||
<i
|
||
data-lucide="search"
|
||
class="search-icon"
|
||
style="width: 16px; height: 16px"
|
||
></i>
|
||
<div class="search-input-wrapper">
|
||
<input
|
||
type="text"
|
||
id="search-input"
|
||
placeholder="Rechercher ..."
|
||
autocomplete="off"
|
||
/>
|
||
<div class="search-actions">
|
||
<button
|
||
class="search-btn tog"
|
||
id="search-case-btn"
|
||
type="button"
|
||
title="Respecter la casse (Alt-C)"
|
||
>
|
||
Aa
|
||
</button>
|
||
<button
|
||
class="search-btn tog"
|
||
id="search-word-btn"
|
||
type="button"
|
||
title="Mot entier (Alt-W)"
|
||
>
|
||
wd
|
||
</button>
|
||
<button
|
||
class="search-btn tog"
|
||
id="search-regex-btn"
|
||
type="button"
|
||
title="Expression régulière (Alt-R)"
|
||
>
|
||
.*
|
||
</button>
|
||
<span class="search-sep"></span>
|
||
<button
|
||
class="search-btn icon-only"
|
||
id="search-filter-btn"
|
||
type="button"
|
||
title="Filtres de chemin (Alt-F)"
|
||
>
|
||
<i
|
||
data-lucide="filter"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
<span class="search-sep"></span>
|
||
<span
|
||
class="search-count"
|
||
id="search-match-count"
|
||
>0/0</span
|
||
>
|
||
<button
|
||
class="search-btn icon-only"
|
||
id="search-prev-btn"
|
||
type="button"
|
||
title="Résultat précédent"
|
||
>
|
||
↑
|
||
</button>
|
||
<button
|
||
class="search-btn icon-only"
|
||
id="search-next-btn"
|
||
type="button"
|
||
title="Résultat suivant"
|
||
>
|
||
↓
|
||
</button>
|
||
<button
|
||
class="search-btn icon-only"
|
||
id="search-clear-btn"
|
||
type="button"
|
||
title="Effacer"
|
||
aria-label="Effacer la recherche"
|
||
>
|
||
<i
|
||
data-lucide="x"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<!-- Path filter row -->
|
||
<div
|
||
class="search-filter-row"
|
||
id="search-filter-row"
|
||
style="display: none"
|
||
>
|
||
<input
|
||
type="text"
|
||
class="search-filter-input"
|
||
id="search-include-input"
|
||
placeholder="Inclure: **/*.md, notes/**"
|
||
/>
|
||
<input
|
||
type="text"
|
||
class="search-filter-input"
|
||
id="search-exclude-input"
|
||
placeholder="Exclure: vendor/*, *.lock"
|
||
/>
|
||
</div>
|
||
<!-- Advanced search autocomplete dropdown -->
|
||
<div
|
||
class="search-dropdown"
|
||
id="search-dropdown"
|
||
role="listbox"
|
||
aria-label="Suggestions de recherche"
|
||
hidden
|
||
>
|
||
<div
|
||
class="search-dropdown__section search-dropdown__section--history"
|
||
id="search-dropdown-history"
|
||
>
|
||
<div class="search-dropdown__section-header">
|
||
<span>Historique</span>
|
||
<button
|
||
class="search-dropdown__clear-btn"
|
||
id="search-dropdown-clear-history"
|
||
type="button"
|
||
title="Effacer l'historique"
|
||
>
|
||
<i
|
||
data-lucide="trash-2"
|
||
style="width: 12px; height: 12px"
|
||
></i>
|
||
</button>
|
||
</div>
|
||
<ul
|
||
class="search-dropdown__list"
|
||
id="search-dropdown-history-list"
|
||
></ul>
|
||
</div>
|
||
<div
|
||
class="search-dropdown__section search-dropdown__section--titles"
|
||
id="search-dropdown-titles"
|
||
>
|
||
<div class="search-dropdown__section-header">
|
||
<span>Fichiers</span>
|
||
</div>
|
||
<ul
|
||
class="search-dropdown__list"
|
||
id="search-dropdown-titles-list"
|
||
></ul>
|
||
</div>
|
||
<div
|
||
class="search-dropdown__section search-dropdown__section--tags"
|
||
id="search-dropdown-tags"
|
||
>
|
||
<div class="search-dropdown__section-header">
|
||
<span>Tags</span>
|
||
</div>
|
||
<ul
|
||
class="search-dropdown__list"
|
||
id="search-dropdown-tags-list"
|
||
></ul>
|
||
</div>
|
||
<div
|
||
class="search-dropdown__empty"
|
||
id="search-dropdown-empty"
|
||
hidden
|
||
>
|
||
Aucune suggestion
|
||
</div>
|
||
</div>
|
||
<!-- Active search filter chips -->
|
||
<div
|
||
class="search-chips"
|
||
id="search-chips"
|
||
hidden
|
||
></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="header-right">
|
||
<div
|
||
class="vault-context-indicator"
|
||
id="vault-context-indicator"
|
||
title="Contexte vault actif"
|
||
>
|
||
<i
|
||
data-lucide="database"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
<span id="vault-context-text">All</span>
|
||
</div>
|
||
<!-- User menu (visible when logged in) -->
|
||
<div class="user-menu" id="user-menu"></div>
|
||
<div class="header-menu">
|
||
<button
|
||
class="header-menu-btn"
|
||
id="header-menu-btn"
|
||
title="Options"
|
||
>
|
||
<i
|
||
data-lucide="settings"
|
||
style="width: 18px; height: 18px"
|
||
></i>
|
||
</button>
|
||
<div
|
||
class="header-menu-dropdown"
|
||
id="header-menu-dropdown"
|
||
>
|
||
<div
|
||
class="menu-list"
|
||
role="menu"
|
||
aria-label="Options"
|
||
>
|
||
<label
|
||
class="menu-list-row menu-list-select-row hidden"
|
||
for="vault-filter"
|
||
>
|
||
<span
|
||
class="menu-list-icon"
|
||
aria-hidden="true"
|
||
>
|
||
<i
|
||
data-lucide="folders"
|
||
style="width: 17px; height: 17px"
|
||
></i>
|
||
</span>
|
||
<span class="menu-list-content">
|
||
<span class="menu-list-title"
|
||
>Vault</span
|
||
>
|
||
<div
|
||
class="custom-dropdown"
|
||
id="vault-filter-dropdown"
|
||
>
|
||
<button
|
||
class="custom-dropdown-trigger"
|
||
type="button"
|
||
aria-haspopup="listbox"
|
||
aria-expanded="false"
|
||
>
|
||
<span
|
||
class="custom-dropdown-selected"
|
||
>Tous les vaults</span
|
||
>
|
||
<i
|
||
data-lucide="chevron-down"
|
||
style="
|
||
width: 14px;
|
||
height: 14px;
|
||
"
|
||
></i>
|
||
</button>
|
||
<ul
|
||
class="custom-dropdown-menu"
|
||
role="listbox"
|
||
id="vault-filter-options"
|
||
>
|
||
<li
|
||
role="option"
|
||
data-value="all"
|
||
class="custom-dropdown-option selected"
|
||
>
|
||
Tous les vaults
|
||
</li>
|
||
</ul>
|
||
<input
|
||
type="hidden"
|
||
id="vault-filter"
|
||
value="all"
|
||
/>
|
||
</div>
|
||
</span>
|
||
</label>
|
||
<button
|
||
class="menu-list-row menu-list-button"
|
||
id="theme-toggle"
|
||
type="button"
|
||
role="menuitem"
|
||
>
|
||
<span
|
||
class="menu-list-icon"
|
||
aria-hidden="true"
|
||
>
|
||
<i
|
||
data-lucide="sun"
|
||
style="width: 17px; height: 17px"
|
||
></i>
|
||
</span>
|
||
<span class="menu-list-content">
|
||
<span class="menu-list-title"
|
||
>Thème</span
|
||
>
|
||
<span
|
||
class="menu-list-subtitle"
|
||
id="theme-label"
|
||
>Clair</span
|
||
>
|
||
</span>
|
||
</button>
|
||
<button
|
||
class="menu-list-row menu-list-button hidden"
|
||
id="admin-menu-row"
|
||
type="button"
|
||
role="menuitem"
|
||
>
|
||
<span
|
||
class="menu-list-icon"
|
||
aria-hidden="true"
|
||
>
|
||
<i
|
||
data-lucide="shield"
|
||
style="width: 17px; height: 17px"
|
||
></i>
|
||
</span>
|
||
<span class="menu-list-content">
|
||
<span class="menu-list-title"
|
||
>Administration</span
|
||
>
|
||
<span class="menu-list-subtitle"
|
||
>Gérer les utilisateurs</span
|
||
>
|
||
</span>
|
||
</button>
|
||
<button
|
||
class="menu-list-row menu-list-button"
|
||
id="config-open-btn"
|
||
type="button"
|
||
role="menuitem"
|
||
>
|
||
<span
|
||
class="menu-list-icon"
|
||
aria-hidden="true"
|
||
>
|
||
<i
|
||
data-lucide="settings"
|
||
style="width: 17px; height: 17px"
|
||
></i>
|
||
</span>
|
||
<span class="menu-list-content">
|
||
<span class="menu-list-title"
|
||
>Configurations</span
|
||
>
|
||
<span class="menu-list-subtitle"
|
||
>Paramètres de l'application</span
|
||
>
|
||
</span>
|
||
</button>
|
||
<button
|
||
class="menu-list-row menu-list-button"
|
||
id="help-open-btn"
|
||
type="button"
|
||
role="menuitem"
|
||
>
|
||
<span
|
||
class="menu-list-icon"
|
||
aria-hidden="true"
|
||
>
|
||
<i
|
||
data-lucide="book-open"
|
||
style="width: 17px; height: 17px"
|
||
></i>
|
||
</span>
|
||
<span class="menu-list-content">
|
||
<span class="menu-list-title"
|
||
>Guide d'utilisation</span
|
||
>
|
||
<span class="menu-list-subtitle"
|
||
>Ouvrir l'aide</span
|
||
>
|
||
</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Main -->
|
||
<div class="main-body">
|
||
<!-- Mobile overlay -->
|
||
<div class="sidebar-overlay" id="sidebar-overlay"></div>
|
||
|
||
<!-- Sidebar -->
|
||
<aside
|
||
class="sidebar"
|
||
id="sidebar"
|
||
role="navigation"
|
||
aria-label="Navigation des vaults"
|
||
>
|
||
<!-- Sidebar filter -->
|
||
<div class="sidebar-filter">
|
||
<div class="sidebar-filter-input-wrapper">
|
||
<i
|
||
data-lucide="filter"
|
||
class="sidebar-filter-icon"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
<input
|
||
type="text"
|
||
id="sidebar-filter-input"
|
||
placeholder="Filtrer fichiers..."
|
||
autocomplete="off"
|
||
/>
|
||
<div class="sidebar-filter-actions">
|
||
<button
|
||
class="sidebar-filter-btn"
|
||
id="sidebar-filter-case-btn"
|
||
type="button"
|
||
title="Respecter la casse"
|
||
aria-label="Respecter la casse"
|
||
>
|
||
<span>Aa</span>
|
||
</button>
|
||
<button
|
||
class="sidebar-filter-btn"
|
||
id="sidebar-filter-clear-btn"
|
||
type="button"
|
||
title="Effacer le filtrage"
|
||
aria-label="Effacer le filtrage"
|
||
>
|
||
<i
|
||
data-lucide="x"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tab bar -->
|
||
<div
|
||
class="sidebar-tabs"
|
||
role="tablist"
|
||
aria-label="Sections sidebar"
|
||
>
|
||
<button
|
||
class="sidebar-tab active"
|
||
id="sidebar-tab-vaults"
|
||
role="tab"
|
||
aria-selected="true"
|
||
aria-controls="sidebar-panel-vaults"
|
||
data-tab="vaults"
|
||
title="Vaults"
|
||
>
|
||
<i
|
||
data-lucide="folder-tree"
|
||
style="width: 18px; height: 18px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="sidebar-tab"
|
||
id="sidebar-tab-tags"
|
||
role="tab"
|
||
aria-selected="false"
|
||
aria-controls="sidebar-panel-tags"
|
||
data-tab="tags"
|
||
title="Tags"
|
||
>
|
||
<i
|
||
data-lucide="tag"
|
||
style="width: 18px; height: 18px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="sidebar-tab"
|
||
id="sidebar-tab-recent"
|
||
role="tab"
|
||
aria-selected="false"
|
||
aria-controls="sidebar-panel-recent"
|
||
data-tab="recent"
|
||
title="Récent"
|
||
>
|
||
<i
|
||
data-lucide="clock"
|
||
style="width: 18px; height: 18px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="sidebar-tab"
|
||
id="sidebar-tab-saved"
|
||
role="tab"
|
||
aria-selected="false"
|
||
aria-controls="sidebar-panel-saved"
|
||
data-tab="saved"
|
||
title="Sauvegardes"
|
||
>
|
||
<i
|
||
data-lucide="bookmark"
|
||
style="width: 18px; height: 18px"
|
||
></i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Vaults panel -->
|
||
<div
|
||
class="sidebar-tab-panel active"
|
||
id="sidebar-panel-vaults"
|
||
role="tabpanel"
|
||
aria-labelledby="sidebar-tab-vaults"
|
||
>
|
||
<div
|
||
class="custom-dropdown sidebar-dropdown"
|
||
id="vault-quick-select-dropdown"
|
||
>
|
||
<button
|
||
class="custom-dropdown-trigger"
|
||
type="button"
|
||
aria-haspopup="listbox"
|
||
aria-expanded="false"
|
||
>
|
||
<span class="custom-dropdown-selected"
|
||
>Tous les vaults</span
|
||
>
|
||
<i
|
||
data-lucide="chevron-down"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
<ul
|
||
class="custom-dropdown-menu"
|
||
role="listbox"
|
||
id="vault-quick-select-options"
|
||
>
|
||
<li
|
||
role="option"
|
||
data-value="all"
|
||
class="custom-dropdown-option selected"
|
||
>
|
||
Tous les vaults
|
||
</li>
|
||
</ul>
|
||
<input
|
||
type="hidden"
|
||
id="vault-quick-select"
|
||
value="all"
|
||
/>
|
||
</div>
|
||
<div
|
||
id="vault-tree"
|
||
role="tree"
|
||
aria-label="Arborescence des fichiers"
|
||
></div>
|
||
</div>
|
||
|
||
<!-- Tags panel -->
|
||
<div
|
||
class="sidebar-tab-panel"
|
||
id="sidebar-panel-tags"
|
||
role="tabpanel"
|
||
aria-labelledby="sidebar-tab-tags"
|
||
>
|
||
<div class="tag-cloud" id="tag-cloud"></div>
|
||
</div>
|
||
|
||
<!-- Recent panel -->
|
||
<div
|
||
class="sidebar-tab-panel"
|
||
id="sidebar-panel-recent"
|
||
role="tabpanel"
|
||
aria-labelledby="sidebar-tab-recent"
|
||
>
|
||
<div class="recent-filter-bar">
|
||
<select id="recent-vault-filter">
|
||
<option value="">Tous les vaults</option>
|
||
</select>
|
||
</div>
|
||
<div id="recent-list" class="recent-list"></div>
|
||
<div id="recent-empty" class="recent-empty hidden">
|
||
<i
|
||
data-lucide="inbox"
|
||
style="width: 32px; height: 32px"
|
||
></i>
|
||
<span>Aucun fichier récent</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Saved Searches panel -->
|
||
<div
|
||
class="sidebar-tab-panel"
|
||
id="sidebar-panel-saved"
|
||
role="tabpanel"
|
||
aria-labelledby="sidebar-tab-saved"
|
||
>
|
||
<div id="saved-searches-list" class="recent-list"></div>
|
||
<div id="saved-searches-empty" class="recent-empty">
|
||
<i
|
||
data-lucide="bookmark"
|
||
style="width: 32px; height: 32px"
|
||
></i>
|
||
<span>Aucune recherche sauvegardée</span>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- Sidebar resize handle -->
|
||
<div
|
||
class="sidebar-resize-handle"
|
||
id="sidebar-resize-handle"
|
||
></div>
|
||
|
||
<!-- Content Wrapper (tab bar + content area) -->
|
||
<div class="vault-context-bar" id="vault-context-bar">
|
||
<span class="vault-context-pill" id="vault-context-pill">📂 Toutes les vaults</span>
|
||
</div>
|
||
<div class="content-wrapper">
|
||
<!-- Tab bar -->
|
||
<div class="tab-bar" id="tab-bar" hidden>
|
||
<div class="tab-list" id="tab-list"></div>
|
||
</div>
|
||
|
||
<!-- Content -->
|
||
<main
|
||
class="content-area"
|
||
id="content-area"
|
||
aria-label="Contenu principal"
|
||
>
|
||
<div
|
||
id="dashboard-home"
|
||
class="dashboard-home"
|
||
role="region"
|
||
aria-label="Tableau de bord"
|
||
>
|
||
<!-- Dashboard Tabs -->
|
||
<div class="dashboard-tabs">
|
||
<button
|
||
class="dashboard-tab active"
|
||
data-tab="stats"
|
||
>
|
||
<i
|
||
data-lucide="bar-chart-3"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
Statistiques
|
||
</button>
|
||
<button
|
||
class="dashboard-tab"
|
||
data-tab="bookmarks"
|
||
>
|
||
<i
|
||
data-lucide="bookmark"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
Bookmarks
|
||
</button>
|
||
<button class="dashboard-tab" data-tab="recent">
|
||
<i
|
||
data-lucide="clock"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
Récents
|
||
</button>
|
||
<button class="dashboard-tab" data-tab="shared">
|
||
<i
|
||
data-lucide="share-2"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
Partagés
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Stats Panel -->
|
||
<div
|
||
id="dashboard-panel-stats"
|
||
class="dashboard-panel active"
|
||
>
|
||
<div
|
||
id="dashboard-stats-grid"
|
||
class="dashboard-stats-grid"
|
||
>
|
||
<div class="dashboard-stats-loading">
|
||
Chargement...
|
||
</div>
|
||
</div>
|
||
<div
|
||
id="dashboard-conflicts-container"
|
||
style="margin-top: 16px"
|
||
></div>
|
||
</div>
|
||
|
||
<!-- Bookmarks Panel -->
|
||
<div
|
||
id="dashboard-panel-bookmarks"
|
||
class="dashboard-panel"
|
||
>
|
||
<div
|
||
id="dashboard-bookmarks-grid"
|
||
class="dashboard-recent-grid"
|
||
></div>
|
||
<div
|
||
id="dashboard-bookmarks-empty"
|
||
class="dashboard-recent-empty"
|
||
>
|
||
<i data-lucide="pin"></i>
|
||
<span>Aucun bookmark</span>
|
||
<p>
|
||
Épinglez des fichiers pour les retrouver
|
||
ici.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Recent Panel -->
|
||
<div
|
||
id="dashboard-panel-recent"
|
||
class="dashboard-panel"
|
||
>
|
||
<div class="dashboard-header">
|
||
<div class="dashboard-title-row">
|
||
<span
|
||
id="dashboard-count"
|
||
class="dashboard-badge"
|
||
></span>
|
||
</div>
|
||
</div>
|
||
<div
|
||
id="dashboard-recent-grid"
|
||
class="dashboard-recent-grid"
|
||
></div>
|
||
<div
|
||
id="dashboard-loading"
|
||
class="dashboard-loading"
|
||
>
|
||
<div class="skeleton-card"></div>
|
||
<div class="skeleton-card"></div>
|
||
<div class="skeleton-card"></div>
|
||
<div class="skeleton-card"></div>
|
||
<div class="skeleton-card"></div>
|
||
<div class="skeleton-card"></div>
|
||
</div>
|
||
<div
|
||
id="dashboard-recent-empty"
|
||
class="dashboard-recent-empty hidden"
|
||
>
|
||
<i data-lucide="inbox"></i>
|
||
<span>Aucun fichier récent</span>
|
||
<p>
|
||
Ouvrez un fichier pour le voir
|
||
apparaître ici
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Shared Panel -->
|
||
<div
|
||
id="dashboard-panel-shared"
|
||
class="dashboard-panel"
|
||
>
|
||
<div
|
||
id="dashboard-shared-grid"
|
||
class="dashboard-recent-grid"
|
||
></div>
|
||
<div
|
||
id="dashboard-shared-empty"
|
||
class="dashboard-recent-empty"
|
||
>
|
||
<i data-lucide="share-2"></i>
|
||
<span>Aucun document partagé</span>
|
||
<p>
|
||
Partagez un document pour le voir
|
||
apparaître ici
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
<!-- /content-wrapper -->
|
||
|
||
<!-- Right sidebar resize handle -->
|
||
<div
|
||
class="right-sidebar-resize-handle"
|
||
id="right-sidebar-resize-handle"
|
||
></div>
|
||
|
||
<!-- Right Sidebar (Outline/TOC) -->
|
||
<aside
|
||
class="right-sidebar"
|
||
id="right-sidebar"
|
||
role="complementary"
|
||
aria-label="Table des matières"
|
||
>
|
||
<div class="right-sidebar-header">
|
||
<h2 class="right-sidebar-title">SUR CETTE PAGE</h2>
|
||
<button
|
||
class="right-sidebar-toggle-btn"
|
||
id="right-sidebar-toggle-btn"
|
||
type="button"
|
||
title="Masquer le panneau"
|
||
aria-label="Masquer le panneau"
|
||
>
|
||
<i
|
||
data-lucide="chevron-right"
|
||
style="width: 16px; height: 16px"
|
||
></i>
|
||
</button>
|
||
</div>
|
||
<div class="outline-panel" id="outline-panel">
|
||
<nav
|
||
class="outline-list"
|
||
id="outline-list"
|
||
role="navigation"
|
||
aria-label="Navigation dans le document"
|
||
>
|
||
<!-- Outline items will be injected here -->
|
||
</nav>
|
||
<div class="outline-empty" id="outline-empty" hidden>
|
||
<i
|
||
data-lucide="list"
|
||
style="width: 24px; height: 24px; opacity: 0.3"
|
||
></i>
|
||
<span>Aucun titre dans ce document</span>
|
||
</div>
|
||
</div>
|
||
<div class="reading-progress" id="reading-progress">
|
||
<div class="reading-progress-bar">
|
||
<div
|
||
class="reading-progress-fill"
|
||
id="reading-progress-fill"
|
||
></div>
|
||
</div>
|
||
<div
|
||
class="reading-progress-text"
|
||
id="reading-progress-text"
|
||
>
|
||
0%
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Editor Modal -->
|
||
<div class="editor-modal" id="editor-modal">
|
||
<div class="editor-container">
|
||
<div class="editor-header">
|
||
<div class="editor-title" id="editor-title">Édition</div>
|
||
<div class="editor-actions">
|
||
<button
|
||
class="editor-btn danger"
|
||
id="editor-delete"
|
||
title="Supprimer"
|
||
aria-label="Supprimer"
|
||
>
|
||
<i
|
||
data-lucide="trash-2"
|
||
style="width: 16px; height: 16px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="editor-btn"
|
||
id="editor-cancel"
|
||
title="Annuler"
|
||
aria-label="Annuler"
|
||
>
|
||
<i
|
||
data-lucide="x"
|
||
style="width: 16px; height: 16px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="editor-btn primary"
|
||
id="editor-save"
|
||
title="Sauvegarder"
|
||
aria-label="Sauvegarder"
|
||
>
|
||
<i
|
||
data-lucide="check"
|
||
style="width: 16px; height: 16px"
|
||
></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="editor-body" id="editor-body">
|
||
<div id="ai-toolbar-container"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Configurations Modal -->
|
||
<div class="editor-modal" id="config-modal">
|
||
<div class="editor-container">
|
||
<div class="editor-header">
|
||
<div class="editor-title">Configurations</div>
|
||
<div class="editor-actions">
|
||
<button
|
||
class="editor-btn"
|
||
id="config-close"
|
||
title="Fermer"
|
||
aria-label="Fermer"
|
||
>
|
||
<i
|
||
data-lucide="x"
|
||
style="width: 16px; height: 16px"
|
||
></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="editor-body" id="config-body">
|
||
<div class="config-content">
|
||
<!-- Performance Settings - Frontend -->
|
||
<section class="config-section">
|
||
<h2>Paramètres de recherche</h2>
|
||
<p class="config-description">
|
||
Ces paramètres s'appliquent immédiatement côté
|
||
client.
|
||
</p>
|
||
|
||
<div class="config-row">
|
||
<label class="config-label" for="cfg-debounce"
|
||
>Délai debounce (ms)</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-debounce"
|
||
class="config-input config-input--num"
|
||
min="100"
|
||
max="2000"
|
||
step="50"
|
||
value="300"
|
||
/>
|
||
<span class="config-hint"
|
||
>Délai avant exécution de la recherche
|
||
(100-2000)</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-results-per-page"
|
||
>Résultats par page</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-results-per-page"
|
||
class="config-input config-input--num"
|
||
min="10"
|
||
max="200"
|
||
step="10"
|
||
value="50"
|
||
/>
|
||
<span class="config-hint"
|
||
>Nombre de résultats affichés par page
|
||
(10-200)</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label class="config-label" for="cfg-min-query"
|
||
>Longueur min. requête</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-min-query"
|
||
class="config-input config-input--num"
|
||
min="1"
|
||
max="5"
|
||
step="1"
|
||
value="2"
|
||
/>
|
||
<span class="config-hint"
|
||
>Nombre minimum de caractères avant
|
||
recherche (1-5)</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label class="config-label" for="cfg-timeout"
|
||
>Timeout recherche (ms)</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-timeout"
|
||
class="config-input config-input--num"
|
||
min="5000"
|
||
max="120000"
|
||
step="5000"
|
||
value="30000"
|
||
/>
|
||
<span class="config-hint"
|
||
>Annuler la recherche après ce délai
|
||
(5000-120000)</span
|
||
>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Historique récent -->
|
||
<section class="config-section">
|
||
<h2>
|
||
📋 Historique récent
|
||
<span class="config-badge-restart"
|
||
>Redémarrage non requis</span
|
||
>
|
||
</h2>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-recent-limit"
|
||
>Nombre de fichiers dans l'historique</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-recent-limit"
|
||
class="config-input config-input--num"
|
||
min="5"
|
||
max="100"
|
||
step="5"
|
||
value="20"
|
||
/>
|
||
<span class="config-hint"
|
||
>Entre 5 et 100 fichiers (sauvegarde sur le
|
||
serveur)</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-max-backups"
|
||
>Max backups par fichier</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-max-backups"
|
||
class="config-input config-input--num"
|
||
min="1"
|
||
max="50"
|
||
step="1"
|
||
value="10"
|
||
/>
|
||
<span class="config-hint"
|
||
>Nombre maximum de versions backup conservees par fichier (1-50)</span
|
||
>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Performance Settings - Backend -->
|
||
<section class="config-section">
|
||
<h2>
|
||
Paramètres backend
|
||
<span class="config-badge-restart"
|
||
>Redémarrage requis</span
|
||
>
|
||
</h2>
|
||
<p class="config-description">
|
||
Ces paramètres sont sauvegardés sur le serveur.
|
||
Certains nécessitent un redémarrage ou une
|
||
réindexation.
|
||
</p>
|
||
|
||
<div class="config-row">
|
||
<label class="config-label" for="cfg-workers"
|
||
>Workers de recherche</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-workers"
|
||
class="config-input config-input--num"
|
||
min="1"
|
||
max="8"
|
||
step="1"
|
||
value="2"
|
||
/>
|
||
<span class="config-hint"
|
||
>Threads dédiés à la recherche (1-8)</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-max-content"
|
||
>Taille max contenu (octets)</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-max-content"
|
||
class="config-input config-input--num"
|
||
min="10000"
|
||
max="1000000"
|
||
step="10000"
|
||
value="100000"
|
||
/>
|
||
<span class="config-hint"
|
||
>Contenu indexé par fichier (10K-1M).
|
||
Réindexation requise.</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-title-boost"
|
||
>Boost titre</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-title-boost"
|
||
class="config-input config-input--num"
|
||
min="0"
|
||
max="10"
|
||
step="0.5"
|
||
value="3.0"
|
||
/>
|
||
<span class="config-hint"
|
||
>Multiplicateur de pertinence pour les
|
||
correspondances dans le titre</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label class="config-label" for="cfg-tag-boost"
|
||
>Boost tags</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-tag-boost"
|
||
class="config-input config-input--num"
|
||
min="0"
|
||
max="10"
|
||
step="0.5"
|
||
value="2.0"
|
||
/>
|
||
<span class="config-hint"
|
||
>Multiplicateur de pertinence pour les
|
||
correspondances dans les tags</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label class="config-label" for="cfg-prefix-exp"
|
||
>Expansions préfixe max</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-prefix-exp"
|
||
class="config-input config-input--num"
|
||
min="10"
|
||
max="200"
|
||
step="10"
|
||
value="50"
|
||
/>
|
||
<span class="config-hint"
|
||
>Nombre max de tokens élargis par préfixe
|
||
(10-200)</span
|
||
>
|
||
</div>
|
||
|
||
<div class="config-actions-row">
|
||
<button
|
||
class="config-btn-save"
|
||
id="cfg-save-backend"
|
||
>
|
||
Sauvegarder
|
||
</button>
|
||
<button
|
||
class="config-btn-secondary"
|
||
id="cfg-reindex"
|
||
>
|
||
Forcer réindexation
|
||
</button>
|
||
<button
|
||
class="config-btn-secondary"
|
||
id="cfg-reset-defaults"
|
||
>
|
||
Réinitialiser
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Tag Filtering (existing) -->
|
||
<section class="config-section">
|
||
<h2>Filtrage de tags</h2>
|
||
<p class="config-description">
|
||
Définissez les patterns de tags à masquer dans
|
||
la sidebar. Vous pouvez utiliser des wildcards
|
||
pour cibler les tags de template.
|
||
</p>
|
||
|
||
<div
|
||
class="config-filters-list"
|
||
id="config-filters-list"
|
||
></div>
|
||
|
||
<div class="config-add-pattern">
|
||
<input
|
||
type="text"
|
||
id="config-pattern-input"
|
||
placeholder="Ex: #<% ... %> ou #{{ ... }}"
|
||
class="config-input"
|
||
/>
|
||
<button
|
||
id="config-add-btn"
|
||
class="config-btn-add"
|
||
>
|
||
Ajouter
|
||
</button>
|
||
</div>
|
||
|
||
<div
|
||
class="config-regex-preview"
|
||
id="config-regex-preview"
|
||
style="display: none"
|
||
>
|
||
<small
|
||
>Regex : <code id="config-regex-code"></code
|
||
></small>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Watcher / Synchronisation -->
|
||
<section class="config-section">
|
||
<h2>Synchronisation automatique</h2>
|
||
<p class="config-description">
|
||
Surveillance des fichiers en temps réel via
|
||
watchdog. Les modifications sont détectées
|
||
automatiquement et l'index est mis à jour sans
|
||
redémarrage.
|
||
</p>
|
||
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-watcher-enabled"
|
||
>Activer la surveillance</label
|
||
>
|
||
<label class="config-toggle">
|
||
<input
|
||
type="checkbox"
|
||
id="cfg-watcher-enabled"
|
||
checked
|
||
/>
|
||
<span class="config-toggle-slider"></span>
|
||
</label>
|
||
<span class="config-hint"
|
||
>Activer/désactiver la surveillance
|
||
automatique des fichiers</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-watcher-polling"
|
||
>Mode polling (fallback)</label
|
||
>
|
||
<label class="config-toggle">
|
||
<input
|
||
type="checkbox"
|
||
id="cfg-watcher-polling"
|
||
/>
|
||
<span class="config-toggle-slider"></span>
|
||
</label>
|
||
<span class="config-hint"
|
||
>Forcer le mode polling au lieu de inotify
|
||
natif (utile si le mode natif ne fonctionne
|
||
pas)</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-watcher-interval"
|
||
>Intervalle polling (s)</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-watcher-interval"
|
||
class="config-input config-input--num"
|
||
min="1"
|
||
max="30"
|
||
step="1"
|
||
value="5"
|
||
/>
|
||
<span class="config-hint"
|
||
>Intervalle de scrutation en mode polling
|
||
(1-30 secondes)</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-watcher-debounce"
|
||
>Debounce (s)</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-watcher-debounce"
|
||
class="config-input config-input--num"
|
||
min="0.5"
|
||
max="10"
|
||
step="0.5"
|
||
value="2"
|
||
/>
|
||
<span class="config-hint"
|
||
>Délai avant traitement des changements
|
||
groupés (0.5-10 secondes)</span
|
||
>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Hidden Files/Folders Configuration -->
|
||
<section class="config-section">
|
||
<h2>🗂️ Fichiers cachés</h2>
|
||
<p class="config-description">
|
||
Contrôlez l'affichage des fichiers/dossiers
|
||
cachés (commençant par <code>.</code>) par
|
||
vault.
|
||
</p>
|
||
<p
|
||
class="config-hint"
|
||
style="
|
||
margin-bottom: 12px;
|
||
padding: 8px;
|
||
background: var(--background-secondary);
|
||
border-radius: 4px;
|
||
"
|
||
>
|
||
i️ <strong>Note :</strong> Tous les fichiers sont
|
||
toujours indexés et cherchables. Ce paramètre
|
||
contrôle uniquement leur visibilité dans
|
||
l'interface.
|
||
</p>
|
||
|
||
<div id="hidden-files-vault-list">
|
||
<!-- Vault-specific settings will be injected here -->
|
||
</div>
|
||
|
||
<div
|
||
class="config-actions-row"
|
||
style="margin-top: 16px"
|
||
>
|
||
<button
|
||
class="config-btn-save"
|
||
id="cfg-save-hidden-files"
|
||
>
|
||
💾 Sauvegarder
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Diagnostics -->
|
||
<section class="config-section">
|
||
<h2>Diagnostics</h2>
|
||
<p class="config-description">
|
||
Statistiques de l'index et du moteur de
|
||
recherche.
|
||
</p>
|
||
<div
|
||
id="config-diagnostics"
|
||
class="config-diagnostics"
|
||
>
|
||
<div class="config-diag-loading">
|
||
Chargement...
|
||
</div>
|
||
</div>
|
||
<button
|
||
class="config-btn-secondary"
|
||
id="cfg-refresh-diag"
|
||
style="margin-top: 8px"
|
||
>
|
||
Rafraîchir
|
||
</button>
|
||
</section>
|
||
|
||
<!-- À propos -->
|
||
<section class="config-section">
|
||
<h2>📦 À propos</h2>
|
||
<div id="config-about" class="config-diagnostics">
|
||
<div class="config-diag-loading">
|
||
Chargement...
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Webhooks -->
|
||
<section class="config-section">
|
||
<h2>🔔 Webhooks</h2>
|
||
<p class="config-description">
|
||
Notifications HTTP vers des services externes
|
||
lors des changements de fichiers.
|
||
</p>
|
||
<div id="webhooks-list"></div>
|
||
<div class="config-add-row">
|
||
<input
|
||
type="text"
|
||
id="webhook-name-input"
|
||
placeholder="Nom"
|
||
class="config-input"
|
||
style="width: 100px"
|
||
/>
|
||
<input
|
||
type="text"
|
||
id="webhook-url-input"
|
||
placeholder="https://..."
|
||
class="config-input"
|
||
style="flex: 1"
|
||
/>
|
||
<button
|
||
id="webhook-add-btn"
|
||
class="config-btn config-btn-add"
|
||
>
|
||
Ajouter
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Partages publics -->
|
||
<section class="config-section">
|
||
<h2>📤 Partages publics</h2>
|
||
<p class="config-description">
|
||
Liens de partage publics pour des documents
|
||
(lecture seule, sans authentification).
|
||
</p>
|
||
<div id="shares-list"></div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Graph View Modal -->
|
||
<div class="editor-modal" id="graph-modal">
|
||
<div
|
||
class="editor-container"
|
||
style="
|
||
max-width: 95vw;
|
||
width: 1000px;
|
||
height: 85vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
"
|
||
>
|
||
<!-- Header: 2 lignes — nav+titre+contrôles | recherche -->
|
||
<div
|
||
class="editor-header"
|
||
style="
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 6px;
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid var(--border-color);
|
||
"
|
||
>
|
||
<!-- Line 1: nav + title + controls -->
|
||
<div
|
||
style="
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
min-width: 0;
|
||
"
|
||
>
|
||
<button
|
||
class="editor-btn"
|
||
id="graph-nav-back"
|
||
title="Retour"
|
||
style="
|
||
font-size: 0.75rem;
|
||
padding: 2px 4px;
|
||
opacity: 0.3;
|
||
flex-shrink: 0;
|
||
min-width: 22px;
|
||
"
|
||
disabled
|
||
>
|
||
←
|
||
</button>
|
||
<button
|
||
class="editor-btn"
|
||
id="graph-nav-fwd"
|
||
title="Avancer"
|
||
style="
|
||
font-size: 0.75rem;
|
||
padding: 2px 4px;
|
||
opacity: 0.3;
|
||
flex-shrink: 0;
|
||
min-width: 22px;
|
||
"
|
||
disabled
|
||
>
|
||
→
|
||
</button>
|
||
<button
|
||
class="editor-btn"
|
||
id="graph-nav-up"
|
||
title="Dossier parent"
|
||
style="
|
||
font-size: 0.65rem;
|
||
padding: 2px 5px;
|
||
flex-shrink: 0;
|
||
display: none;
|
||
"
|
||
>
|
||
↑
|
||
</button>
|
||
<div
|
||
class="editor-title"
|
||
id="graph-title"
|
||
style="
|
||
font-weight: 600;
|
||
font-size: 0.85rem;
|
||
flex: 1;
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
"
|
||
>
|
||
Vue Graphique
|
||
</div>
|
||
<button
|
||
class="editor-btn"
|
||
id="graph-full-vault"
|
||
title="Vue complète du vault"
|
||
style="
|
||
font-size: 0.65rem;
|
||
padding: 3px 6px;
|
||
flex-shrink: 0;
|
||
"
|
||
>
|
||
🌐 Tout
|
||
</button>
|
||
<span
|
||
style="
|
||
font-size: 0.6rem;
|
||
color: var(--text-muted);
|
||
flex-shrink: 0;
|
||
"
|
||
>Prof.</span
|
||
>
|
||
<input
|
||
type="range"
|
||
id="graph-depth"
|
||
min="0"
|
||
max="3"
|
||
value="1"
|
||
style="width: 40px; flex-shrink: 0"
|
||
title="Profondeur"
|
||
/>
|
||
<button
|
||
class="editor-btn"
|
||
id="graph-zoom-out"
|
||
title="Zoom arrière"
|
||
style="flex-shrink: 0"
|
||
>
|
||
<i
|
||
data-lucide="zoom-out"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="editor-btn"
|
||
id="graph-zoom-in"
|
||
title="Zoom avant"
|
||
style="flex-shrink: 0"
|
||
>
|
||
<i
|
||
data-lucide="zoom-in"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="editor-btn"
|
||
id="graph-reset"
|
||
title="Réinitialiser"
|
||
style="flex-shrink: 0"
|
||
>
|
||
<i
|
||
data-lucide="maximize"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="editor-btn"
|
||
id="graph-export"
|
||
title="Exporter PNG"
|
||
style="flex-shrink: 0"
|
||
>
|
||
<i
|
||
data-lucide="download"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="editor-btn"
|
||
id="graph-fullscreen"
|
||
title="Plein écran"
|
||
style="flex-shrink: 0"
|
||
>
|
||
<i
|
||
data-lucide="expand"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="editor-btn"
|
||
id="graph-close"
|
||
title="Fermer"
|
||
style="flex-shrink: 0"
|
||
>
|
||
<i
|
||
data-lucide="x"
|
||
style="width: 15px; height: 15px"
|
||
></i>
|
||
</button>
|
||
</div>
|
||
<!-- Line 2: centered search -->
|
||
<div style="display: flex; justify-content: center">
|
||
<div
|
||
style="
|
||
position: relative;
|
||
width: 100%;
|
||
max-width: 450px;
|
||
"
|
||
>
|
||
<i
|
||
data-lucide="search"
|
||
style="
|
||
position: absolute;
|
||
left: 10px;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 14px;
|
||
height: 14px;
|
||
color: var(--text-muted);
|
||
pointer-events: none;
|
||
"
|
||
></i>
|
||
<input
|
||
type="text"
|
||
id="graph-search"
|
||
placeholder="Rechercher ou #tag..."
|
||
style="
|
||
width: 100%;
|
||
font-size: 0.78rem;
|
||
padding: 5px 12px 5px 30px;
|
||
border-radius: 8px;
|
||
border: none;
|
||
background: var(--bg-secondary);
|
||
color: var(--text-primary);
|
||
outline: none;
|
||
box-shadow: inset 0 1px 3px
|
||
rgba(0, 0, 0, 0.2);
|
||
"
|
||
/>
|
||
<span
|
||
style="
|
||
position: absolute;
|
||
right: 10px;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
font-size: 0.6rem;
|
||
color: var(--text-muted);
|
||
opacity: 0.4;
|
||
pointer-events: none;
|
||
"
|
||
>Ctrl+survol</span
|
||
>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div
|
||
class="editor-body"
|
||
style="
|
||
flex: 1;
|
||
overflow: hidden;
|
||
position: relative;
|
||
padding: 0;
|
||
"
|
||
>
|
||
<canvas
|
||
id="graph-canvas"
|
||
style="width: 100%; height: 100%; cursor: grab"
|
||
></canvas>
|
||
<!-- Info panel: top-right, shows on hover, stays until closed -->
|
||
<div
|
||
id="graph-info-panel"
|
||
style="
|
||
display: none;
|
||
position: absolute;
|
||
top: 10px;
|
||
left: 10px;
|
||
max-width: 320px;
|
||
background: var(--bg-primary);
|
||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||
border-radius: 8px;
|
||
padding: 12px 14px;
|
||
font-size: 0.78rem;
|
||
color: var(--text-primary);
|
||
z-index: 10;
|
||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
|
||
"
|
||
>
|
||
<button
|
||
id="graph-info-close"
|
||
style="
|
||
position: absolute;
|
||
top: 6px;
|
||
right: 8px;
|
||
background: none;
|
||
border: none;
|
||
color: var(--text-muted);
|
||
cursor: pointer;
|
||
font-size: 1rem;
|
||
line-height: 1;
|
||
padding: 2px;
|
||
"
|
||
title="Fermer"
|
||
>
|
||
✕
|
||
</button>
|
||
<div id="graph-info-content"></div>
|
||
</div>
|
||
<!-- Preview panel: right sidebar, full height, shows on Ctrl+hover, stays until closed -->
|
||
<div
|
||
id="graph-preview-panel"
|
||
style="
|
||
display: none;
|
||
position: absolute;
|
||
top: 0;
|
||
right: 0;
|
||
width: 380px;
|
||
height: 100%;
|
||
background: var(--bg-primary);
|
||
border-left: 1px solid var(--border-color);
|
||
z-index: 9;
|
||
overflow-y: auto;
|
||
font-size: 0.8rem;
|
||
color: var(--text-primary);
|
||
box-shadow: -4px 0 16px rgba(0, 0, 0, 0.3);
|
||
"
|
||
>
|
||
<button
|
||
id="graph-preview-close"
|
||
style="
|
||
position: sticky;
|
||
top: 0;
|
||
float: right;
|
||
background: var(--bg-primary);
|
||
border: 1px solid var(--border-color);
|
||
border-radius: 4px;
|
||
color: var(--text-muted);
|
||
cursor: pointer;
|
||
font-size: 0.9rem;
|
||
padding: 2px 8px;
|
||
z-index: 1;
|
||
margin-bottom: -24px;
|
||
"
|
||
title="Fermer"
|
||
>
|
||
✕ Fermer
|
||
</button>
|
||
<div
|
||
id="graph-preview-content"
|
||
style="padding: 16px; padding-top: 8px"
|
||
></div>
|
||
</div>
|
||
<!-- Status bar + legend -->
|
||
<div
|
||
style="
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 4px 12px;
|
||
background: var(--bg-primary);
|
||
border-top: 1px solid var(--border-color);
|
||
font-size: 0.7rem;
|
||
color: var(--text-muted);
|
||
"
|
||
>
|
||
<span id="graph-status">—</span>
|
||
<div
|
||
style="
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
"
|
||
>
|
||
<label
|
||
style="
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 3px;
|
||
"
|
||
><input
|
||
type="checkbox"
|
||
id="graph-filter-dir"
|
||
checked
|
||
/>
|
||
🟦 Dossier</label
|
||
>
|
||
<label
|
||
style="
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 3px;
|
||
"
|
||
><input
|
||
type="checkbox"
|
||
id="graph-filter-md"
|
||
checked
|
||
/>
|
||
🟩 .md</label
|
||
>
|
||
<label
|
||
style="
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 3px;
|
||
"
|
||
><input
|
||
type="checkbox"
|
||
id="graph-filter-other"
|
||
checked
|
||
/>
|
||
⬜ Autre</label
|
||
>
|
||
<span style="opacity: 0.5">│</span>
|
||
<span>── Parent</span>
|
||
<span style="color: var(--accent-color, #2563eb)"
|
||
>┅┅ Wikilink</span
|
||
>
|
||
<span style="color: #e74c3c">← Backlink</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Help Modal -->
|
||
<div class="editor-modal" id="help-modal">
|
||
<div class="editor-container help-container">
|
||
<div class="editor-header">
|
||
<button
|
||
class="help-hamburger"
|
||
id="help-hamburger"
|
||
title="Sommaire"
|
||
aria-label="Afficher le sommaire"
|
||
onclick="
|
||
var n = document.getElementById('help-nav');
|
||
if (n) {
|
||
var d = n.style.display;
|
||
n.style.display =
|
||
d === 'none' || d === '' ? 'flex' : 'none';
|
||
}
|
||
"
|
||
>
|
||
<i
|
||
data-lucide="menu"
|
||
style="width: 18px; height: 18px"
|
||
></i>
|
||
</button>
|
||
<div class="editor-title" id="help-title">
|
||
Guide d'utilisation ObsiGate
|
||
</div>
|
||
<div class="editor-actions">
|
||
<button
|
||
class="editor-btn"
|
||
id="help-close"
|
||
title="Fermer l'aide"
|
||
aria-label="Fermer l'aide"
|
||
>
|
||
<i
|
||
data-lucide="x"
|
||
style="width: 16px; height: 16px"
|
||
></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="editor-body help-body" id="help-body">
|
||
<nav class="help-nav" id="help-nav">
|
||
<div class="help-nav-header">
|
||
<div class="help-nav-title">Sommaire</div>
|
||
</div>
|
||
<div class="help-nav-search-wrap">
|
||
<input
|
||
type="text"
|
||
class="help-nav-search"
|
||
id="help-nav-search"
|
||
placeholder="Rechercher dans l'aide..."
|
||
autocomplete="off"
|
||
spellcheck="false"
|
||
/>
|
||
<button
|
||
class="help-search-clear"
|
||
id="help-search-clear"
|
||
title="Effacer la recherche"
|
||
aria-label="Effacer"
|
||
onclick="
|
||
var s =
|
||
document.getElementById(
|
||
'help-nav-search',
|
||
);
|
||
if (s) {
|
||
s.value = '';
|
||
s.dispatchEvent(new Event('input'));
|
||
s.focus();
|
||
}
|
||
"
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
<ul class="help-nav-list" id="help-nav-list">
|
||
<li>
|
||
<a href="#help-intro" class="help-nav-link"
|
||
>📘 Introduction</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-interface" class="help-nav-link"
|
||
>🧭 Interface</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-navigation" class="help-nav-link"
|
||
>🗺️ Navigation</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-tabs" class="help-nav-link"
|
||
>📑 Onglets</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-recherche" class="help-nav-link"
|
||
>🔍 Recherche</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-tags" class="help-nav-link"
|
||
>🏷️ Tags</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-fichiers" class="help-nav-link"
|
||
>📁 Fichiers</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-edition" class="help-nav-link"
|
||
>✏️ Édition</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-graphe" class="help-nav-link"
|
||
>🗺️ Graphe</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-ia" class="help-nav-link"
|
||
>🤖 IA Éditeur</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-palette" class="help-nav-link"
|
||
>⌨️ Palette</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-raccourcis" class="help-nav-link"
|
||
>⌨️ Raccourcis</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-partage" class="help-nav-link"
|
||
>🔗 Partage</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-webhooks" class="help-nav-link"
|
||
>🪝 Webhooks</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a
|
||
href="#help-sauvegardes"
|
||
class="help-nav-link"
|
||
>💾 Sauvegardes</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-securite" class="help-nav-link"
|
||
>🛡️ Sécurité</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a
|
||
href="#help-personnalisation"
|
||
class="help-nav-link"
|
||
>🎨 Personnalisation</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-astuces" class="help-nav-link"
|
||
>💡 Astuces</a
|
||
>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
<div class="help-content">
|
||
<section class="help-section help-hero" id="help-intro">
|
||
<div class="help-hero-copy">
|
||
<div class="help-kicker">Guide officiel</div>
|
||
<h1>📘 Bienvenue dans ObsiGate</h1>
|
||
<p class="help-lead">
|
||
ObsiGate est votre porte d'entrée web vers
|
||
vos vaults Obsidian. Accédez, naviguez et
|
||
recherchez dans toutes vos notes depuis
|
||
n'importe quel appareil via une interface
|
||
moderne et responsive.
|
||
</p>
|
||
<div class="help-badges">
|
||
<span class="help-badge"
|
||
>⚡ Navigation rapide</span
|
||
>
|
||
<span class="help-badge"
|
||
>🗂️ Multi-vault</span
|
||
>
|
||
<span class="help-badge"
|
||
>🏷️ Tags intelligents</span
|
||
>
|
||
<span class="help-badge"
|
||
>📝 Lecture et édition</span
|
||
>
|
||
<span class="help-badge"
|
||
>🔍 Recherche TF-IDF</span
|
||
>
|
||
</div>
|
||
</div>
|
||
<div class="help-hero-visual" aria-hidden="true">
|
||
<div class="help-stat-card">
|
||
<span class="help-stat-label"
|
||
>Expérience</span
|
||
>
|
||
<strong>Simple</strong>
|
||
</div>
|
||
<div class="help-stat-card">
|
||
<span class="help-stat-label"
|
||
>Recherche</span
|
||
>
|
||
<strong>Instantanée</strong>
|
||
</div>
|
||
<div class="help-stat-card">
|
||
<span class="help-stat-label">Accès</span>
|
||
<strong>Multi-vault</strong>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-interface">
|
||
<h2>🧭 Interface utilisateur</h2>
|
||
|
||
<h3>En-tête</h3>
|
||
<p>
|
||
La barre supérieure contient les éléments
|
||
essentiels :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Bouton menu hamburger</strong>
|
||
(mobile) : Affiche/masque la sidebar
|
||
</li>
|
||
<li>
|
||
<strong>Bouton toggle sidebar</strong>
|
||
(desktop) : Masque la sidebar pour plus
|
||
d'espace
|
||
</li>
|
||
<li>
|
||
<strong>Logo ObsiGate</strong> : Retour à
|
||
l'accueil
|
||
</li>
|
||
<li>
|
||
<strong>Barre de recherche</strong> :
|
||
Recherche globale avec autocomplétion
|
||
</li>
|
||
<li>
|
||
<strong>Indicateur de vault</strong> :
|
||
Affiche le contexte actif (All, vault1,
|
||
etc.)
|
||
</li>
|
||
<li>
|
||
<strong>Menu Options</strong> : Accès aux
|
||
paramètres, thème, aide
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Sidebar (barre latérale)</h3>
|
||
<p>La sidebar est divisée en deux onglets :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Vaults</strong> : Arborescence des
|
||
fichiers et dossiers
|
||
</li>
|
||
<li>
|
||
<strong>Tags</strong> : Nuage de tags
|
||
cliquables
|
||
</li>
|
||
</ul>
|
||
<p>Fonctionnalités de la sidebar :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Filtrage</strong> : Barre de
|
||
recherche pour filtrer fichiers/tags
|
||
</li>
|
||
<li>
|
||
<strong>Sélection rapide</strong> : Dropdown
|
||
pour changer de vault
|
||
</li>
|
||
<li>
|
||
<strong>Redimensionnement</strong> : Glissez
|
||
le bord droit pour ajuster la largeur
|
||
</li>
|
||
<li>
|
||
<strong>Masquage</strong> : Cliquez sur
|
||
l'icône sidebar dans le header
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Zone de contenu</h3>
|
||
<p>La zone centrale affiche :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Breadcrumb</strong> : Chemin du
|
||
fichier (cliquable pour repositionner la
|
||
sidebar)
|
||
</li>
|
||
<li>
|
||
<strong>Titre et tags</strong> : Métadonnées
|
||
du fichier
|
||
</li>
|
||
<li>
|
||
<strong>Boutons d'action</strong> : Copier,
|
||
Source, Télécharger, Éditer, Ouvrir dans
|
||
nouvelle fenêtre
|
||
</li>
|
||
<li>
|
||
<strong>Contenu rendu</strong> : Markdown
|
||
avec wikilinks et images
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-navigation">
|
||
<h2>🗺️ Navigation</h2>
|
||
|
||
<h3>Arborescence des vaults</h3>
|
||
<p>
|
||
Cliquez sur un vault pour l'ouvrir et voir son
|
||
contenu. Les dossiers affichent un chevron et un
|
||
badge avec le nombre d'éléments.
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Développer/Réduire</strong> :
|
||
Cliquez sur un dossier
|
||
</li>
|
||
<li>
|
||
<strong>Ouvrir un fichier</strong> : Cliquez
|
||
sur le nom du fichier
|
||
</li>
|
||
<li>
|
||
<strong>Icônes</strong> : Chaque type de
|
||
fichier a son icône (markdown, code, etc.)
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Filtrage de la sidebar</h3>
|
||
<p>
|
||
Utilisez la barre de filtrage en haut de la
|
||
sidebar pour rechercher rapidement :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Recherche instantanée</strong> :
|
||
Tapez pour filtrer fichiers et dossiers
|
||
</li>
|
||
<li>
|
||
<strong>Case-sensitive</strong> : Bouton
|
||
"Aa" pour respecter la casse
|
||
</li>
|
||
<li>
|
||
<strong>Effacer</strong> : Bouton "×" pour
|
||
réinitialiser le filtre
|
||
</li>
|
||
<li>
|
||
<strong>Résultats groupés</strong> :
|
||
Affichage par vault avec chemins complets
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Breadcrumb et repositionnement</h3>
|
||
<p>
|
||
Le chemin affiché au-dessus du contenu est
|
||
interactif :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Cliquez sur le vault</strong> :
|
||
Focus sur le vault dans la sidebar
|
||
</li>
|
||
<li>
|
||
<strong>Cliquez sur un segment</strong> :
|
||
Navigation vers ce dossier
|
||
</li>
|
||
<li>
|
||
<strong>Auto-scroll</strong> : La sidebar se
|
||
positionne automatiquement
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Sélection de vault</h3>
|
||
<p>
|
||
Changez de contexte pour filtrer l'affichage :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Menu header</strong> : Dropdown
|
||
"Vault" dans le menu Options
|
||
</li>
|
||
<li>
|
||
<strong>Sidebar dropdown</strong> :
|
||
Sélection rapide en haut de l'onglet Vaults
|
||
</li>
|
||
<li>
|
||
<strong>Tous les vaults</strong> : Vue
|
||
globale de tous vos contenus
|
||
</li>
|
||
<li>
|
||
<strong>Vault spécifique</strong> : Focus
|
||
sur un seul vault
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-tabs">
|
||
<h2>📑 Gestion des onglets</h2>
|
||
<p>
|
||
ObsiGate supporte l'ouverture de plusieurs
|
||
fichiers simultanément dans des onglets.
|
||
</p>
|
||
|
||
<h3>Ouverture d'onglets</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Simple clic</strong> : Ouvre le
|
||
fichier dans un onglet temporaire (aperçu,
|
||
italique)
|
||
</li>
|
||
<li>
|
||
<strong>Double clic</strong> : Ouvre le
|
||
fichier dans un onglet persistant
|
||
</li>
|
||
<li>
|
||
<strong>Navigation récente</strong> :
|
||
L'onglet "Récent" dans la sidebar liste vos
|
||
derniers fichiers
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Navigation entre onglets</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Clic sur un onglet</strong> : Active
|
||
l'onglet
|
||
</li>
|
||
<li>
|
||
<strong>Ctrl+Tab</strong> : Onglet suivant
|
||
</li>
|
||
<li>
|
||
<strong>Ctrl+Shift+Tab</strong> : Onglet
|
||
précédent
|
||
</li>
|
||
<li>
|
||
<strong>Ctrl+W</strong> : Fermer l'onglet
|
||
actif
|
||
</li>
|
||
<li>
|
||
<strong>Bouton ✕</strong> : Ferme l'onglet
|
||
(sauf s'il est seul)
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Fonctionnalités</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Barre d'onglets</strong> : Affichage
|
||
horizontal avec le nom du fichier et son
|
||
icône
|
||
</li>
|
||
<li>
|
||
<strong>Onglet actif</strong> : Surligné en
|
||
couleur d'accentuation
|
||
</li>
|
||
<li>
|
||
<strong>Prévisualisation</strong> : Un
|
||
onglet temporaire (italique) est remplacé
|
||
par le prochain clic
|
||
</li>
|
||
<li>
|
||
<strong>Onglets persistants</strong> :
|
||
Restent ouverts jusqu'à fermeture manuelle
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-recherche">
|
||
<h2>🔍 Recherche</h2>
|
||
|
||
<h3>Recherche simple</h3>
|
||
<p>
|
||
Tapez dans la barre de recherche en haut pour
|
||
lancer une recherche fulltext :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Recherche dans tout</strong> :
|
||
Titre, contenu, tags, chemins
|
||
</li>
|
||
<li>
|
||
<strong>Scoring intelligent</strong> :
|
||
Résultats classés par pertinence TF-IDF
|
||
</li>
|
||
<li>
|
||
<strong>Snippets surlignés</strong> :
|
||
Extraits avec termes en surbrillance
|
||
</li>
|
||
<li>
|
||
<strong>Pagination</strong> : Navigation par
|
||
pages de 50 résultats
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Opérateurs avancés</h3>
|
||
<p>
|
||
Utilisez des opérateurs pour affiner votre
|
||
recherche :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<code>tag:docker</code> ou
|
||
<code>#docker</code> : Filtrer par tag
|
||
</li>
|
||
<li>
|
||
<code>vault:IT</code> : Rechercher dans un
|
||
vault spécifique
|
||
</li>
|
||
<li>
|
||
<code>title:kubernetes</code> : Chercher
|
||
dans les titres uniquement
|
||
</li>
|
||
<li>
|
||
<code>path:recettes/soupes</code> : Filtrer
|
||
par chemin
|
||
</li>
|
||
<li>
|
||
<code>ext:md</code> : Filtrer par type de
|
||
fichier
|
||
</li>
|
||
<li>
|
||
<code>"phrase exacte"</code> : Recherche de
|
||
phrase entre guillemets
|
||
</li>
|
||
</ul>
|
||
<p>
|
||
<strong>Exemples</strong> :
|
||
<code>ext:sh</code> recherche dans les scripts
|
||
bash, <code>ext:py</code> dans les scripts
|
||
Python, <code>ext:md</code> dans les fichiers
|
||
Markdown.
|
||
</p>
|
||
<p>
|
||
<strong>Exemple combiné</strong> :
|
||
<code
|
||
>tag:linux vault:IT ext:md serveur web</code
|
||
>
|
||
recherche "serveur web" dans les fichiers
|
||
Markdown du vault IT avec le tag linux.
|
||
</p>
|
||
|
||
<h3>Autocomplétion</h3>
|
||
<p>
|
||
L'autocomplétion vous aide à trouver rapidement
|
||
:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Historique</strong> : Les 50
|
||
dernières recherches (localStorage)
|
||
</li>
|
||
<li>
|
||
<strong>Fichiers</strong> : Suggestions de
|
||
titres de fichiers
|
||
</li>
|
||
<li>
|
||
<strong>Tags</strong> : Suggestions de tags
|
||
avec compteurs
|
||
</li>
|
||
<li>
|
||
<strong>Navigation clavier</strong> : ↑/↓
|
||
pour naviguer, Enter pour sélectionner
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Chips de filtres actifs</h3>
|
||
<p>
|
||
Les opérateurs utilisés s'affichent sous forme
|
||
de chips colorés :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Visualisation</strong> : Voir d'un
|
||
coup d'œil les filtres actifs
|
||
</li>
|
||
<li>
|
||
<strong>Suppression</strong> : Cliquez sur
|
||
"×" pour retirer un filtre
|
||
</li>
|
||
<li>
|
||
<strong>Couleurs</strong> : Chaque type
|
||
d'opérateur a sa couleur
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Facettes et tri</h3>
|
||
<p>
|
||
Les résultats incluent des facettes pour affiner
|
||
:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Facettes tags</strong> : Compteurs
|
||
par tag dans les résultats
|
||
</li>
|
||
<li>
|
||
<strong>Facettes vaults</strong> : Compteurs
|
||
par vault
|
||
</li>
|
||
<li>
|
||
<strong>Tri par pertinence</strong> : Score
|
||
TF-IDF (défaut)
|
||
</li>
|
||
<li>
|
||
<strong>Tri par date</strong> : Dernière
|
||
modification
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-tags">
|
||
<h2>🏷️ Tags</h2>
|
||
|
||
<h3>Tag cloud</h3>
|
||
<p>
|
||
L'onglet Tags de la sidebar affiche un nuage de
|
||
tags :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Tous les tags</strong> : Extraits
|
||
des frontmatters YAML et inline (#tag)
|
||
</li>
|
||
<li>
|
||
<strong>Cliquable</strong> : Cliquez pour
|
||
filtrer les résultats
|
||
</li>
|
||
<li>
|
||
<strong>Filtrage</strong> : Utilisez la
|
||
barre de filtrage pour chercher un tag
|
||
</li>
|
||
<li>
|
||
<strong>Contexte vault</strong> : Les tags
|
||
s'adaptent au vault sélectionné
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Tags inline vs frontmatter</h3>
|
||
<p>ObsiGate supporte deux types de tags :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Frontmatter YAML</strong> :
|
||
<code>tags: [docker, linux]</code> ou
|
||
<code>tags: docker, linux</code>
|
||
</li>
|
||
<li>
|
||
<strong>Inline</strong> :
|
||
<code>#docker</code> dans le contenu
|
||
markdown
|
||
</li>
|
||
<li>
|
||
<strong>Fusion automatique</strong> : Les
|
||
deux types sont combinés
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Filtrage de tags template</h3>
|
||
<p>
|
||
Dans les Configurations, vous pouvez masquer les
|
||
tags de template :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Patterns wildcards</strong> : Ex:
|
||
<code>#<% ... %></code> ou
|
||
<code>#{{ ... }}</code>
|
||
</li>
|
||
<li>
|
||
<strong>Regex générée</strong> : Aperçu de
|
||
la regex appliquée
|
||
</li>
|
||
<li>
|
||
<strong>Ajout/Suppression</strong> : Gérez
|
||
vos patterns de filtrage
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-fichiers">
|
||
<h2>📄 Fichiers</h2>
|
||
|
||
<h3>Visualisation</h3>
|
||
<p>Les fichiers markdown sont rendus avec :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Wikilinks cliquables</strong> :
|
||
<code>[[lien]]</code> et
|
||
<code>[[lien|texte]]</code>
|
||
</li>
|
||
<li>
|
||
<strong>Images Obsidian</strong> : Support
|
||
de <code>![[image.png]]</code>
|
||
</li>
|
||
<li>
|
||
<strong>Syntax highlighting</strong> :
|
||
Coloration des blocs de code
|
||
</li>
|
||
<li>
|
||
<strong>Tables, listes, quotes</strong> :
|
||
Rendu complet du markdown
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Actions sur fichiers</h3>
|
||
<p>Boutons disponibles au-dessus du contenu :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Copier</strong> : Copie le contenu
|
||
source dans le presse-papiers
|
||
</li>
|
||
<li>
|
||
<strong>Source</strong> : Affiche/masque le
|
||
markdown brut
|
||
</li>
|
||
<li>
|
||
<strong>Télécharger</strong> : Télécharge le
|
||
fichier
|
||
</li>
|
||
<li>
|
||
<strong>Éditer</strong> : Ouvre l'éditeur
|
||
CodeMirror
|
||
</li>
|
||
<li>
|
||
<strong
|
||
>Ouvrir dans nouvelle fenêtre</strong
|
||
>
|
||
: Ouvre le fichier dans un nouvel onglet
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Édition avec CodeMirror 6</h3>
|
||
<p>L'éditeur intégré offre :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Coloration syntaxique</strong> :
|
||
Support de nombreux langages
|
||
</li>
|
||
<li>
|
||
<strong>Numéros de ligne</strong> :
|
||
Navigation facile
|
||
</li>
|
||
<li>
|
||
<strong>Autocomplétion</strong> :
|
||
Suggestions contextuelles
|
||
</li>
|
||
<li>
|
||
<strong>Recherche</strong> : Ctrl+F pour
|
||
chercher dans le fichier
|
||
</li>
|
||
<li>
|
||
<strong>Sauvegarde</strong> : Bouton ✓ pour
|
||
enregistrer
|
||
</li>
|
||
<li>
|
||
<strong>Suppression</strong> : Bouton
|
||
corbeille pour supprimer
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Types de fichiers supportés</h3>
|
||
<p>ObsiGate indexe et affiche :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Markdown</strong> : .md (rendu
|
||
complet)
|
||
</li>
|
||
<li>
|
||
<strong>Code</strong> : .py, .js, .ts, .jsx,
|
||
.tsx, .java, .c, .cpp, .rs, .go, etc.
|
||
</li>
|
||
<li>
|
||
<strong>Config</strong> : .json, .yaml,
|
||
.yml, .toml, .xml, .ini, .env
|
||
</li>
|
||
<li>
|
||
<strong>Scripts</strong> : .sh, .bash, .ps1,
|
||
.bat
|
||
</li>
|
||
<li>
|
||
<strong>Web</strong> : .html, .css, .scss
|
||
</li>
|
||
<li>
|
||
<strong>Autres</strong> : .txt, .log, .sql,
|
||
.csv
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- ✏️ Édition -->
|
||
<section class="help-section" id="help-edition">
|
||
<h2>✏️ Édition avancée</h2>
|
||
|
||
<h3>Éditeur CodeMirror 6</h3>
|
||
<p>
|
||
L'éditeur intégré offre une expérience complète
|
||
d'édition :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Coloration syntaxique</strong> :
|
||
Python, JS, HTML, CSS, Java, C++, Rust, Go
|
||
et bien d'autres
|
||
</li>
|
||
<li>
|
||
<strong>Numéros de ligne</strong> :
|
||
Navigation facilitée dans les fichiers longs
|
||
</li>
|
||
<li>
|
||
<strong>Find in page</strong> : Ctrl+F pour
|
||
chercher dans le fichier (casse, regex, mot
|
||
entier)
|
||
</li>
|
||
<li>
|
||
<strong>Sauvegarde automatique</strong> :
|
||
Auto-save silencieux après 2s d'inactivité,
|
||
flash vert de confirmation
|
||
</li>
|
||
<li>
|
||
<strong>Bouton ✓</strong> : Sauvegarde
|
||
manuelle
|
||
</li>
|
||
<li>
|
||
<strong>Bouton 🗑️</strong> : Suppression du
|
||
fichier
|
||
</li>
|
||
<li>
|
||
<strong>Barre d'outils AI</strong> :
|
||
Complétion, réécriture, traduction (voir
|
||
section <a href="#help-ia">IA</a>)
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- 🗺️ Graphe -->
|
||
<section class="help-section" id="help-graphe">
|
||
<h2>🗺️ Vue Graphe</h2>
|
||
<p>
|
||
La vue graphe offre une visualisation
|
||
interactive des connexions entre vos notes via
|
||
les wikilinks.
|
||
</p>
|
||
|
||
<h3>Ouverture</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Menu contextuel</strong> : Clic
|
||
droit sur un vault ou dossier → Vue
|
||
Graphique
|
||
</li>
|
||
<li>
|
||
<strong>Bouton dédié</strong> : Dans la
|
||
barre d'outils (le cas échéant)
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Interaction</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Zoom/Pan</strong> : Molette pour
|
||
zoomer, cliquer-glisser pour se déplacer
|
||
</li>
|
||
<li>
|
||
<strong>Slider de profondeur</strong> :
|
||
Contrôle la profondeur d'exploration (0-3)
|
||
</li>
|
||
<li>
|
||
<strong>Filtre par tag</strong> : N'affiche
|
||
que les nœuds avec un tag spécifique
|
||
</li>
|
||
<li>
|
||
<strong>Filtre par type</strong> :
|
||
Inclut/exclut fichiers, dossiers, markdown,
|
||
autres
|
||
</li>
|
||
<li>
|
||
<strong>Recherche visuelle</strong> : Barre
|
||
de recherche pour surligner des nœuds
|
||
</li>
|
||
<li>
|
||
<strong>Mode focus</strong> : Centre la vue
|
||
sur un nœud spécifique
|
||
</li>
|
||
<li>
|
||
<strong>Navigation ← → ↑</strong> :
|
||
Historique de navigation entre les nœuds
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Affichage</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Nœuds</strong> : Fichiers (carrés)
|
||
et dossiers (cercles) avec icônes
|
||
</li>
|
||
<li>
|
||
<strong>Arêtes</strong> : Wikilinks sortants
|
||
(bleu) et backlinks entrants (vert)
|
||
</li>
|
||
<li>
|
||
<strong>Panneau d'info</strong> :
|
||
Métadonnées du nœud (tags, liens, chemin)
|
||
</li>
|
||
<li>
|
||
<strong>Ctrl+survol</strong> : Aperçu du
|
||
contenu de la note sans naviguer
|
||
</li>
|
||
<li>
|
||
<strong>Plein écran</strong> : Bouton pour
|
||
agrandir la vue
|
||
</li>
|
||
<li>
|
||
<strong>Export PNG</strong> : Sauvegardez le
|
||
graphe en image
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Performance</h3>
|
||
<p>
|
||
La vue utilise l'algorithme Barnes-Hut pour
|
||
calculer la disposition en O(n log n),
|
||
garantissant des performances fluides même avec
|
||
des centaines de nœuds.
|
||
</p>
|
||
</section>
|
||
|
||
<section
|
||
class="help-section"
|
||
id="help-personnalisation"
|
||
>
|
||
<h2>🎨 Personnalisation</h2>
|
||
|
||
<h3>Thème clair/sombre</h3>
|
||
<p>Basculez entre les thèmes :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Menu Options</strong> : Cliquez sur
|
||
"Thème" dans le menu
|
||
</li>
|
||
<li>
|
||
<strong>Raccourci</strong> :
|
||
<code>Ctrl+T</code>
|
||
</li>
|
||
<li>
|
||
<strong>Persistance</strong> : Votre choix
|
||
est sauvegardé en localStorage
|
||
</li>
|
||
<li>
|
||
<strong>Highlight.js</strong> : Les blocs de
|
||
code s'adaptent au thème
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Redimensionnement de la sidebar</h3>
|
||
<p>
|
||
Sur desktop, ajustez la largeur de la sidebar :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Handle de redimensionnement</strong>
|
||
: Bordure droite de la sidebar
|
||
</li>
|
||
<li>
|
||
<strong>Glisser-déposer</strong> : Cliquez
|
||
et glissez pour ajuster
|
||
</li>
|
||
<li>
|
||
<strong>Limites</strong> : Min 200px, Max
|
||
500px
|
||
</li>
|
||
<li>
|
||
<strong>Persistance</strong> : La largeur
|
||
est sauvegardée
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Configuration avancée</h3>
|
||
<p>
|
||
Le modal Configurations (menu Options) permet de
|
||
:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Paramètres de recherche</strong> :
|
||
Délai debounce, résultats par page, timeout
|
||
</li>
|
||
<li>
|
||
<strong>Paramètres backend</strong> :
|
||
Workers, boosts TF-IDF, expansions préfixe
|
||
</li>
|
||
<li>
|
||
<strong>Filtrage de tags</strong> : Patterns
|
||
pour masquer les tags template
|
||
</li>
|
||
<li>
|
||
<strong>Diagnostics</strong> : Stats index,
|
||
mémoire, moteur de recherche
|
||
</li>
|
||
<li>
|
||
<strong>Réindexation</strong> : Forcer un
|
||
rescan des vaults
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- ⌨️ Palette de commandes -->
|
||
<section class="help-section" id="help-palette">
|
||
<h2>⌨️ Palette de commandes</h2>
|
||
<p>
|
||
La palette de commandes permet d'accéder
|
||
rapidement aux fichiers et aux actions sans
|
||
utiliser la souris.
|
||
</p>
|
||
|
||
<h3>Ouverture</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Ctrl+Shift+Espace</strong> : Palette
|
||
de fichiers (recherche par titre)
|
||
</li>
|
||
<li>
|
||
<strong>Ctrl+Alt+Espace</strong> : Palette
|
||
de commandes (liste d'actions)
|
||
</li>
|
||
<li>
|
||
<strong>Tab</strong> : Bascule entre mode
|
||
fichiers et mode commandes
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Mode fichiers</h3>
|
||
<p>
|
||
Tapez le nom d'un fichier pour le trouver
|
||
rapidement. La recherche utilise l'API
|
||
<code>/api/suggest</code> pour des suggestions
|
||
instantanées. Appuyez sur <kbd>Enter</kbd> pour
|
||
ouvrir le fichier sélectionné.
|
||
</p>
|
||
|
||
<h3>Mode commandes</h3>
|
||
<p>
|
||
Tapez <code>></code> (ou Ctrl+Alt+Espace)
|
||
pour voir la liste des actions disponibles :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
🏠 <strong>Accueil</strong> : Retour à
|
||
l'accueil
|
||
</li>
|
||
<li>
|
||
✏️ <strong>Éditer fichier courant</strong> :
|
||
Ouvre l'éditeur sur l'onglet actif
|
||
</li>
|
||
<li>
|
||
🪟 <strong>Pop-out</strong> : Ouvre le
|
||
document dans une fenêtre détachée
|
||
</li>
|
||
<li>
|
||
📄 <strong>Créer fichier markdown</strong> :
|
||
Crée un nouveau fichier .md et l'ouvre dans
|
||
l'éditeur
|
||
</li>
|
||
<li>
|
||
🗑️
|
||
<strong>Supprimer fichier courant</strong> :
|
||
Supprime le fichier de l'onglet actif
|
||
</li>
|
||
<li>
|
||
📁 <strong>Créer répertoire</strong> : Crée
|
||
un nouveau dossier
|
||
</li>
|
||
<li>
|
||
🗑️ <strong>Supprimer répertoire</strong> :
|
||
Supprime un dossier et son contenu
|
||
</li>
|
||
<li>
|
||
🌓 <strong>Changer le thème</strong> :
|
||
Bascule clair/sombre
|
||
</li>
|
||
<li>
|
||
🔄 <strong>Réindexer</strong> : Force la
|
||
réindexation complète
|
||
</li>
|
||
<li>
|
||
❓ <strong>Aide</strong> : Ouvre ce guide
|
||
</li>
|
||
<li>
|
||
⚙️ <strong>Configuration</strong> : Ouvre
|
||
les paramètres
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li>
|
||
<kbd>↑</kbd> <kbd>↓</kbd> : Se déplacer dans
|
||
la liste
|
||
</li>
|
||
<li><kbd>Enter</kbd> : Ouvrir/sélectionner</li>
|
||
<li><kbd>Esc</kbd> : Fermer la palette</li>
|
||
<li>
|
||
<kbd>Tab</kbd> : Basculer entre fichiers et
|
||
commandes
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-raccourcis">
|
||
<h2>⌨️ Raccourcis clavier</h2>
|
||
|
||
<h3>Navigation</h3>
|
||
<ul>
|
||
<li>
|
||
<code>Ctrl+K</code> ou <code>Cmd+K</code> :
|
||
Focaliser la barre de recherche
|
||
</li>
|
||
<li>
|
||
<code>/</code> : Focaliser la recherche
|
||
(hors champ texte)
|
||
</li>
|
||
<li>
|
||
<code>Escape</code> : Fermer les suggestions
|
||
/ quitter la recherche
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Recherche et autocomplétion</h3>
|
||
<ul>
|
||
<li>
|
||
<code>↑</code> / <code>↓</code> : Naviguer
|
||
dans les suggestions
|
||
</li>
|
||
<li>
|
||
<code>Enter</code> : Sélectionner la
|
||
suggestion active ou lancer la recherche
|
||
</li>
|
||
<li>
|
||
<code>Escape</code> : Fermer le dropdown de
|
||
suggestions
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Interface</h3>
|
||
<ul>
|
||
<li>
|
||
<code>Ctrl+T</code> : Basculer le thème
|
||
clair/sombre
|
||
</li>
|
||
<li>
|
||
<code>Ctrl+Shift+Espace</code> : Palette de
|
||
fichiers
|
||
</li>
|
||
<li>
|
||
<code>Ctrl+Alt+Espace</code> : Palette de
|
||
commandes
|
||
</li>
|
||
<li>
|
||
<code>Escape</code> : Fermer la palette /
|
||
les suggestions
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Onglets</h3>
|
||
<ul>
|
||
<li>
|
||
<code>Ctrl+W</code> : Fermer l'onglet actif
|
||
</li>
|
||
<li><code>Ctrl+Tab</code> : Onglet suivant</li>
|
||
<li>
|
||
<code>Ctrl+Shift+Tab</code> : Onglet
|
||
précédent
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Éditeur CodeMirror</h3>
|
||
<ul>
|
||
<li>
|
||
<code>Ctrl+F</code> : Rechercher dans le
|
||
fichier
|
||
</li>
|
||
<li><code>Ctrl+Z</code> : Annuler</li>
|
||
<li><code>Ctrl+Y</code> : Refaire</li>
|
||
<li>
|
||
<code>Ctrl+S</code> : Sauvegarder (si
|
||
configuré)
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-ai">
|
||
<h2>🤖 Intelligence Artificielle dans l'Éditeur</h2>
|
||
<p>
|
||
ObsiGate intègre un assistant IA directement
|
||
dans l'éditeur de texte. Pour l'activer,
|
||
configurez au moins un provider AI dans le
|
||
fichier <code>.env</code> (DeepSeek, OpenRouter
|
||
ou Gemini).
|
||
</p>
|
||
|
||
<h3>Activation</h3>
|
||
<ol>
|
||
<li>
|
||
Ajoutez votre clé API dans
|
||
<code>.env</code> :
|
||
<code>DEEPSEEK_API_KEY=sk-...</code>
|
||
</li>
|
||
<li>
|
||
Redémarrez le conteneur :
|
||
<code
|
||
>docker compose down && docker compose
|
||
up -d --build</code
|
||
>
|
||
</li>
|
||
<li>
|
||
Ouvrez un fichier en mode Édition (bouton ✏️
|
||
Éditer)
|
||
</li>
|
||
<li>
|
||
La barre d'outils AI apparaît sous le titre
|
||
de l'éditeur
|
||
</li>
|
||
</ol>
|
||
|
||
<h3>Barre d'outils AI</h3>
|
||
<p>
|
||
La barre d'outils contient les boutons suivants
|
||
:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>✦ AI</strong> — Complétion inline
|
||
(<kbd>Ctrl+J</kbd>). Complète
|
||
automatiquement le texte là où se trouve le
|
||
curseur.
|
||
</li>
|
||
<li>
|
||
<strong>Éditer ▾</strong> — Menu de
|
||
modification du texte sélectionné :
|
||
<ul>
|
||
<li>
|
||
🪄
|
||
<strong>Improve writing</strong> :
|
||
Améliore la qualité, la clarté et le
|
||
flux du texte
|
||
</li>
|
||
<li>
|
||
🔤
|
||
<strong
|
||
>Fix spelling & grammar</strong
|
||
>
|
||
: Corrige les fautes d'orthographe
|
||
et de grammaire
|
||
</li>
|
||
<li>
|
||
📏 <strong>Make shorter</strong> :
|
||
Rend le texte plus concis tout en
|
||
préservant l'information
|
||
</li>
|
||
<li>
|
||
📐 <strong>Make longer</strong> :
|
||
Ajoute des détails, exemples ou
|
||
explications
|
||
</li>
|
||
<li>
|
||
📋
|
||
<strong>Simplify language</strong> :
|
||
Simplifie le langage, évite le
|
||
jargon
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<strong>Ton ▾</strong> — Change le ton du
|
||
texte :
|
||
<ul>
|
||
<li>
|
||
💼 <strong>Professional</strong> :
|
||
Ton formel et professionnel
|
||
</li>
|
||
<li>
|
||
💬 <strong>Casual</strong> : Ton
|
||
décontracté et conversationnel
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<strong>Traduire ▾</strong> — Traduit le
|
||
texte sélectionné vers une autre langue :
|
||
<ul>
|
||
<li>
|
||
🇬🇧 English · 🇨🇳 Chinese · 🇯🇵
|
||
Japanese · 🇩🇪 German · 🇫🇷 French ·
|
||
🇪🇸 Spanish
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<strong>Générer ▾</strong> — Génère du
|
||
contenu à partir de la sélection :
|
||
<ul>
|
||
<li>
|
||
ℹ️ <strong>Explain this</strong> :
|
||
Explique le texte sélectionné de
|
||
façon claire
|
||
</li>
|
||
<li>
|
||
📝 <strong>Summarize</strong> :
|
||
Résume le texte de façon concise
|
||
</li>
|
||
<li>
|
||
✏️
|
||
<strong>Continue writing</strong> :
|
||
Continue l'écriture à partir du
|
||
texte
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<strong>💬 Réécrire</strong> — Réécrit le
|
||
texte selon vos instructions personnalisées.
|
||
Une boîte de dialogue vous demande votre
|
||
instruction.
|
||
</li>
|
||
<li>
|
||
<strong>🧰 Boîte ▾</strong> — Outils de
|
||
conversion :
|
||
<ul>
|
||
<li>
|
||
📋
|
||
<strong>Convert to list</strong> :
|
||
Transforme le texte en liste
|
||
Markdown
|
||
</li>
|
||
<li>
|
||
📊
|
||
<strong>Convert to table</strong> :
|
||
Transforme en tableau Markdown
|
||
</li>
|
||
<li>
|
||
⚙️
|
||
<strong
|
||
>Generate frontmatter</strong
|
||
>
|
||
: Génère un bloc YAML frontmatter
|
||
</li>
|
||
<li>
|
||
🔷
|
||
<strong>Convert to canvas</strong> :
|
||
Convertit en diagramme Mermaid.js
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Indicateurs visuels</h3>
|
||
<ul>
|
||
<li>
|
||
Pendant une requête AI, un toast
|
||
<strong
|
||
>⏳ AI: traitement en cours...</strong
|
||
>
|
||
s'affiche
|
||
</li>
|
||
<li>
|
||
Une fois terminé,
|
||
<strong>AI: texte traité ✓</strong> confirme
|
||
le succès
|
||
</li>
|
||
<li>
|
||
En cas d'erreur de clé API :
|
||
<strong>AI: clé API invalide</strong>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Sauvegarde automatique</h3>
|
||
<p>
|
||
L'éditeur sauvegarde automatiquement après 2
|
||
secondes d'inactivité. Le bouton de sauvegarde
|
||
<strong>flashe en vert</strong> brièvement pour
|
||
confirmer.
|
||
</p>
|
||
|
||
<h3>Providers supportés</h3>
|
||
<table>
|
||
<tr>
|
||
<th>Provider</th>
|
||
<th>Variable .env</th>
|
||
<th>Modèle par défaut</th>
|
||
</tr>
|
||
<tr>
|
||
<td>DeepSeek</td>
|
||
<td><code>DEEPSEEK_API_KEY</code></td>
|
||
<td><code>deepseek-chat</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>OpenRouter</td>
|
||
<td><code>OPENROUTER_API_KEY</code></td>
|
||
<td><code>openai/gpt-4o-mini</code></td>
|
||
</tr>
|
||
<tr>
|
||
<td>Gemini</td>
|
||
<td><code>GEMINI_API_KEY</code></td>
|
||
<td><code>gemini-2.0-flash</code></td>
|
||
</tr>
|
||
</table>
|
||
<p>
|
||
Pour changer de provider par défaut :
|
||
<code>AI_DEFAULT_PROVIDER=openrouter</code>
|
||
</p>
|
||
</section>
|
||
|
||
<!-- 🔗 Partage -->
|
||
<section class="help-section" id="help-partage">
|
||
<h2>🔗 Partage et Webhooks</h2>
|
||
|
||
<h3>Publication publique</h3>
|
||
<p>
|
||
ObsiGate permet de partager des documents via un
|
||
lien public temporaire.
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Bouton Partager</strong> : Dans les
|
||
actions du fichier, génère un lien unique
|
||
</li>
|
||
<li>
|
||
<strong>Token unique</strong> : 64
|
||
caractères hexadécimaux, impossible à
|
||
deviner
|
||
</li>
|
||
<li>
|
||
<strong>Expiration configurable</strong> :
|
||
Durée de vie en heures
|
||
</li>
|
||
<li>
|
||
<strong>Lecture seule</strong> : La vue
|
||
publique n'affiche que le contenu sans
|
||
édition
|
||
</li>
|
||
<li>
|
||
<strong>Gestion des liens</strong> : Liste
|
||
et révocation dans les Configurations
|
||
</li>
|
||
<li>
|
||
<strong>Export PDF</strong> : Téléchargement
|
||
du document partagé en PDF via
|
||
<code>/s/{token}/pdf</code>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- 🪝 Webhooks -->
|
||
<section class="help-section" id="help-webhooks">
|
||
<h2>🪝 Webhooks</h2>
|
||
<p>
|
||
Les webhooks permettent à ObsiGate de
|
||
<strong
|
||
>notifier automatiquement des services
|
||
externes</strong
|
||
>
|
||
lorsque des fichiers ou dossiers sont modifiés.
|
||
Chaque événement déclenche un
|
||
<code>POST</code> HTTP vers l'URL de votre
|
||
choix, avec un payload JSON détaillé.
|
||
</p>
|
||
|
||
<h3>Cas d'usage</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Automatisation CI/CD</strong> :
|
||
Déclencher un build quand une note de
|
||
procédure est mise à jour
|
||
</li>
|
||
<li>
|
||
<strong>Synchronisation</strong> : Copier
|
||
les nouveaux fichiers vers un autre système
|
||
(SharePoint, Google Drive)
|
||
</li>
|
||
<li>
|
||
<strong>Notifications</strong> : Alerter un
|
||
canal Slack/Discord quand un document est
|
||
créé
|
||
</li>
|
||
<li>
|
||
<strong>Audit externe</strong> : Logger
|
||
toutes les modifications dans une base de
|
||
données externe
|
||
</li>
|
||
<li>
|
||
<strong>Déploiement</strong> : Publier un
|
||
article de blog quand un fichier est marqué
|
||
<code>publish: true</code>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Événements supportés</h3>
|
||
<div style="overflow-x: auto">
|
||
<table
|
||
style="
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 0.85rem;
|
||
margin: 8px 0 16px;
|
||
"
|
||
>
|
||
<tr style="background: var(--bg-secondary)">
|
||
<th
|
||
style="
|
||
padding: 8px 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
Événement
|
||
</th>
|
||
<th
|
||
style="
|
||
padding: 8px 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
Déclencheur
|
||
</th>
|
||
<th
|
||
style="
|
||
padding: 8px 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
Données
|
||
</th>
|
||
</tr>
|
||
<tr>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>file_created</code>
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
Création via l'API ou la palette
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>vault</code>,
|
||
<code>path</code>
|
||
</td>
|
||
</tr>
|
||
<tr style="background: var(--bg-secondary)">
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>file_deleted</code>
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
Suppression via l'API ou l'éditeur
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>vault</code>,
|
||
<code>path</code>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>file_renamed</code>
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
Renommage via l'API
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>vault</code>,
|
||
<code>old_path</code>,
|
||
<code>new_path</code>
|
||
</td>
|
||
</tr>
|
||
<tr style="background: var(--bg-secondary)">
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>directory_created</code>
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
Création de dossier via l'API
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>vault</code>,
|
||
<code>path</code>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>directory_deleted</code>
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
Suppression de dossier via l'API
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>vault</code>,
|
||
<code>path</code>
|
||
</td>
|
||
</tr>
|
||
<tr style="background: var(--bg-secondary)">
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>directory_renamed</code>
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
Renommage de dossier via l'API
|
||
</td>
|
||
<td
|
||
style="
|
||
padding: 8px 12px;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
>
|
||
<code>vault</code>,
|
||
<code>old_path</code>,
|
||
<code>new_path</code>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
<p>
|
||
<em
|
||
>Note : l'événement
|
||
<code>file_modified</code> est réservé pour
|
||
usage futur. Les modifications de contenu
|
||
via l'éditeur ne déclenchent pas encore de
|
||
webhook.</em
|
||
>
|
||
</p>
|
||
|
||
<h3>Format du payload</h3>
|
||
<p>
|
||
Chaque webhook reçoit un <code>POST</code> avec
|
||
<code>Content-Type: application/json</code> :
|
||
</p>
|
||
<pre
|
||
style="
|
||
background: var(--bg-secondary);
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
overflow-x: auto;
|
||
font-size: 0.78rem;
|
||
"
|
||
><code>{
|
||
"event": "file_created",
|
||
"timestamp": "2026-06-03T14:30:00.123456+00:00",
|
||
"data": {
|
||
"vault": "IT",
|
||
"path": "procedures/deploiement.md"
|
||
}
|
||
}</code></pre>
|
||
|
||
<h3>Sécurité : signature HMAC-SHA256</h3>
|
||
<p>
|
||
Si vous configurez un secret, chaque requête
|
||
inclut un header
|
||
<code>X-ObsiGate-Signature</code> :
|
||
</p>
|
||
<pre
|
||
style="
|
||
background: var(--bg-secondary);
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
overflow-x: auto;
|
||
font-size: 0.78rem;
|
||
"
|
||
><code>X-ObsiGate-Signature: sha256=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08</code></pre>
|
||
<p>
|
||
Pour vérifier côté récepteur : calculez
|
||
<code>HMAC-SHA256(corps_brut, secret)</code> et
|
||
comparez. Le header
|
||
<code>X-ObsiGate-Event</code> contient aussi le
|
||
type d'événement pour un routage rapide.
|
||
</p>
|
||
|
||
<h3>Configuration</h3>
|
||
<p>
|
||
Les webhooks se gèrent dans le modal
|
||
<strong>Configurations</strong> (⚙️ menu
|
||
Options), section Webhooks. Réservé aux
|
||
administrateurs.
|
||
</p>
|
||
<ol>
|
||
<li>
|
||
Allez dans ⚙️ Configurations → onglet
|
||
Webhooks
|
||
</li>
|
||
<li>
|
||
Remplissez :
|
||
<strong>Nom</strong> (descriptif),
|
||
<strong>URL</strong> (endpoint cible),
|
||
<strong>Secret</strong> (optionnel)
|
||
</li>
|
||
<li>Cochez les événements à écouter</li>
|
||
<li>Cliquez <strong>Ajouter</strong></li>
|
||
</ol>
|
||
<p>
|
||
Les webhooks peuvent être activés/désactivés,
|
||
modifiés ou supprimés à tout moment. Le
|
||
<code>last_fired_at</code> indique la dernière
|
||
exécution.
|
||
</p>
|
||
|
||
<h3>Exemples concrets</h3>
|
||
|
||
<h4>Récepteur Python (Flask)</h4>
|
||
<pre
|
||
style="
|
||
background: var(--bg-secondary);
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
overflow-x: auto;
|
||
font-size: 0.78rem;
|
||
"
|
||
><code>from flask import Flask, request\nimport hmac, hashlib\n\napp = Flask(__name__)\nWEBHOOK_SECRET = "mon-secret" # même que dans ObsiGate\n\[email protected]("/webhook", methods=["POST"])\ndef webhook():\n # Vérifier la signature\n signature = request.headers.get("X-ObsiGate-Signature", "")\n body = request.get_data()\n expected = "sha256=" + hmac.new(\n WEBHOOK_SECRET.encode(), body, hashlib.sha256\n ).hexdigest()\n if not hmac.compare_digest(signature, expected):\n return "Invalid signature", 403\n\n payload = request.get_json()\n print(f"Événement: {payload['event']}")\n print(f"Fichier: {payload['data']['vault']}/{payload['data']['path']}")\n return "OK", 200\n\napp.run(port=5000)</code></pre>
|
||
|
||
<h4>n8n / Make (no-code)</h4>
|
||
<ol>
|
||
<li>
|
||
Créez un
|
||
<strong>Webhook Trigger</strong> dans n8n ou
|
||
Make
|
||
</li>
|
||
<li>
|
||
Copiez l'URL générée (ex:
|
||
<code
|
||
>https://n8n.monserveur.com/webhook/abc123</code
|
||
>)
|
||
</li>
|
||
<li>
|
||
Dans ObsiGate, ajoutez un webhook pointant
|
||
vers cette URL
|
||
</li>
|
||
<li>Sélectionnez les événements souhaités</li>
|
||
<li>
|
||
Le workflow se déclenche automatiquement à
|
||
chaque événement
|
||
</li>
|
||
</ol>
|
||
|
||
<h4>Notification Discord</h4>
|
||
<p>
|
||
Utilisez un webhook relais (n8n, Make, ou un
|
||
script) pour transformer le payload ObsiGate en
|
||
message Discord :
|
||
</p>
|
||
<pre
|
||
style="
|
||
background: var(--bg-secondary);
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
overflow-x: auto;
|
||
font-size: 0.78rem;
|
||
"
|
||
><code># Exemple avec curl + jq dans un script bash
|
||
WEBHOOK_URL="https://discord.com/api/webhooks/..."
|
||
OBSIGATE_SECRET="mon-secret"
|
||
|
||
# Lire le payload depuis stdin
|
||
read -r payload
|
||
event=$(echo "$payload" | jq -r '.event')
|
||
path=$(echo "$payload" | jq -r '.data.path')
|
||
|
||
curl -H "Content-Type: application/json" -d "{
|
||
\"content\": \"📝 **$event** — $path\"
|
||
}" "$WEBHOOK_URL"</code></pre>
|
||
|
||
<h4>Tester avec curl</h4>
|
||
<pre
|
||
style="
|
||
background: var(--bg-secondary);
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
overflow-x: auto;
|
||
font-size: 0.78rem;
|
||
"
|
||
><code># Simuler ce qu'ObsiGate envoie (pour tester votre endpoint)
|
||
curl -X POST https://votre-serveur.com/webhook \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-ObsiGate-Event: file_created" \
|
||
-H "X-ObsiGate-Signature: sha256=$(echo -n '{"event":"file_created",...}' | openssl dgst -sha256 -hmac 'mon-secret' | cut -d' ' -f2)" \
|
||
-d '{"event":"file_created","timestamp":"2026-06-03T14:30:00Z","data":{"vault":"IT","path":"notes/test.md"}}'</code></pre>
|
||
|
||
<h3>Limitations actuelles</h3>
|
||
<ul>
|
||
<li>
|
||
Timeout de <strong>5 secondes</strong> par
|
||
requête — les webhooks sont "fire and
|
||
forget" (pas de retry)
|
||
</li>
|
||
<li>
|
||
Les modifications détectées par le watcher
|
||
filesystem (watchdog)
|
||
<strong>ne déclenchent pas</strong> de
|
||
webhooks — seules les opérations via l'API
|
||
REST sont prises en compte
|
||
</li>
|
||
<li>
|
||
<code>file_modified</code> n'est pas encore
|
||
dispatché (réservé pour version future)
|
||
</li>
|
||
<li>Pas de retry automatique en cas d'échec</li>
|
||
<li>
|
||
Pas de filtrage par vault — un webhook
|
||
écoute toutes les vaults
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
<section class="help-section" id="help-sauvegardes">
|
||
<h2>💾 Sauvegardes et Audits</h2>
|
||
|
||
<h3>Backup automatique</h3>
|
||
<p>
|
||
ObsiGate crée automatiquement des sauvegardes
|
||
avant chaque modification destructive.
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Avant écriture</strong> : Sauvegarde
|
||
du contenu original dans
|
||
<code>.obsigate-backup/</code>
|
||
</li>
|
||
<li>
|
||
<strong>Timestamp</strong> : Chaque backup
|
||
est horodaté
|
||
</li>
|
||
<li>
|
||
<strong>Répertoire dédié</strong> :
|
||
<code>.obsigate-backup/</code> dans le
|
||
répertoire de la vault
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Audit log</h3>
|
||
<p>
|
||
Toutes les opérations sensibles sont tracées
|
||
dans un journal.
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Journal</strong> : Fichier
|
||
<code>data/audit.log</code> au format JSON
|
||
lines
|
||
</li>
|
||
<li>
|
||
<strong>Événements tracés</strong> :
|
||
Écritures, suppressions, changements de
|
||
configuration
|
||
</li>
|
||
<li>
|
||
<strong>Rotation</strong> : Rotation
|
||
automatique à 10 Mo
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- 🛡️ Sécurité -->
|
||
<section class="help-section" id="help-securite">
|
||
<h2>🛡️ Sécurité</h2>
|
||
|
||
<h3>Authentification</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>JWT + Argon2id</strong> : Tokens JWT
|
||
avec mots de passe hachés Argon2id
|
||
</li>
|
||
<li>
|
||
<strong>Contrôle d'accès par vault</strong>
|
||
: Chaque utilisateur voit uniquement ses
|
||
vaults
|
||
</li>
|
||
<li>
|
||
<strong>Refresh tokens</strong> : Cookies
|
||
HttpOnly avec rotation automatique
|
||
</li>
|
||
<li>
|
||
<strong>Rate limiting</strong> : 10
|
||
tentatives / 15 min par IP + verrouillage
|
||
compte
|
||
</li>
|
||
<li>
|
||
<strong>Compte admin</strong> : Créé
|
||
automatiquement au premier démarrage
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Protection</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Secret redactor</strong> : Masque
|
||
JWT, clés API, tokens GitHub dans les
|
||
aperçus
|
||
</li>
|
||
<li>
|
||
<strong>Path traversal</strong> : Validation
|
||
des chemins contre les attaques
|
||
<code>../</code>
|
||
</li>
|
||
<li>
|
||
<strong>Headers CSP</strong> :
|
||
Content-Security-Policy, X-Frame-Options,
|
||
XSS-Protection
|
||
</li>
|
||
<li>
|
||
<strong>Atomic writes</strong> : Écriture
|
||
via fichier temporaire + renommage atomique
|
||
</li>
|
||
<li>
|
||
<strong>Non-root Docker</strong> : Conteneur
|
||
tourne avec UID 1000
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-astuces">
|
||
<h2>💡 Astuces et bonnes pratiques</h2>
|
||
|
||
<h3>Workflow recommandé</h3>
|
||
<ol>
|
||
<li>
|
||
<strong>Sélectionnez un contexte</strong> :
|
||
Choisissez un vault pour réduire le bruit
|
||
</li>
|
||
<li>
|
||
<strong>Explorez l'arborescence</strong> :
|
||
Naviguez dans les dossiers
|
||
</li>
|
||
<li>
|
||
<strong>Utilisez les tags</strong> : Filtrez
|
||
par tags pour affiner
|
||
</li>
|
||
<li>
|
||
<strong>Recherchez intelligemment</strong> :
|
||
Combinez opérateurs et texte libre
|
||
</li>
|
||
<li>
|
||
<strong>Profitez de l'historique</strong> :
|
||
Réutilisez vos recherches fréquentes
|
||
</li>
|
||
</ol>
|
||
|
||
<h3>Optimisations</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Masquez la sidebar</strong> : Plus
|
||
d'espace pour le contenu
|
||
</li>
|
||
<li>
|
||
<strong
|
||
>Utilisez le filtrage sidebar</strong
|
||
>
|
||
: Plus rapide que la recherche globale pour
|
||
trouver un fichier
|
||
</li>
|
||
<li>
|
||
<strong>Favorisez les opérateurs</strong> :
|
||
<code>tag:</code> et
|
||
<code>vault:</code> accélèrent la recherche
|
||
</li>
|
||
<li>
|
||
<strong>Breadcrumb cliquable</strong> :
|
||
Repositionnez rapidement la sidebar
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Trucs et astuces</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Navigation visuelle</strong> : Le
|
||
breadcrumb repositionne automatiquement la
|
||
sidebar
|
||
</li>
|
||
<li>
|
||
<strong>Gestion de l'espace</strong> :
|
||
Réduisez les sections Vaults/Tags selon vos
|
||
besoins
|
||
</li>
|
||
<li>
|
||
<strong>Confort de lecture</strong> :
|
||
Ajustez la largeur de la sidebar
|
||
</li>
|
||
<li>
|
||
<strong>Mobile-friendly</strong> : Utilisez
|
||
le bouton hamburger sur mobile
|
||
</li>
|
||
<li>
|
||
<strong>Wikilinks</strong> : Naviguez entre
|
||
notes comme dans Obsidian
|
||
</li>
|
||
<li>
|
||
<strong>Images</strong> : Support complet
|
||
des syntaxes Obsidian
|
||
</li>
|
||
</ul>
|
||
|
||
<h3>Cas d'usage avancés</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Recherche multi-critères</strong> :
|
||
<code
|
||
>tag:docker tag:linux vault:IT
|
||
nginx</code
|
||
>
|
||
</li>
|
||
<li>
|
||
<strong>Exploration par tags</strong> :
|
||
Cliquez sur un tag dans une note pour voir
|
||
toutes les notes similaires
|
||
</li>
|
||
<li>
|
||
<strong>Édition rapide</strong> : Ouvrez
|
||
l'éditeur, modifiez, sauvegardez
|
||
</li>
|
||
<li>
|
||
<strong>Export</strong> : Téléchargez des
|
||
fichiers pour backup ou partage
|
||
</li>
|
||
<li>
|
||
<strong>Multi-fenêtres</strong> : Ouvrez
|
||
plusieurs notes dans des onglets séparés
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<div class="help-footer">
|
||
<p>
|
||
<strong>ObsiGate v1.7.0</strong> - Porte
|
||
d'entrée web pour vos vaults Obsidian
|
||
</p>
|
||
<p>
|
||
Pour plus d'informations, consultez le
|
||
<a
|
||
href="https://git.dracodev.net/Projets/ObsiGate"
|
||
target="_blank"
|
||
>dépôt du projet</a
|
||
>.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Find in Page Bar -->
|
||
<div class="find-in-page-bar" id="find-in-page-bar" hidden>
|
||
<div class="find-in-page-content">
|
||
<i data-lucide="search" class="find-icon"></i>
|
||
<input
|
||
type="text"
|
||
id="find-input"
|
||
placeholder="Rechercher..."
|
||
autocomplete="off"
|
||
aria-label="Rechercher dans la page"
|
||
/>
|
||
<span class="find-counter" id="find-counter" aria-live="polite"
|
||
>0 occurrence</span
|
||
>
|
||
<div class="find-nav-buttons">
|
||
<button
|
||
class="find-btn"
|
||
id="find-prev"
|
||
title="Précédent (Shift+Enter)"
|
||
aria-label="Résultat précédent"
|
||
disabled
|
||
>
|
||
<i
|
||
data-lucide="chevron-up"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
<button
|
||
class="find-btn"
|
||
id="find-next"
|
||
title="Suivant (Enter)"
|
||
aria-label="Résultat suivant"
|
||
disabled
|
||
>
|
||
<i
|
||
data-lucide="chevron-down"
|
||
style="width: 14px; height: 14px"
|
||
></i>
|
||
</button>
|
||
</div>
|
||
<div class="find-options">
|
||
<button
|
||
class="find-btn find-option-btn"
|
||
id="find-case-sensitive"
|
||
title="Respecter la casse"
|
||
aria-label="Respecter la casse"
|
||
aria-pressed="false"
|
||
>
|
||
<span class="find-option-text">Aa</span>
|
||
</button>
|
||
<button
|
||
class="find-btn find-option-btn"
|
||
id="find-whole-word"
|
||
title="Mot entier"
|
||
aria-label="Mot entier"
|
||
aria-pressed="false"
|
||
>
|
||
<span class="find-option-text">abc</span>
|
||
</button>
|
||
<button
|
||
class="find-btn find-option-btn"
|
||
id="find-regex"
|
||
title="Expression régulière"
|
||
aria-label="Expression régulière"
|
||
aria-pressed="false"
|
||
>
|
||
<span class="find-option-text">.*</span>
|
||
</button>
|
||
</div>
|
||
<button
|
||
class="find-btn find-close"
|
||
id="find-close"
|
||
title="Fermer (Escape)"
|
||
aria-label="Fermer la recherche"
|
||
>
|
||
<i data-lucide="x" style="width: 16px; height: 16px"></i>
|
||
</button>
|
||
</div>
|
||
<div class="find-error" id="find-error" hidden></div>
|
||
</div>
|
||
|
||
<script type="module" src="/static/js/app.js"></script>
|
||
|
||
<!-- ── Mobile Bottom Toolbar ── -->
|
||
<nav
|
||
class="mobile-toolbar"
|
||
id="mobile-toolbar"
|
||
aria-label="Barre d'outils mobile"
|
||
>
|
||
<button
|
||
class="mt-btn"
|
||
id="mt-explorer"
|
||
title="Explorateur"
|
||
aria-label="Explorateur de vault"
|
||
>
|
||
<i
|
||
data-lucide="folder-open"
|
||
style="width: 20px; height: 20px"
|
||
></i>
|
||
<span class="mt-label">Explorer</span>
|
||
</button>
|
||
<button
|
||
class="mt-btn"
|
||
id="mt-search"
|
||
title="Rechercher un fichier"
|
||
aria-label="Rechercher un fichier"
|
||
>
|
||
<i data-lucide="search" style="width: 20px; height: 20px"></i>
|
||
<span class="mt-label">Recherche</span>
|
||
</button>
|
||
<button
|
||
class="mt-btn mt-btn-primary"
|
||
id="mt-palette"
|
||
title="Commandes"
|
||
aria-label="Palette de commandes"
|
||
>
|
||
<i data-lucide="terminal" style="width: 20px; height: 20px"></i>
|
||
<span class="mt-label">Commandes</span>
|
||
</button>
|
||
<button
|
||
class="mt-btn"
|
||
id="mt-tabs"
|
||
title="Onglets"
|
||
aria-label="Onglets ouverts"
|
||
>
|
||
<i data-lucide="files" style="width: 20px; height: 20px"></i>
|
||
<span class="mt-badge" id="mt-tab-count" style="display: none"
|
||
>0</span
|
||
>
|
||
<span class="mt-label">Onglets</span>
|
||
</button>
|
||
</nav>
|
||
|
||
<!-- ── Mobile Tab Switcher (bottom sheet) ── -->
|
||
<div class="mt-tab-switcher" id="mt-tab-switcher">
|
||
<div class="mt-sheet-handle"></div>
|
||
<div class="mt-sheet-header">
|
||
<span class="mt-sheet-title">Fichiers ouverts</span>
|
||
<div class="mt-sheet-actions">
|
||
<button class="mt-sheet-close-all" id="mt-close-all" title="Fermer tout" aria-label="Fermer tous les fichiers">Fermer tout</button>
|
||
<button class="mt-sheet-close" id="mt-sheet-close" aria-label="Fermer">✕</button>
|
||
</div>
|
||
</div>
|
||
<div class="mt-sheet-list" id="mt-tab-list"></div>
|
||
</div>
|
||
<div class="mt-overlay" id="mt-overlay"></div>
|
||
</body>
|
||
</html>
|