ObsiViewer/docs/GRAPH/INTEGRATION_CHECKLIST.md

8.6 KiB

📋 Checklist d'intégration - Wikilinks & Graph View

Ce qui a été créé automatiquement

Services (3 fichiers)

  • src/services/wikilink-parser.service.ts
  • src/services/note-index.service.ts
  • src/services/note-preview.service.ts

Composants (4 composants)

  • src/components/note-preview-card/
  • src/components/graph-options-panel/
  • src/components/graph-view-container/
  • src/components/graph-view/ (modifié avec d3-force)

Modifications

  • src/components/tags-view/note-viewer/note-viewer.component.ts (hover preview)
  • src/styles.css (styles wikilinks et overlays)

Documentation (4 fichiers)

  • docs/WIKILINKS_README.md
  • docs/WIKILINKS_GRAPH_IMPLEMENTATION.md
  • docs/WIKILINKS_QUICK_START.md
  • INTEGRATION_CHECKLIST.md (ce fichier)

Tests

  • src/services/wikilink-parser.service.spec.ts

🔧 Étapes d'intégration manuelle

Étape 1 : Identifier votre service de vault principal

Trouvez où vous chargez les notes dans votre application.

Exemple possible : src/services/vault.service.ts ou src/app.component.ts

// Votre fichier actuel (à identifier)
export class VaultService {
  notes = signal<Note[]>([]);
  
  loadNotes() {
    // Votre logique de chargement actuelle
    this.http.get<Note[]>('/api/notes').subscribe(notes => {
      this.notes.set(notes);
    });
  }
}

Étape 2 : Ajouter le scan du vault

Fichier à modifier : Le service identifié à l'étape 1

import { NoteIndexService } from './services/note-index.service';

export class VaultService {
  private noteIndexService = inject(NoteIndexService);
  notes = signal<Note[]>([]);
  
  loadNotes() {
    this.http.get<Note[]>('/api/notes').subscribe(notes => {
      this.notes.set(notes);
      
      // ✨ AJOUTER CETTE LIGNE
      this.noteIndexService.scanVault(notes);
    });
  }
}

Checkpoint : L'index est construit au chargement du vault


Étape 3 : Identifier votre composant de vue de note

Trouvez le composant qui affiche une note individuelle.

Exemple possible :

  • src/components/note-page/note-page.component.ts
  • src/components/note-display/note-display.component.ts
  • src/app/pages/note/note.component.ts

Étape 4 : Activer les previews dans note-viewer

Fichier à modifier : Le composant identifié à l'étape 3

// AVANT
@Component({
  template: `
    <app-note-viewer
      [note]="currentNote()"
      [noteHtmlContent]="htmlContent()">
    </app-note-viewer>
  `
})

// APRÈS - Ajouter [allNotes]
@Component({
  template: `
    <app-note-viewer
      [note]="currentNote()"
      [noteHtmlContent]="htmlContent()"
      [allNotes]="allNotes()">  <!-- ✨ AJOUTER -->
    </app-note-viewer>
  `
})
export class NotePageComponent {
  private vaultService = inject(VaultService);
  
  currentNote = signal<Note>(...);
  allNotes = computed(() => this.vaultService.notes());  // ✨ AJOUTER
}

Checkpoint : Hover sur un wikilink affiche une preview card


Étape 5 : Ajouter le toggle Document/Graph

Fichier à modifier : Le même composant qu'à l'étape 4

import { GraphViewContainerComponent } from './components/graph-view-container/graph-view-container.component';

@Component({
  template: `
    <div class="note-page-container">
      <!-- Toolbar avec toggle -->
      <div class="toolbar flex gap-2 p-4 border-b">
        <button 
          (click)="viewMode.set('document')"
          [class.active]="viewMode() === 'document'"
          class="px-4 py-2 rounded">
          📄 Document
        </button>
        <button 
          (click)="viewMode.set('graph')"
          [class.active]="viewMode() === 'graph'"
          class="px-4 py-2 rounded">
          🕸️ Graph
        </button>
      </div>
      
      <!-- Contenu conditionnel -->
      <div class="content-area flex-1">
        @if (viewMode() === 'document') {
          <app-note-viewer
            [note]="currentNote()"
            [noteHtmlContent]="htmlContent()"
            [allNotes]="allNotes()"
            (wikiLinkActivated)="onWikiLinkClick($event)">
          </app-note-viewer>
        } @else {
          <app-graph-view-container
            [centerNoteId]="currentNote().id"
            (nodeSelected)="onNodeSelected($event)">
          </app-graph-view-container>
        }
      </div>
    </div>
  `,
  imports: [NoteViewerComponent, GraphViewContainerComponent],
  styles: [`
    .note-page-container {
      display: flex;
      flex-direction: column;
      height: 100%;
    }
    
    .toolbar button.active {
      background-color: #4f46e5;
      color: white;
    }
    
    .content-area {
      overflow: auto;
    }
  `]
})
export class NotePageComponent {
  viewMode = signal<'document' | 'graph'>('document');  // ✨ AJOUTER
  currentNote = signal<Note>(...);
  allNotes = computed(() => this.vaultService.notes());
  
  onNodeSelected(nodeId: string) {  // ✨ AJOUTER
    // Naviguer vers la note sélectionnée
    this.router.navigate(['/note', nodeId]);
  }
  
  onWikiLinkClick(link: WikiLinkActivation) {  // ✨ AJOUTER
    this.router.navigate(['/note', link.target], {
      fragment: link.heading || link.block
    });
  }
}

Checkpoint : Bouton Graph affiche le graphe interactif


🧪 Tests de validation

  1. Créer une note avec [[test]]
  2. Vérifier que le lien est bleu et souligné
  3. Clic → navigation fonctionne

Test 2 : Preview au survol

  1. Hover sur un wikilink
  2. Attendre 300ms
  3. Une carte apparaît avec titre + extrait
  4. Quitter → carte disparaît

Test 3 : Graph View

  1. Cliquer sur "Graph"
  2. Voir le graphe avec le nœud actuel au centre
  3. Drag un nœud → il se déplace
  4. Ajuster un slider → le graphe réagit

Test 4 : Liens orphelins

  1. Créer [[note-inexistante]]
  2. Le lien doit être gris avec pointillés
  3. Hover → pas de preview (normal)

🎨 Personnalisation optionnelle

Ajouter dans src/styles.css :

:root {
  --wiki-link: #10b981;              /* Vert */
  --wiki-link-hover: #059669;
  --wiki-link-orphan: #ef4444;       /* Rouge */
  --wiki-link-orphan-hover: #dc2626;
}

Forces du graphe par défaut

Modifier src/components/graph-view-container/graph-view-container.component.ts :

displayOptions = signal<GraphDisplayOptions>({
  showArrows: true,
  textFadeThreshold: 50,
  nodeSize: 7,              // Nœuds plus gros
  linkThickness: 2,         // Liens plus épais
  chargeStrength: -150,     // Plus de répulsion
  linkDistance: 120,        // Liens plus longs
  centerStrength: 0.1,      // Plus de centrage
  centerNodeId: undefined
});

📊 Vérification finale

Cochez chaque élément :

Fonctionnalités core

  • Scanner du vault appelé au chargement
  • Wikilinks sont cliquables
  • Preview card s'affiche au hover (300ms)
  • Graph View remplace le document
  • Drag & drop des nœuds fonctionne

Options du graphe

  • Slider "Node size" modifie la taille
  • Slider "Link thickness" modifie l'épaisseur
  • Toggle "Arrows" affiche/cache les flèches
  • Bouton "Animate" relance la simulation
  • Forces ajustables fonctionnent

Performance

  • Graph avec 100 notes : fluide (60fps)
  • Preview s'ouvre rapidement (<500ms)
  • Pas d'erreur dans la console

Responsive

  • Desktop : Panneau options fixe à droite
  • Mobile : Drawer coulissant pour options
  • Preview cards s'adaptent à l'écran

🆘 Problèmes courants

"Property 'allNotes' does not exist"

Vous avez oublié d'ajouter l'input dans votre composant parent :

allNotes = computed(() => this.vaultService.notes());

"Cannot find module 'graph-view-container'"

Vérifiez le chemin d'import relatif depuis votre composant.

"Le graphe est vide"

// Vérifier que le scan a été fait
console.log('Nodes:', this.noteIndexService.getAllNodes().length);

// Si 0, appeler scanVault()
this.noteIndexService.scanVault(this.allNotes());

"Les previews ne s'affichent jamais"

Vérifiez que [allNotes] est bien passé au note-viewer.


📚 Ressources

  • Documentation complète : docs/WIKILINKS_GRAPH_IMPLEMENTATION.md
  • Guide rapide : docs/WIKILINKS_QUICK_START.md
  • Exemples de code : Voir les docs ci-dessus

C'est fait !

Une fois toutes les étapes complétées, vous avez :

Wikilinks cliquables avec preview au survol
🕸️ Graph View interactif avec toutes les options
Performance optimisée pour 1000+ notes
📱 Responsive desktop et mobile

Bon travail ! 🎉