Gestion des Carnets de Notes

Opérations CRUD complètes pour la gestion des carnets de notes dans le cadre des investigations. Toutes les opérations de modification chargent automatiquement le projet dans le cache partagé.


Liste des Carnets de Notes

GET /api/{tenantId}/{projectId}/notebook/investigation/{investigationId}

Retourne tous les carnets de notes d'une investigation.

Paramètres de chemin

Paramètre Type Obligatoire Description
tenantId GUID Oui Identifiant du locataire
projectId GUID Oui Identifiant du projet
investigationId GUID Oui Identifiant de l'investigation

Réponse (200 OK)

[
  {
    "notebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "investigationId": "11111111-2222-3333-4444-555555555555",
    "name": "Main",
    "description": "Carnet d'analyse principal",
    "dateCreated": "2024-01-15T10:30:00Z",
    "dateModified": "2024-01-20T14:45:00Z",
    "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "modifiedBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "notebookType": 0,
    "notebookOrder": 1.0,
    "lastExecutionDuration": 2.5,
    "blockCount": 12
  },
  {
    "notebookId": "bbbbbbbb-cccc-dddd-eeee-ffffffffffff",
    "investigationId": "11111111-2222-3333-4444-555555555555",
    "name": "Analyse de Variantes",
    "description": "Exploration des variantes de processus",
    "dateCreated": "2024-01-16T09:00:00Z",
    "dateModified": "2024-01-18T11:30:00Z",
    "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "modifiedBy": null,
    "notebookType": 0,
    "notebookOrder": 2.0,
    "lastExecutionDuration": 1.2,
    "blockCount": 8
  }
]

Réponses d'erreur

Non trouvé (404)

{
  "Error": "Investigation non trouvée",
  "InvestigationId": "11111111-2222-3333-4444-555555555555"
}

Obtenir un Carnet de Notes

GET /api/{tenantId}/{projectId}/notebook/{notebookId}

Retourne les informations détaillées d'un carnet de notes spécifique.

Paramètres de chemin

Paramètre Type Obligatoire Description
tenantId GUID Oui Identifiant du locataire
projectId GUID Oui Identifiant du projet
notebookId GUID Oui Identifiant du carnet de notes

Réponse (200 OK)

{
  "notebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "investigationId": "11111111-2222-3333-4444-555555555555",
  "name": "Main",
  "description": "Carnet d'analyse principal",
  "dateCreated": "2024-01-15T10:30:00Z",
  "dateModified": "2024-01-20T14:45:00Z",
  "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "modifiedBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "notebookType": 0,
  "notebookOrder": 1.0,
  "lastExecutionDuration": 2.5,
  "blockCount": 12
}

Créer un Carnet de Notes

POST /api/{tenantId}/{projectId}/notebook/investigation/{investigationId}

Crée un nouveau carnet de notes vide dans l'investigation.

Paramètres de chemin

Paramètre Type Obligatoire Description
tenantId GUID Oui Identifiant du locataire
projectId GUID Oui Identifiant du projet
investigationId GUID Oui Identifiant de l'investigation

Corps de la requête

{
  "name": "Analyse de Processus",
  "description": "Flux de travail d'analyse détaillée du processus",
  "notebookType": 0
}

Champs de la requête

Champ Type Obligatoire Description
name string Oui Nom du carnet (unique dans l'investigation)
description string Non Description du carnet
notebookType integer Non Type (0=Standard, défaut)

Réponse (201 Created)

{
  "notebookId": "cccccccc-dddd-eeee-ffff-000000000000",
  "investigationId": "11111111-2222-3333-4444-555555555555",
  "name": "Analyse de Processus",
  "description": "Flux de travail d'analyse détaillée du processus",
  "dateCreated": "2024-03-01T10:00:00Z",
  "dateModified": "2024-03-01T10:00:00Z",
  "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "modifiedBy": null,
  "notebookType": 0,
  "notebookOrder": 3.0,
  "lastExecutionDuration": 0,
  "blockCount": 0
}

Réponses d'erreur

Requête incorrecte (400)

{
  "Error": "Échec de la création du carnet. Le nom peut déjà exister dans cette investigation."
}

Créer à partir d'un Modèle

POST /api/{tenantId}/{projectId}/notebook/investigation/{investigationId}/from-template

Crée un carnet de notes à partir d'un modèle prédéfini, incluant tous les blocs et configurations.

Paramètres de chemin

Paramètre Type Obligatoire Description
tenantId GUID Oui Identifiant du locataire
projectId GUID Oui Identifiant du projet
investigationId GUID Oui Identifiant de l'investigation

Corps de la requête

{
  "templateId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "name": "Analyse Processus Découverte",
  "description": "Analyse utilisant le modèle Process Discovery"
}

Champs de la requête

Champ Type Obligatoire Description
templateId GUID Oui Modèle à utiliser
name string Non Remplace le nom du modèle
description string Non Remplace la description du modèle

Réponse (201 Created)

Retourne le carnet créé avec les blocs du modèle.

Réponses d'erreur

Non trouvé (404)

{
  "Error": "Modèle non trouvé"
}

Mettre à Jour un Carnet de Notes

PUT /api/{tenantId}/{projectId}/notebook/{notebookId}

Met à jour les métadonnées du carnet. Supporte le verrouillage optimiste via DateModified.

Paramètres de chemin

Paramètre Type Obligatoire Description
tenantId GUID Oui Identifiant du locataire
projectId GUID Oui Identifiant du projet
notebookId GUID Oui Identifiant du carnet

Corps de la requête

{
  "name": "Nom du Carnet Mis à Jour",
  "description": "Description mise à jour",
  "notebookOrder": 2.5,
  "dateModified": "2024-01-20T14:45:00Z"
}

Champs de la requête

Champ Type Obligatoire Description
name string Oui Nom du carnet
description string Non Description du carnet
notebookOrder decimal Non Ordre d'affichage
dateModified datetime Non Pour verrouillage optimiste

Réponse (200 OK)

Retourne le carnet mis à jour.

Verrouillage optimiste

Si dateModified est fourni et ne correspond pas à la valeur actuelle du serveur, renvoie 409 Conflict :

{
  "Error": "CONFLICT",
  "Message": "Le carnet a été modifié par un autre utilisateur depuis votre dernière récupération",
  "YourDateModified": "2024-01-20T14:45:00Z",
  "CurrentDateModified": "2024-01-21T09:30:00Z",
  "ModifiedBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "Resolution": "GET /api/{tenantId}/{projectId}/notebook/{notebookId} pour récupérer l'état actuel, puis réessayer"
}

Supprimer un Carnet de Notes

DELETE /api/{tenantId}/{projectId}/notebook/{notebookId}

Supprime définitivement un carnet de notes et tous ses blocs.

Paramètres de chemin

Paramètre Type Obligatoire Description
tenantId GUID Oui Identifiant du locataire
projectId GUID Oui Identifiant du projet
notebookId GUID Oui Identifiant du carnet

Réponse (200 OK)

{
  "Message": "Carnet supprimé avec succès",
  "NotebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}

Copier un Carnet de Notes

POST /api/{tenantId}/{projectId}/notebook/{notebookId}/copy

Crée une copie complète d'un carnet, incluant tous les blocs. Peut copier vers la même ou une autre investigation.

Paramètres de chemin

Paramètre Type Obligatoire Description
tenantId GUID Oui Identifiant du locataire
projectId GUID Oui Identifiant du projet
notebookId GUID Oui Identifiant du carnet source

Corps de la requête

{
  "name": "Copie de l'Analyse Principale",
  "destinationInvestigationId": "22222222-3333-4444-5555-666666666666"
}

Champs de la requête

Champ Type Obligatoire Description
name string Non Nom de la copie (par défaut : "Copie de ")
destinationInvestigationId GUID Non Investigation cible (par défaut : même investigation)

Réponse (201 Created)

Retourne la copie nouvellement créée du carnet.


Obtenir l'URL Partageable

GET /api/{tenantId}/{projectId}/notebook/{notebookId}/url

Génère une URL partageable pour un accès direct au carnet dans l'interface utilisateur.

Réponse (200 OK)

{
  "notebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "url": "https://your-mindzie-instance.com/investigation/12345678/87654321/11111111/notebook/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "relativePath": "/investigation/12345678/87654321/11111111/notebook/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "expiresAt": null
}

Exemples d'Implémentation

Python

import requests

BASE_URL = 'https://your-mindzie-instance.com'
TENANT_ID = '12345678-1234-1234-1234-123456789012'
PROJECT_ID = '87654321-4321-4321-4321-210987654321'

class NotebookManager:
    def __init__(self, api_key):
        self.headers = {
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        }

    def list_notebooks(self, investigation_id):
        """Liste tous les carnets d'une investigation."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/investigation/{investigation_id}'
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def get_notebook(self, notebook_id):
        """Obtient les détails d'un carnet."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}'
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def create_notebook(self, investigation_id, name, description=None):
        """Crée un nouveau carnet."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/investigation/{investigation_id}'
        data = {'name': name, 'description': description}
        response = requests.post(url, json=data, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def create_from_template(self, investigation_id, template_id, name=None):
        """Crée un carnet à partir d'un modèle."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/investigation/{investigation_id}/from-template'
        data = {'templateId': template_id, 'name': name}
        response = requests.post(url, json=data, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def update_notebook(self, notebook_id, name, description=None, date_modified=None):
        """Met à jour un carnet avec verrouillage optimiste."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}'
        data = {'name': name, 'description': description}
        if date_modified:
            data['dateModified'] = date_modified
        response = requests.put(url, json=data, headers=self.headers)
        if response.status_code == 409:
            conflict = response.json()
            raise Exception(f"Conflit : {conflict['Message']}")
        response.raise_for_status()
        return response.json()

    def delete_notebook(self, notebook_id):
        """Supprime un carnet."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}'
        response = requests.delete(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def copy_notebook(self, notebook_id, name=None, destination_investigation=None):
        """Copie un carnet."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}/copy'
        data = {'name': name}
        if destination_investigation:
            data['destinationInvestigationId'] = destination_investigation
        response = requests.post(url, json=data, headers=self.headers)
        response.raise_for_status()
        return response.json()

# Utilisation
manager = NotebookManager('your-api-key')
investigation_id = '11111111-2222-3333-4444-555555555555'

# Liste des carnets
notebooks = manager.list_notebooks(investigation_id)
print(f"{len(notebooks)} carnets trouvés")

# Création d'un carnet
notebook = manager.create_notebook(investigation_id, 'Nouvelle Analyse', 'Mon flux de travail')
print(f"Carnet créé : {notebook['notebookId']}")

# Copier le carnet
copy = manager.copy_notebook(notebook['notebookId'], 'Copie de Nouvelle Analyse')
print(f"Copie créée : {copy['notebookId']}")

# Mise à jour avec verrouillage optimiste
try:
    updated = manager.update_notebook(
        notebook['notebookId'],
        'Analyse renommée',
        date_modified=notebook['dateModified']
    )
except Exception as e:
    print(f"Mise à jour échouée : {e}")

JavaScript/Node.js

const BASE_URL = 'https://your-mindzie-instance.com';
const TENANT_ID = '12345678-1234-1234-1234-123456789012';
const PROJECT_ID = '87654321-4321-4321-4321-210987654321';

class NotebookManager {
  constructor(apiKey) {
    this.headers = {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    };
  }

  async listNotebooks(investigationId) {
    const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/notebook/investigation/${investigationId}`;
    const response = await fetch(url, { headers: this.headers });
    if (!response.ok) throw new Error(`Échec : ${response.status}`);
    return response.json();
  }

  async createNotebook(investigationId, name, description = null) {
    const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/notebook/investigation/${investigationId}`;
    const response = await fetch(url, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify({ name, description })
    });
    if (!response.ok) throw new Error(`Échec : ${response.status}`);
    return response.json();
  }

  async updateNotebook(notebookId, name, description = null, dateModified = null) {
    const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/notebook/${notebookId}`;
    const body = { name, description };
    if (dateModified) body.dateModified = dateModified;

    const response = await fetch(url, {
      method: 'PUT',
      headers: this.headers,
      body: JSON.stringify(body)
    });

    if (response.status === 409) {
      const conflict = await response.json();
      throw new Error(`Conflit : ${conflict.Message}`);
    }
    if (!response.ok) throw new Error(`Échec : ${response.status}`);
    return response.json();
  }

  async deleteNotebook(notebookId) {
    const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/notebook/${notebookId}`;
    const response = await fetch(url, {
      method: 'DELETE',
      headers: this.headers
    });
    if (!response.ok) throw new Error(`Échec : ${response.status}`);
    return response.json();
  }

  async copyNotebook(notebookId, name = null, destinationInvestigationId = null) {
    const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/notebook/${notebookId}/copy`;
    const body = {};
    if (name) body.name = name;
    if (destinationInvestigationId) body.destinationInvestigationId = destinationInvestigationId;

    const response = await fetch(url, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify(body)
    });
    if (!response.ok) throw new Error(`Échec : ${response.status}`);
    return response.json();
  }
}

// Utilisation
const manager = new NotebookManager('your-api-key');
const investigationId = '11111111-2222-3333-4444-555555555555';

// Liste des carnets
const notebooks = await manager.listNotebooks(investigationId);
console.log(`${notebooks.length} carnets trouvés`);

// Création et copie
const notebook = await manager.createNotebook(investigationId, 'Nouvelle Analyse');
const copy = await manager.copyNotebook(notebook.notebookId, 'Copie de l\'Analyse');

Bonnes Pratiques

  1. Chargement automatique : Ne chargez pas explicitement les projets pour les opérations CRUD sur les carnets - c'est automatique
  2. Verrouillage optimiste : Incluez dateModified dans les mises à jour pour détecter les conflits
  3. Modèles : Utilisez des modèles pour des flux d'analyse cohérents
  4. Nommage : Utilisez des noms descriptifs et uniques dans chaque investigation
  5. Nettoyage : Supprimez les carnets inutilisés pour garder les investigations organisées