The SW was the root cause of all persistent French text issues. Even after rebuild, browsers with a registered SW would serve cached old files (viewer.js without data-i18n, old locale JSONs). SW-killer runs before any module script: 1. Detects if SW is controlling the page 2. Unregisters all SW registrations 3. Clears all caches 4. Reloads the page once (sessionStorage flag to prevent loop) Other fixes in this commit: - auth.js: import setLocale statically (was dynamic import) - auth.js: import loadVaults/loadTags from sidebar.js - sw.js: add JS modules + locales to STATIC_ASSETS for versioning - sw.js: CACHE_VERSION v4→v5
4826 lines
254 KiB
HTML
4826 lines
254 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 data-i18n="header.logo">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" data-i18n="header.logo">ObsiGate</span>
|
||
</div>
|
||
<p class="login-subtitle" data-i18n="auth.login_title">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" data-i18n="auth.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" data-i18n="auth.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 data-i18n="auth.remember_me">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" data-i18n="auth.login_button">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"
|
||
data-i18n-placeholder="header.search_placeholder"
|
||
placeholder="Rechercher ..."
|
||
autocomplete="off"
|
||
/>
|
||
<div class="search-actions">
|
||
<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>
|
||
<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"
|
||
data-i18n-placeholder="search.include_placeholder" placeholder="Inclure: **/*.md, notes/**"
|
||
/>
|
||
<input
|
||
type="text"
|
||
class="search-filter-input"
|
||
id="search-exclude-input"
|
||
data-i18n-placeholder="search.exclude_placeholder" 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 data-i18n="search.dropdown_history">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 data-i18n="palette.mode_files">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 data-i18n="sidebar.tab_tags">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">
|
||
<!-- Offline indicator (hidden by default) -->
|
||
<div
|
||
class="header-icon offline-indicator"
|
||
id="offline-badge"
|
||
style="display:none"
|
||
title="Mode hors-ligne"
|
||
></div>
|
||
<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" data-i18n="help.all_vaults">
|
||
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" data-i18n="header.menu_theme"
|
||
>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" data-i18n="header.menu_admin"
|
||
>Administration</span
|
||
>
|
||
<span class="menu-list-subtitle" data-i18n="header.menu_admin_desc"
|
||
>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" data-i18n="header.menu_config"
|
||
>Configurations</span
|
||
>
|
||
<span class="menu-list-subtitle" data-i18n="header.menu_config_desc"
|
||
>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" data-i18n="header.menu_help"
|
||
>Guide d'utilisation</span
|
||
>
|
||
<span class="menu-list-subtitle" data-i18n="header.menu_help_desc"
|
||
>Ouvrir l'aide</span
|
||
>
|
||
</span>
|
||
</button>
|
||
<button
|
||
class="menu-list-row menu-list-button"
|
||
id="about-open-btn"
|
||
type="button"
|
||
role="menuitem"
|
||
>
|
||
<span
|
||
class="menu-list-icon"
|
||
aria-hidden="true"
|
||
>
|
||
<i
|
||
data-lucide="sparkles"
|
||
style="width: 17px; height: 17px"
|
||
></i>
|
||
</span>
|
||
<span class="menu-list-content">
|
||
<span class="menu-list-title" data-i18n="header.menu_about"
|
||
>A propos</span
|
||
>
|
||
<span class="menu-list-subtitle" data-i18n="header.menu_about_desc"
|
||
>Version, credits & info</span
|
||
>
|
||
</span>
|
||
</button>
|
||
<button
|
||
class="menu-list-row menu-list-button"
|
||
id="profile-open-btn"
|
||
type="button"
|
||
role="menuitem"
|
||
>
|
||
<span
|
||
class="menu-list-icon"
|
||
aria-hidden="true"
|
||
>
|
||
<i
|
||
data-lucide="user"
|
||
style="width: 17px; height: 17px"
|
||
></i>
|
||
</span>
|
||
<span class="menu-list-content">
|
||
<span class="menu-list-title" data-i18n="header.menu_profile"
|
||
>Profil</span
|
||
>
|
||
<span class="menu-list-subtitle" data-i18n="header.menu_profile_desc"
|
||
>Langue & preferences</span
|
||
>
|
||
</span>
|
||
</button>
|
||
<button
|
||
class="menu-list-row menu-list-button"
|
||
id="logout-btn"
|
||
type="button"
|
||
role="menuitem"
|
||
>
|
||
<span
|
||
class="menu-list-icon"
|
||
aria-hidden="true"
|
||
>
|
||
<i
|
||
data-lucide="log-out"
|
||
style="width: 17px; height: 17px; color: var(--danger)"
|
||
></i>
|
||
</span>
|
||
<span class="menu-list-content">
|
||
<span class="menu-list-title" data-i18n="header.menu_logout"
|
||
style="color:var(--danger)"
|
||
>Deconnexion</span
|
||
>
|
||
<span class="menu-list-subtitle" data-i18n="header.menu_logout_desc"
|
||
>Quitter la session</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"
|
||
data-i18n-placeholder="sidebar.filter_placeholder" 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" data-i18n="help.all_vaults">
|
||
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="" data-i18n="help.all_vaults">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 data-i18n="dashboard.no_recent">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 class="saved-filter-bar" id="saved-filter-bar">
|
||
<button class="saved-filter-pill active" data-filter="all" data-i18n="common.all">Tous</button>
|
||
<button class="saved-filter-pill" data-filter="search" data-i18n="sidebar.tab_saved">Recherches</button>
|
||
<button class="saved-filter-pill" data-filter="directory">Repertoires</button>
|
||
</div>
|
||
<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 sauvegardee</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" data-i18n="common.loading">
|
||
Chargement...
|
||
</div>
|
||
</div>
|
||
<div
|
||
id="dashboard-conflicts-container"
|
||
style="margin-top: 16px"
|
||
></div>
|
||
<!-- Quick Help -->
|
||
<div class="quick-help" id="quick-help">
|
||
<div class="qh-header">
|
||
<i
|
||
data-lucide="keyboard"
|
||
style="width: 16px; height: 16px"
|
||
></i>
|
||
<span data-i18n="help.shortcuts_title">Raccourcis & Astuces</span>
|
||
<button
|
||
class="qh-toggle"
|
||
id="qh-toggle"
|
||
title="Masquer"
|
||
aria-label="Masquer l'aide"
|
||
>
|
||
−
|
||
</button>
|
||
</div>
|
||
<div class="qh-body" id="qh-body">
|
||
<div class="qh-row">
|
||
<span class="qh-kbd"
|
||
>Ctrl+Shift+Space</span
|
||
>
|
||
<span class="qh-desc"
|
||
>Palette de commandes</span
|
||
>
|
||
</div>
|
||
<div class="qh-row">
|
||
<span class="qh-kbd"
|
||
>Ctrl+Alt+Space</span
|
||
>
|
||
<span class="qh-desc"
|
||
>Palette de fichiers (nav.
|
||
rapide)</span
|
||
>
|
||
</div>
|
||
<div class="qh-row">
|
||
<span class="qh-kbd">Ctrl+K</span>
|
||
<span class="qh-desc"
|
||
>Focus barre de recherche</span
|
||
>
|
||
</div>
|
||
<div class="qh-row">
|
||
<span class="qh-kbd">/</span>
|
||
<span class="qh-desc"
|
||
>Recherche rapide (hors champ
|
||
texte)</span
|
||
>
|
||
</div>
|
||
<div class="qh-row">
|
||
<span class="qh-kbd">Ctrl+S</span>
|
||
<span class="qh-desc"
|
||
>Sauvegarder le fichier
|
||
ouvert</span
|
||
>
|
||
</div>
|
||
<div class="qh-row">
|
||
<span class="qh-kbd">Ctrl+F</span>
|
||
<span class="qh-desc"
|
||
>Rechercher dans le
|
||
document</span
|
||
>
|
||
</div>
|
||
<div class="qh-row">
|
||
<span class="qh-kbd">Esc</span>
|
||
<span class="qh-desc"
|
||
>Fermer l'editeur / modale</span
|
||
>
|
||
</div>
|
||
<div class="qh-row">
|
||
<span class="qh-kbd">Ctrl+J</span>
|
||
<span class="qh-desc"
|
||
>Completion IA inline (dans
|
||
l'editeur)</span
|
||
>
|
||
</div>
|
||
<div class="qh-row">
|
||
<span class="qh-kbd">Alt+I</span>
|
||
<span class="qh-desc"
|
||
>Insertion rapide (editeur
|
||
Forge)</span
|
||
>
|
||
</div>
|
||
<div class="qh-row">
|
||
<span class="qh-kbd">F1</span>
|
||
<span class="qh-desc"
|
||
>Aide de l'editeur Forge</span
|
||
>
|
||
</div>
|
||
<div class="qh-divider"></div>
|
||
<div class="qh-tip">
|
||
<i
|
||
data-lucide="lightbulb"
|
||
style="
|
||
width: 14px;
|
||
height: 14px;
|
||
"
|
||
></i>
|
||
<span
|
||
>Survolez un document avec
|
||
<strong>Ctrl</strong> pour un
|
||
apercu rapide. Cliquez sur
|
||
<strong>Forge</strong> dans la
|
||
barre d'outils pour l'editeur
|
||
avance.</span
|
||
>
|
||
</div>
|
||
</div>
|
||
</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 data-i18n="auto.c089d968">
|
||
É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 data-i18n="dashboard.no_recent">Aucun fichier récent</span>
|
||
<p data-i18n="auto.753d30a8">
|
||
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 data-i18n="dashboard.no_shares">Aucun document partagé</span>
|
||
<p data-i18n="auto.e61598c1">
|
||
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" data-i18n="viewer.on_this_page">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 data-i18n="viewer.no_headings">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">
|
||
<span class="editor-brand" data-i18n="header.logo">ObsiGate</span>
|
||
<input
|
||
class="editor-title-input"
|
||
id="editor-title-input"
|
||
data-i18n-placeholder="forge.title_placeholder" placeholder="Titre..."
|
||
spellcheck="false"
|
||
title="Titre (sync avec # Heading)"
|
||
/>
|
||
<span class="editor-sep">/</span>
|
||
<input
|
||
class="editor-filename-input"
|
||
id="editor-filename-input"
|
||
placeholder="nom.md"
|
||
spellcheck="false"
|
||
title="Renommer le fichier"
|
||
/>
|
||
<div class="editor-spacer"></div>
|
||
<span class="editor-save-dot ok" id="editor-save-dot"
|
||
><span class="dot"></span
|
||
><span id="editor-save-label">Saved</span></span
|
||
>
|
||
<button
|
||
class="editor-btn danger"
|
||
id="editor-delete"
|
||
title="Supprimer"
|
||
aria-label="Supprimer"
|
||
>
|
||
🗑
|
||
</button>
|
||
<button
|
||
class="editor-btn"
|
||
id="editor-cancel"
|
||
title="Annuler"
|
||
aria-label="Annuler"
|
||
>
|
||
✕
|
||
</button>
|
||
<button
|
||
class="editor-btn primary"
|
||
id="editor-save"
|
||
title="Sauvegarder"
|
||
aria-label="Sauvegarder"
|
||
>
|
||
✓
|
||
</button>
|
||
</div>
|
||
<div class="editor-body editor-body-cm" id="editor-body">
|
||
<div id="ai-toolbar-container"></div>
|
||
</div>
|
||
<div class="editor-footer">
|
||
<span class="editor-stat-file" id="editor-stat-file"></span>
|
||
<span class="editor-stat-words" id="editor-stat-words"
|
||
>0 words</span
|
||
>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Configurations Modal -->
|
||
<div class="editor-modal" id="config-modal">
|
||
<div class="editor-container">
|
||
<div class="editor-header">
|
||
<div class="editor-title" data-i18n="header.menu_config">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 help-body" id="config-body">
|
||
<nav class="help-nav" id="config-nav">
|
||
<div class="help-nav-header">
|
||
<div class="help-nav-title" data-i18n="config.title">Configuration</div>
|
||
</div>
|
||
<div class="help-nav-search-wrap">
|
||
<input
|
||
type="text"
|
||
class="help-nav-search"
|
||
id="config-nav-search"
|
||
data-i18n-placeholder="settings.search_placeholder" placeholder="Rechercher..."
|
||
autocomplete="off"
|
||
spellcheck="false"
|
||
/>
|
||
<button
|
||
class="help-search-clear"
|
||
id="config-search-clear"
|
||
title="Effacer"
|
||
onclick="
|
||
var s =
|
||
document.getElementById(
|
||
'config-nav-search',
|
||
);
|
||
if (s) {
|
||
s.value = '';
|
||
s.dispatchEvent(new Event('input'));
|
||
s.focus();
|
||
}
|
||
"
|
||
>
|
||
X
|
||
</button>
|
||
</div>
|
||
<ul class="help-nav-list">
|
||
<li><a href="#cfg-search" class="help-nav-link" data-i18n="help.nav_search"></a></li>
|
||
<li><a href="#cfg-recent" class="help-nav-link" data-i18n="config.section_recent"></a></li>
|
||
<li><a href="#cfg-backend-settings" class="help-nav-link" data-i18n="config.section_backend"></a></li>
|
||
<li><a href="#cfg-tags" class="help-nav-link" data-i18n="config.section_tags"></a></li>
|
||
<li><a href="#cfg-sync" class="help-nav-link" data-i18n="settings.sync"></a></li>
|
||
<li><a href="#cfg-hidden-files" class="help-nav-link" data-i18n="config.section_hidden"></a></li>
|
||
<li><a href="#cfg-diags" class="help-nav-link" data-i18n="settings.diagnostics"></a></li>
|
||
<li><a href="#cfg-ai" class="help-nav-link" data-i18n="settings.ai"></a></li>
|
||
<li><a href="#cfg-themes" class="help-nav-link" data-i18n="settings.themes"></a></li>
|
||
<li><a href="#cfg-profile" class="help-nav-link" data-i18n="settings.profile"></a></li>
|
||
<li><a href="#cfg-about" class="help-nav-link" data-i18n="settings.about"></a></li>
|
||
<li><a href="#cfg-webhooks" class="help-nav-link" data-i18n="config.section_webhooks"></a></li>
|
||
<li><a href="#cfg-partages-publics" class="help-nav-link" data-i18n="config.section_shares"></a></li>
|
||
</ul>
|
||
</nav>
|
||
<div class="help-content" id="config-scroll">
|
||
<div class="config-content">
|
||
<!-- Performance Settings - Frontend -->
|
||
<section
|
||
class="config-section help-section"
|
||
id="cfg-search"
|
||
>
|
||
<h2 data-i18n="config.section_search">Paramètres de recherche</h2>
|
||
<p class="config-description" data-i18n="auto.7e13c97a">
|
||
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>
|
||
|
||
<!-- Recent History -->
|
||
<section id="cfg-recent" class="config-section help-section">
|
||
<h2>
|
||
📋 <span data-i18n="settings.history_section">Historique récent</span>
|
||
<span class="config-badge-restart"
|
||
data-i18n="settings.no_restart_badge">Redémarrage non requis</span
|
||
>
|
||
</h2>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-recent-limit"
|
||
data-i18n="settings.history_count_label"
|
||
>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"
|
||
data-i18n="settings.history_count_desc"
|
||
>Entre 5 et 100 fichiers (sauvegarde sur le serveur)</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-max-backups"
|
||
data-i18n="config.max_backups_label"
|
||
>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"
|
||
data-i18n="config.max_backups_desc"
|
||
>Nombre maximum de versions backup conservées par fichier (1-50)</span
|
||
>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Performance Settings - Backend -->
|
||
<section id="cfg-backend-settings" class="config-section help-section">
|
||
<h2 data-i18n="config.section_backend">
|
||
Paramètres backend
|
||
<span class="config-badge-restart"
|
||
data-i18n="config.restart_required">Redémarrage requis</span
|
||
>
|
||
</h2>
|
||
<p class="config-description" data-i18n="auto.b114ed1c">
|
||
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"
|
||
data-i18n="config.search_workers_label"
|
||
>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"
|
||
data-i18n="config.search_workers_hint"
|
||
>Threads dédiés à la recherche (1-8)</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-max-content"
|
||
data-i18n="config.max_content_label"
|
||
>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"
|
||
data-i18n="config.max_content_hint"
|
||
>Contenu indexé par fichier (10K-1M). Réindexation requise.</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-title-boost"
|
||
data-i18n="config.title_boost_label"
|
||
>Boost titre</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-title-boost"
|
||
class="config-input config-input--num"
|
||
min="0.1"
|
||
max="10"
|
||
step="0.5"
|
||
value="3"
|
||
/>
|
||
<span class="config-hint"
|
||
data-i18n="config.title_boost_hint"
|
||
>Multiplicateur de pertinence pour les correspondances dans le titre</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-tag-boost"
|
||
data-i18n="config.tag_boost_label"
|
||
>Boost tags</label
|
||
>
|
||
<input
|
||
type="number"
|
||
id="cfg-tag-boost"
|
||
class="config-input config-input--num"
|
||
min="0.1"
|
||
max="10"
|
||
step="0.5"
|
||
value="2"
|
||
/>
|
||
<span class="config-hint"
|
||
data-i18n="config.tag_boost_hint"
|
||
>Multiplicateur de pertinence pour les correspondances dans les tags</span
|
||
>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-prefix-exp"
|
||
data-i18n="config.prefix_expansions_label"
|
||
>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"
|
||
data-i18n="config.prefix_expansions_hint"
|
||
>Nombre max de tokens élargis par préfixe (10-200)</span
|
||
>
|
||
</div>
|
||
</section>
|
||
<div class="config-actions-row">
|
||
<button class="config-btn-save"
|
||
id="cfg-save-backend" data-i18n="help.shortcut_save">
|
||
Sauvegarder
|
||
</button>
|
||
<button class="config-btn-secondary"
|
||
id="cfg-reindex" data-i18n="settings.reindex">
|
||
Forcer réindexation
|
||
</button>
|
||
<button class="config-btn-secondary"
|
||
id="cfg-reset-defaults" data-i18n="config.reset">
|
||
Réinitialiser
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Tag Filtering (existing) -->
|
||
<section class="config-section help-section">
|
||
<h2 id="cfg-tags" data-i18n="config.tag_filtering_label">Filtrage de tags</h2>
|
||
<p class="config-description" data-i18n="auto.e0b8a606">
|
||
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" data-i18n="config.add_webhook">
|
||
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 help-section"
|
||
id="cfg-sync"
|
||
>
|
||
<h2 data-i18n="config.section_watcher">Synchronisation automatique</h2>
|
||
<p class="config-description" data-i18n="auto.d33601dc">
|
||
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 id="cfg-hidden-files" class="config-section help-section">
|
||
<h2 data-i18n="auto.f8ba6127">🗂️ 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 data-i18n="config.note">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 help-section"
|
||
id="cfg-diags"
|
||
>
|
||
<h2 data-i18n="config.diagnostics">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" data-i18n="common.loading">
|
||
Chargement...
|
||
</div>
|
||
</div>
|
||
<button class="config-btn-secondary"
|
||
id="cfg-refresh-diag"
|
||
style="margin-top: 8px" data-i18n="header.refresh">
|
||
Rafraîchir
|
||
</button>
|
||
</section>
|
||
|
||
<!-- Cles API AI -->
|
||
<section
|
||
class="config-section help-section"
|
||
id="cfg-ai"
|
||
>
|
||
<h2>🤖 Cles API Intelligence Artificielle</h2>
|
||
<p class="config-description">
|
||
Configurez vos cles API. Cliquez sur
|
||
<strong data-i18n="config.test">Tester</strong> pour charger les
|
||
modeles.
|
||
</p>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-deepseek-key"
|
||
>DeepSeek API Key</label
|
||
>
|
||
<input
|
||
type="password"
|
||
id="cfg-deepseek-key"
|
||
class="config-input"
|
||
placeholder="sk-..."
|
||
autocomplete="off"
|
||
/>
|
||
<select
|
||
id="cfg-deepseek-model"
|
||
class="config-select"
|
||
style="width: 200px"
|
||
>
|
||
<option value="">-- Modele --</option>
|
||
</select>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-openrouter-key"
|
||
>OpenRouter API Key</label
|
||
>
|
||
<input
|
||
type="password"
|
||
id="cfg-openrouter-key"
|
||
class="config-input"
|
||
placeholder="sk-or-..."
|
||
autocomplete="off"
|
||
/>
|
||
<select
|
||
id="cfg-openrouter-model"
|
||
class="config-select"
|
||
style="width: 200px"
|
||
>
|
||
<option value="">-- Modele --</option>
|
||
</select>
|
||
</div>
|
||
<div class="config-row">
|
||
<label
|
||
class="config-label"
|
||
for="cfg-gemini-key"
|
||
>Gemini API Key</label
|
||
>
|
||
<input
|
||
type="password"
|
||
id="cfg-gemini-key"
|
||
class="config-input"
|
||
placeholder="AIza..."
|
||
autocomplete="off"
|
||
/>
|
||
<select
|
||
id="cfg-gemini-model"
|
||
class="config-select"
|
||
style="width: 200px"
|
||
>
|
||
<option value="">-- Modele --</option>
|
||
</select>
|
||
</div>
|
||
<div
|
||
class="config-actions-row"
|
||
style="margin-top: 16px"
|
||
>
|
||
<button class="config-btn-save"
|
||
id="cfg-save-ai-keys" data-i18n="help.shortcut_save">
|
||
Sauvegarder
|
||
</button>
|
||
<button class="config-btn-secondary"
|
||
id="cfg-test-ai-keys" data-i18n="config.test">
|
||
Tester
|
||
</button>
|
||
<span
|
||
id="cfg-ai-status"
|
||
style="
|
||
font-size: 12px;
|
||
color: var(--text-muted);
|
||
margin-left: 12px;
|
||
"
|
||
></span>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Themes -->
|
||
<section
|
||
class="config-section help-section"
|
||
id="cfg-themes"
|
||
>
|
||
<h2 data-i18n="auto.c14b5603">🎨 Thèmes</h2>
|
||
<p class="config-description" data-i18n="auto.caac40b9">
|
||
Choisissez un thème visuel. Chaque thème
|
||
offre un mode sombre et clair.
|
||
</p>
|
||
<div class="theme-grid" id="theme-grid">
|
||
<div class="config-diag-loading" data-i18n="common.loading">Chargement...</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Profil -->
|
||
<section
|
||
class="config-section help-section"
|
||
id="cfg-profile"
|
||
>
|
||
<h2 data-i18n="config.profile">👤 Profil utilisateur</h2>
|
||
<p class="config-description" data-i18n="config.profile_desc">
|
||
Préférences personnelles pour personnaliser
|
||
l'expérience ObsiGate.
|
||
</p>
|
||
<div class="profile-form" id="profile-form">
|
||
<div class="profile-field">
|
||
<label for="profile-lang" data-i18n="config.lang_label">Langue préférée</label>
|
||
<select id="profile-lang" class="config-select">
|
||
<option value="fr">Francais</option>
|
||
<option value="en">English</option>
|
||
<option value="es">Espanol</option>
|
||
<option value="de">Deutsch</option>
|
||
</select>
|
||
<span class="profile-hint" data-i18n="config.lang_hint">Utilisée par l'autocomplétion et le ghost text.</span>
|
||
</div>
|
||
<div class="profile-field">
|
||
<label for="profile-name" data-i18n="config.display_name">Nom d'affichage</label>
|
||
<input type="text" id="profile-name" class="config-input" placeholder="Votre nom" maxlength="60">
|
||
</div>
|
||
<button class="config-save-btn" id="profile-save" data-i18n="config.save">Enregistrer</button>
|
||
<button class="config-save-btn" id="profile-logout" style="background:var(--danger-bg);color:var(--danger);border-color:var(--danger);margin-left:8px" data-i18n="config.logout">Déconnexion</button>
|
||
<span class="profile-saved" id="profile-saved" style="display:none" data-i18n="config.saved">✓ Sauvegardé</span>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- À propos -->
|
||
<section
|
||
class="config-section help-section"
|
||
id="cfg-about"
|
||
>
|
||
<h2 data-i18n="auto.a3319169">📦 À propos</h2>
|
||
<div
|
||
id="config-about"
|
||
class="config-diagnostics"
|
||
>
|
||
<div class="config-diag-loading" data-i18n="common.loading">
|
||
Chargement...
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Webhooks -->
|
||
<section id="cfg-webhooks" class="config-section help-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"
|
||
data-i18n-placeholder="config.webhook_name_placeholder" 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" data-i18n="config.add_webhook">
|
||
Ajouter
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Partages publics -->
|
||
<section class="config-section help-section">
|
||
<h2 id="cfg-partages-publics">📤 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>
|
||
</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" data-i18n="help.modal_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" data-i18n="help.toc_title">Sommaire</div>
|
||
</div>
|
||
<div class="help-nav-search-wrap">
|
||
<input
|
||
type="text"
|
||
class="help-nav-search"
|
||
id="help-nav-search"
|
||
data-i18n-placeholder="help.search_placeholder" data-i18n-placeholder="help.search_placeholder" 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"
|
||
data-i18n="help.nav_intro">📘 Introduction</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-interface" class="help-nav-link"
|
||
data-i18n="help.nav_interface">🧭 Interface</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-navigation" class="help-nav-link"
|
||
data-i18n="help.nav_navigation">🗺️ Navigation</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-tabs" class="help-nav-link"
|
||
data-i18n="help.nav_tabs">📑 Onglets</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-recherche" class="help-nav-link"
|
||
data-i18n="help.nav_search">🔍 Recherche</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-tags" class="help-nav-link"
|
||
data-i18n="help.nav_tags">🏷️ Tags</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-fichiers" class="help-nav-link"
|
||
data-i18n="help.nav_files">📁 Fichiers</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-edition" class="help-nav-link"
|
||
data-i18n="help.nav_editing">✏️ Édition</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-graphe" class="help-nav-link"
|
||
data-i18n="help.nav_graph">🗺️ Graphe</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-ia" class="help-nav-link"
|
||
data-i18n="help.nav_ai">🤖 IA Éditeur</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-palette" class="help-nav-link"
|
||
data-i18n="help.nav_palette">⌨️ Palette</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-raccourcis" class="help-nav-link"
|
||
data-i18n="help.nav_shortcuts">⌨️ Raccourcis</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-partage" class="help-nav-link"
|
||
data-i18n="help.nav_sharing">🔗 Partage</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-webhooks" class="help-nav-link"
|
||
data-i18n="help.nav_webhooks">🪝 Webhooks</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a
|
||
href="#help-sauvegardes"
|
||
class="help-nav-link"
|
||
data-i18n="help.nav_backups">💾 Sauvegardes</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-securite" class="help-nav-link"
|
||
data-i18n="help.nav_security">🛡️ Sécurité</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a
|
||
href="#help-personnalisation"
|
||
class="help-nav-link"
|
||
data-i18n="help.nav_customization">🎨 Personnalisation</a
|
||
>
|
||
</li>
|
||
<li>
|
||
<a href="#help-astuces" class="help-nav-link"
|
||
data-i18n="help.nav_tips">💡 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" data-i18n="help.guide_official">Guide officiel</div>
|
||
<h1 data-i18n="help.welcome_title">📘 Bienvenue dans ObsiGate</h1>
|
||
<p class="help-lead" data-i18n="auto.6c166d35">
|
||
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" data-i18n="help.welcome_tag1"
|
||
>⚡ Navigation rapide</span
|
||
>
|
||
<span class="help-badge" data-i18n="help.welcome_tag2"
|
||
>🗂️ Multi-vault</span
|
||
>
|
||
<span class="help-badge" data-i18n="help.welcome_tag3"
|
||
>🏷️ Tags intelligents</span
|
||
>
|
||
<span class="help-badge" data-i18n="help.welcome_tag4"
|
||
>📝 Lecture et édition</span
|
||
>
|
||
<span class="help-badge" data-i18n="help.welcome_tag5"
|
||
>🔍 Recherche TF-IDF</span
|
||
>
|
||
</div>
|
||
</div>
|
||
<div class="help-hero-visual" aria-hidden="true">
|
||
<div class="help-stat-card">
|
||
<span class="help-stat-label" data-i18n="help.experience"
|
||
>Expérience</span
|
||
>
|
||
<strong data-i18n="help.simple">Simple</strong>
|
||
</div>
|
||
<div class="help-stat-card">
|
||
<span class="help-stat-label" data-i18n="help.search_bar"
|
||
>Recherche</span
|
||
>
|
||
<strong data-i18n="help.instant">Instantanée</strong>
|
||
</div>
|
||
<div class="help-stat-card">
|
||
<span class="help-stat-label" data-i18n="help.access"
|
||
>Accès</span
|
||
>
|
||
<strong data-i18n="help.multi_vault">Multi-vault</strong>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-interface">
|
||
<h2 data-i18n="help.nav_interface">🧭 Interface utilisateur</h2>
|
||
|
||
<h3 data-i18n="help.header_section">En-tête</h3>
|
||
<p data-i18n="auto.209c5490">
|
||
La barre supérieure contient les éléments
|
||
essentiels :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.hamburger_btn">Bouton menu hamburger</strong>
|
||
: <span data-i18n="help.desc_hamburger">obile) : Affiche/masque la sidebar</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.sidebar_toggle_btn">Bouton toggle sidebar</strong> <span data-i18n="help.desc_sidebar_toggle">(desktop) : Masque la sidebar pour plus
|
||
d'espace</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.logo">Logo ObsiGate</strong> <span data-i18n="help.desc_logo">: Retour à
|
||
l'accueil</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.search_bar">Barre de recherche</strong> <span data-i18n="help.desc_search_bar">:
|
||
Recherche globale avec autocomplétion</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.vault_indicator">Indicateur de vault</strong> <span data-i18n="help.desc_vault_indicator">:
|
||
Affiche le contexte actif (All, vault1,
|
||
etc.)</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.menu_options">Menu Options</strong> <span data-i18n="help.desc_menu_options">: Accès aux
|
||
paramètres, thème, aide</span>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.sidebar_section">Sidebar (barre latérale)</h3>
|
||
<p data-i18n="help.sidebar_tabs">La sidebar est divisée en deux onglets :</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="sidebar.tab_vaults">Vaults</strong> <span data-i18n="help.desc_vaults_tab">: Arborescence des
|
||
fichiers et dossiers</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="sidebar.tab_tags">Tags</strong> <span data-i18n="help.desc_tags_tab">: Nuage de tags
|
||
cliquables</span>
|
||
</li>
|
||
</ul>
|
||
<p data-i18n="help.sidebar_features">Fonctionnalités de la sidebar :</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.filtering">Filtrage</strong> <span data-i18n="help.desc_filtering">: Barre de
|
||
recherche pour filtrer fichiers/tags</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.quick_select">Sélection rapide</strong> <span data-i18n="help.desc_quick_select">: Dropdown
|
||
pour changer de vault</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.resize">Redimensionnement</strong> <span data-i18n="help.desc_resize">: Glissez
|
||
le bord droit pour ajuster la largeur</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.hide">Masquage</strong> <span data-i18n="help.desc_hide">: Cliquez sur
|
||
l'icône sidebar dans le header</span>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.content_area">Zone de contenu</h3>
|
||
<p data-i18n="help.content_shows">La zone centrale affiche :</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.breadcrumb">Breadcrumb</strong> <span data-i18n="help.desc_breadcrumb">: Chemin du
|
||
fichier (cliquable pour repositionner la
|
||
sidebar)</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.title_tags">Titre et tags</strong> <span data-i18n="help.desc_title_tags">: Métadonnées
|
||
du fichier</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.action_buttons">Boutons d'action</strong> <span data-i18n="help.desc_action_buttons">: Copier,
|
||
Source, Télécharger, Éditer, Ouvrir dans
|
||
nouvelle fenêtre</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.rendered_content">Contenu rendu</strong> <span data-i18n="help.desc_rendered_content">: Markdown
|
||
avec wikilinks et images</span>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-navigation">
|
||
<h2 data-i18n="help.733f0559">🗺️ Navigation</h2>
|
||
|
||
<h3 data-i18n="help.tree_section">Arborescence des vaults</h3>
|
||
<p data-i18n="auto.4c908ade">
|
||
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 data-i18n="sidebar.expand_collapse">Développer/Réduire</strong><span data-i18n="help.desc_expand">:
|
||
Cliquez sur un dossier</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="sidebar.open_file">Ouvrir un fichier</strong><span data-i18n="help.desc_open_file">: Cliquez
|
||
sur le nom du fichier</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="sidebar.file_icons">Icônes</strong><span data-i18n="help.desc_fdeaf803"> : Chaque type de
|
||
fichier a son icône (markdown, code, etc.)</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.sidebar_filtering">Filtrage de la sidebar</h3>
|
||
<p data-i18n="help.desc_filter_usage">
|
||
Utilisez la barre de filtrage en haut de la
|
||
sidebar pour rechercher rapidement :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="sidebar.filter_instant">Recherche instantanée</strong><span data-i18n="help.desc_instant_filter">:
|
||
Tapez pour filtrer fichiers et dossiers</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.case_sensitive">Case-sensitive</strong><span data-i18n="help.desc_case_sensitive">: Bouton
|
||
"Aa" pour respecter la casse</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.clear">Effacer</strong><span data-i18n="help.desc_a4a4e21b"> : Bouton "×" pour
|
||
réinitialiser le filtre</span></li>
|
||
<li>
|
||
<strong data-i18n="help.results_grouped">Résultats groupés</strong><span data-i18n="help.desc_grouped_results">:
|
||
Affichage par vault avec chemins complets</span>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.breadcrumb_reposition">Breadcrumb et repositionnement</h3>
|
||
<p data-i18n="auto.1abf6661">
|
||
Le chemin affiché au-dessus du contenu est
|
||
interactif :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.click_vault">Cliquez sur le vault</strong><span data-i18n="help.desc_click_vault">:
|
||
Focus sur le vault dans la sidebar</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.click_segment">Cliquez sur un segment</strong><span data-i18n="help.desc_click_segment">:
|
||
Navigation vers ce dossier</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.auto_scroll">Auto-scroll</strong><span data-i18n="help.desc_autoscroll">: La sidebar se
|
||
positionne automatiquement</span>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.vault_selector">Sélection de vault</h3>
|
||
<p data-i18n="help.desc_vault_context">
|
||
Changez de contexte pour filtrer l'affichage :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.menu_header">Menu header</strong><span data-i18n="help.desc_menu_header">: Dropdown
|
||
"Vault" dans le menu Options</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.sidebar_dropdown">Sidebar dropdown</strong><span data-i18n="help.desc_085ec31f"> :
|
||
Sélection rapide en haut de l'onglet Vaults</span></li>
|
||
<li>
|
||
<strong data-i18n="help.all_vaults">Tous les vaults</strong><span data-i18n="help.desc_all_vaults">: Vue
|
||
globale de tous vos contenus</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.vault_specific">Vault spécifique</strong><span data-i18n="help.desc_specific_vault">: Focus
|
||
sur un seul vault</span>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-tabs">
|
||
<h2 data-i18n="help.8c5341e0">📑 Gestion des onglets</h2>
|
||
<p data-i18n="auto.27a2f7c1">
|
||
ObsiGate supporte l'ouverture de plusieurs
|
||
fichiers simultanément dans des onglets.
|
||
</p>
|
||
|
||
<h3 data-i18n="help.tabs_section">Ouverture d'onglets</h3>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.single_click">Simple clic</strong><span data-i18n="help.desc_e3fce7a3"> : Ouvre le
|
||
fichier dans un onglet temporaire (aperçu,
|
||
italique)</span></li>
|
||
<li>
|
||
<strong data-i18n="help.double_click">Double clic</strong><span data-i18n="help.desc_double_click">: Ouvre le
|
||
fichier dans un onglet persistant</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.recent_nav">Navigation récente</strong><span data-i18n="help.desc_d186a19e"> :
|
||
L'onglet "Récent" dans la sidebar liste vos
|
||
derniers fichiers</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.tab_nav">Navigation entre onglets</h3>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.click_tab">Clic sur un onglet</strong><span data-i18n="help.desc_click_tab">: Active
|
||
l'onglet</span>
|
||
</li>
|
||
<li>
|
||
<strong>Ctrl+Tab</strong><span data-i18n="help.desc_ctrl_tab">: Onglet suivant</span>
|
||
</li>
|
||
<li>
|
||
<strong>Ctrl+Shift+Tab</strong><span data-i18n="help.desc_e5246734"> : Onglet
|
||
précédent</span></li>
|
||
<li>
|
||
<strong>Ctrl+W</strong><span data-i18n="help.desc_ctrl_w">: Fermer l'onglet
|
||
actif</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.close_tab_x">Bouton ✕</strong><span data-i18n="help.desc_close_btn">: Ferme l'onglet
|
||
(sauf s'il est seul)</span>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.tab_features">Fonctionnalités</h3>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.tab_bar">Barre d'onglets</strong><span data-i18n="help.desc_170a6982"> : Affichage
|
||
horizontal avec le nom du fichier et son
|
||
icône</span></li>
|
||
<li>
|
||
<strong data-i18n="help.active_tab">Onglet actif</strong><span data-i18n="help.desc_6b649b1e"> : Surligné en
|
||
couleur d'accentuation</span></li>
|
||
<li>
|
||
<strong data-i18n="help.preview_tab">Prévisualisation</strong><span data-i18n="help.desc_ef1531ce"> : Un
|
||
onglet temporaire (italique) est remplacé
|
||
par le prochain clic</span></li>
|
||
<li>
|
||
<strong data-i18n="help.persistent_tabs">Onglets persistants</strong><span data-i18n="help.desc_5ab8c78d"> :
|
||
Restent ouverts jusqu'à fermeture manuelle</span></li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-recherche">
|
||
<h2 data-i18n="help.adf30d78">🔍 Recherche</h2>
|
||
|
||
<h3 data-i18n="help.simple_search">Recherche simple</h3>
|
||
<p data-i18n="help.desc_search_intro">
|
||
Tapez dans la barre de recherche en haut pour
|
||
lancer une recherche fulltext :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="search.full_text">Recherche dans tout</strong><span data-i18n="help.desc_search_all">:
|
||
Titre, contenu, tags, chemins</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.smart_scoring">Scoring intelligent</strong><span data-i18n="help.desc_00b9572b"> :
|
||
Résultats classés par pertinence TF-IDF</span></li>
|
||
<li>
|
||
<strong data-i18n="help.highlighted_snippets">Snippets surlignés</strong><span data-i18n="help.desc_snippets">:
|
||
Extraits avec termes en surbrillance</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.pagination">Pagination</strong><span data-i18n="help.desc_53bfaeca"> : Navigation par
|
||
pages de 50 résultats</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.advanced_operators">Opérateurs avancés</h3>
|
||
<p data-i18n="auto.4bc1f00a">
|
||
Utilisez des opérateurs pour affiner votre
|
||
recherche :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<span data-i18n="help.desc_op_tag"><code>tag:docker</code> ou
|
||
<code>#docker</code> : Filtrer par tag</span>
|
||
</li>
|
||
<li>
|
||
<span data-i18n="help.desc_op_vault"><code>vault:IT</code> : Rechercher dans un
|
||
vault spécifique</span>
|
||
</li>
|
||
<li>
|
||
<span data-i18n="help.desc_op_title"><code>title:kubernetes</code> : Chercher
|
||
dans les titres uniquement</span>
|
||
</li>
|
||
<li>
|
||
<span data-i18n="help.desc_op_path"><code>path:recettes/soupes</code> : Filtrer
|
||
par chemin</span>
|
||
</li>
|
||
<li>
|
||
<span data-i18n="help.desc_op_ext"><code>ext:md</code> : Filtrer par type de
|
||
fichier</span>
|
||
</li>
|
||
<li>
|
||
<span data-i18n="help.desc_op_phrase"><code>"phrase exacte"</code> : Recherche de
|
||
phrase entre guillemets</span>
|
||
</li>
|
||
</ul>
|
||
<p>
|
||
<strong>Exemples</strong><span data-i18n="help.desc_examples">:
|
||
<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></span>
|
||
<p>
|
||
<strong data-i18n="auto.1a54bd69">Exemple combiné</strong> :
|
||
<code
|
||
>tag:linux vault:IT ext:md serveur web</code
|
||
>
|
||
<span data-i18n="help.desc_combined">recherche "serveur web" dans les fichiers
|
||
Markdown du vault IT avec le tag linux.</span>
|
||
</p>
|
||
|
||
<h3 data-i18n="help.autocomplete">Autocomplétion</h3>
|
||
<p data-i18n="auto.404c8f1c">
|
||
L'autocomplétion vous aide à trouver rapidement
|
||
:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="search.dropdown_history">Historique</strong><span data-i18n="help.desc_4de7e318"> : Les 50
|
||
dernières recherches (localStorage)</span></li>
|
||
<li>
|
||
<strong data-i18n="palette.mode_files">Fichiers</strong><span data-i18n="help.desc_file_suggest">: Suggestions de
|
||
titres de fichiers</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="sidebar.tab_tags">Tags</strong><span data-i18n="help.desc_tag_suggest">: Suggestions de tags
|
||
avec compteurs</span>
|
||
</li>
|
||
<li>
|
||
<strong>Navigation clavier</strong><span data-i18n="help.desc_6b8fc728"> : ↑/↓
|
||
pour naviguer, Enter pour sélectionner</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.active_filter_chips">Chips de filtres actifs</h3>
|
||
<p data-i18n="auto.03a6e5b1">
|
||
Les opérateurs utilisés s'affichent sous forme
|
||
de chips colorés :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Visualisation</strong><span data-i18n="help.desc_chip_view">: Voir d'un
|
||
coup d'œil les filtres actifs</span>
|
||
</li>
|
||
<li>
|
||
<strong>Suppression</strong><span data-i18n="help.desc_chip_remove">: Cliquez sur
|
||
"×" pour retirer un filtre</span>
|
||
</li>
|
||
<li>
|
||
<strong>Couleurs</strong><span data-i18n="help.desc_6ebebdfd"> : Chaque type
|
||
d'opérateur a sa couleur</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.a648c49e">Facettes et tri</h3>
|
||
<p data-i18n="auto.cd7332c8">
|
||
Les résultats incluent des facettes pour affiner
|
||
:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Facettes tags</strong><span data-i18n="help.desc_cf5ccd40"> : Compteurs
|
||
par tag dans les résultats</span></li>
|
||
<li>
|
||
<strong>Facettes vaults</strong><span data-i18n="help.desc_facet_vaults">: Compteurs
|
||
par vault</span>
|
||
</li>
|
||
<li>
|
||
<strong>Tri par pertinence</strong><span data-i18n="help.desc_9fec424d"> : Score
|
||
TF-IDF (défaut)</span></li>
|
||
<li>
|
||
<strong>Tri par date</strong><span data-i18n="help.desc_42a81347"> : Dernière
|
||
modification</span></li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-tags">
|
||
<h2 data-i18n="help.2507242f">🏷️ Tags</h2>
|
||
|
||
<h3 data-i18n="help.5f87ea79">Tag cloud</h3>
|
||
<p data-i18n="help.desc_tag_cloud_intro">
|
||
L'onglet Tags de la sidebar affiche un nuage de
|
||
tags :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Tous les tags</strong><span data-i18n="help.desc_all_tags">: Extraits
|
||
des frontmatters YAML et inline (#tag)</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.clickable">Cliquable</strong><span data-i18n="help.desc_6caffeed"> : Cliquez pour
|
||
filtrer les résultats</span></li>
|
||
<li>
|
||
<strong data-i18n="help.filtering">Filtrage</strong><span data-i18n="help.desc_tag_filter_use">: Utilisez la
|
||
barre de filtrage pour chercher un tag</span>
|
||
</li>
|
||
<li>
|
||
<strong>Contexte vault</strong><span data-i18n="help.desc_6a5ddef2"> : Les tags
|
||
s'adaptent au vault sélectionné</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.2c03a7ba">Tags inline vs frontmatter</h3>
|
||
<p data-i18n="help.desc_two_tag_types">ObsiGate supporte deux types de tags :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Frontmatter YAML</strong><span data-i18n="help.desc_frontmatter">:
|
||
<code>tags: [docker, linux]</code> ou
|
||
<code>tags: docker, linux</code></span>
|
||
</li>
|
||
<li>
|
||
<strong>Inline</strong><span data-i18n="help.desc_inline_tags">:
|
||
<code>#docker</code> dans le contenu
|
||
markdown</span>
|
||
</li>
|
||
<li>
|
||
<strong>Fusion automatique</strong><span data-i18n="help.desc_828db5da"> : Les
|
||
deux types sont combinés</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.63f024d4">Filtrage de tags template</h3>
|
||
<p data-i18n="help.desc_template_intro">
|
||
Dans les Configurations, vous pouvez masquer les
|
||
tags de template :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Patterns wildcards</strong><span data-i18n="help.desc_patterns">: Ex:
|
||
<code>#<% ... %></code> ou
|
||
<code>#{{ ... }}</code></span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="auto.5d936af6">Regex générée</strong><span data-i18n="help.desc_b9c94994"> : Aperçu de
|
||
la regex appliquée</span></li>
|
||
<li>
|
||
<strong data-i18n="help.add_remove">Ajout/Suppression</strong><span data-i18n="help.desc_ef3f8158"> : Gérez
|
||
vos patterns de filtrage</span></li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-fichiers">
|
||
<h2 data-i18n="help.c017944b">📄 Fichiers</h2>
|
||
|
||
<h3 data-i18n="help.cf8615b1">Visualisation</h3>
|
||
<p data-i18n="help.desc_md_render">Les fichiers markdown sont rendus avec :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Wikilinks cliquables</strong><span data-i18n="help.desc_wikilinks">:
|
||
<code>[[lien]]</code> et
|
||
<code>[[lien|texte]]</code></span>
|
||
</li>
|
||
<li>
|
||
<strong>Images Obsidian</strong><span data-i18n="help.desc_images">: Support
|
||
de <code>![[image.png]]</code></span>
|
||
</li>
|
||
<li>
|
||
<strong>Syntax highlighting</strong><span data-i18n="help.desc_syntax_hl">:
|
||
Coloration des blocs de code</span>
|
||
</li>
|
||
<li>
|
||
<strong>Tables, listes, quotes</strong><span data-i18n="help.desc_markdown_all">:
|
||
Rendu complet du markdown</span>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.context_actions">Actions sur fichiers</h3>
|
||
<p data-i18n="help.actions_detail">Boutons disponibles au-dessus du contenu :</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="viewer.copy">Copier</strong><span data-i18n="help.desc_copy_btn">: Copie le contenu
|
||
source dans le presse-papiers</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="viewer.source">Source</strong><span data-i18n="help.desc_source_btn">: Affiche/masque le
|
||
markdown brut</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="viewer.download">Télécharger</strong><span data-i18n="help.desc_a52fc3b1"> : Télécharge le
|
||
fichier</span></li>
|
||
<li>
|
||
<strong data-i18n="viewer.edit">Éditer</strong><span data-i18n="help.desc_995a711f"> : Ouvre l'éditeur
|
||
CodeMirror</span></li>
|
||
<li>
|
||
<strong
|
||
>Ouvrir dans nouvelle fenêtre</strong
|
||
><span data-i18n="help.desc_open_new">: Ouvre le fichier dans un nouvel onglet</span>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="auto.1efbbc9a">Édition avec CodeMirror 6</h3>
|
||
<p data-i18n="auto.edf89626">L'éditeur intégré offre :</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Coloration syntaxique</strong><span data-i18n="help.desc_cm_syntax">:
|
||
Support de nombreux langages</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="auto.1d46301c">Numéros de ligne</strong><span data-i18n="help.desc_cm_lines">:
|
||
Navigation facile</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.autocomplete">Autocomplétion</strong><span data-i18n="help.desc_cm_autocomplete">:
|
||
Suggestions contextuelles</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="settings.search">Recherche</strong><span data-i18n="help.desc_cm_search">: Ctrl+F pour
|
||
chercher dans le fichier</span>
|
||
</li>
|
||
<li>
|
||
<strong>Sauvegarde</strong><span data-i18n="help.desc_save_btn_new">: Bouton ✓ pour
|
||
enregistrer</span>
|
||
</li>
|
||
<li>
|
||
<strong>Suppression</strong><span data-i18n="help.desc_delete_btn_new">: Bouton
|
||
corbeille pour supprimer</span>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="auto.ec7260fa">Types de fichiers supportés</h3>
|
||
<p data-i18n="help.indexes">ObsiGate indexe et affiche :</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="viewer.markdown">Markdown</strong> : .md (rendu
|
||
complet)
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="mermaid.code">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 data-i18n="help.other">Autres</strong> : .txt, .log, .sql,
|
||
.csv
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- ✏️ Édition -->
|
||
<section class="help-section" id="help-edition">
|
||
<h2 data-i18n="auto.f346076a">✏️ Édition avancée</h2>
|
||
|
||
<h3 data-i18n="auto.695d9e47">Éditeur CodeMirror 6</h3>
|
||
<p data-i18n="auto.ef8c5f4d">
|
||
L'éditeur intégré offre une expérience complète
|
||
d'édition :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>Coloration syntaxique</strong><span data-i18n="help.desc_adv_syntax">:
|
||
Python, JS, HTML, CSS, Java, C++, Rust, Go
|
||
et bien d'autres</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="auto.1d46301c">Numéros de ligne</strong><span data-i18n="help.desc_9f78b3ec"> :
|
||
Navigation facilitée dans les fichiers longs</span></li>
|
||
<li>
|
||
<strong>Find in page</strong><span data-i18n="help.desc_find_in_page">: Ctrl+F pour
|
||
chercher dans le fichier (casse, regex, mot
|
||
entier)</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.auto_save">Sauvegarde automatique</strong><span data-i18n="help.desc_065f53ee"> :
|
||
Auto-save silencieux après 2s d'inactivité,
|
||
flash vert de confirmation</span></li>
|
||
<li>
|
||
<strong>Bouton ✓</strong><span data-i18n="help.desc_check_btn">: Sauvegarde
|
||
manuelle</span>
|
||
</li>
|
||
<li>
|
||
<strong>Bouton 🗑️</strong><span data-i18n="help.desc_trash_btn">: Suppression du
|
||
fichier</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.toolbar_section">Barre d'outils AI</strong><span data-i18n="help.desc_c8532869"> :
|
||
Complétion, réécriture, traduction (voir
|
||
section</span><a href="#help-ia" data-i18n="settings.ai">🤖 IA</a>)
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- 🗺️ Graphe -->
|
||
<section class="help-section" id="help-graphe">
|
||
<h2 data-i18n="help.9c7a0a8d">🗺️ Vue Graphe</h2>
|
||
<p data-i18n="help.desc_graph_intro">
|
||
La vue graphe offre une visualisation
|
||
interactive des connexions entre vos notes via
|
||
les wikilinks.
|
||
</p>
|
||
|
||
<h3 data-i18n="help.b6619ac9">Ouverture</h3>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.graph_context">Menu contextuel</strong><span data-i18n="help.desc_context_menu">: Clic
|
||
droit sur un vault ou dossier → Vue
|
||
Graphique</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.popout_button">Bouton dédié</strong><span data-i18n="help.desc_e23c94dd"> : Dans la
|
||
barre d'outils (le cas échéant)</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.61ee5a22">Interaction</h3>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.graph_zoom">Zoom/Pan</strong><span data-i18n="help.desc_f0adf67a"> : Molette pour
|
||
zoomer, cliquer-glisser pour se déplacer</span></li>
|
||
<li>
|
||
<strong data-i18n="help.graph_depth">Slider de profondeur</strong><span data-i18n="help.desc_9edeaa11"> :
|
||
Contrôle la profondeur d'exploration (0-3)</span></li>
|
||
<li>
|
||
<strong data-i18n="help.graph_tag_filter">Filtre par tag</strong><span data-i18n="help.desc_89bd3c4c"> : N'affiche
|
||
que les nœuds avec un tag spécifique</span></li>
|
||
<li>
|
||
<strong data-i18n="help.graph_type_filter">Filtre par type</strong><span data-i18n="help.desc_filter_type">:
|
||
Inclut/exclut fichiers, dossiers, markdown,
|
||
autres</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.graph_visual">Recherche visuelle</strong><span data-i18n="help.desc_visual_search">: Barre
|
||
de recherche pour surligner des nœuds</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.graph_focus">Mode focus</strong><span data-i18n="help.desc_a9db82b5"> : Centre la vue
|
||
sur un nœud spécifique</span></li>
|
||
<li>
|
||
<strong data-i18n="help.graph_nav_arrows">Navigation ← → ↑</strong><span data-i18n="help.desc_graph_nav">:
|
||
Historique de navigation entre les nœuds</span>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.8caed987">Affichage</h3>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.graph_nodes">Nœuds</strong><span data-i18n="help.desc_ab2c4150"> : Fichiers (carrés)
|
||
et dossiers (cercles) avec icônes</span></li>
|
||
<li>
|
||
<strong data-i18n="help.nodes_edges">Arêtes</strong><span data-i18n="help.desc_edges">: Wikilinks sortants
|
||
(bleu) et backlinks entrants (vert)</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.graph_info">Panneau d'info</strong><span data-i18n="help.desc_8717768b"> :
|
||
Métadonnées du nœud (tags, liens, chemin)</span></li>
|
||
<li>
|
||
<strong data-i18n="help.graph_preview">Ctrl+survol</strong><span data-i18n="help.desc_a579cf4d"> : Aperçu du
|
||
contenu de la note sans naviguer</span></li>
|
||
<li>
|
||
<strong data-i18n="graph.fullscreen">Plein écran</strong><span data-i18n="help.desc_fullscreen">: Bouton pour
|
||
agrandir la vue</span>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.graph_export">Export PNG</strong><span data-i18n="help.desc_export_png">: Sauvegardez le
|
||
graphe en image</span>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 id="cfg-performance" data-i18n="config.section_perf">Performance</h3>
|
||
<p data-i18n="auto.aa8ca265">
|
||
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 data-i18n="help.86e3825d">🎨 Personnalisation</h2>
|
||
|
||
<h3 data-i18n="auto.337d8626">Thème clair/sombre</h3>
|
||
<p data-i18n="help.theme_toggle">Basculez entre les thèmes :</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.menu_options">Menu Options</strong><span data-i18n="help.desc_beed5686"> : Cliquez sur
|
||
"Thème" dans le menu</span></li>
|
||
<li>
|
||
<strong>Raccourci</strong> :
|
||
<code>Ctrl+T</code>
|
||
</li>
|
||
<li>
|
||
<strong>Persistance</strong><span data-i18n="help.desc_e5b67e3d"> : Votre choix
|
||
est sauvegardé en localStorage</span></li>
|
||
<li>
|
||
<strong>Highlight.js</strong><span data-i18n="help.desc_d5c977ac"> : Les blocs de
|
||
code s'adaptent au thème</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.7bcbb2e3">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 data-i18n="auto.1a8a8118">Glisser-déposer</strong> : Cliquez
|
||
et glissez pour ajuster
|
||
</li>
|
||
<li>
|
||
<strong>Limites</strong> : Min 200px, Max
|
||
500px
|
||
</li>
|
||
<li>
|
||
<strong>Persistance</strong><span data-i18n="help.desc_6a80241e"> : La largeur
|
||
est sauvegardée</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="auto.9122fd5c">Configuration avancée</h3>
|
||
<p>
|
||
Le modal Configurations (menu Options) permet de
|
||
:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="config.section_search">Paramètres de recherche</strong><span data-i18n="help.desc_6b88a375"> :
|
||
Délai debounce, résultats par page, timeout</span></li>
|
||
<li>
|
||
<strong data-i18n="settings.backend_section">Paramètres backend</strong><span data-i18n="help.desc_5d0fbb81"> :
|
||
Workers, boosts TF-IDF, expansions préfixe</span></li>
|
||
<li>
|
||
<strong data-i18n="config.tag_filtering_label">Filtrage de tags</strong> : Patterns
|
||
pour masquer les tags template
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="config.diagnostics">Diagnostics</strong><span data-i18n="help.desc_6ae5342c"> : Stats index,
|
||
mémoire, moteur de recherche</span></li>
|
||
<li>
|
||
<strong data-i18n="auto.83a0efdf">Réindexation</strong> : Forcer un
|
||
rescan des vaults
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- ⌨️ Palette de commandes -->
|
||
<section class="help-section" id="help-palette">
|
||
<h2 data-i18n="help.62308f96">⌨️ Palette de commandes</h2>
|
||
<p data-i18n="auto.774dbd63">
|
||
La palette de commandes permet d'accéder
|
||
rapidement aux fichiers et aux actions sans
|
||
utiliser la souris.
|
||
</p>
|
||
|
||
<h3 data-i18n="help.b6619ac9">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 data-i18n="help.6d547397">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 data-i18n="help.3cf370b1">Mode commandes</h3>
|
||
<p>
|
||
Tapez <code>></code> (ou Ctrl+Alt+Espace)
|
||
pour voir la liste des actions disponibles :
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
🏠 <strong data-i18n="viewer.breadcrumb_home">Accueil</strong> : Retour à
|
||
l'accueil
|
||
</li>
|
||
<li>
|
||
✏️ <strong data-i18n="auto.b893650a">É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 data-i18n="auto.aedff644">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 data-i18n="auto.195a8e44">Créer répertoire</strong> : Crée
|
||
un nouveau dossier
|
||
</li>
|
||
<li>
|
||
🗑️ <strong data-i18n="auto.5a486420">Supprimer répertoire</strong> :
|
||
Supprime un dossier et son contenu
|
||
</li>
|
||
<li>
|
||
🌓 <strong data-i18n="theme.change">Changer le thème</strong> :
|
||
Bascule clair/sombre
|
||
</li>
|
||
<li>
|
||
🔄 <strong data-i18n="config.reindex">Réindexer</strong> : Force la
|
||
réindexation complète
|
||
</li>
|
||
<li>
|
||
❓ <strong data-i18n="header.help">Aide</strong> : Ouvre ce guide
|
||
</li>
|
||
<li>
|
||
⚙️ <strong data-i18n="config.title">Configuration</strong> : Ouvre
|
||
les paramètres
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.nav_navigation">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 data-i18n="help.2a2e5b0f">⌨️ Raccourcis clavier</h2>
|
||
|
||
<h3 data-i18n="help.nav_navigation">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 data-i18n="auto.13c3ee2c">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 data-i18n="help.nav_interface">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 data-i18n="help.nav_tabs">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 data-i18n="auto.a131dfab">É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 data-i18n="auto.c4922a99">🤖 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 data-i18n="help.activation">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 data-i18n="auto.5d4a2516">
|
||
Ouvrez un fichier en mode Édition (bouton ✏️
|
||
Éditer)
|
||
</li>
|
||
<li data-i18n="auto.396d0dd8">
|
||
La barre d'outils AI apparaît sous le titre
|
||
de l'éditeur
|
||
</li>
|
||
</ol>
|
||
|
||
<h3 data-i18n="help.toolbar_section">Barre d'outils AI</h3>
|
||
<p>
|
||
La barre d'outils contient les boutons suivants
|
||
:
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong>✦ AI</strong><span data-i18n="help.desc_3ace259e"> — Complétion inline
|
||
(</span><kbd>Ctrl+J</kbd>). Complète
|
||
automatiquement le texte là où se trouve le
|
||
curseur.
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="auto.a105a2d9">Éditer ▾</strong><span data-i18n="help.desc_a0ec890a"> — Menu de
|
||
modification du texte sélectionné :</span><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><span data-i18n="help.desc_1c130d89"> — Traduit le
|
||
texte sélectionné vers une autre langue :</span><ul>
|
||
<li>
|
||
🇬🇧 English · 🇨🇳 Chinese · 🇯🇵
|
||
Japanese · 🇩🇪 German · 🇫🇷 French ·
|
||
🇪🇸 Spanish
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="auto.ce4eb802">Générer ▾</strong><span data-i18n="help.desc_991307d6"> — Génère du
|
||
contenu à partir de la sélection :</span><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 data-i18n="auto.62c3d50d">💬 Réécrire</strong><span data-i18n="help.desc_c63f02cc"> — Réécrit le
|
||
texte selon vos instructions personnalisées.
|
||
Une boîte de dialogue vous demande votre
|
||
instruction.</span></li>
|
||
<li>
|
||
<strong data-i18n="auto.0257e77f">🧰 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 data-i18n="help.096367af">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 data-i18n="auto.4d281c6c">AI: texte traité ✓</strong> confirme
|
||
le succès
|
||
</li>
|
||
<li>
|
||
En cas d'erreur de clé API :
|
||
<strong data-i18n="auto.13eb7a51">AI: clé API invalide</strong>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.2dad2bfd">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 data-i18n="auto.272dd29a">Providers supportés</h3>
|
||
<table>
|
||
<tr>
|
||
<th>Provider</th>
|
||
<th>Variable .env</th>
|
||
<thdata-i18n="auto.033a9ddf">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 data-i18n="help.8c65b2f2">🔗 Partage et Webhooks</h2>
|
||
|
||
<h3 data-i18n="help.public_shares">Publication publique</h3>
|
||
<p>
|
||
ObsiGate permet de partager des documents via un
|
||
lien public temporaire.
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.share_button">Bouton Partager</strong><span data-i18n="help.desc_d66e911c"> : Dans les
|
||
actions du fichier, génère un lien unique</span></li>
|
||
<li>
|
||
<strong>Token unique</strong><span data-i18n="help.desc_04493800"> : 64
|
||
caractères hexadécimaux, impossible à
|
||
deviner</span></li>
|
||
<li>
|
||
<strong>Expiration configurable</strong><span data-i18n="help.desc_858681a1"> :
|
||
Durée de vie en heures</span></li>
|
||
<li>
|
||
<strong>Lecture seule</strong><span data-i18n="help.desc_e47d2328"> : La vue
|
||
publique n'affiche que le contenu sans
|
||
édition</span></li>
|
||
<li>
|
||
<strong>Gestion des liens</strong><span data-i18n="help.desc_5e9a7fd9"> : Liste
|
||
et révocation dans les Configurations</span></li>
|
||
<li>
|
||
<strong data-i18n="help.pdf_export">Export PDF</strong><span data-i18n="help.desc_e93517a5"> : Téléchargement
|
||
du document partagé en PDF via</span><code>/s/{token}/pdf</code>
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- 🪝 Webhooks -->
|
||
<section class="help-section" id="help-webhooks">
|
||
<h2 data-i18n="help.29afa01d">🪝 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 data-i18n="help.use_cases">Cas d'usage</h3>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.ci_cd">Automatisation CI/CD</strong><span data-i18n="help.desc_1ba39cc4"> :
|
||
Déclencher un build quand une note de
|
||
procédure est mise à jour</span></li>
|
||
<li>
|
||
<strong data-i18n="header.sync_status">Synchronisation</strong><span data-i18n="help.desc_d9cdaa89"> : Copier
|
||
les nouveaux fichiers vers un autre système
|
||
(SharePoint, Google Drive)</span></li>
|
||
<li>
|
||
<strong>Notifications</strong><span data-i18n="help.desc_6f7c5889"> : Alerter un
|
||
canal Slack/Discord quand un document est
|
||
créé</span></li>
|
||
<li>
|
||
<strong data-i18n="help.external_audit">Audit externe</strong><span data-i18n="help.desc_599f3242"> : Logger
|
||
toutes les modifications dans une base de
|
||
données externe</span></li>
|
||
<li>
|
||
<strong data-i18n="auto.a232672b">Déploiement</strong><span data-i18n="help.desc_2f2c16b5"> : Publier un
|
||
article de blog quand un fichier est marqué</span><code>publish: true</code>
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="auto.ba768f01">É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);
|
||
"
|
||
data-i18n="auto.f5a8c116">
|
||
Événement
|
||
</th>
|
||
<th
|
||
style="
|
||
padding: 8px 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
data-i18n="auto.d4d28717">
|
||
Déclencheur
|
||
</th>
|
||
<th
|
||
style="
|
||
padding: 8px 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid
|
||
var(--border);
|
||
"
|
||
data-i18n="auto.460b8298">
|
||
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);
|
||
"
|
||
data-i18n="auto.a05514cb">
|
||
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);
|
||
"
|
||
data-i18n="auto.fc694490">
|
||
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);
|
||
"
|
||
data-i18n="auto.2bc66bab">
|
||
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 data-i18n="help.77f4f06e">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 data-i18n="auto.28bf6aab">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 data-i18n="config.title">Configuration</h3>
|
||
<p>
|
||
Les webhooks se gèrent dans le modal
|
||
<strong data-i18n="header.menu_config">Configurations</strong> (⚙️ menu
|
||
Options), section Webhooks. Réservé aux
|
||
administrateurs.
|
||
</p>
|
||
<ol>
|
||
<li>
|
||
Allez dans ⚙️ Configurations → onglet
|
||
Webhooks
|
||
</li>
|
||
<li>
|
||
Remplissez :
|
||
<strong data-i18n="config.webhook_name_placeholder">Nom</strong> (descriptif),
|
||
<strong data-i18n="config.webhook_url_placeholder">URL</strong> (endpoint cible),
|
||
<strong>Secret</strong> (optionnel)
|
||
</li>
|
||
<li data-i18n="auto.7c9cdc3c">Cochez les événements à écouter</li>
|
||
<li>Cliquez <strong data-i18n="config.add_webhook">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 data-i18n="help.550b0240">Exemples concrets</h3>
|
||
|
||
<h4 data-i18n="auto.b419c2c2">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 data-i18n="help.d1ea1dc6">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 data-i18n="auto.14c75ac6">Sélectionnez les événements souhaités</li>
|
||
<li data-i18n="auto.2a5af19b">
|
||
Le workflow se déclenche automatiquement à
|
||
chaque événement
|
||
</li>
|
||
</ol>
|
||
|
||
<h4 data-i18n="help.229fd3e2">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 data-i18n="help.40dd7e38">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 data-i18n="help.381abec7">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 data-i18n="auto.98c547ea">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 data-i18n="auto.1d3330cc">Pas de retry automatique en cas d'échec</li>
|
||
<li data-i18n="auto.4dfa6a25">
|
||
Pas de filtrage par vault — un webhook
|
||
écoute toutes les vaults
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
<section class="help-section" id="help-sauvegardes">
|
||
<h2 data-i18n="help.62549eca">💾 Sauvegardes et Audits</h2>
|
||
|
||
<h3 data-i18n="help.backup_auto">Backup automatique</h3>
|
||
<p data-i18n="auto.ab5e6155">
|
||
ObsiGate crée automatiquement des sauvegardes
|
||
avant chaque modification destructive.
|
||
</p>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="help.before_write">Avant écriture</strong> : Sauvegarde
|
||
du contenu original dans
|
||
<code>.obsigate-backup/</code>
|
||
</li>
|
||
<li>
|
||
<strong>Timestamp</strong><span data-i18n="help.desc_31e7253b"> : Chaque backup
|
||
est horodaté</span></li>
|
||
<li>
|
||
<strong data-i18n="auto.41d7c6af">Répertoire dédié</strong> :
|
||
<code>.obsigate-backup/</code> dans le
|
||
répertoire de la vault
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.audit_log">Audit log</h3>
|
||
<p data-i18n="auto.2bc24d2e">
|
||
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 data-i18n="auto.598a0ca7">Événements tracés</strong><span data-i18n="help.desc_9f321d1e"> :
|
||
Écritures, suppressions, changements de
|
||
configuration</span></li>
|
||
<li>
|
||
<strong>Rotation</strong><span data-i18n="help.desc_19cf5730"> : Rotation
|
||
automatique à 10 Mo</span></li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- 🛡️ Sécurité -->
|
||
<section class="help-section" id="help-securite">
|
||
<h2 data-i18n="auto.37561472">🛡️ Sécurité</h2>
|
||
|
||
<h3 data-i18n="help.c48fb18a">Authentification</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>JWT + Argon2id</strong><span data-i18n="help.desc_8f0bffe3"> : Tokens JWT
|
||
avec mots de passe hachés Argon2id</span></li>
|
||
<li>
|
||
<strong data-i18n="auto.72e515fa">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 data-i18n="help.rate_limiting">Rate limiting</strong> : 10
|
||
tentatives / 15 min par IP + verrouillage
|
||
compte
|
||
</li>
|
||
<li>
|
||
<strong>Compte admin</strong><span data-i18n="help.desc_5fc28b7d"> : Créé
|
||
automatiquement au premier démarrage</span></li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.83f1d9ca">Protection</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Secret redactor</strong><span data-i18n="help.desc_9846fc07"> : Masque
|
||
JWT, clés API, tokens GitHub dans les
|
||
aperçus</span></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 data-i18n="help.atomic_writes">Atomic writes</strong><span data-i18n="help.desc_752789ab"> : Écriture
|
||
via fichier temporaire + renommage atomique</span></li>
|
||
<li>
|
||
<strong>Non-root Docker</strong> : Conteneur
|
||
tourne avec UID 1000
|
||
</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<section class="help-section" id="help-astuces">
|
||
<h2 data-i18n="help.686f8313">💡 Astuces et bonnes pratiques</h2>
|
||
|
||
<h3 data-i18n="auto.559ef1da">Workflow recommandé</h3>
|
||
<ol>
|
||
<li>
|
||
<strong data-i18n="auto.678711b5">Sélectionnez un contexte</strong><span data-i18n="help.desc_39979e71"> :
|
||
Choisissez un vault pour réduire le bruit</span></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><span data-i18n="help.desc_ae213f54"> :
|
||
Combinez opérateurs et texte libre</span></li>
|
||
<li>
|
||
<strong>Profitez de l'historique</strong><span data-i18n="help.desc_71eeb16a"> :
|
||
Réutilisez vos recherches fréquentes</span></li>
|
||
</ol>
|
||
|
||
<h3 data-i18n="help.fe388b67">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 data-i18n="auto.3be698f6">Favorisez les opérateurs</strong> :
|
||
<code>tag:</code> et
|
||
<code>vault:</code> accélèrent la recherche
|
||
</li>
|
||
<li>
|
||
<strong data-i18n="help.breadcrumb_clickable">Breadcrumb cliquable</strong> :
|
||
Repositionnez rapidement la sidebar
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.2a92203f">Trucs et astuces</h3>
|
||
<ul>
|
||
<li>
|
||
<strong>Navigation visuelle</strong> : Le
|
||
breadcrumb repositionne automatiquement la
|
||
sidebar
|
||
</li>
|
||
<li>
|
||
<strong>Gestion de l'espace</strong><span data-i18n="help.desc_287be69c"> :
|
||
Réduisez les sections Vaults/Tags selon vos
|
||
besoins</span></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 data-i18n="help.wikilinks">Wikilinks</strong> : Naviguez entre
|
||
notes comme dans Obsidian
|
||
</li>
|
||
<li>
|
||
<strong>Images</strong> : Support complet
|
||
des syntaxes Obsidian
|
||
</li>
|
||
</ul>
|
||
|
||
<h3 data-i18n="help.advanced_use_cases">Cas d'usage avancés</h3>
|
||
<ul>
|
||
<li>
|
||
<strong data-i18n="auto.b86ba5ea">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 data-i18n="auto.4fa5d7c2">Édition rapide</strong><span data-i18n="help.desc_cb6f0bfd"> : Ouvrez
|
||
l'éditeur, modifiez, sauvegardez</span></li>
|
||
<li>
|
||
<strong data-i18n="help.export">Export</strong><span data-i18n="help.desc_f9083ce5"> : Téléchargez des
|
||
fichiers pour backup ou partage</span></li>
|
||
<li>
|
||
<strong data-i18n="auto.79f6e1dd">Multi-fenêtres</strong><span data-i18n="help.desc_9cb5974c"> : Ouvrez
|
||
plusieurs notes dans des onglets séparés</span></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"
|
||
data-i18n-placeholder="settings.search_placeholder" 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>
|
||
// Force-kill stale Service Worker and reload fresh
|
||
(function(){if('serviceWorker'in navigator&&navigator.serviceWorker.controller){var reloaded=sessionStorage.getItem('_sw_killed');if(!reloaded){navigator.serviceWorker.getRegistrations().then(function(regs){regs.forEach(function(r){r.unregister()})});caches.keys().then(function(names){names.forEach(function(n){caches.delete(n)})});sessionStorage.setItem('_sw_killed','1');location.reload(true)}}else{sessionStorage.removeItem('_sw_killed')}})();
|
||
</script>
|
||
<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" data-i18n="settings.search">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" data-i18n="palette.mode_commands">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" data-i18n="help.nav_tabs">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>
|
||
<!-- Floating results bar (outside content-area, survives innerHTML) -->
|
||
<div class="results-bar" id="results-bar" style="display:none">
|
||
<span class="results-bar-count" id="rb-count">0/0</span>
|
||
<button class="results-bar-btn" id="rb-prev" title="Resultat precedent" aria-label="Precedent">↑</button>
|
||
<button class="results-bar-btn" id="rb-next" title="Resultat suivant" aria-label="Suivant">↓</button>
|
||
<span class="results-bar-sep"></span>
|
||
<button class="results-bar-btn tog" id="rb-case" title="Respecter la casse (Alt-C)">Aa</button>
|
||
<button class="results-bar-btn tog" id="rb-word" title="Mot entier (Alt-W)">wd</button>
|
||
<button class="results-bar-btn tog" id="rb-regex" title="Expression reguliere (Alt-R)">.*</button>
|
||
</div>
|
||
<!-- Offline conflict resolution modal -->
|
||
<div class="editor-modal" id="offline-conflict-modal">
|
||
<div class="editor-container" style="max-width:520px">
|
||
<div class="editor-header">
|
||
<span class="editor-brand">Conflit hors-ligne</span>
|
||
<div class="editor-spacer"></div>
|
||
<button class="editor-btn" id="offline-conflict-close" title="Fermer" aria-label="Fermer">✕</button>
|
||
</div>
|
||
<div class="editor-body" style="padding:20px;overflow:auto">
|
||
<p style="color:var(--text-secondary);margin-bottom:12px" id="offline-conflict-msg"></p>
|
||
<div style="display:flex;gap:8px">
|
||
<button class="editor-btn primary" id="offline-conflict-keep-local">Garder ma version</button>
|
||
<button class="editor-btn" id="offline-conflict-keep-server" data-i18n="offline.keep_server">Garder version serveur</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- About Modal -->
|
||
<div class="about-overlay" id="about-overlay">
|
||
<div class="about-modal">
|
||
<button class="about-close" id="about-close" aria-label="Fermer">×</button>
|
||
<div class="about-hero">
|
||
<div class="about-logo">
|
||
<svg width="56" height="56" viewBox="0 0 56 56" fill="none">
|
||
<rect width="56" height="56" rx="14" fill="var(--accent)" opacity="0.15"/>
|
||
<rect x="12" y="8" width="14" height="18" rx="3" fill="var(--accent)" opacity="0.9"/>
|
||
<rect x="29" y="8" width="14" height="18" rx="3" fill="var(--accent)" opacity="0.5"/>
|
||
<rect x="12" y="30" width="14" height="18" rx="3" fill="var(--accent)" opacity="0.7"/>
|
||
<rect x="29" y="30" width="14" height="18" rx="3" fill="var(--accent)" opacity="0.35"/>
|
||
</svg>
|
||
</div>
|
||
<h1 class="about-title" data-i18n="header.logo">ObsiGate</h1>
|
||
<p class="about-tagline">Vos notes Obsidian,<br>simplement accessibles.</p>
|
||
<span class="about-version">v2.0.0-dev</span>
|
||
</div>
|
||
<div class="about-body">
|
||
<div class="about-stats">
|
||
<div class="about-stat">
|
||
<span class="about-stat-value" id="about-stat-files">—</span>
|
||
<span class="about-stat-label" data-i18n="palette.mode_files">Fichiers</span>
|
||
</div>
|
||
<div class="about-stat">
|
||
<span class="about-stat-value" id="about-stat-vaults">—</span>
|
||
<span class="about-stat-label" data-i18n="sidebar.tab_vaults">Vaults</span>
|
||
</div>
|
||
<div class="about-stat">
|
||
<span class="about-stat-value">285</span>
|
||
<span class="about-stat-label">Tests</span>
|
||
</div>
|
||
</div>
|
||
<div class="about-stack">
|
||
<h3>Construit avec</h3>
|
||
<div class="about-stack-grid">
|
||
<span class="about-stack-badge">🐍 FastAPI</span>
|
||
<span class="about-stack-badge">⚡ vanilla JS</span>
|
||
<span class="about-stack-badge">🎨 CSS custom</span>
|
||
<span class="about-stack-badge">🐳 Docker</span>
|
||
<span class="about-stack-badge">🔍 TF-IDF</span>
|
||
<span class="about-stack-badge">📝 CodeMirror 6</span>
|
||
<span class="about-stack-badge">🧜 Mermaid.js</span>
|
||
<span class="about-stack-badge">🧠 Argon2id</span>
|
||
<span class="about-stack-badge">🔄 Watchdog</span>
|
||
<span class="about-stack-badge">📊 WeasyPrint</span>
|
||
<span class="about-stack-badge">🧪 Playwright</span>
|
||
<span class="about-stack-badge">🤖 AI multi-provider</span>
|
||
</div>
|
||
</div>
|
||
<div class="about-footer">
|
||
<div class="about-meta">
|
||
<span>Derniere livraison : <strong id="about-build-date">Juin 2026</strong></span>
|
||
<span>Git : <strong id="about-commit">—</strong></span>
|
||
</div>
|
||
<p class="about-joke" id="about-joke"></p>
|
||
<p class="about-copy">© 2026 — Fait avec ☕, 🎧 et quelques <code>git push --force</code> accidentels.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</body>
|
||
</html>
|