- Added UrlStateService to sync app state with URL parameters for note selection, tags, folders, and search - Implemented URL state effects in AppComponent to handle navigation from URL parameters - Updated sidebar and layout components to reflect URL state changes in UI - Added URL state updates when navigating via note selection, tag clicks, and search - Modified note sharing to use URL parameters instead of route paths - Added auto-opening of relevant
11 KiB
UrlStateService - Exemples d'URL et Cas d'Usage
📌 Table des matières
- Exemples simples
- Exemples combinés
- Cas d'usage réels
- Partage de liens
- Gestion des erreurs
- Bonnes pratiques
Exemples Simples
1. Ouvrir une note
URL:
https://app.example.com/viewer?note=Docs/Architecture.md
Résultat:
- La note
Docs/Architecture.mds'ouvre dans la vue note - Le contenu est chargé et affiché
- La note est mise en surbrillance dans la liste
Code:
await this.urlState.openNote('Docs/Architecture.md');
2. Filtrer par tag
URL:
https://app.example.com/viewer?tag=Ideas
Résultat:
- Affiche toutes les notes avec le tag
Ideas - Le tag est mis en surbrillance dans la liste des tags
- La liste des notes est filtrée
Code:
await this.urlState.filterByTag('Ideas');
3. Filtrer par dossier
URL:
https://app.example.com/viewer?folder=Notes/Meetings
Résultat:
- Affiche toutes les notes du dossier
Notes/Meetings - Le dossier est mis en surbrillance dans l'arborescence
- La liste des notes est filtrée
Code:
await this.urlState.filterByFolder('Notes/Meetings');
4. Afficher un quick link
URL:
https://app.example.com/viewer?quick=Favoris
Résultat:
- Affiche les notes marquées comme favoris
- Le quick link est mis en surbrillance
- La liste des notes est filtrée
Code:
await this.urlState.filterByQuickLink('Favoris');
5. Rechercher
URL:
https://app.example.com/viewer?search=performance
Résultat:
- Affiche les résultats de recherche pour "performance"
- Les notes contenant le terme sont listées
- Le terme est mis en surbrillance
Code:
await this.urlState.updateSearch('performance');
Exemples Combinés
1. Note avec recherche
URL:
https://app.example.com/viewer?note=Docs/Architecture.md&search=performance
Résultat:
- Ouvre la note
Docs/Architecture.md - Met en surbrillance les occurrences de "performance"
- Permet de naviguer entre les occurrences
Code:
await this.urlState.openNote('Docs/Architecture.md');
await this.urlState.updateSearch('performance');
2. Dossier avec tag
URL:
https://app.example.com/viewer?folder=Notes/Meetings&tag=Important
Résultat:
- Affiche les notes du dossier
Notes/Meetings - Filtre par le tag
Important - Affiche l'intersection des deux filtres
Code:
await this.urlState.filterByFolder('Notes/Meetings');
await this.urlState.filterByTag('Important');
3. Quick link avec recherche
URL:
https://app.example.com/viewer?quick=Archive&search=2024
Résultat:
- Affiche les notes archivées
- Filtre par le terme "2024"
- Affiche les notes archivées contenant "2024"
Code:
await this.urlState.filterByQuickLink('Archive');
await this.urlState.updateSearch('2024');
4. Dossier avec recherche
URL:
https://app.example.com/viewer?folder=Journal&search=2025
Résultat:
- Affiche les notes du dossier
Journal - Filtre par le terme "2025"
- Affiche les notes du journal contenant "2025"
Code:
await this.urlState.filterByFolder('Journal');
await this.urlState.updateSearch('2025');
Cas d'Usage Réels
1. Documentation d'Architecture
Scénario: Vous travaillez sur l'architecture et voulez partager une note spécifique avec votre équipe.
URL:
https://app.example.com/viewer?note=Docs/Architecture.md
Avantages:
- Lien direct vers la note
- Pas besoin de naviguer manuellement
- Contexte clair pour l'équipe
2. Réunion d'équipe
Scénario: Vous voulez afficher les notes de réunion d'un mois spécifique.
URL:
https://app.example.com/viewer?folder=Notes/Meetings/2025-01&tag=Important
Avantages:
- Filtre par dossier et tag
- Affiche uniquement les réunions importantes
- Facile à partager avec l'équipe
3. Recherche de bug
Scénario: Vous cherchez des notes contenant "bug" dans le dossier "Issues".
URL:
https://app.example.com/viewer?folder=Issues&search=bug
Avantages:
- Recherche ciblée dans un dossier
- Résultats pertinents
- Facile à reproduire
4. Favoris du projet
Scénario: Vous voulez afficher les notes favorites du projet "ProjectX".
URL:
https://app.example.com/viewer?quick=Favoris&search=ProjectX
Avantages:
- Affiche les favoris
- Filtre par projet
- Vue d'ensemble rapide
5. Tâches urgentes
Scénario: Vous voulez voir les tâches urgentes du jour.
URL:
https://app.example.com/viewer?quick=Tâches&tag=Urgent
Avantages:
- Affiche les tâches
- Filtre par urgence
- Priorisation facile
6. Brouillons à publier
Scénario: Vous voulez voir les brouillons prêts à être publiés.
URL:
https://app.example.com/viewer?quick=Brouillons&tag=Prêt
Avantages:
- Affiche les brouillons
- Filtre par statut
- Workflow clair
7. Archive par année
Scénario: Vous voulez consulter l'archive de 2024.
URL:
https://app.example.com/viewer?folder=Archive/2024
Avantages:
- Affiche l'archive d'une année
- Navigation facile
- Historique accessible
Partage de Liens
1. Partage simple
Scénario: Vous voulez partager une note avec un collègue.
// Générer le lien
const shareUrl = this.urlState.generateShareUrl();
// Copier dans le presse-papiers
await this.urlState.copyCurrentUrlToClipboard();
// Afficher un toast
this.toast.success('Lien copié!');
Résultat:
https://app.example.com/viewer?note=Docs/Architecture.md
2. Partage avec contexte
Scénario: Vous voulez partager une note avec un contexte de recherche.
// Générer le lien avec contexte
const shareUrl = this.urlState.generateShareUrl({
note: 'Docs/Architecture.md',
search: 'performance'
});
// Partager
await navigator.clipboard.writeText(shareUrl);
Résultat:
https://app.example.com/viewer?note=Docs/Architecture.md&search=performance
3. Partage de filtre
Scénario: Vous voulez partager un filtre avec votre équipe.
// Appliquer le filtre
await this.urlState.filterByTag('Ideas');
// Générer et copier le lien
const shareUrl = this.urlState.generateShareUrl();
await navigator.clipboard.writeText(shareUrl);
Résultat:
https://app.example.com/viewer?tag=Ideas
4. Bouton de partage
Scénario: Vous voulez ajouter un bouton de partage dans l'interface.
@Component({
selector: 'app-share-button',
template: `
<button (click)="shareCurrentState()" class="share-btn">
📤 Partager
</button>
`
})
export class ShareButtonComponent {
urlState = inject(UrlStateService);
toast = inject(ToastService);
async shareCurrentState(): Promise<void> {
try {
await this.urlState.copyCurrentUrlToClipboard();
this.toast.success('Lien copié!');
} catch (error) {
this.toast.error('Erreur lors de la copie');
}
}
}
Gestion des Erreurs
1. Note introuvable
URL:
https://app.example.com/viewer?note=NonExistent.md
Résultat:
- Message d'avertissement dans la console
- L'état n'est pas mis à jour
- L'interface reste dans l'état précédent
Code:
try {
await this.urlState.openNote('NonExistent.md');
} catch (error) {
console.error('Note not found');
this.toast.error('Note introuvable');
}
2. Tag inexistant
URL:
https://app.example.com/viewer?tag=NonExistent
Résultat:
- Message d'avertissement dans la console
- L'état n'est pas mis à jour
- L'interface reste dans l'état précédent
Code:
try {
await this.urlState.filterByTag('NonExistent');
} catch (error) {
console.error('Tag not found');
this.toast.warning('Tag inexistant');
}
3. Dossier inexistant
URL:
https://app.example.com/viewer?folder=NonExistent
Résultat:
- Message d'avertissement dans la console
- L'état n'est pas mis à jour
- L'interface reste dans l'état précédent
Code:
try {
await this.urlState.filterByFolder('NonExistent');
} catch (error) {
console.error('Folder not found');
this.toast.warning('Dossier inexistant');
}
4. Quick link invalide
URL:
https://app.example.com/viewer?quick=Invalid
Résultat:
- Message d'avertissement dans la console
- L'état n'est pas mis à jour
- L'interface reste dans l'état précédent
Code:
try {
await this.urlState.filterByQuickLink('Invalid');
} catch (error) {
console.error('Invalid quick link');
this.toast.warning('Quick link invalide');
}
Bonnes Pratiques
1. Toujours valider les données
// ❌ Mauvais - Pas de validation
await this.urlState.openNote(userInput);
// ✅ Bon - Validation
const note = this.vault.allNotes().find(n => n.filePath === userInput);
if (note) {
await this.urlState.openNote(userInput);
} else {
this.toast.error('Note introuvable');
}
2. Gérer les erreurs
// ❌ Mauvais - Pas de gestion d'erreur
await this.urlState.filterByTag(userInput);
// ✅ Bon - Gestion d'erreur
try {
await this.urlState.filterByTag(userInput);
} catch (error) {
console.error('Error:', error);
this.toast.error('Erreur lors du filtrage');
}
3. Utiliser les signaux
// ❌ Mauvais - Pas réactif
const tag = this.urlState.currentState().tag;
// ✅ Bon - Réactif
const tag = this.urlState.activeTag;
4. Écouter les changements
// ❌ Mauvais - Pas d'écoute
this.urlState.openNote('Note.md');
// ✅ Bon - Écouter les changements
effect(() => {
const note = this.urlState.currentNote();
if (note) {
console.log('Note changed:', note.title);
}
});
5. Nettoyer les ressources
// ❌ Mauvais - Pas de nettoyage
this.urlState.stateChange$.subscribe(event => {
console.log('State changed:', event);
});
// ✅ Bon - Nettoyage
private destroy$ = new Subject<void>();
constructor() {
this.urlState.stateChange$
.pipe(takeUntil(this.destroy$))
.subscribe(event => {
console.log('State changed:', event);
});
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
6. Utiliser les types
// ❌ Mauvais - Pas de types
const state = this.urlState.currentState();
// ✅ Bon - Avec types
const state: UrlState = this.urlState.currentState();
7. Documenter les URLs
/**
* Ouvre une note spécifique
*
* URL: /viewer?note=Docs/Architecture.md
*
* @param notePath - Chemin de la note (ex: 'Docs/Architecture.md')
*/
async openNote(notePath: string): Promise<void> {
// ...
}
Résumé
Le UrlStateService offre une solution flexible pour gérer l'état de l'interface via l'URL:
- ✅ Exemples simples pour les cas courants
- ✅ Exemples combinés pour les cas complexes
- ✅ Cas d'usage réels pour l'inspiration
- ✅ Partage de liens facile
- ✅ Gestion des erreurs robuste
- ✅ Bonnes pratiques pour la qualité du code
Utilisez ces exemples comme base pour intégrer le service dans votre application.