i18n - docs translations (#15720)

Created by Github action

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds a full French documentation set covering developers (API,
webhooks, backend/frontend, self‑hosting) and user guide (CRM
essentials, data model, workflows, settings, integrations, pricing,
reporting).
> 
> - **Docs (FR i18n)**:
> - **Developers**: Add `API`, `Webhooks`, backend (best practices,
custom objects, feature flags, architecture, commands, Zapier), frontend
(best practices, architecture, commands, hotkeys, style guide,
Storybook, Figma), self‑hosting (Docker Compose, upgrade guide, cloud
providers), introduction.
> - **User Guide**: Add getting started (what is Twenty,
create/configure workspace, migration, import/export), CRM essentials
(contacts/accounts, pipelines, views), data model (objects, fields,
relations, table views), collaboration (emails/calendars, notes, tasks),
integrations API (overview, integrations), workflows (getting started,
features, credits, internal automations, services), settings (profile,
permissions, members, domains, releases, email/calendar setup), pricing
(billing/FAQ), reporting overview, resources (GitHub, glossary),
introduction.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9ba8c2457156e8d25bf41c055731acface4b5277. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: github-actions <github-actions@twenty.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
github-actions[bot]
2025-11-08 10:20:29 +01:00
committed by GitHub
parent 0fc538ac09
commit 154fb4665e
57 changed files with 5606 additions and 6 deletions
@@ -0,0 +1,56 @@
---
title: API
image: /images/docs/getting-started/api.png
info: Découvrez comment utiliser nos API.
---
<Frame>
<img src="/images/docs/getting-started/api.png" alt="Header" />
</Frame>
## Vue d'ensemble
L'API de Twenty permet aux développeurs d'interagir de manière programmée avec la plateforme CRM de Twenty. En utilisant l'API, vous pouvez intégrer Twenty avec d'autres systèmes, automatiser la synchronisation des données, et construire des solutions personnalisées autour de vos données clients. L'API fournit des points d'accès pour **créer, lire, mettre à jour et supprimer** des objets CRM principaux (comme les personnes et les entreprises) ainsi que pour accéder à la configuration des métadonnées.
**API Playground :** Vous pouvez désormais accéder à l'API Playground dans les paramètres de l'application. Pour essayer les appels API en temps réel, connectez-vous à votre espace de travail Twenty et naviguez vers **Paramètres → APIs & Webhooks**. Cela ouvre le API Playground intégré et les paramètres pour les clés API.
**[Accédez aux paramètres de l'API](https://app.twenty.com/settings)**
## Authentification
L'API de Twenty utilise des clés API pour l'authentification. Chaque requête vers des points d'accès protégés doit inclure une clé API dans l'en-tête.
- **Clés API :** Vous pouvez générer une nouvelle clé API depuis la page de **paramètres de l'API** de votre application Twenty. Chaque clé API est un jeton secret qui accorde l'accès à vos données CRM, alors gardez-le en sécurité. Si une clé est compromise, révoquez-la dans les paramètres et générez-en une nouvelle.
- **En-tête Auth :** Une fois que vous avez une clé API, incluez-la dans l'en-tête `Authorization` de vos requêtes HTTP. Utilisez le schéma de jeton Bearer. Par exemple :
```
Authorization: Bearer YOUR_API_KEY
```
Remplacez `VOTRE_CLÉ_API` par la clé que vous avez obtenue. Cet en-tête doit être présent sur **toutes les requêtes API**. Si le jeton est manquant ou invalide, l'API répondra avec une erreur d'authentification (HTTP 401 Non autorisé).
## Points d'accès API
Toutes les ressources peuvent être consultées via REST ou GraphQL.
- **Cloud :** `https://api.twenty.com/` ou votre domaine / sous-domaine personnalisé
- **Instances auto-hébergées :** Si vous exécutez Twenty sur votre propre serveur, utilisez votre propre domaine à la place de `api.twenty.com` (par exemple, `https://<votre-domaine>/rest/`).
Les points d'accès sont groupés en deux catégories : **Core API** et **Metadata API**. L'**API principale** traite les données CRM primaires (personnes, entreprises, notes, tâches), tandis que l'**API des métadonnées** couvre les données de configuration (comme les champs personnalisés ou les définitions d'objets). La plupart des intégrations utiliseront principalement l'API principale.
### API principale
Accessible sur `/rest/` ou `/graphql/`.
L'**API principale** sert de l'interface unifiée pour gérer les entités CRM principales (personnes, entreprises, notes, tâches) et leurs relations, offrant des modèles d'interaction **REST et GraphQL**.
### API de métadonnées
Accessible sur `/rest/metadata/` ou `/metadata/`.
Les points d'accès de l'API de métadonnées permettent de récupérer des informations sur votre schéma et vos paramètres. Par exemple, vous pouvez récupérer les définitions des champs personnalisés, des schémas d'objets, etc.
- **Exemples de points d'accès :**
- `GET /rest/metadata/objects` Liste tous les types d'objets et leurs métadonnées (champs, relations).
- `GET /rest/metadata/objects/{objectName}` Obtenez les métadonnées d'un objet spécifique (par exemple, `people`, `companies`).
- `GET /rest/metadata/picklists` Récupérer les options de champ de liste déroulante définies dans le CRM.
Typiquement, les points d'accès des métadonnées sont utilisés pour comprendre la structure des données (pour des intégrations dynamiques ou la création de formulaires) plutôt que pour gérer des enregistrements réels. Ils sont principalement en lecture seule dans la plupart des cas. Une authentification est également requise pour ceux-ci (utilisez votre clé API).
@@ -0,0 +1,87 @@
---
title: Webhooks
image: /images/docs/getting-started/webhooks.png
info: Découvrez comment utiliser nos Webhooks.
---
<Frame>
<img src="/images/docs/getting-started/webhooks.png" alt="Header" />
</Frame>
## Vue d'ensemble
Les Webhooks dans Twenty complètent l'API en permettant des **notifications en temps réel** à vos propres applications lors de certains événements dans votre CRM. Au lieu de sonder continuellement l'API pour les changements, vous pouvez configurer des webhooks pour que Twenty **pousse** des données vers votre système chaque fois que des événements spécifiques se produisent (par exemple, lorsqu'un nouvel enregistrement est créé ou qu'un enregistrement existant est mis à jour). Cela aide à synchroniser instantanément et efficacement les systèmes externes avec Twenty.
Avec les webhooks, Twenty enverra une requête HTTP POST à une URL que vous spécifiez, contenant des détails sur l'événement. Vous pouvez ensuite traiter ces données dans votre application (par exemple, pour mettre à jour votre base de données externe, déclencher des flux de travail ou envoyer des alertes).
## Configuration d'un Webhook
Pour créer un webhook dans Twenty, utilisez les paramètres **APIs & Webhooks** dans votre application Twenty :
1. **Naviguer vers les Paramètres :** Dans votre application Twenty, allez dans **Paramètres → APIs & Webhooks**.
2. **Créer un Webhook :** Dans **Webhooks**, cliquez sur **+ Créer un webhook**.
3. **Entrez l'URL :** Fournissez l'URL de l'endpoint sur votre serveur où vous souhaitez que Twenty envoie les requêtes webhook. Cela doit être une URL publiquement accessible qui peut gérer les requêtes POST.
4. **Enregistrer :** Cliquez sur **Enregistrer** pour créer le webhook. Le nouveau webhook sera actif immédiatement.
Vous pouvez créer plusieurs webhooks si vous avez besoin d'envoyer différents événements vers différents endpoints. Chaque webhook est essentiellement un abonnement pour tous les événements pertinents (actuellement, Twenty envoie tous types d'événements à l'URL donnée ; filtrer des types d'événements spécifiques peut être configurable dans l'interface utilisateur). Si vous devez supprimer un webhook, vous pouvez le supprimer de la même page des paramètres (sélectionnez le webhook et choisissez supprimer).
## Événements et Charges utiles
Une fois qu'un webhook est configuré, Twenty enverra une requête HTTP POST à l'URL que vous avez spécifiée chaque fois qu'un événement déclencheur se produit dans vos données CRM. Les événements communs qui déclenchent les webhooks incluent :
- **Enregistrement Créé :** par exemple, une nouvelle personne est ajoutée (`person.created`), une nouvelle entreprise est créée (`company.created`), une note est créée (`note.created`), etc.
- **Enregistrement Mis à Jour :** par exemple, les informations d'une personne existante sont mises à jour (`person.updated`), un enregistrement d'entreprise est édité (`company.updated`), etc.
- **Enregistrement Supprimé :** par exemple, une personne ou une entreprise est supprimée (`person.deleted`, `company.deleted`).
- **Autres Événements :** Si applicable, d'autres événements d'objet ou déclencheurs personnalisés (par exemple, si des tâches ou d'autres objets sont mis à jour, des types d'événements similaires seraient utilisés comme `task.created`, `note.updated`, etc.).
La requête POST du webhook contient une charge utile JSON dans son corps. La charge utile comprendra généralement au moins deux choses : le type d'événement et les données relatives à cet événement (souvent l'enregistrement qui a été créé/mise à jour). Par exemple, un webhook pour une nouvelle personne créée pourrait envoyer une charge utile comme :
```
{
"event": "person.created",
"data": {
"id": "abc12345",
"firstName": "Alice",
"lastName": "Doe",
"email": "alice@example.com",
"createdAt": "2025-02-10T15:30:45Z",
"createdBy": "user_123"
},
"timestamp": "2025-02-10T15:30:50Z"
}
```
Dans cet exemple :
- `"event"` spécifie ce qui s'est passé (`person.created`).
- `"data"` contient les détails du nouvel enregistrement (les mêmes informations que vous obtiendriez si vous demandiez cette personne via l'API).
- `"timestamp"` est le moment où l'événement s'est produit (en UTC).
Votre endpoint devrait être prêt à recevoir de telles données JSON via POST. En général, vous allez analyser le JSON, regarder le type d'événement `"event"` pour comprendre ce qui s'est passé, et ensuite utiliser les `"data"` en conséquence (par exemple, créer un nouveau contact dans votre système ou mettre à jour un contact existant).
**Remarque :** Il est important de répondre avec un **statut HTTP 2xx** depuis votre endpoint webhook pour accuser réception avec succès. Si l'expéditeur du webhook de Twenty ne reçoit pas une réponse 2xx, il peut considérer que la livraison a échoué. (À l'avenir, une logique de réessai pourrait tenter de renvoyer les webhooks échoués, donc essayez toujours de retourner un 200 OK aussi rapidement que possible après le traitement des données.)
## Validation des Webhooks
Pour garantir la sécurité de vos endpoints webhook, Twenty inclut une signature dans l'en-tête `X-Twenty-Webhook-Signature`.
Cette signature est un hachage HMAC SHA256 de la charge utile de la requête, calculé en utilisant votre clé secrète.
Pour valider la signature, vous devrez :
1. Concaténer le timestamp (de l'en-tête `X-Twenty-Webhook-Timestamp`), un deux-points, et la chaîne JSON de la charge utile
2. Calculer le hachage HMAC SHA256 en utilisant votre clé secrète comme clé ()
3. Comparer le résultat de la somme de contrôle hexadécimale avec l'en-tête de signature
Voici un exemple en Node.js :
```javascript
const crypto = require("crypto");
const timestamp = "1735066639761";
const payload = JSON.stringify({...});
const secret = "your-secret";
const stringToSign = `${timestamp}:${JSON.stringify(payload)}`;
const signature = crypto.createHmac("sha256", secret)
.update(stringToSign)
.digest("hex");
```
@@ -0,0 +1,27 @@
---
title: Meilleures pratiques
image: /images/user-guide/tips/light-bulb.png
---
<Frame>
<img src="/images/user-guide/tips/light-bulb.png" alt="Header" />
</Frame>
Ce document décrit les meilleures pratiques à suivre lors de travaux sur le backend.
## Suivez une approche modulaire
Le backend suit une approche modulaire, qui est un principe fondamental lors de l'utilisation de NestJS. Assurez-vous de décomposer votre code en modules réutilisables pour maintenir une base de code propre et organisée.
Chaque module doit encapsuler une fonctionnalité particulière et avoir un périmètre bien défini. Cette approche modulaire permet une séparation claire des préoccupations et supprime les complexités inutiles.
## Exposez des services à utiliser dans les modules
Créez toujours des services avec une responsabilité claire et unique, ce qui améliore la lisibilité et la maintenabilité du code. Nommez les services de manière descriptive et cohérente.
Vous devez également exposer les services que vous souhaitez utiliser dans d'autres modules. Exposer des services à d'autres modules est possible grâce au puissant système d'injection de dépendance de NestJS, et favorise un couplage lâche entre les composants.
## Évitez d'utiliser le type `any`
Lorsque vous déclarez une variable comme `any`, le vérificateur de type de TypeScript ne procède à aucune vérification, rendant possible l'assignation de n'importe quel type de valeur à la variable. TypeScript utilise l'inférence de type pour déterminer le type d'une variable en fonction de sa valeur. En le déclarant comme `any`, TypeScript ne peut plus deviner le type. Cela rend difficile la détection des erreurs liées aux types pendant le développement, conduisant à des erreurs d'exécution et rendant le code moins maintenable, moins fiable et plus difficile à comprendre pour d'autres.
C'est pourquoi tout devrait avoir un type. Donc si vous créez un nouvel objet avec un prénom et un nom, vous devriez créer une interface ou un type contenant un prénom et un nom qui définit la forme de l'objet que vous manipulez.
@@ -0,0 +1,45 @@
---
title: Objets personnalisés
image: /images/user-guide/objects/objects.png
---
<Frame>
<img src="/images/user-guide/objects/objects.png" alt="Header" />
</Frame>
Les objets sont des structures qui vous permettent de stocker des données (enregistrements, attributs et valeurs) spécifiques à une organisation. Twenty fournit à la fois des objets standard et personnalisés.
Les objets standard sont des objets intégrés avec un ensemble d'attributs disponibles pour tous les utilisateurs. Les exemples d'objets standard dans Twenty incluent Société et Personne. Les objets standard ont des champs standard également disponibles pour tous les utilisateurs de Twenty, comme Company.displayName.
Les objets personnalisés sont des objets que vous pouvez créer pour stocker des informations uniques à votre organisation. Ils ne sont pas intégrés ; les membres de votre espace de travail peuvent créer et personnaliser des objets personnalisés pour contenir des informations que les objets standard ne conviennent pas.
## Schéma de haut niveau
<div style={{textAlign: 'center'}}>
<img src="/images/docs/server/custom-object-schema.png" alt="High level schema" />
</div>
<br/>
## Comment cela fonctionne
Les objets personnalisés proviennent de tables de métadonnées qui déterminent la forme, le nom et le type des objets. Toutes ces informations sont présentes dans la base de données des schémas de métadonnées, composée de tables :
- **DataSource** : Détaille où les données sont présentes.
- **Objet** : Décrit l'objet et lie à une DataSource.
- **Champ** : Décrit les champs d'un objet et se connecte à l'objet.
Pour ajouter un objet personnalisé, le workspaceMember interrogera l'API /metadata. Cela met à jour les métadonnées en conséquence et calcule un schéma GraphQL basé sur les métadonnées, en le stockant dans un cache GQL pour une utilisation ultérieure.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/server/add-custom-objects.jpeg" alt="Query the /metadata API to add custom objects" />
</div>
<br/>
Pour obtenir des données, le processus implique de faire des requêtes via le point de terminaison /graphql et de les transmettre via le Query Resolver.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/server/custom-object-schema.png" alt="Query the /graphql endpoint to fetch data" />
</div>
@@ -0,0 +1,51 @@
---
title: Drapeaux de fonctionnalité
image: /images/user-guide/table-views/table.png
---
<Frame>
<img src="/images/user-guide/table-views/table.png" alt="Header" />
</Frame>
Les drapeaux de fonctionnalité sont utilisés pour masquer les fonctionnalités expérimentales. Pour Twenty, ils sont définis au niveau de l'espace de travail et non au niveau de l'utilisateur.
## Ajout d'un nouveau drapeau de fonctionnalité
Dans `FeatureFlagKey.ts` ajoutez l'indicateur de fonctionnalité :
```ts
type FeatureFlagKey =
| 'IS_FEATURENAME_ENABLED'
| ...;
```
Ajoutez-le également à l'énumération dans `feature-flag.entity.ts` :
```ts
enum FeatureFlagKeys {
IsFeatureNameEnabled = 'IS_FEATURENAME_ENABLED',
...
}
```
Pour appliquer un drapeau de fonctionnalité sur une fonctionnalité de **backend**, utilisez :
```ts
@Gate({
featureFlag: 'IS_FEATURENAME_ENABLED',
})
```
Pour appliquer un drapeau de fonctionnalité sur une fonctionnalité de **frontend**, utilisez :
```ts
const isFeatureNameEnabled = useIsFeatureEnabled('IS_FEATURENAME_ENABLED');
```
## Configurer les drapeaux de fonctionnalité pour le déploiement
Modifiez l'enregistrement correspondant dans la Table `core.featureFlag` :
| iD | clé | workspaceId | valeur |
| --------- | ------------------------ | ----------- | ------ |
| Aléatoire | `IS_FEATURENAME_ENABLED` | WorkspaceID | `vrai` |
@@ -0,0 +1,130 @@
---
title: Architecture des Dossiers
info: Un regard détaillé sur l'architecture des dossiers de notre serveur
image: /images/user-guide/fields/field.png
---
<Frame>
<img src="/images/user-guide/fields/field.png" alt="Header" />
</Frame>
La structure du répertoire backend est la suivante :
```
server
└───ability
└───constants
└───core
└───database
└───decorators
└───filters
└───guards
└───health
└───integrations
└───metadata
└───workspace
└───utils
```
## Capacité
Définit les permissions et inclut des gestionnaires pour chaque entité.
## Décorateurs
Définit des décorateurs personnalisés dans NestJS pour des fonctionnalités supplémentaires.
Voir [décorateurs personnalisés](https://docs.nestjs.com/custom-decorators) pour plus de détails.
## Filtres
Inclut des filtres d'exception pour gérer les exceptions qui pourraient se produire dans les points de terminaison GraphQL.
## Gardes
Voir [gardiens](https://docs.nestjs.com/guards) pour plus de détails.
## Santé
Inclut une API REST disponible publiquement (healthz) qui renvoie un JSON pour confirmer si la base de données fonctionne comme prévu.
## Métadonnées
Définit des objets personnalisés et met une API GraphQL à disposition (graphql/metadata).
## Espace de travail
Génère et sert un schéma GraphQL personnalisé basé sur les métadonnées.
### Structure du répertoire de l'espace de travail
```
workspace
└───workspace-schema-builder
└───factories
└───graphql-types
└───database
└───interfaces
└───object-definitions
└───services
└───storage
└───utils
└───workspace-resolver-builder
└───factories
└───interfaces
└───workspace-query-builder
└───factories
└───interfaces
└───workspace-query-runner
└───interfaces
└───utils
└───workspace-datasource
└───workspace-manager
└───workspace-migration-runner
└───utils
└───workspace.module.ts
└───workspace.factory.spec.ts
└───workspace.factory.ts
```
La racine du répertoire de l'espace de travail inclut le fichier `workspace.factory.ts`, qui contient la fonction `createGraphQLSchema`. Cette fonction génère un schéma spécifique à l'espace de travail en utilisant les métadonnées pour adapter un schéma pour chaque espace de travail. En séparant la construction du schéma et du résolveur, nous utilisons la fonction `makeExecutableSchema`, qui combine ces éléments distincts.
Cette stratégie n'est pas seulement une question d'organisation, mais aide également à l'optimisation, comme la mise en cache des définitions de type générées pour améliorer les performances et la scalabilité.
### Constructeur de schéma d'espace de travail
Génère le schéma GraphQL, et inclut :
#### Usines :
Constructeurs spécialisés pour générer des constructions liées à GraphQL.
- La type.factory traduit les métadonnées de champs en types GraphQL en utilisant le `TypeMapperService`.
- La type-definition.factory crée des objets d'entrée ou de sortie GraphQL dérivés de `objectMetadata`.
#### Types GraphQL
Inclut des énumérations, des entrées, des objets et des scalaires, et sert de blocs de construction pour la construction du schéma.
#### Interfaces et définitions d'objets
Contient les plans pour les entités GraphQL, et inclut à la fois des types prédéfinis et personnalisés comme `MONEY` ou `URL`.
#### Services
Contient le service responsable de l'association du FieldMetadataType avec son type scalaire ou modificateur de requête GraphQL approprié.
#### Stockage
Inclut la classe `TypeDefinitionsStorage` qui contient des définitions de type réutilisables, empêchant la duplication des types GraphQL.
### Constructeur de résolveur d'espace de travail
Crée des fonctions de résolveur pour interroger et modifier le schéma GraphQL.
Chaque usine de ce répertoire est responsable de la production d'un type de résolveur distinct, comme le `FindManyResolverFactory`, conçu pour une application adaptable à plusieurs tables.
### Exécuteur de requêtes d'espace de travail
Exécute les requêtes générées sur la base de données et analyse le résultat.
@@ -0,0 +1,108 @@
---
title: Commandes Backend
image: /images/user-guide/kanban-views/kanban.png
---
<Frame>
<img src="/images/user-guide/kanban-views/kanban.png" alt="Header" />
</Frame>
## Commandes utiles
Ces commandes doivent être exécutées depuis le dossier packages/twenty-server.
Depuis n'importe quel autre dossier, vous pouvez exécuter `npx nx <commande> twenty-server` (ou `npx nx run twenty-server:<commande>`).
### Configuration initiale
```
npx nx database:reset twenty-server # setup the database with dev seeds
```
### Démarrer le serveur
```
npx nx run twenty-server:start
```
### Analyse
```
npx nx run twenty-server:lint # pass --fix to fix lint errors
```
### Test
```
npx nx run twenty-server:test:unit # run unit tests
npx nx run twenty-server:test:integration # run integration tests
```
Remarque: vous pouvez exécuter `npx nx run twenty-server:test:integration:with-db-reset` si vous avez besoin de réinitialiser la base de données avant de lancer les tests d'intégration.
### Réinitialiser la base de données
Si vous souhaitez réinitialiser et peupler la base de données, vous pouvez exécuter la commande suivante :
```bash
npx nx run twenty-server:database:reset
```
### Migrations
#### Pour les objets dans les schémas Core/Metadata (TypeORM)
```bash
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
```
#### Pour les objets de l'Espace de travail
Il n'y a pas de fichiers de migrations, les migrations sont générées automatiquement pour chaque espace de travail, stockées dans la base de données et appliquées avec cette commande
```bash
npx nx run twenty-server:command workspace:sync-metadata -f
```
<Warning>
Cette action supprimera la base de données et relancera les migrations et les semences.
Assurez-vous de sauvegarder toutes les données que vous souhaitez conserver avant d'exécuter cette commande.
</Warning>
## Écosystème Tech
Twenty utilise principalement NestJS pour le backend.
Prisma a été le premier ORM que nous avons utilisé. Mais pour permettre aux utilisateurs de créer des champs et objets personnalisés, un niveau inférieur avait plus de sens car nous avons besoin d'un contrôle granulaire. Le projet utilise maintenant TypeORM.
Voici à quoi ressemble maintenant la pile technologique.
**Noyau**
- [NestJS](https://nestjs.com/)
- [TypeORM](https://typeorm.io/)
- [GraphQL Yoga](https://the-guild.dev/graphql/yoga-server)
**Base de données**
- [Postgres](https://www.postgresql.org/)
**Intégrations tierces**
- [Sentry](https://sentry.io/welcome/) pour suivre les bugs.
**Tests**
- [Jest](https://jestjs.io/)
**Outils**
- [Yarn](https://yarnpkg.com/)
- [ESLint](https://eslint.org/)
**Développement**
- [AWS EKS](https://aws.amazon.com/eks/)
@@ -0,0 +1,91 @@
---
title: Application Zapier
image: /images/user-guide/integrations/plug.png
---
<Frame>
<img src="/images/user-guide/integrations/plug.png" alt="Header" />
</Frame>
Synchronisez facilement Twenty avec plus de 3000 applications à l'aide de [Zapier](https://zapier.com/). Automatisez les tâches, boostez la productivité et dynamisez vos relations client !
## À propos de Zapier
Zapier est un outil qui vous permet d'automatiser des flux de travail en connectant les applications que votre équipe utilise quotidiennement. Le concept fondamental de Zapier est l'automatisation des flux de travail, appelés Zaps, et inclut des déclencheurs et des actions.
Vous pouvez en savoir plus sur le fonctionnement de Zapier [ici](https://zapier.com/how-it-works).
## Installation
### Étape 1 : Installez les packages Zapier
```bash
cd packages/twenty-zapier
yarn
```
### Étape 2 : Connectez-vous avec le CLI
Utilisez vos identifiants Zapier pour vous connecter en utilisant le CLI :
```bash
zapier login
```
### Étape 3 : Configurer les variables d'environnement
Depuis le dossier `packages/twenty-zapier`, exécutez :
```bash
cp .env.example .env
```
Exécutez l'application localement, rendez-vous sur [http://localhost:3000/settings/api-webhooks](http://localhost:3000/settings/api-webhooks) et générez une clé API.
Remplacez la valeur **YOUR_API_KEY** dans le fichier `.env` par la clé API que vous venez de générer.
## Développement
<Warning>
Assurez-vous d'exécuter `yarn build` avant toute commande `zapier`.
</Warning>
### Test
```bash
yarn test
```
### Analyse
```bash
yarn format
```
### Surveillez et compilez pendant que vous éditez le code
```bash
yarn watch
```
### Validez votre application Zapier
```bash
yarn validate
```
### Déployez votre application Zapier
```bash
yarn deploy
```
### Liste de toutes les commandes CLI de Zapier
```bash
zapier
```
@@ -0,0 +1,19 @@
---
title: Bugs et demandes
image: /images/user-guide/api/api.png
info: Demandez de l'aide sur GitHub ou Discord
---
<Frame>
<img src="/images/user-guide/api/api.png" alt="Header" />
</Frame>
## Signaler des bogues
Pour signaler un bogue, veuillez [créer un problème sur GitHub](https://github.com/twentyhq/twenty/issues/new).
Vous pouvez également demander de l'aide sur [Discord](https://discord.gg/cx5n4Jzs57).
## Demandes de fonctionnalités
Si vous n'êtes pas sûr qu'il s'agisse d'un bogue, et que vous pensez que cela ressemble plus à une demande de fonctionnalité, alors vous devriez probablement [ouvrir une discussion à la place](https://github.com/twentyhq/twenty/discussions/new).
@@ -0,0 +1,333 @@
---
title: Meilleures pratiques
image: /images/user-guide/tips/light-bulb.png
---
<Frame>
<img src="/images/user-guide/tips/light-bulb.png" alt="Header" />
</Frame>
Ce document décrit les meilleures pratiques à suivre lors de votre travail sur l'interface frontend.
## Gestion de l'état
React et Recoil gèrent la gestion de l'état dans la base de code.
### Utilisez `useRecoilState` pour stocker l'état
C'est une bonne pratique de créer autant d'atomes que nécessaire pour stocker votre état.
<Warning>
Il vaut mieux utiliser des atomes supplémentaires plutôt que d'essayer d'être trop concis en perçant les propriétés.
</Warning>
```tsx
export const myAtomState = atom({
key: 'myAtomState',
default: 'default value',
});
export const MyComponent = () => {
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
return (
<div>
<input
value={myAtom}
onChange={(e) => setMyAtom(e.target.value)}
/>
</div>
);
}
```
### Ne pas utiliser `useRef` pour stocker l'état
Évitez d'utiliser `useRef` pour stocker l'état.
Si vous souhaitez stocker un état, vous devez utiliser `useState` ou `useRecoilState`.
Consultez [comment gérer les re-rendus](#managing-re-renders) si vous avez l'impression d'avoir besoin de `useRef` pour empêcher certains re-rendus.
## Gestion des re-rendus
Les re-rendus peuvent être difficiles à gérer dans React.
Voici quelques règles à suivre pour éviter les re-rendus inutiles.
Gardez à l'esprit que vous pouvez **toujours** éviter les re-rendus en comprenant leur cause.
### Travaillez au niveau racine
Éviter les re-rendus dans les nouvelles fonctionnalités est désormais facile en les éliminant au niveau racine.
Le composant secondaire `PageChangeEffect` contient seulement un `useEffect` qui retient toute la logique à exécuter lors d'un changement de page.
De cette manière, vous savez qu'il n'y a qu'un seul endroit qui peut déclencher un re-rendu.
### Toujours réfléchir à deux fois avant d'ajouter `useEffect` dans votre code.
Les re-rendus sont souvent causés par des `useEffect` inutiles.
Vous devriez réfléchir si vous avez besoin de `useEffect`, ou si vous pouvez déplacer la logique dans une fonction de gestion d'événements.
Vous trouverez généralement facile de déplacer la logique dans une fonction `handleClick` ou `handleChange`.
Vous pouvez également les trouver dans des bibliothèques comme Apollo : `onCompleted`, `onError`, etc.
### Utilisez un composant frère pour extraire `useEffect` ou la logique de récupération des données
Si vous pensez devoir ajouter un `useEffect` dans votre composant racine, vous devriez envisager de l'extraire dans un composant secondaire.
Vous pouvez appliquer la même chose à la logique de récupération de données, avec les hooks Apollo.
```tsx
// ❌ Bad, will cause re-renders even if data is not changing,
// because useEffect needs to be re-evaluated
export const PageComponent = () => {
const [data, setData] = useRecoilState(dataState);
const [someDependency] = useRecoilState(someDependencyState);
useEffect(() => {
if(someDependency !== data) {
setData(someDependency);
}
}, [someDependency]);
return <div>{data}</div>;
};
export const App = () => (
<RecoilRoot>
<PageComponent />
</RecoilRoot>
);
```
```tsx
// ✅ Good, will not cause re-renders if data is not changing,
// because useEffect is re-evaluated in another sibling component
export const PageComponent = () => {
const [data, setData] = useRecoilState(dataState);
return <div>{data}</div>;
};
export const PageData = () => {
const [data, setData] = useRecoilState(dataState);
const [someDependency] = useRecoilState(someDependencyState);
useEffect(() => {
if(someDependency !== data) {
setData(someDependency);
}
}, [someDependency]);
return <></>;
};
export const App = () => (
<RecoilRoot>
<PageData />
<PageComponent />
</RecoilRoot>
);
```
### Utilisez les états de famille de recoil et les sélecteurs de famille de recoil
Les états et sélecteurs de famille recoil sont un excellent moyen d'éviter les re-rendus.
Ils sont utiles lorsque vous devez stocker une liste d'articles.
### Vous ne devriez pas utiliser `React.memo(MyComponent)`
Évitez d'utiliser `React.memo()` car cela ne résout pas la cause du re-rendu, mais brise plutôt la chaîne de re-rendu, ce qui peut entraîner un comportement inattendu et rendre le code très difficile à refactoriser.
### Limitez l'utilisation de `useCallback` ou `useMemo`
Ils ne sont souvent pas nécessaires et rendront le code plus difficile à lire et à maintenir pour un gain de performance imperceptible.
## Console.logs
Les déclarations `console.log` sont précieuses pendant le développement, offrant des insights en temps réel sur les valeurs de variables et le flux de code. Mais, les laisser dans le code de production peut entraîner plusieurs problèmes :
1. **Performance** : Un journalisation excessive peut affecter les performances d'exécution, notamment sur les applications côté client.
2. **Sécurité** : La journalisation de données sensibles peut exposer des informations critiques à toute personne qui inspecte la console du navigateur.
3. **Propreté** : Remplir la console de logs peut masquer les avertissements ou erreurs importants que les développeurs ou outils doivent voir.
4. **Professionnalisme** : Les utilisateurs finaux ou clients vérifiant la console et voyant une myriade de déclarations de log pourraient remettre en question la qualité et la finition du code.
Assurez-vous de supprimer tous les `console.logs` avant de pousser le code en production.
## Nomination
### Nom des variables
Les noms de variables doivent décrire précisément l'objectif ou la fonction de la variable.
#### Le problème avec les noms génériques
Les noms génériques en programmation ne sont pas idéaux car ils manquent de spécificité, ce qui conduit à une ambiguïté et réduit la lisibilité du code. De tels noms ne parviennent pas à transmettre l'objectif de la variable ou de la fonction, rendant difficile pour les développeurs de comprendre l'intention du code sans une enquête plus approfondie. Cela peut entraîner un temps de débogage accru, une plus grande vulnérabilité aux erreurs et des difficultés de maintenance et de collaboration. Pendant ce temps, des noms descriptifs rendent le code explicite et plus facile à naviguer, améliorant la qualité du code et la productivité des développeurs.
```tsx
// ❌ Bad, uses a generic name that doesn't communicate its
// purpose or content clearly
const [value, setValue] = useState('');
```
```tsx
// ✅ Good, uses a descriptive name
const [email, setEmail] = useState('');
```
#### Certains mots à éviter dans les noms de variables
- factice
### Gestionnaires d'événements
Les noms des gestionnaires d'événements doivent commencer par `handle`, tandis que `on` est un préfixe utilisé pour nommer les événements dans les propriétés des composants.
```tsx
// ❌ Bad
const onEmailChange = (val: string) => {
// ...
};
```
```tsx
// ✅ Good
const handleEmailChange = (val: string) => {
// ...
};
```
## Props optionnels
Évitez de passer la valeur par défaut pour un prop optionnel.
**EXEMPLE**
Prenez le composant`EmailField` défini ci-dessous :
```tsx
type EmailFieldProps = {
value: string;
disabled?: boolean;
};
const EmailField = ({ value, disabled = false }: EmailFieldProps) => (
<TextInput value={value} disabled={disabled} fullWidth />
);
```
**Utilisation**
```tsx
// ❌ Bad, passing in the same value as the default value adds no value
const Form = () => <EmailField value="username@email.com" disabled={false} />;
```
```tsx
// ✅ Good, assumes the default value
const Form = () => <EmailField value="username@email.com" />;
```
## Composant en tant que props
Essayez autant que possible de transmettre des composants non instanciés comme props, afin que les enfants puissent décider eux-mêmes des props qu'ils ont besoin de passer.
L'exemple le plus courant pour cela est les composants icône :
```tsx
const SomeParentComponent = () => <MyComponent Icon={MyIcon} />;
// In MyComponent
const MyComponent = ({ MyIcon }: { MyIcon: IconComponent }) => {
const theme = useTheme();
return (
<div>
<MyIcon size={theme.icon.size.md}>
</div>
)
};
```
Pour que React comprenne qu'un composant est un composant, vous devez utiliser PascalCase, pour l'instancier plus tard avec `<MyIcon>`
## Forage de Props : Gardez-le Minimal
Le forage de props, dans le contexte de React, fait référence à la pratique consistant à passer des variables d'état et leurs setters à travers de nombreuses couches de composants, même si les composants intermédiaires ne les utilisent pas. Bien que parfois nécessaire, un forage de props excessif peut entraîner :
1. **Lisibilité Réduite** : Retrouver l'origine d'un prop ou l'endroit où il est utilisé peut devenir complexe dans une structure de composants profondément imbriquée.
2. **Défis de Maintenance** : Des modifications dans la structure des props d'un composant peuvent nécessiter des ajustements dans plusieurs composants, même s'ils n'utilisent pas directement le prop.
3. **Réutilisabilité Réduite du Composant** : Un composant recevant beaucoup de props uniquement pour les transmettre devient moins polyvalent et plus difficile à réutiliser dans différents contextes.
Si vous sentez que vous utilisez un forage de props excessif, voir [les meilleures pratiques de gestion d'état](#state-management).
## Imports
Lors de l'importation, optez pour les alias désignés plutôt que de spécifier des chemins complets ou relatifs.
**Les Alias**
```js
{
alias: {
"~": path.resolve(__dirname, "src"),
"@": path.resolve(__dirname, "src/modules"),
"@testing": path.resolve(__dirname, "src/testing"),
},
}
```
**Utilisation**
```tsx
// ❌ Bad, specifies the entire relative path
import {
CatalogDecorator
} from '../../../../../testing/decorators/CatalogDecorator';
import {
ComponentDecorator
} from '../../../../../testing/decorators/ComponentDecorator';
```
```tsx
// ✅ Good, utilises the designated aliases
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
import { ComponentDecorator } from 'twenty-ui/testing';
```
## Validation de Schéma
[Zod](https://github.com/colinhacks/zod) est le validateur de schéma pour les objets non typés :
```js
const validationSchema = z
.object({
exist: z.boolean(),
email: z
.string()
.email('Email must be a valid email'),
password: z
.string()
.regex(PASSWORD_REGEX, 'Password must contain at least 8 characters'),
})
.required();
type Form = z.infer<typeof validationSchema>;
```
## Changements Radicaux
Effectuez toujours des tests manuels approfondis avant de continuer pour garantir que les modifications n'ont pas causé de perturbations ailleurs, étant donné que les tests n'ont pas encore été intégrés de manière extensive.
@@ -0,0 +1,114 @@
---
title: Architecture des Dossiers
info: Un aperçu détaillé de notre architecture de dossiers
image: /images/user-guide/fields/field.png
---
<Frame>
<img src="/images/user-guide/fields/field.png" alt="Header" />
</Frame>
Dans ce guide, vous explorerez les détails de la structure du répertoire de projet et comment elle contribue à l'organisation et à la maintenabilité de Twenty.
En suivant cette convention d'architecture de dossiers, il est plus facile de trouver les fichiers liés à des fonctionnalités spécifiques et de s'assurer que l'application est évolutive et maintenable.
```
front
└───modules
│ └───module1
│ │ └───submodule1
│ └───module2
│ └───ui
│ │ └───display
│ │ └───inputs
│ │ │ └───buttons
│ │ └───...
└───pages
└───...
```
## Pages
Comprend les composants de haut niveau définis par les routes de l'application. Ils importent des composants plus bas niveau du dossier des modules (plus de détails ci-dessous).
## Modules
Chaque module représente une fonctionnalité ou un groupe de fonctionnalités, comprenant ses composants spécifiques, ses états, et sa logique opérationnelle.
Ils doivent tous suivre la structure ci-dessous. Vous pouvez imbriquer des modules dans des modules (appelés sous-modules) et les mêmes règles s'appliqueront.
```
module1
└───components
│ └───component1
│ └───component2
└───constants
└───contexts
└───graphql
│ └───fragments
│ └───queries
│ └───mutations
└───hooks
│ └───internal
└───states
│ └───selectors
└───types
└───utils
```
### Contextes
Un contexte est un moyen de transmettre des données à travers l'arborescence de composants sans avoir à transmettre les propriétés manuellement à chaque niveau.
Voir [React Context](https://react.dev/reference/react#context-hooks) pour plus de détails.
### GraphQL
Comprend des fragments, des requêtes et des mutations.
Voir [GraphQL](https://graphql.org/learn/) pour plus de détails.
- Fragments
Un fragment est une partie réutilisable d'une requête, que vous pouvez utiliser dans différents endroits. En utilisant des fragments, il est plus facile d'éviter de dupliquer du code.
Voir [GraphQL Fragments](https://graphql.org/learn/queries/#fragments) pour plus de détails.
- Requêtes
Voir [GraphQL Queries](https://graphql.org/learn/queries/) pour plus de détails.
- Mutations
Voir [GraphQL Mutations](https://graphql.org/learn/queries/#mutations) pour plus de détails.
### Hooks
Voir [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) pour plus de détails.
### États
Contient la logique de gestion des états. [RecoilJS](https://recoiljs.org) gère cela.
- Sélecteurs : Voir [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) pour plus de détails.
La gestion de l'état intégrée de React gère toujours l'état au sein d'un composant.
### Utilitaires
Devrait juste contenir des fonctions pures réutilisables. Autrement, créez des hooks personnalisés dans le dossier `hooks`.
## UI
Contient tous les composants d'interface utilisateur réutilisables utilisés dans l'application.
Ce dossier peut contenir des sous-dossiers, comme `data`, `display`, `feedback`, et `input` pour des types de composants spécifiques. Chaque composant doit être autonome et réutilisable, de sorte que vous puissiez l'utiliser dans différentes parties de l'application.
En séparant les composants UI des autres composants dans le dossier `modules`, il est plus facile de maintenir un design cohérent et d'effectuer des changements de l'interface utilisateur sans affecter d'autres parties (logique métier) de la base de code.
## Interface et dépendances
Vous pouvez importer le code d'autres modules depuis n'importe quel module, sauf pour le dossier `ui`. Cela permettra de garder son code facile à tester.
### Interne
Chaque partie (hooks, états, ...) d'un module peut avoir un dossier `interne`, qui contient des parties utilisées uniquement au sein du module.
@@ -0,0 +1,96 @@
---
title: Commandes Frontend
image: /images/user-guide/create-workspace/workspace-cover.png
---
<Frame>
<img src="/images/user-guide/create-workspace/workspace-cover.png" alt="Header" />
</Frame>
## Commandes utiles
### Lancement de l'application
```bash
npx nx start twenty-front
```
### Régénérer le schéma GraphQL basé sur le schéma API GraphQL
```bash
npx nx run twenty-front:graphql:generate --configuration=metadata
```
OU
```bash
npx nx run twenty-front:graphql:generate
```
### Analyse
```bash
npx nx run twenty-front:lint # pass --fix to fix lint errors
```
## Traductions
```bash
npx nx run twenty-front:lingui:extract
npx nx run twenty-front:lingui:compile
```
### Test
```bash
npx nx run twenty-front:test # run jest tests
npx nx run twenty-front:storybook:serve:dev # run storybook
npx nx run twenty-front:storybook:test # run tests # (needs yarn storybook:serve:dev to be running)
npx nx run twenty-front:storybook:coverage # (needs yarn storybook:serve:dev to be running)
```
## Écosystème Tech
Le projet a une stack simple et propre, avec un code boilerplate minimal.
**Application**
- [React](https://react.dev/)
- [Apollo](https://www.apollographql.com/docs/)
- [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
- [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
- [TypeScript](https://www.typescriptlang.org/)
**Tests**
- [Jest](https://jestjs.io/)
- [Storybook](https://storybook.js.org/)
**Outils**
- [Yarn](https://yarnpkg.com/)
- [Craco](https://craco.js.org/docs/)
- [ESLint](https://eslint.org/)
## Architecture
### Routage
[React Router](https://reactrouter.com/) gère le routage.
Pour éviter les [re-renders](/developers/frontend-development/best-practices-front#managing-re-renders) inutiles, toute la logique de routage est dans un `useEffect` dans `PageChangeEffect`.
### Gestion de l'État
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) gère la gestion de l'état.
Voir [les meilleures pratiques](/developers/frontend-development/best-practices-front#state-management) pour plus d'informations sur la gestion de l'état.
## Tests
[Jest](https://jestjs.io/) sert de guide pour les tests unitaires tandis que [Storybook](https://storybook.js.org/) est utilisé pour les tests de composants.
Jest est principalement utilisé pour tester les fonctions utilitaires, et non les composants eux-mêmes.
Storybook est utilisé pour tester le comportement des composants isolés, ainsi que pour afficher le système de design.
@@ -0,0 +1,183 @@
---
title: Raccourcis clavier
image: /images/user-guide/table-views/table.png
---
<Frame>
<img src="/images/user-guide/table-views/table.png" alt="Header" />
</Frame>
## Introduction
Lorsque vous devez écouter une touche de raccourci, vous utilisez normalement l'événement `onKeyDown`.
Cependant, dans `twenty-front`, vous pourriez avoir des conflits entre les mêmes raccourcis utilisés dans différents composants, montés en même temps.
Par exemple, si vous avez une page qui écoute la touche Entrée, et une fenêtre modale qui écoute aussi la touche Entrée, avec un composant Select à l'intérieur de cette fenêtre qui écoute également la touche Entrée, vous risquez d'avoir un conflit lorsque tous sont montés en même temps.
## Le hook `useScopedHotkeys`
Pour résoudre ce problème, nous avons un hook personnalisé qui permet d'écouter les raccourcis sans aucun conflit.
Vous l'insérez dans un composant et il écoutera les raccourcis uniquement lorsque le composant est monté ET lorsque le **périmètre du raccourci** spécifié est actif.
## Comment écouter les raccourcis en pratique ?
Deux étapes sont nécessaires pour configurer l'écoute des raccourcis :
1. Définir le [périmètre du raccourci](#what-is-a-hotkey-scope-) qui écoutera les raccourcis
2. Utiliser le hook `useScopedHotkeys` pour écouter les raccourcis
La configuration des périmètres de raccourcis est nécessaire même sur des pages simples, car d'autres éléments de l'interface utilisateur comme le menu de gauche ou le menu de commandes pourraient également écouter les raccourcis.
## Cas d'utilisation des raccourcis
En général, vous aurez deux cas d'utilisation nécessitant des raccourcis :
1. Dans une page ou un composant monté dans une page
2. Dans un composant de type modal qui prend le focus à la suite d'une action utilisateur
Le deuxième cas d'utilisation peut se produire de manière récursive : un menu déroulant dans une fenêtre modale par exemple.
### Écouter les raccourcis dans une page
Exemple :
```tsx
const PageListeningEnter = () => {
const {
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
// 1. Set the hotkey scope in a useEffect
useEffect(() => {
setHotkeyScopeAndMemorizePreviousScope(
ExampleHotkeyScopes.ExampleEnterPage,
);
// Revert to the previous hotkey scope when the component is unmounted
return () => {
goBackToPreviousHotkeyScope();
};
}, [goBackToPreviousHotkeyScope, setHotkeyScopeAndMemorizePreviousScope]);
// 2. Use the useScopedHotkeys hook
useScopedHotkeys(
Key.Enter,
() => {
// Some logic executed on this page when the user presses Enter
// ...
},
ExampleHotkeyScopes.ExampleEnterPage,
);
return <div>My page that listens for Enter</div>;
};
```
### Écouter les raccourcis dans un composant de type modal
Pour cet exemple, nous allons utiliser un composant modal qui écoute la touche Échap pour informer son parent de le fermer.
Ici, l'interaction utilisateur change le périmètre.
```tsx
const ExamplePageWithModal = () => {
const [showModal, setShowModal] = useState(false);
const {
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
const handleOpenModalClick = () => {
// 1. Set the hotkey scope when user opens the modal
setShowModal(true);
setHotkeyScopeAndMemorizePreviousScope(
ExampleHotkeyScopes.ExampleModal,
);
};
const handleModalClose = () => {
// 1. Revert to the previous hotkey scope when the modal is closed
setShowModal(false);
goBackToPreviousHotkeyScope();
};
return <div>
<h1>My page with a modal</h1>
<button onClick={handleOpenModalClick}>Open modal</button>
{showModal && <MyModalComponent onClose={handleModalClose} />}
</div>;
};
```
Ensuite, dans le composant modal :
```tsx
const MyDropdownComponent = ({ onClose }: { onClose: () => void }) => {
// 2. Use the useScopedHotkeys hook to listen for Escape.
// Note that escape is a common hotkey that could be used by many other components
// So it's important to use a hotkey scope to avoid conflicts
useScopedHotkeys(
Key.Escape,
() => {
onClose()
},
ExampleHotkeyScopes.ExampleModal,
);
return <div>My modal component</div>;
};
```
Il est important d'utiliser ce schéma lorsque vous n'êtes pas sûr que l'utilisation simple d'un useEffect avec montage/démontage suffira à éviter les conflits.
Ces conflits peuvent être difficiles à déboguer et peuvent survenir plus souvent qu'on ne le croit avec les useEffects.
## Qu'est-ce qu'un périmètre de raccourci ?
Un périmètre de raccourci est une chaîne de caractères qui représente un contexte dans lequel les raccourcis sont actifs. Il est généralement encodé sous forme d'enum.
Lorsque vous modifiez le périmètre de raccourci, les raccourcis qui écoutent ce périmètre seront activés et ceux qui écoutent d'autres périmètres seront désactivés.
Vous ne pouvez définir qu'un seul périmètre à la fois.
Par exemple, les périmètres de raccourcis pour chaque page sont définis dans l'`enum PageHotkeyScope` :
```tsx
export enum PageHotkeyScope {
Settings = 'settings',
CreateWorkspace = 'create-workspace',
SignInUp = 'sign-in-up',
CreateProfile = 'create-profile',
PlanRequired = 'plan-required',
ShowPage = 'show-page',
PersonShowPage = 'person-show-page',
CompanyShowPage = 'company-show-page',
CompaniesPage = 'companies-page',
PeoplePage = 'people-page',
OpportunitiesPage = 'opportunities-page',
ProfilePage = 'profile-page',
WorkspaceMemberPage = 'workspace-member-page',
TaskPage = 'task-page',
}
```
En interne, le périmètre sélectionné est stocké dans un état Recoil qui est partagé dans toute l'application :
```tsx
export const currentHotkeyScopeState = createState<HotkeyScope>({
key: 'currentHotkeyScopeState',
defaultValue: INITIAL_HOTKEYS_SCOPE,
});
```
Mais cet état Recoil ne doit jamais être manipulé manuellement ! Nous verrons comment l'utiliser dans la prochaine section.
## Comment cela fonctionne-t-il en interne ?
Nous avons créé un léger emballage au-dessus de [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) qui le rend plus performant et évite les rendus inutiles.
Nous créons également un état Recoil pour gérer l'état du périmètre des raccourcis et le rendre disponible partout dans l'application.
@@ -0,0 +1,8 @@
---
title: Storybook
description: Parcourir la bibliothèque de composants UI de Twenty
---
Consultez notre bibliothèque de composants complète et la documentation dans Storybook.
[Ouvrir Storybook →](https://storybook.twenty.com)
@@ -0,0 +1,295 @@
---
title: Guide de style
image: /images/user-guide/notes/notes_header.png
---
<Frame>
<img src="/images/user-guide/notes/notes_header.png" alt="Header" />
</Frame>
Ce document inclut les règles à suivre lors de l'écriture de code.
L'objectif ici est d'avoir une base de code cohérente, facile à lire et à maintenir.
Pour cela, il vaut mieux être un peu plus verbeux que trop concis.
Gardez toujours à l'esprit que les gens lisent le code plus souvent qu'ils ne l'écrivent, surtout dans un projet open source où tout le monde peut contribuer.
Il existe de nombreuses règles qui ne sont pas définies ici, mais qui sont vérifiées automatiquement par des linters.
## React
### Utilisez des composants fonctionnels
Utilisez toujours des composants fonctionnels TSX.
N'utilisez pas `import` par défaut avec `const`, car c'est plus difficile à lire et plus difficile à importer avec l'autocomplétion du code.
```tsx
// ❌ Bad, harder to read, harder to import with code completion
const MyComponent = () => {
return <div>Hello World</div>;
};
export default MyComponent;
// ✅ Good, easy to read, easy to import with code completion
export function MyComponent() {
return <div>Hello World</div>;
};
```
### Propriétés
Créez le type des props et nommez-le `(NomDuComposant)Props` s'il n'est pas nécessaire de l'exporter.
Utilisez la déstructuration des props.
```tsx
// ❌ Bad, no type
export const MyComponent = (props) => <div>Hello {props.name}</div>;
// ✅ Good, type
type MyComponentProps = {
name: string;
};
export const MyComponent = ({ name }: MyComponentProps) => <div>Hello {name}</div>;
```
#### Évitez d'utiliser `React.FC` ou `React.FunctionComponent` pour définir les types de props.
```tsx
/* ❌ - Bad, defines the component type annotations with `FC`
* - With `React.FC`, the component implicitly accepts a `children` prop
* even if it's not defined in the prop type. This might not always be
* desirable, especially if the component doesn't intend to render
* children.
*/
const EmailField: React.FC<{
value: string;
}> = ({ value }) => <TextInput value={value} disabled fullWidth />;
```
```tsx
/* ✅ - Good, a separate type (OwnProps) is explicitly defined for the
* component's props
* - This method doesn't automatically include the children prop. If
* you want to include it, you have to specify it in OwnProps.
*/
type EmailFieldProps = {
value: string;
};
const EmailField = ({ value }: EmailFieldProps) => (
<TextInput value={value} disabled fullWidth />
);
```
#### Pas de propagation de props à variable unique dans les éléments JSX
Évitez d'utiliser la propagation de props à variable unique dans les éléments JSX, comme `{...props}`. Cette pratique résulte souvent en un code moins lisible et plus difficile à maintenir car il n'est pas clair quels props le composant reçoit.
```tsx
/* ❌ - Bad, spreads a single variable prop into the underlying component
*/
const MyComponent = (props: OwnProps) => {
return <OtherComponent {...props} />;
}
```
```tsx
/* ✅ - Good, Explicitly lists all props
* - Enhances readability and maintainability
*/
const MyComponent = ({ prop1, prop2, prop3 }: MyComponentProps) => {
return <OtherComponent {...{ prop1, prop2, prop3 }} />;
};
```
Raisonnement :
- D'un coup d'œil, il est plus clair quels props le code transmet, le rendant plus facile à comprendre et à maintenir.
- Cela aide à éviter le couplage serré entre les composants via leurs props.
- Les outils de linting facilitent l'identification des props mal orthographiés ou inutilisées lorsque vous listez explicitement les props.
## JavaScript
### Utilisez l'opérateur de coalescence nulle `??`
```tsx
// ❌ Bad, can return 'default' even if value is 0 or ''
const value = process.env.MY_VALUE || 'default';
// ✅ Good, will return 'default' only if value is null or undefined
const value = process.env.MY_VALUE ?? 'default';
```
### Utilisez la chaîne facultative `?.`
```tsx
// ❌ Bad
onClick && onClick();
// ✅ Good
onClick?.();
```
## TypeScript
### Utilisez `type` au lieu de `interface`
Utilisez toujours `type` au lieu de `interface`, car ils se chevauchent presque toujours, et `type` est plus flexible.
```tsx
// ❌ Bad
interface MyInterface {
name: string;
}
// ✅ Good
type MyType = {
name: string;
};
```
### Utilisez des littéraux de chaîne au lieu d'enums
[Les littéraux de chaîne](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) sont la méthode de référence pour gérer des valeurs semblables à des enums dans TypeScript. Ils sont plus faciles à étendre avec Pick et Omit, et offrent une meilleure expérience pour le développeur, notamment avec l'autocompletion de code.
Vous pouvez voir pourquoi TypeScript recommande d'éviter les enums [ici](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).
```tsx
// ❌ Bad, utilizes an enum
enum Color {
Red = "red",
Green = "green",
Blue = "blue",
}
let color = Color.Red;
```
```tsx
// ✅ Good, utilizes a string literal
let color: "red" | "green" | "blue" = "red";
```
#### GraphQL et bibliothèques internes
Vous devriez utiliser les enums générés par le codegen GraphQL.
Il est également préférable d'utiliser un enum lors de l'utilisation d'une bibliothèque interne, afin que la bibliothèque interne n'ait pas à exposer un type de littéral de chaîne qui n'est pas lié à l'API interne.
Exemple :
```TSX
const {
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
setHotkeyScopeAndMemorizePreviousScope(
RelationPickerHotkeyScope.RelationPicker,
);
```
## Stylisme
### Utilisez StyledComponents
Styliser les composants avec [styled-components](https://emotion.sh/docs/styled).
```tsx
// ❌ Bad
<div className="my-class">Hello World</div>
```
```tsx
// ✅ Good
const StyledTitle = styled.div`
color: red;
`;
```
Préfixez les composants stylisés avec "Styled" pour les différencier des composants "réels".
```tsx
// ❌ Bad
const Title = styled.div`
color: red;
`;
```
```tsx
// ✅ Good
const StyledTitle = styled.div`
color: red;
`;
```
### Thematisation
Utiliser le thème pour la majorité du stylisme des composants est l'approche préférée.
#### Unités de mesure
Évitez d'utiliser des valeurs `px` ou `rem` directement dans les composants stylisés. Les valeurs nécessaires sont généralement déjà définies dans le thème, il est donc recommandé d'utiliser le thème à ces fins.
#### Couleurs
Évitez d'introduire de nouvelles couleurs ; utilisez plutôt la palette existante du thème. Si la palette ne correspond pas, veuillez laisser un commentaire pour que l'équipe puisse rectifier cela.
```tsx
// ❌ Bad, directly specifies style values without utilizing the theme
const StyledButton = styled.button`
color: #333333;
font-size: 1rem;
font-weight: 400;
margin-left: 4px;
border-radius: 50px;
`;
```
```tsx
// ✅ Good, utilizes the theme
const StyledButton = styled.button`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.md};
font-weight: ${({ theme }) => theme.font.weight.regular};
margin-left: ${({ theme }) => theme.spacing(1)};
border-radius: ${({ theme }) => theme.border.rounded};
`;
```
## Application d'interdiction d'importations de type
Évitez les importations de type. Pour appliquer cette norme, une règle ESLint vérifie et signale toutes les importations de type. Cela aide à maintenir la cohérence et la lisibilité dans le code TypeScript.
```tsx
// ❌ Bad
import { type Meta, type StoryObj } from '@storybook/react';
// ❌ Bad
import type { Meta, StoryObj } from '@storybook/react';
// ✅ Good
import { Meta, StoryObj } from '@storybook/react';
```
### Pourquoi éviter les importations de type
- **Cohérence** : En évitant les importations de type et en utilisant une seule approche pour les importations de type et de valeur, la base de code reste cohérente dans son style d'importation de module.
- **Lisibilité** : Les importations sans type améliorent la lisibilité du code en clarifiant quand vous importez des valeurs ou des types. Cela réduit l'ambiguïté et facilite la compréhension de l'objectif des symboles importés.
- **Maintenabilité** : Cela améliore la maintenabilité de la base de code car les développeurs peuvent identifier et localiser les importations uniquement de type lors de la révision ou de la modification du code.
### Règle ESLint
Une règle ESLint, `@typescript-eslint/consistent-type-imports`, applique la norme d'importation sans type. Cette règle génère des erreurs ou des avertissements pour toutes les violations d'importations de type.
Veillez à ce que cette règle aborde spécifiquement les rares cas particuliers où se produisent des importations de type involontaires. TypeScript lui-même déconseille cette pratique, comme mentionné dans les [notes de version de TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). Dans la majorité des situations, vous ne devriez pas avoir besoin d'utiliser des importations uniquement de type.
Pour garantir la conformité de votre code avec cette règle, assurez-vous d'exécuter ESLint dans le cadre de votre flux de travail de développement.
@@ -0,0 +1,66 @@
---
title: Travailler avec Figma
info: Apprenez comment vous pouvez collaborer avec le Figma de Twenty
image: /images/user-guide/objects/objects.png
---
<Frame>
<img src="/images/user-guide/objects/objects.png" alt="Header" />
</Frame>
Figma est un outil de conception d'interface collaboratif qui aide à surmonter la barrière de communication entre designers et développeurs.
Ce guide explique comment vous pouvez collaborer avec Figma.
## Accès
1. **Accédez au lien partagé :** Vous pouvez accéder au fichier Figma du projet [ici](https://www.figma.com/file/xt8O9mFeLl46C5InWwoMrN/Twenty).
2. **Se connecter :** Si vous n'êtes pas déjà connecté, Figma vous invitera à le faire.
Les fonctionnalités clés ne sont disponibles que pour les utilisateurs connectés, telles que le mode développeur et la possibilité de sélectionner un cadre dédié.
<Warning>
Vous ne pourrez pas collaborer efficacement sans compte.
</Warning>
## Structure de Figma
Sur la barre latérale gauche, vous pouvez accéder aux différentes pages du Figma de Twenty. Voici comment elles sont organisées :
- **Page des composants :** C'est la première page. Le designer l'utilise pour créer et organiser les éléments de design réutilisables utilisés dans tout le fichier design. Par exemple, boutons, icônes, symboles ou tout autre composant réutilisable. Elle sert à maintenir la cohérence dans le design.
- **Page principale :** La deuxième page est la page principale, qui montre l'interface utilisateur complète du projet. Vous pouvez appuyer sur _**Play**_ pour utiliser le prototype complet de l'application.
- **Pages des fonctionnalités :** Les autres pages sont généralement dédiées aux fonctionnalités en cours de développement. Elles contiennent le design de fonctionnalités ou modules spécifiques de l'application ou du site web. Elles sont généralement encore en cours de développement.
## Conseils utiles
Avec un accès en lecture seule, vous ne pouvez pas modifier le design, mais vous pouvez accéder à toutes les fonctionnalités utiles pour convertir les designs en code.
### Utiliser le mode dev
Le Mode Dev de Figma améliore la productivité des développeurs en fournissant une navigation simple dans le design, une gestion efficace des ressources, des outils de communication performants, des intégrations de boîte à outils, des extraits de code rapides et des informations clés sur les calques, comblant ainsi le fossé entre design et développement. Vous pouvez en savoir plus sur le mode Dev [ici](https://www.figma.com/dev-mode/).
Basculez vers le mode « Développeur » dans la partie droite de la barre d'outils pour voir les spécifications du design, copier du CSS et accéder aux ressources.
### Utilisez le Prototype
Cliquez sur n'importe quel élément du canvas et appuyez sur le bouton « Play » en haut à droite de l'interface pour accéder à la vue du prototype. Le mode Prototype vous permet d'interagir avec le design comme s'il s'agissait du produit final. Il montre le flux entre les écrans et comment les éléments de l'interface tels que les boutons, les liens ou les menus se comportent lorsqu'ils sont interactifs.
1. **Comprendre les transitions et animations :** En mode Prototype, vous pouvez voir toutes les transitions ou animations ajoutées par un designer entre écrans ou éléments UI, fournissant des instructions visuelles claires aux développeurs sur le comportement et le style attendus.
2. **Clarification de l'implémentation :** Un prototype peut aussi aider à réduire les ambiguïtés. Les développeurs peuvent interagir avec lui pour mieux comprendre la fonctionnalité ou l'apparence de certains éléments.
Pour des détails et instructions plus complets sur l'apprentissage de la plateforme Figma, vous pouvez visiter la [Documentation officielle de Figma](https://help.figma.com/hc/fr).
### Mesurer les distances
Sélectionnez un élément, maintenez la touche `Option` (Mac) ou `Alt` (Windows), puis survolez un autre élément pour voir la distance entre eux.
### Extension Figma pour VSCode (Recommandée)
[Figma pour VS Code](https://marketplace.visualstudio.com/items?itemName=figma.figma-vscode-extension)
vous permet de naviguer et d'inspecter les fichiers design, de collaborer avec les designers, de suivre les changements et d'accélérer la mise en œuvre - le tout sans quitter votre éditeur de texte.
Cela fait partie de nos extensions recommandées.
## Collaboration
1. **Utilisation des commentaires :** N'hésitez pas à utiliser la fonction commentaire en cliquant sur l'icône de bulle dans la partie gauche de la barre d'outils.
2. **Conversation par curseur :** Une fonctionnalité intéressante de Figma est la conversation par curseur. Il suffit d'appuyer sur `;` sur Mac et `/` sur Windows pour envoyer un message si vous voyez quelqu'un d'autre utiliser Figma en même temps que vous.
@@ -0,0 +1,36 @@
---
title: Vue d'ensemble
description: Documentation technique pour les contributeurs et développeurs travaillant avec Twenty
---
## Commencer
<CardGroup cols={2}>
<Card title="Local Setup" href="/developers/local-setup" img="/images/user-guide/fields/field.png">
Le guide pour les contributeurs (ou les développeurs curieux) qui veulent exécuter Twenty localement (sur un ordinateur portable, PC...)
</Card>
<Card title="Self-Hosting" href="/developers/self-hosting/docker-compose" img="/images/user-guide/integrations/plug.png">
Apprenez à héberger Twenty sur votre propre serveur
</Card>
<Card title="API and Webhooks" href="/developers/api-and-webhooks/api" img="/images/user-guide/api/api.png">
APIs REST et GraphQL, webhooks et intégrations
</Card>
</CardGroup>
## Contribution
<CardGroup cols={2}>
<Card title="Bugs and Requests" href="/developers/bug-and-requests" img="/images/user-guide/api/api.png">
Demandez de l'aide sur GitHub ou Discord
</Card>
<Card title="Frontend Development" href="/developers/frontend-development/frontend-commands" img="/images/user-guide/create-workspace/workspace-cover.png">
Commandes frontales, Figma, Meilleures pratiques React...
</Card>
<Card title="Backend Development" href="/developers/backend-development/server-commands" img="/images/user-guide/kanban-views/kanban.png">
NestJS, Objets personnalisés, Files d'attente...
</Card>
</CardGroup>
@@ -0,0 +1,45 @@
---
title: Autres méthodes
image: /images/user-guide/notes/notes_header.png
---
<Frame>
<img src="/images/user-guide/notes/notes_header.png" alt="Header" />
</Frame>
<Warning>
Ce document est maintenu par la communauté. Il pourrait contenir des problèmes.
</Warning>
## Kubernetes via Terraform et Manifests
La documentation communautaire pour le déploiement de Kubernetes est disponible [ici](https://github.com/twentyhq/twenty/tree/main/packages/twenty-docker/k8s)
### Coolify
Déployer Twenty sur les serveurs avec Coolify. (l'image officielle sur Coolify sera bientôt disponible)
[Documentation Coolify](https://coolify.io/docs/get-started/introduction)
### EasyPanel
Déployez Twenty sur EasyPanel avec le modèle maintenu par la communauté ci-dessous.
[Déployer sur EasyPanel](https://easypanel.io/docs/templates/twenty)
### Elest.io
Déployez Twenty sur les serveurs avec Elest.io en utilisant le lien ci-dessous.
[Déployer sur Elest.io](https://elest.io/open-source/twenty)
### Twenty sur Railway
Déployez Twenty sur Railway avec le modèle maintenu par la communauté ci-dessous.
[![Déployer sur Railway](https://railway.com/button.svg)](https://railway.com/deploy/nAL3hA)
## Autres
N'hésitez pas à ouvrir une PR pour ajouter d'autres options de fournisseur cloud.
@@ -0,0 +1,214 @@
---
title: 1-Clic avec Docker Compose
image: /images/user-guide/objects/objects.png
---
<Frame>
<img src="/images/user-guide/objects/objects.png" alt="Header" />
</Frame>
<Warning>
Les conteneurs Docker sont pour l'hébergement en production ou l'auto-hébergement, pour la contribution veuillez consulter le [Configuration Locale](https://docs.twenty.com/developers/local-setup).
</Warning>
## Vue d'ensemble
Ce guide fournit des instructions pas-à-pas pour installer et configurer l'application Twenty à l'aide de Docker Compose. L'objectif est de simplifier le processus et d'éviter les erreurs courantes qui pourraient compromettre votre configuration.
**Important :** Modifiez uniquement les paramètres explicitement mentionnés dans ce guide. Modifier d'autres configurations peut entraîner des problèmes.
Consultez les documents [Configurer les Variables dEnvironnement](https://docs.twenty.com/developers/self-hosting/setup) pour la configuration avancée. Toutes les variables d'environnement doivent être déclarées dans le fichier docker-compose.yml au niveau du serveur et/ou du travailleur, selon la variable.
## Exigences du Système
- RAM : Assurez-vous que votre environnement dispose d'au moins 2 Go de RAM. Une mémoire insuffisante peut provoquer des plantages des processus.
- Docker & Docker Compose : Assurez-vous que les deux sont installés et à jour.
## Option 1 : Script en une seule ligne
Installez la dernière version stable de Twenty avec une seule commande :
```bash
bash <(curl -sL https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/scripts/install.sh)
```
Pour installer une version ou une branche spécifique :
```bash
VERSION=vx.y.z BRANCH=branch-name bash <(curl -sL https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/scripts/install.sh)
```
- Remplacez x.y.z par le numéro de version désiré.
- Remplacez nom-branche par le nom de la branche que vous souhaitez installer.
## Option 2 : Étapes manuelles
Suivez ces étapes pour une installation manuelle.
### Étape 1 : Configurez le Fichier Environnement
1. **Créez le Fichier .env**
Copiez le fichier d'exemple d'environnement vers un nouveau fichier .env dans votre répertoire de travail :
```bash
curl -o .env https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-docker/.env.example
```
2. **Générez des Jetons Secrets**
Exécutez la commande suivante pour générer une chaîne aléatoire unique :
```bash
openssl rand -base64 32
```
**Important :** Gardez cette valeur secrète / ne la partagez pas.
3. **Mettez à jour le `.env`**
Remplacez la valeur de l'espace réservé dans votre fichier .env par le jeton généré :
```ini
APP_SECRET=first_random_string
```
4. **Définissez le Mot de Passe de Postgres**
Mettez à jour la valeur `PG_DATABASE_PASSWORD` dans le fichier .env avec un mot de passe fort sans caractères spéciaux.
```ini
PG_DATABASE_PASSWORD=my_strong_password
```
### Étape 2 : Obtenez le Fichier Docker Compose
Téléchargez le fichier `docker-compose.yml` dans votre répertoire de travail :
```bash
curl -o docker-compose.yml https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-docker/docker-compose.yml
```
### Étape 3 : Lancer l'Application
Démarrez les conteneurs Docker :
```bash
docker compose up -d
```
### Étape 4 : Accéder à l'Application
Si vous hébergez twentyCRM sur votre ordinateur, ouvrez votre navigateur et allez à [http://localhost:3000](http://localhost:3000).
Si vous l'hébergez sur un serveur, vérifiez que le serveur fonctionne et que tout est en ordre avec
```bash
curl http://localhost:3000
```
## Configuration
### Exposer Twenty à un Accès Externe
Par défaut, Twenty fonctionne sur `localhost` au port `3000`. Pour y accéder via un domaine externe ou une adresse IP, vous devez configurer le `SERVER_URL` dans votre fichier `.env`.
#### Comprendre `SERVER_URL`
- **Protocole :** Utilisez `http` ou `https` selon votre configuration.
- Utilisez `http` si vous n'avez pas configuré SSL.
- Utilisez `https` si vous avez configuré SSL.
- **Domaine/IP :** Il s'agit du nom de domaine ou de l'adresse IP où votre application est accessible.
- **Port :** Incluez le numéro de port si vous n'utilisez pas les ports par défaut (`80` pour `http`, `443` pour `https`).
### Exigences SSL
Le SSL (HTTPS) est requis pour que certaines fonctionnalités des navigateurs fonctionnent correctement. Bien que ces fonctionnalités puissent fonctionner lors du développement local (car les navigateurs traitent localhost différemment), une configuration SSL appropriée est nécessaire lors de l'hébergement de Twenty sur un domaine régulier.
Par exemple, l'API du presse-papiers pourrait nécessiter un contexte sécurisé - certaines fonctionnalités comme les boutons de copie dans toute l'application pourraient ne pas fonctionner sans HTTPS activé.
Nous vous recommandons vivement de mettre en place Twenty derrière un proxy inverse avec terminaison SSL pour une sécurité et une fonctionnalité optimales.
#### Configurer `SERVER_URL`
1. **Déterminez Votre URL d'Accès**
- **Sans Proxy Inverse (Accès Direct):**
Si vous accédez directement à l'application sans un proxy inverse :
```ini
SERVER_URL=http://your-domain-or-ip:3000
```
- **Avec Proxy Inverse (Ports Standards):**
Si vous utilisez un proxy inverse comme Nginx ou Traefik et que vous avez SSL configuré :
```ini
SERVER_URL=https://your-domain-or-ip
```
- **Avec Proxy Inverse (Ports Personnalisés):**
Si vous utilisez des ports non standards :
```ini
SERVER_URL=https://your-domain-or-ip:custom-port
```
2. **Mettez à jour le Fichier `.env`**
Ouvrez votre fichier `.env` et mettez à jour le `SERVER_URL`:
```ini
SERVER_URL=http(s)://your-domain-or-ip:your-port
```
**Exemples :**
- Accès direct sans SSL :
```ini
SERVER_URL=http://123.45.67.89:3000
```
- Accès via domaine avec SSL :
```ini
SERVER_URL=https://mytwentyapp.com
```
3. **Redémarrez l'Application**
Pour que les changements prennent effet, redémarrez les conteneurs Docker :
```bash
docker compose down
docker compose up -d
```
#### Considérations
- **Configuration du Proxy Inverse :**
Assurez-vous que votre proxy inverse redirige les requêtes vers le port interne correct (`3000` par défaut). Configurez la terminaison SSL et tous les en-têtes nécessaires.
- **Paramètres de Pare-feu :**
Ouvrez les ports nécessaires dans votre pare-feu pour permettre l'accès externe.
- **Cohérence :**
Le `SERVER_URL` doit correspondre à la façon dont les utilisateurs accèdent à votre application dans leurs navigateurs.
#### Persistance
- **Volumes de Données :**
La configuration de Docker Compose utilise des volumes pour persister les données pour la base de données et le stockage du serveur.
- **Environnements sans État :**
Si vous déployez dans un environnement sans état (par exemple, certains services cloud), configurez un stockage externe pour persister les données.
## Résolution des problèmes
Si vous rencontrez un problème, consultez [Dépannage](https://docs.twenty.com/developers/self-hosting/troubleshooting) pour des solutions.
@@ -0,0 +1,390 @@
---
title: Guide de mise à niveau
image: /images/user-guide/notes/notes_header.png
---
<Frame>
<img src="/images/user-guide/notes/notes_header.png" alt="Header" />
</Frame>
## Consignes générales
**Assurez-vous toujours de sauvegarder votre base de données avant de commencer le processus de mise à niveau** en exécutant `docker exec -it <db_container_name_or_id> pg_dumpall -U <postgres_user> > databases_backup.sql`.
Pour restaurer la sauvegarde, exécutez `cat databases_backup.sql | docker exec -i <db_container_name_or_id> psql -U <postgres_user>`.
Si vous avez utilisé Docker Compose, suivez ces étapes :
1. Dans un terminal, sur l'hôte où Twenty est en cours d'exécution, éteignez Twenty: `docker compose down`
2. Mettez à niveau la version en changeant la valeur `TAG` dans le fichier .env près de votre docker-compose. (Nous recommandons de consommer la version `major.minor` telle que `v0.53`)
3. Remettez Twenty en ligne avec `docker compose up -d`
Si vous souhaitez mettre à niveau votre instance de quelques versions, par exemple de la v0.33.0 à la v0.35.0, vous devez mettre à niveau votre instance de manière séquentielle, dans cet exemple de la v0.33.0 à la v0.34.0, puis de la v0.34.0 à la v0.35.0.
**Assurez-vous qu'après chaque version mise à niveau, votre sauvegarde ne soit pas corrompue.**
## Étapes de mise à niveau spécifiques à la version
## v1.0
Bonjour Twenty v1.0 ! 🎉
## v0.60
### Améliorations des performances
Toutes les interactions avec l'API des métadonnées ont été optimisées pour de meilleures performances, en particulier pour la manipulation des métadonnées d'objets et les opérations de création d'espaces de travail.
Nous avons remanié notre stratégie de mise en cache pour privilégier les accès cache plutôt que les requêtes de base de données lorsque c'est possible, améliorant ainsi significativement les performances des opérations de l'API des métadonnées.
Si vous rencontrez des problèmes d'exécution après la mise à niveau, vous devrez peut-être vider votre cache pour vous assurer qu'il est synchronisé avec les dernières modifications. Exécutez cette commande dans votre conteneur twenty-server :
```bash
yarn command:prod cache:flush
```
### v0.55
Mettez à niveau votre instance Twenty pour utiliser l'image v0.55
Vous n'avez plus besoin de lancer de commande, la nouvelle image se chargera automatiquement de l'exécution de toutes les migrations requises.
### Erreur `L'utilisateur n'a pas d'autorisation`
Si vous rencontrez des erreurs d'autorisation sur la plupart des requêtes après la mise à niveau, vous devrez peut-être vider votre cache pour recalculer les dernières autorisations.
Dans votre conteneur `twenty-server`, exécutez :
```bash
yarn command:prod cache:flush
```
Ce problème est spécifique à cette version de Twenty et ne devrait pas être nécessaire pour les futures mises à niveau.
### v0.54
Depuis la version `0.53`, aucune action manuelle n'est nécessaire.
#### Abandon du schéma de métadonnées
Nous avons fusionné le schéma `metadata` dans celui de `core` pour simplifier la récupération de données de `TypeORM`.
Nous avons intégré l'étape de commande `migrate` dans la commande `upgrade`. Nous ne recommandons pas l'exécution manuelle de `migrate` dans l'un de vos conteneurs serveur/travailleur.
### Depuis la v0.53
À partir de `0.53`, la mise à niveau est effectuée de manière programmatique au sein du `DockerFile`, cela signifie que vous ne devez plus exécuter de commande manuellement.
Assurez-vous de continuer à mettre à jour votre instance de manière séquentielle, sans sauter de version majeure (par exemple, de `0.43.3` à `0.44.0` est autorisé, mais de `0.43.1` à `0.45.0` ne l'est pas), sinon cela pourrait entraîner une désynchronisation de la version de l'espace de travail pouvant entraîner une erreur d'exécution et des fonctionnalités manquantes.
Pour vérifier si un espace de travail a été correctement migré, vous pouvez consulter sa version dans la base de données dans la table `core.workspace`.
Il doit toujours être dans la plage de la version `major.minor` de votre instance Twenty actuelle, vous pouvez consulter la version de votre instance dans le panneau d'administration (à l'adresse `/settings/admin-panel`, accessible si votre utilisateur a la propriété `canAccessFullAdminPanel` définie comme vraie dans la base de données) ou en exécutant `echo $APP_VERSION` dans votre conteneur `twenty-server`.
Pour corriger une version d'espace de travail désynchronisée, vous devrez effectuer une mise à niveau à partir de la version correspondante de Twenty en suivant le guide de mise à niveau correspondant séquentiellement, et ainsi de suite jusqu'à atteindre la version souhaitée.
#### Suppression de `auditLog`
Nous avons supprimé l'objet standard auditLog, ce qui signifie que la taille de votre sauvegarde pourrait être considérablement réduite après cette migration.
### v0.51 à v0.52
Mettez à jour votre instance Twenty pour utiliser l'image v0.52
```
yarn database:migrate:prod
yarn command:prod upgrade
```
#### J'ai un espace de travail bloqué dans la version entre `0.52.0` et `0.52.6`
Malheureusement, `0.52.0` et `0.52.6` ont été entièrement supprimés de dockerHub.
Vous devrez mettre à jour manuellement la version de votre espace de travail à `0.51.0` dans la base de données et mettre à niveau en utilisant la version twenty `0.52.11` en suivant son guide de mise à niveau juste au-dessus.
### v0.50 à v0.51
Mettez à jour votre instance Twenty pour utiliser l'image v0.51
```
yarn database:migrate:prod
yarn command:prod upgrade
```
### v0.44.0 à v0.50.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.50.0
```
yarn database:migrate:prod
yarn command:prod upgrade
```
#### Mutation docker-compose.yml
Cette version inclut une mutation `docker-compose.yml` pour donner au service `worker` accès au volume `server-local-data`.
Veuillez mettre à jour votre `docker-compose.yml` local avec [docker-compose.yml v0.50.0](https://github.com/twentyhq/twenty/blob/v0.50.0/packages/twenty-docker/docker-compose.yml)
### v0.43.0 à v0.44.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.44.0
```
yarn database:migrate:prod
yarn command:prod upgrade
```
### v0.42.0 à v0.43.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.43.0
```
yarn database:migrate:prod
yarn command:prod upgrade
```
Dans cette version, nous avons également changé pour l'image postgres:16 dans `docker-compose.yml`.
#### (Option 1) Migration de base de données
Conserver l'image postgres-spilo existante est correct, mais vous devrez geler la version dans votre docker-compose.yml à 0.43.0.
#### (Option 2) Migration de base de données
Si vous souhaitez migrer votre base de données vers la nouvelle image postgres:16, suivez ces étapes :
1. Exportez votre base de données depuis l'ancien conteneur postgres-spilo
```
docker exec -it twenty-db-1 sh
pg_dump -U {YOUR_POSTGRES_USER} -d {YOUR_POSTGRES_DB} > databases_backup.sql
exit
docker cp twenty-db-1:/home/postgres/databases_backup.sql .
```
Assurez-vous que votre fichier de sauvegarde n'est pas vide.
2. Mettez à jour votre docker-compose.yml pour utiliser l'image postgres:16 comme dans le fichier [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml).
3. Restaurez la base de données vers le nouveau conteneur postgres:16
```
docker cp databases_backup.sql twenty-db-1:/databases_backup.sql
docker exec -it twenty-db-1 sh
psql -U {YOUR_POSTGRES_USER} -d {YOUR_POSTGRES_DB} -f databases_backup.sql
exit
```
### v0.41.0 à v0.42.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.42.0
```
yarn database:migrate:prod
yarn command:prod upgrade-0.42
```
**Variables d'environnement**
- Supprimé : `FRONT_PORT`, `FRONT_PROTOCOL`, `FRONT_DOMAIN`, `PORT`
- Ajouté : `FRONTEND_URL`, `NODE_PORT`, `MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION`, `MESSAGING_PROVIDER_MICROSOFT_ENABLED`, `CALENDAR_PROVIDER_MICROSOFT_ENABLED`, `IS_MICROSOFT_SYNC_ENABLED`
### v0.40.0 à v0.41.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.41.0
```
yarn database:migrate:prod
yarn command:prod upgrade-0.41
```
**Variables d'environnement**
- Supprimé : `AUTH_MICROSOFT_TENANT_ID`
### v0.35.0 à v0.40.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.40.0
```
yarn database:migrate:prod
yarn command:prod upgrade-0.40
```
**Variables d'environnement**
- Ajouté : `IS_EMAIL_VERIFICATION_REQUIRED`, `EMAIL_VERIFICATION_TOKEN_EXPIRES_IN`, `WORKFLOW_EXEC_THROTTLE_LIMIT`, `WORKFLOW_EXEC_THROTTLE_TTL`
### v0.34.0 à v0.35.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.35.0
```
yarn database:migrate:prod
yarn command:prod upgrade-0.35
```
La commande `yarn database:migrate:prod` appliquera les migrations à la structure de la base de données (schémas core et metadata)
La commande `yarn command:prod upgrade-0.35` s'occupe de la migration des données de tous les espaces de travail.
**Variables d'environnement**
- Nous avons remplacé `ENABLE_DB_MIGRATIONS` par `DISABLE_DB_MIGRATIONS` (la valeur par défaut est désormais `false`, vous n'avez probablement rien à paramétrer)
### v0.33.0 à v0.34.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.34.0
```
yarn database:migrate:prod
yarn command:prod upgrade-0.34
```
La commande `yarn database:migrate:prod` appliquera les migrations à la structure de la base de données (schémas core et metadata)
La commande `yarn command:prod upgrade-0.34` s'occupe de la migration des données de tous les espaces de travail.
**Variables d'environnement**
- Supprimé : `FRONT_BASE_URL`
- Ajouté : `FRONT_DOMAIN`, `FRONT_PROTOCOL`, `FRONT_PORT`
Nous avons mis à jour notre méthode de gestion des URL frontend.
Vous pouvez maintenant définir l'URL frontend en utilisant les variables `FRONT_DOMAIN`, `FRONT_PROTOCOL` et `FRONT_PORT`.
Si FRONT_DOMAIN n'est pas défini, l'URL frontend reviendra à `SERVER_URL`.
### v0.32.0 à v0.33.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.33.0
```
yarn command:prod cache:flush
yarn database:migrate:prod
yarn command:prod upgrade-0.33
```
La commande `yarn command:prod cache:flush` videra le cache Redis.
La commande `yarn database:migrate:prod` appliquera les migrations à la structure de la base de données (schémas core et metadata)
La commande `yarn command:prod upgrade-0.33` s'occupe de la migration des données de tous les espaces de travail.
À partir de cette version, l'image twenty-postgres pour la DB est devenue obsolète et twenty-postgres-spilo est utilisé à la place.
Si vous souhaitez continuer à utiliser l'image twenty-postgres, remplacez simplement `twentycrm/twenty-postgres:${TAG}` par `twentycrm/twenty-postgres` dans docker-compose.yml.
### v0.31.0 à v0.32.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.32.0
**Migration de schéma et de données**
```
yarn database:migrate:prod
yarn command:prod upgrade-0.32
```
La commande `yarn database:migrate:prod` appliquera les migrations à la structure de la base de données (schémas core et metadata)
La commande `yarn command:prod upgrade-0.32` s'occupe de la migration des données de tous les espaces de travail.
**Variables d'environnement**
Nous avons mis à jour notre méthode de gestion de la connexion Redis.
- Supprimé : `REDIS_HOST`, `REDIS_PORT`, `REDIS_USERNAME`, `REDIS_PASSWORD`
- Ajouté : `REDIS_URL`
Mettez à jour votre fichier `.env` pour utiliser la nouvelle variable `REDIS_URL` au lieu des paramètres de connexion Redis individuels.
Nous avons également simplifié notre méthode de gestion des tokens JWT.
- Supprimé : `ACCESS_TOKEN_SECRET`, `LOGIN_TOKEN_SECRET`, `REFRESH_TOKEN_SECRET`, `FILE_TOKEN_SECRET`
- Ajouté : `APP_SECRET`
Mettez à jour votre fichier `.env` pour utiliser la nouvelle variable `APP_SECRET` à la place des secrets de tokens individuels (vous pouvez utiliser le même secret qu'avant ou générer une nouvelle chaîne aléatoire).
**Compte connecté**
Si vous utilisez un compte connecté pour synchroniser vos emails et calendriers Google, vous devrez activer l'API des personnes sur votre console d'administration Google.
### v0.30.0 à v0.31.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.31.0
**Migration de schéma et de données :**
```
yarn database:migrate:prod
yarn command:prod upgrade-0.31
```
La commande `yarn database:migrate:prod` appliquera les migrations à la structure de la base de données (schémas core et metadata)
La commande `yarn command:prod upgrade-0.31` s'occupe de la migration des données de tous les espaces de travail.
### v0.24.0 à v0.30.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.30.0
**Changement significatif**:
Pour améliorer les performances, Twenty nécessite désormais la configuration de cache redis. Nous avons mis à jour notre [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml) pour refléter cela.
Assurez-vous de mettre à jour votre configuration et vos variables d'environnement en conséquence :
```
REDIS_HOST={your-redis-host}
REDIS_PORT={your-redis-port}
CACHE_STORAGE_TYPE=redis
```
**Migration de schéma et de données :**
```
yarn database:migrate:prod
yarn command:prod upgrade-0.30
```
La commande `yarn database:migrate:prod` appliquera les migrations à la structure de la base de données (schémas core et metadata)
La commande `yarn command:prod upgrade-0.30` s'occupe de la migration des données de tous les espaces de travail.
### v0.23.0 à v0.24.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.24.0
Exécutez les commandes suivantes :
```
yarn database:migrate:prod
yarn command:prod upgrade-0.24
```
La commande `yarn database:migrate:prod` appliquera les migrations à la structure de la base de données (schémas core et metadata)
La commande `yarn command:prod upgrade-0.24` s'occupe de la migration des données de tous les espaces de travail.
### v0.22.0 à v0.23.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.23.0
Exécutez les commandes suivantes :
```
yarn database:migrate:prod
yarn command:prod upgrade-0.23
```
La commande `yarn database:migrate:prod` appliquera les migrations à la base de données.
La commande `yarn command:prod upgrade-0.23` s'occupe de la migration des données, y compris le transfert des activités vers les tâches/notes.
### v0.21.0 à v0.22.0
Mettez à jour votre instance Twenty pour utiliser l'image v0.22.0
Exécutez les commandes suivantes :
```
yarn database:migrate:prod
yarn command:prod workspace:sync-metadata -f
yarn command:prod upgrade-0.22
```
La commande `yarn database:migrate:prod` appliquera les migrations à la base de données.
La commande `yarn command:prod workspace:sync-metadata -f` synchronisera la définition des objets standard avec les tables de métadonnées et appliquera les migrations nécessaires aux espaces de travail existants.
La commande `yarn command:prod upgrade-0.22` appliquera des transformations de données spécifiques pour sadapter aux nouvelles `defaultRequestInstrumentationOptions` dobjet.