230 lines
16 KiB
Markdown
230 lines
16 KiB
Markdown
# 📘 Guide d'Implémentation : Fonctionnalités de Partage et Collaboration (Style Notion pour Flowdesk)
|
|
|
|
> Sources officielles consultées : [Sharing & permissions](https://www.notion.com/help/sharing-and-permissions), [Comments, mentions & reactions](https://www.notion.com/help/comments-mentions-and-reminders), [Suggested edits](https://www.notion.com/help/suggested-edits), [Create & manage groups](https://www.notion.com/help/create-and-manage-groups), [Who's who in a workspace](https://www.notion.com/help/whos-who-in-a-workspace), [Collaborate in a workspace](https://www.notion.com/help/collaborate-within-a-workspace).
|
|
|
|
## 1. Vue d'ensemble des fonctionnalités cibles
|
|
Pour reproduire l'expérience de collaboration de Notion, le clone Flowdesk doit intégrer cinq piliers fonctionnels :
|
|
|
|
1. **Partage granulaire** : Invitation de membres, d'invités externes (guests, par email), partage avec des groupes, des teamspaces, ou partage public par lien / publication web.
|
|
2. **Niveaux d'accès (RBAC)** : `Full access`, `Can edit`, `Can edit content`, `Can create`, `Can comment`, `Can view` — avec sémantique précise (voir §2 et §4).
|
|
3. **Permissions au niveau des pages de base de données (Page-Level Access)** : Règles d'accès dynamiques basées sur les propriétés « Personne » ou « Créé par ».
|
|
4. **Droits sur les rôles du workspace** : membres, membres restreints, invités (guests), membres temporaires, propriétaires, admins de membres, groupes (dont groupes synchronisés via SCIM).
|
|
5. **Collaboration synchrone & asynchrone** : présence en temps réel (avatars), édition simultanée, commentaires (page, bloc, propriété), mentions (@), réactions, suggestions d'édition (suggested edits) et verrouillage de page.
|
|
|
|
---
|
|
|
|
## 2. Guide d'utilisation (Flux Utilisateur)
|
|
*L'agent IA doit reproduire ces flux interactifs :*
|
|
|
|
### 2.1 Initier le partage
|
|
1. L'utilisateur clique sur **« Partager »** en haut à droite de la page.
|
|
2. La modale propose trois actions : **inviter des personnes**, **copier le lien de la page**, **publier sur le web** (onglet `Publish`, distinct du simple partage par lien).
|
|
3. Pour inviter, l'utilisateur tape un nom (membre ou groupe) ou un email d'invité externe. Le système propose une autocomplétion en temps réel.
|
|
4. Un menu déroulant à côté de chaque nom permet de choisir le niveau d'accès, puis l'utilisateur clique sur **Inviter**.
|
|
|
|
### 2.2 Configurer l'accès général (General access)
|
|
Un sélecteur définit la visibilité par défaut de la page :
|
|
- **`Only people invited`** : seuls l'utilisateur et les personnes invitées y ont accès.
|
|
- **`Everyone at {workspace}`** : tous les membres du workspace y accèdent via la recherche ou le lien — avec option **« Hide in search »** pour masquer la page des résultats de recherche.
|
|
- **`Anyone on the web with link`** : toute personne disposant du lien peut y accéder, même sans compte Notion (connexion requise uniquement pour commenter/modifier) — avec option **« Link expires »** pour faire expirer le lien.
|
|
|
|
Pour chaque groupe d'accès général, on peut attribuer un niveau d'accès indépendant.
|
|
|
|
> **Note (sécurité Enterprise)** : les propriétaires peuvent désactiver les liens publics via `Settings → Security → Disable publishing sites, forms and public links`.
|
|
|
|
### 2.3 Demander l'accès (Request access)
|
|
- **Aucune page accessible** : en ouvrant une page, l'utilisateur voit un bouton `No access` → envoie une demande, notifie le créateur/éditeur qui peut accepter ou refuser.
|
|
- **Accès en lecture/commentaire** : `Share → dropdown de son propre niveau → Request edit access`. La demande est envoyée au créateur de la page.
|
|
|
|
### 2.4 Règles de base de données (Page-level access, optionnel)
|
|
1. Ouvrir la **base source** (pas une vue liée).
|
|
2. `Share` → section **`Page-level access`** → **`Add a new rule`**.
|
|
3. Choisir une propriété `Person` ou `Created by`, puis un niveau d'accès → **`Create rule`**.
|
|
|
|
Exemple : « Les personnes dans la propriété `Assigné à` peuvent **modifier** leur propre ligne ». Les règles s'appliquent à **toutes les vues** de la base, y compris les **vues liées**. Chaque source de données (data source) d'une base multi-sources peut avoir ses propres règles.
|
|
|
|
### 2.5 Arrêter de partager
|
|
- Glisser la page vers la section **`Private`** de la sidebar (supprime l'accès de tous les autres).
|
|
- Ou `Share` → dropdown de chaque personne/groupe/teamspace → **`Remove`**.
|
|
|
|
---
|
|
|
|
## 3. Représentation Visuelle (UI/UX) pour l'Agent IA
|
|
*Instructions de conception d'interface pour la génération de code frontend :*
|
|
|
|
### Bouton de partage
|
|
En haut à droite, dans la barre de titre de la page. Bouton secondaire avec icône de partage (ou libellé « Partager »).
|
|
|
|
### Modale de partage (Share Modal)
|
|
- Champ de saisie en haut avec placeholder « Inviter des personnes... ».
|
|
- Liste verticale des utilisateurs/groupes ayant accès. Chaque ligne : **Avatar + Nom/Email + Dropdown de permission (ex. « Peut modifier » ▼) + Icône X (suppression)**.
|
|
- Section **« General access »** avec le sélecteur principal et les options conditionnelles (case « Hide in search », expiration du lien).
|
|
- Section **« Page-level access »** (base de données uniquement) listant les règles existantes + bouton « Add a new rule ».
|
|
- **Validation en lecture seule** : la modale doit montrer à l'utilisateur courant son niveau d'accès courant, avec la possibilité de « Request edit access ».
|
|
|
|
### Indicateurs de présence (Presence Bar)
|
|
- Barre horizontale en haut de la page, alignée à droite, affichant les avatars des utilisateurs ayant accès.
|
|
- **Avatar plein** : personne actuellement sur la page.
|
|
- **Avatar estompé (opacité réduite)** : personne récemment partie.
|
|
- **Avatars mobiles** : en collaboration simultanée, les avatars se déplacent **à côté des blocs** que chacun lit/édite.
|
|
- **Au survol** : infobulle avec Nom, Email et « Dernière activité il y a X ».
|
|
- **Au clic** : la vue défile jusqu'à la position de lecture/édition de la personne ciblée.
|
|
- **Historique** : menu `•••` en haut à droite → bas du menu : « Dernière modification par X, il y a Y ».
|
|
|
|
### Système de commentaires
|
|
- **Discussion de page (top-level)** : au survol du haut de la page, bouton « Add comment ».
|
|
- **Commentaires inline** (plusieurs déclencheurs) : sélection de texte → « Comment » ; icône `⋮⋮` à gauche du bloc → « Comment » ; bouton `💬` au survol du bloc ; raccourci `Ctrl/Cmd + Shift + M` ; clic sur un `💬` existant pour répondre.
|
|
- **Panneau de commentaires (Comments pane)** : icône `💬` en haut de page (pastille rouge si non-lus). Filtrage par personne / statut (ouverts / résolus). Tri par dernier message.
|
|
- **Indicateur de résolution** : ✔️ pour résoudre, `•••` → Éditer / Supprimer, `↪️` pour rouvrir un commentaire résolu.
|
|
- **Réactions** : surligner un texte → `🙂` → emoji ; survol d'un commentaire → `🙂` → emoji.
|
|
- **Commentaires de base de données** : `💬` associé aux lignes (table/board/gallery) ; `⋮⋮`/`•••` → « Comment » ; commentaires sur les **propriétés** (survol d'une propriété → `💬`).
|
|
- **Mentions (@)** : la saisie de « @ » ouvre un menu contextuel (Popper) à trois types : **Personnes/groupes**, **Pages** (lien inline + backlink auto), **Date** (aujourd'hui/demain/hier ou date).
|
|
- **Mode Suggestion (Suggested edits)** : activé via `•••` → « Suggest edits ». Bandeau `Suggesting` en haut. Les suggestions (ajout/suppression) apparaissent dans la marge, acceptables (✔️) ou refusables (❌), réactives (emoji) et commentables.
|
|
|
|
### Verrouillage de page / base
|
|
- **Lock page** (`•••` → `Lock page`) : page en lecture seule pour tous, badge `Locked` dans le breadcrumb.
|
|
- **Lock database** : verrouille la structure (vues/propriétés) tout en permettant l'édition des données.
|
|
- **Déverrouillage** : `Locked` → `Unlock for me` (déverrouille pour soi uniquement) ou `Unlock for everyone`.
|
|
|
|
---
|
|
|
|
## 4. Guide d'Implémentation Technique (Architecture & Données)
|
|
*Spécifications pour que l'agent IA génère le backend et la logique métier :*
|
|
|
|
### A. Modèle de données (Schéma relationnel simplifié)
|
|
```sql
|
|
-- Principaux (Utilisateurs et Groupes)
|
|
CREATE TABLE principals (
|
|
id UUID PRIMARY KEY,
|
|
type VARCHAR(20), -- 'user' | 'group' | 'teamspace' | 'guest'
|
|
name VARCHAR(255),
|
|
email VARCHAR(255) UNIQUE, -- NULL pour les groupes
|
|
workspace_role VARCHAR(20), -- 'member' | 'restricted_member' | 'guest' |
|
|
-- 'temporary_member' | 'workspace_owner' |
|
|
-- 'membership_admin' | 'organization_owner'
|
|
is_scim_managed BOOLEAN DEFAULT false -- groupes synchronisés via identité externe
|
|
);
|
|
|
|
-- Appartenance utilisateur -> groupe (N:N)
|
|
CREATE TABLE group_members (
|
|
group_id UUID REFERENCES principals(id),
|
|
member_id UUID REFERENCES principals(id),
|
|
PRIMARY KEY (group_id, member_id)
|
|
);
|
|
|
|
-- Ressources (Pages, Bases de données)
|
|
CREATE TABLE resources (
|
|
id UUID PRIMARY KEY,
|
|
type VARCHAR(50), -- 'page' | 'database'
|
|
parent_id UUID, -- Héritage des permissions
|
|
workspace_id UUID,
|
|
is_locked BOOLEAN DEFAULT false -- verrou de page
|
|
);
|
|
|
|
-- Permissions (RBAC avec héritage)
|
|
CREATE TABLE permissions (
|
|
id UUID PRIMARY KEY,
|
|
resource_id UUID REFERENCES resources(id),
|
|
principal_id UUID REFERENCES principals(id),
|
|
access_level VARCHAR(20), -- 'full' | 'edit' | 'edit_content' | 'create' | 'comment' | 'view'
|
|
is_inherited BOOLEAN DEFAULT false -- true si hérité du parent / teamspace / workspace
|
|
);
|
|
|
|
-- Règles d'accès au niveau de la page de base de données (Page-Level Access)
|
|
CREATE TABLE page_level_rules (
|
|
id UUID PRIMARY KEY,
|
|
database_id UUID REFERENCES resources(id),
|
|
target_property_name VARCHAR(50), -- propriété 'Person' OU 'Created by'
|
|
access_level VARCHAR(20), -- 'edit' | 'comment' | 'view' (etc.)
|
|
data_source_id UUID NULL -- en cas de base multi-sources
|
|
);
|
|
|
|
-- Commentaires
|
|
CREATE TABLE comments (
|
|
id UUID PRIMARY KEY,
|
|
resource_id UUID REFERENCES resources(id),
|
|
block_id UUID NULL, -- NULL = discussion de page ; sinon bloc/propriété ciblé
|
|
author_id UUID REFERENCES principals(id),
|
|
content TEXT,
|
|
thread_id UUID NULL, -- pour les réponses groupées
|
|
is_resolved BOOLEAN DEFAULT false,
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
|
|
-- Réactions
|
|
CREATE TABLE reactions (
|
|
id UUID PRIMARY KEY,
|
|
target_type VARCHAR(20), -- 'comment' | 'text' | 'suggestion'
|
|
target_id UUID,
|
|
author_id UUID REFERENCES principals(id),
|
|
emoji VARCHAR(8)
|
|
);
|
|
|
|
-- Suggestions d'édition (Suggested edits)
|
|
CREATE TABLE suggestions (
|
|
id UUID PRIMARY KEY,
|
|
resource_id UUID REFERENCES resources(id),
|
|
block_id UUID,
|
|
author_id UUID REFERENCES principals(id),
|
|
operation VARCHAR(10), -- 'insert' | 'delete'
|
|
payload TEXT, -- contenu proposé / supprimé
|
|
status VARCHAR(20), -- 'open' | 'accepted' | 'rejected'
|
|
created_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
```
|
|
|
|
### B. Sémantique exacte des niveaux d'accès
|
|
| Niveau | Effets |
|
|
|---|---|
|
|
| `Full access` | Modifier tout le contenu **et** partager la page avec qui l'on veut. |
|
|
| `Can edit` | Modifier le contenu, **sans** pouvoir partager. |
|
|
| `Can edit content` | **Pages de base de données uniquement** : créer/modifier des pages de la base et leurs propriétés, sans toucher à la structure (propriétés, vues, tris, filtres). |
|
|
| `Can create` | **Pages de base de données uniquement** (Business/Enterprise) : créer de nouvelles pages, sans voir/modifier les pages existantes (soumissions de tickets, formulaires...). |
|
|
| `Can comment` | Commenter et suggérer des modifications, sans éditer ni partager. |
|
|
| `Can view` | Lecture seule. |
|
|
|
|
### C. Logique de résolution des permissions
|
|
1. Vérifier une permission **explicite** pour l'utilisateur **ou** l'un de ses groupes sur la ressource cible.
|
|
2. Si aucune permission explicite, remonter l'arbre (`parent_id`) pour vérifier les permissions **héritées** de la page parente, du teamspace ou du workspace.
|
|
3. Pour les bases de données, évaluer dynamiquement les `page_level_rules` : si l'ID de l'utilisateur correspond à la valeur de la propriété `target_property_name` de la ligne, appliquer le niveau d'accès de la règle.
|
|
4. **Principe du niveau le plus large** : Notion respecte **toujours le niveau d'accès le plus étendu** accordé à un utilisateur (permission personnelle + groupe + workspace + règle de base).
|
|
|
|
> ⚠️ **Piège à implémenter** : une règle `Can view` sur une personne est écrasée si l'utilisateur reçoit « Everyone at workspace → Full access ». L'agent doit sommer toutes les sources d'accès et retenir le maximum (ordre : `full > edit > edit_content > create > comment > view`).
|
|
|
|
5. **Sans accès à la base** mais avec une règle de page : l'utilisateur n'accède qu'aux lignes concernées via une **notification** ou une **vue liée** ; il ne peut pas créer de nouvelles pages (il faut un formulaire).
|
|
|
|
### D. Collaboration en temps réel (Stack technique recommandée)
|
|
- **Synchronisation d'état** : CRDT (**Yjs** ou **Automerge**) pour l'édition simultanée sans verrou (Notion ne verrouille pas un bloc en cours d'édition — le dernier changement l'emporte).
|
|
- **Transport** : **WebSockets** (Socket.io, Hocuspocus, ou Liveblocks) pour diffuser les mises à jour de contenu, les événements de présence et les commentaires.
|
|
- **Gestion de la présence** : registre en mémoire des `user_id` connectés à un `resource_id`, avec diffusion des avatars actifs et de leur **position de bloc** (curseur/édition) aux clients connectés, à la connexion/déconnexion et périodiquement.
|
|
|
|
### E. Endpoints API clés à générer
|
|
- `POST /api/resources/:id/share` : ajoute/met à jour une entrée dans `permissions` (invitation membre, invité, groupe).
|
|
- `GET /api/resources/:id/access-check` : retourne le niveau d'accès **effectif** (calcul d'héritage + règle la plus large).
|
|
- `POST /api/resources/:id/page-level-rules` : crée une règle d'accès par propriété Person/Created by.
|
|
- `POST /api/comments` : crée un commentaire (gestion du `block_id`/`thread_id` pour l'inline).
|
|
- `POST /api/suggestions` : crée une suggestion d'édition ; `POST /api/suggestions/:id/accept` / `reject`.
|
|
- `POST /api/access-requests` : crée une demande d'accès / d'édition.
|
|
- `POST /api/resources/:id/lock` : verrouille/déverrouille une page ou la structure d'une base.
|
|
- `WS /ws/collaboration?resourceId=:id` : canal WebSocket pour CRDT, présence et commentaires temps réel.
|
|
|
|
---
|
|
|
|
## 5. Recommandations spécifiques pour le clone Flowdesk
|
|
1. **Adaptation métier** : pour un usage support/tickets, prioriser les **Page-Level Access rules** (`Can create` pour les soumissions, `Can edit` sur la propriété « Assigné à »). C'est le mécanisme qui permet à un client de ne voir/modifier que « son » ticket sans accéder à toute la base.
|
|
2. **Sécurité** : chaque requête API (lecture/écriture) doit passer par le middleware de résolution des permissions **avant** tout accès BDD. Ne jamais faire confiance au client. Appliquer le principe du niveau le plus large côté serveur, de façon centralisée.
|
|
3. **Émuler le verrouillage** : implémenter `is_locked` au niveau ressource (et structure vs données pour les bases) pour éviter les modifications accidentelles sans révoquer les droits.
|
|
4. **Notifier intelligemment** : reproduire les règles Notion — pas de notification si la personne a la page ouverte, email uniquement si Notion est fermé, pas de notification si la personne n'a pas accès à la page mentionnée.
|
|
5. **Bibliothèques Frontend suggérées** : composants « headless » **Radix UI** ou **Headless UI** pour la modale de partage, les dropdowns, les infobulles de présence et le menu de mentions.
|
|
|
|
---
|
|
|
|
## 6. Glossaire rapide des rôles (Who's who)
|
|
- **Member** : personne de l'organisation, facturée sur les plans payants.
|
|
- **Restricted member** : accès limité aux teamspaces/pages assignés ; ne peut pas créer de teamspace.
|
|
- **Guest** : personne externe, invité page par page ; ne reçoit jamais d'accès workspace-wide et ne peut pas être ajouté à un groupe.
|
|
- **Temporary member** : consultant Marketplace avec accès à durée limitée (expiration automatique).
|
|
- **Workspace owner** : admin gérant les paramètres, les membres et la suppression du workspace.
|
|
- **Membership admin** : (Enterprise) ajoute/retire des membres sans changer les paramètres.
|
|
- **Organization owner** : (Enterprise) gère plusieurs workspaces d'une organisation.
|
|
- **Group owner** : gère la composition d'un groupe sans être admin du workspace. |