snapshot of https://github.com/twentyhq/twenty.git (main, 2026-09-17; blobs > 131072B omitted)
Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-17 23:28:13 +05:00
commit e7da97194a
32688 changed files with 4208681 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
---
title: Osvědčené postupy
---
Tento dokument popisuje osvědčené postupy, které byste měli dodržovat při práci na backendu.
## Dodržujte modulární přístup
Backend sleduje modulární přístup, což je základní princip při práci s NestJS. Ujistěte se, že rozdělujete svůj kód na znovupoužitelné moduly, abyste udrželi čistý a organizovaný kód.
Každý modul by měl zahrnovat určitou funkci nebo funkcionalitu a mít jasně definovaný rozsah. Tento modulární přístup umožňuje jasné oddělení odpovědností a odstraňuje zbytečné složitosti.
## Zpřístupněte služby pro použití v modulech.
Vždy vytvářejte služby s jasně vymezenou jedinou odpovědností, což zvyšuje čitelnost a udržovatelnost kódu. Pojmenovávejte služby výstižně a konzistentně.
Měli byste také zpřístupnit služby, které chcete používat v jiných modulech. Zpřístupnění služeb ostatním modulům je možné díky výkonnému systému injektování závislostí v NestJS a podporuje volné vazby mezi komponentami.
## Vyhněte se použití typu `any`
Když deklarujete proměnnou jako `any`, kontrolor typů TypeScriptu neprovádí kontrolu typů, což umožňuje přiřadit proměnné jakýkoliv typ hodnot. TypeScript používá odvozování typů ke stanovení typu proměnné na základě hodnoty. Prohlášením jako `any` TypeScript již nemůže odvodit typ. To ztěžuje chycení chyb souvisejících s typy během vývoje, což vede k chybám za běhu a činí kód obtížně udržovatelným, méně spolehlivým a těžším na pochopení pro ostatní.
Proto by všechno mělo mít typ. Pokud tedy vytvoříte nový objekt se jménem a příjmením, měli byste vytvořit rozhraní nebo typ, který obsahuje jméno a příjmení a definuje tvar objektu, se kterým pracujete.

View File

@@ -0,0 +1,39 @@
---
title: Vlastní objekty
---
Objekty jsou struktury, které vám umožňují ukládat data (záznamy, atributy a hodnoty) specifická pro organizaci. Twenty poskytuje jak standardní, tak vlastní objekty.
Standardní objekty jsou vestavěné objekty se sadou atributů dostupných pro všechny uživatele. Příklady standardních objektů v Twenty zahrnují Firma a Osoba. Standardní objekty mají standardní pole, která jsou také dostupná pro všechny uživatele Twenty, jako například Firma.displayName.
Vlastní objekty jsou objekty, které můžete vytvářet pro ukládání informací specifických pro vaši organizaci. Nejsou vestavěné; členové vaší pracovní skupiny mohou vytvářet a upravovat vlastní objekty pro ukládání informací, které nejsou vhodné pro standardní objekty.
## Schema na vysoké úrovni
<div style={{textAlign: 'center'}}>
<img src="/images/docs/server/custom-object-schema.png" alt="Schema na vysoké úrovni" />
</div>
<br />
## Jak to funguje
Vlastní objekty pocházejí z tabulek metadat, které určují tvar, název a typ objektů. Veškeré tyto informace jsou přítomny v databázi schémat metadat, která se skládá z následujících tabulek:
* **Zdroj dat**: Definuje, kde se data nacházejí.
* **Objekt**: Popisuje objekt a odkazuje na DataSource.
* **Pole**: Vymezuje pole objektu a připojuje je k objektu.
Pro přidání vlastního objektu vyhledá člen pracovní skupiny rozhraní /metadata API. To aktualizuje metadata odpovídajícím způsobem a generuje GraphQL schéma na základě metadat, které se ukládá v GQL cache pro pozdější použití.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/server/add-custom-objects.jpeg" alt="Vyhledejte /metadata API pro přidání vlastních objektů" />
</div>
<br />
Pro načtení dat proces zahrnuje provádění dotazů přes /graphql endpoint a jejich předání přes Query Resolver.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/server/custom-object-schema.png" alt="Dotazujte se na /graphql endpoint pro načtení dat." />
</div>

View File

@@ -0,0 +1,46 @@
---
title: Příznaky funkcí
---
Příznaky funkcí slouží k skrytí zkušebních funkcí. Pro Twenty jsou nastaveny na úrovni pracovního prostoru, nikoli na úrovni uživatele.
## Přidání nového příznaku funkce
V `FeatureFlagKey.ts` přidat příznak funkce:
```ts
type FeatureFlagKey =
| 'IS_FEATURENAME_ENABLED'
| ...;
```
Také jej přidejte do výčtu v `feature-flag.entity.ts`:
```ts
enum FeatureFlagKeys {
IsFeatureNameEnabled = 'IS_FEATURENAME_ENABLED',
...
}
```
Pro uplatnění příznaku funkce na **backendové** funkci použijte:
```ts
@Gate({
featureFlag: 'IS_FEATURENAME_ENABLED',
})
```
Pro uplatnění příznaku funkce na **frontendové** funkci použijte:
```ts
const isFeatureNameEnabled = useIsFeatureEnabled('IS_FEATURENAME_ENABLED');
```
## Nakonfigurujte příznaky funkcí pro nasazení
Změnit odpovídající záznam v tabulce `core.featureFlag`:
| id | klíč | workspaceId | hodnota |
| ------- | ------------------- | ----------- | -------- |
| Náhodný | `IS_FUNKCEPOVOLENA` | WorkspaceID | `pravda` |

View File

@@ -0,0 +1,125 @@
---
title: Architektura složek
info: Podrobný pohled do struktury složek našeho serveru
---
Struktura adresářů backendu je následující:
```
server
└───ability
└───constants
└───core
└───database
└───decorators
└───filters
└───guards
└───health
└───integrations
└───metadata
└───workspace
└───utils
```
## Oprávnění
Definuje oprávnění a zahrnuje zpracovníky pro každou entitu.
## Dekorátory
Definuje vlastní dekorátory v NestJS pro přídavnou funkčnost.
Více podrobností naleznete ve [vlastních dekorátorech](https://docs.nestjs.com/custom-decorators).
## Filtry
Zahrnuje filtry výjimek k zpracování výjimek, které mohou nastat v koncových bodech GraphQL.
## Guards
Více podrobností naleznete ve [strážích](https://docs.nestjs.com/guards).
## Zdraví
Zahrnuje veřejně dostupné REST API (healthz), které vrací JSON k potvrzení, zda databáze funguje, jak se očekává.
## Metadata
Definuje vlastní objekty a poskytuje GraphQL API (graphql/metadata).
## Pracovní prostor
Generuje a poskytuje vlastní schéma GraphQL na základě metadat.
### Struktura adresáře pracovního prostoru
```
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
```
Kořen adresáře pracovního prostoru zahrnuje `workspace.factory.ts`, soubor obsahující funkci `createGraphQLSchema`. Tato funkce generuje specifická schémata pracovních prostorů pomocí metadat pro přizpůsobení schématu individuálním pracovním prostorům. Oddělením konstrukce schématu a resolveru používáme funkci `makeExecutableSchema`, která kombinuje tyto různé prvky.
Tato strategie neslouží pouze k organizaci, ale pomáhá i v optimalizaci, jako je ukládání vytvořených typových definic do mezipaměti pro zvýšení výkonu a škálovatelnosti.
### Builder schématu pracovního prostoru
Generuje schéma GraphQL a zahrnuje:
#### Továrny:
Specializované konstruktory pro generování konstrukcí souvisejících s GraphQL.
* type.factory překládá metadata pole do typů GraphQL pomocí `TypeMapperService`.
* type-definition.factory vytváří vstupní nebo výstupní grafové objekty odvozené z `objectMetadata`.
#### GraphQL typy
Zahrnuje výčty, vstupy, objekty a skaláry a slouží jako stavební bloky pro konstrukci schématu.
#### Rozhraní a objektové definice
Obsahuje plány pro GraphQL entity a zahrnuje jak předdefinované, tak vlastní typy jako `MONEY` nebo `URL`.
#### Služby
Obsahuje službu, která spojuje FieldMetadataType s odpovídajícími GraphQL skalárami nebo modifikátory dotazů.
#### Úložiště
Zahrnuje třídu `TypeDefinitionsStorage`, která obsahuje opakovaně použitelné definice typů, zabraňující duplikaci typů GraphQL.
### Builder resolveru pracovního prostoru
Vytváří funkce pro řešení dotazů a mutací v GraphQL schématu.
Každá továrna v tomto adresáři je zodpovědná za produkci specifického typu resolveru, jako je továrna `FindManyResolverFactory`, navržená pro adaptabilní aplikaci na různé tabulky.
### Runner dotazů pracovního prostoru
Spouští vygenerované dotazy na databázi a analyzuje výsledek.

View File

@@ -0,0 +1,41 @@
---
title: Fronta zpráv
---
Fronty usnadňují provádění asynchronních operací. Mohou být použity pro provádění úkolů na pozadí, jako je například zaslání uvítacího e-mailu při registraci.
Každý případ použití bude mít svou vlastní třídu fronty rozšířenou z `MessageQueueServiceBase`.
Aktuálně podporujeme pouze `bull-mq`[bull-mq](https://bullmq.io/) jako ovladač fronty.
## Kroky pro vytvoření a použití nové fronty
1. Přidejte název fronty pro vaši novou frontu pod výčtem `MESSAGE_QUEUES`.
2. Poskytněte implementaci továrny fronty s názvem fronty jako token závislosti.
3. Injektujte frontu, kterou jste vytvořili, do požadovaného modulu/služby s názvem fronty jako token závislosti.
4. Přidejte třídu pracovníka s injekcí založenou na tokenu stejně jako producent.
### Ukázkové použití
```ts
class Resolver {
constructor(@Inject(MESSAGE_QUEUES.custom) private queue: MessageQueueService) {}
async onSomeAction() {
//business logic
await this.queue.add(someData);
}
}
//async worker
class CustomWorker {
constructor(@Inject(MESSAGE_QUEUES.custom) private queue: MessageQueueService) {
this.initWorker();
}
async initWorker() {
await this.queue.work(async ({ id, data }) => {
//worker logic
});
}
}
```

View File

@@ -0,0 +1,87 @@
---
title: Příkazy backendu
icon: terminal
---
## Užitečné příkazy
Tyto příkazy by měly být vykonávány z adresáře packages/twenty-server.
Z jakéhokoli jiného adresáře můžete spustit `npx nx {command} twenty-server` (nebo `npx nx run twenty-server:{command}`).
### První nastavení
```
npx nx database:reset twenty-server # setup the database with dev seeds
```
### Spuštění serveru
```
npx nx run twenty-server:start
```
### Linter
```
npx nx run twenty-server:lint # pass --fix to fix lint errors
```
### Testovat
```
npx nx run twenty-server:test:unit # run unit tests
npx nx run twenty-server:test:integration # run integration tests
```
Poznámka: můžete spustit `npx nx run twenty-server:test:integration:with-db-reset`, pokud potřebujete před spuštěním integračních testů obnovit databázi.
### Obnovení databáze
Pokud chcete resetovat a naplnit databázi daty, můžete spustit následující příkaz:
```bash
npx nx run twenty-server:database:reset
```
### Migrace
#### Pro objekty ve schématech Core/Metadata (TypeORM)
```bash
npx nx run twenty-server:database:migrate:generate
```
## Technologický stack
Twenty primárně používá NestJS pro backend.
Prisma byl první ORM, který jsme použili. Ale aby uživatelé mohli vytvářet vlastní pole a vlastní objekty, dává větší smysl používat nižší úroveň, abychom mohli mít jemnou kontrolu. Projekt nyní používá TypeORM.
Takto nyní vypadá technologický stack.
**Jádro**
* [NestJS](https://nestjs.com/)
* [TypeORM](https://typeorm.io/)
* [GraphQL Yoga](https://the-guild.dev/graphql/yoga-server)
**Databáze**
* [Postgres](https://www.postgresql.org/)
**Integrace třetích stran**
* [Sentry](https://sentry.io/welcome/) pro sledování chyb
**Testování**
* [Jest](https://jestjs.io/)
**Nástroje**
* [Yarn](https://yarnpkg.com/)
* [Oxlint](https://oxc.rs/docs/guide/usage/linter.html)
**Vývoj**
* [AWS EKS](https://aws.amazon.com/eks/)

View File

@@ -0,0 +1,85 @@
---
title: Zapier App
---
Snadno synchronizujte Twenty s více než 3000 aplikacemi pomocí [Zapier](https://zapier.com/). Automatizujte úkoly, zvyšte produktivitu a zlepšete vztahy se zákazníky!
## O Zapier
Zapier je nástroj, který umožňuje automatizovat pracovní postupy připojením aplikací, které váš tým používá každý den. Základním konceptem Zapier je automatizace pracovních postupů, nazývaných Zaps, které zahrnují spouštěče a akce.
Více o tom, jak Zapier funguje, se dozvíte [zde](https://zapier.com/how-it-works).
## Nastavení
### Krok 1: Nainstalujte balíčky Zapier
```bash
cd packages/twenty-zapier
yarn
```
### Krok 2: Přihlaste se pomocí CLI
Použijte své Zapier přihlašovací údaje k přihlášení pomocí CLI:
```bash
zapier login
```
### Krok 3: Nastavte proměnné prostředí
Z adresáře `packages/twenty-zapier` spusťte:
```bash
cp .env.example .env
```
Spusťte aplikaci lokálně, přejděte na [http://localhost:3000/settings/api-webhooks](http://localhost:3000/settings/api-webhooks), a vygenerujte klíč API.
Nahraďte hodnotu **YOUR_API_KEY** v souboru `.env` klíčem API, který jste právě vygenerovali.
## Vývoj
<Warning>
Ujistěte se, že před jakýmkoli příkazem `zapier` spustíte `yarn build`.
</Warning>
### Testovat
```bash
yarn test
```
### Linter
```bash
yarn format
```
### Sledování a kompilace při úpravě kódu
```bash
yarn watch
```
### Ověřte svou aplikaci Zapier
```bash
yarn validate
```
### Nasazení vaší aplikace Zapier
```bash
yarn deploy
```
### Seznam všech příkazů Zapier CLI
```bash
zapier
```

View File

@@ -0,0 +1,79 @@
---
title: Hlášení chyb, požadavky a pull requesty
icon: bug
info: Nahlašujte problémy, žádejte o nové funkce a přispívejte kódem
---
## Nahlášení chyb
Chcete-li nahlásit chybu, prosím [vytvořte issue na GitHubu](https://github.com/twentyhq/twenty/issues/new).
O pomoc můžete také požádat na [Discordu](https://discord.gg/cx5n4Jzs57).
## Požadavky na funkce
Pokud si nejste jisti, zda se jedná o chybu, a máte pocit, že je to spíše žádost o funkci, pak byste pravděpodobně měli [otevřít diskuzi](https://github.com/twentyhq/twenty/discussions/new).
## Odešlete pull request
Přispívání kódem do Twenty začíná pull requestem (PR).
### Než začnete
1. Zkontrolujte [existující issues](https://github.com/twentyhq/twenty/issues) ohledně související práce
2. Pro nové funkce nejprve otevřete issue k diskusi
3. Prostudujte si náš [Kodex chování](https://github.com/twentyhq/twenty/blob/main/.github/CODE_OF_CONDUCT.md)
### Fork a klonování
1. Vytvořte fork repozitáře na GitHubu
2. Naklonujte svůj fork:
```bash
git clone https://github.com/YOUR_USERNAME/twenty.git
cd twenty
```
3. Přidejte vzdálený upstream:
```bash
git remote add upstream https://github.com/twentyhq/twenty.git
```
### Vytvoření větve
```bash
git checkout -b feature/your-feature-name
```
Používejte výstižné názvy větví:
* `feature/add-export-button`
* `fix/login-redirect-issue`
* `docs/update-api-guide`
### Proveďte změny
1. Pište čistý, dobře zdokumentovaný kód
2. Dodržujte stávající styl kódu
3. Přidejte testy pro novou funkcionalitu
4. Podle potřeby aktualizujte dokumentaci
### Odešlete svůj PR
1. Odešlete svou větev:
```bash
git push origin feature/your-feature-name
```
2. Otevřete PR na GitHubu
3. Vyplňte šablonu PR
4. Propojte související issues
### Kontrolní seznam PR
* [ ] Kód odpovídá projektovým zásadám stylu
* [ ] Testy procházejí lokálně
* [ ] Dokumentace je aktualizována
* [ ] Popis PR vysvětluje změny

View File

@@ -0,0 +1,329 @@
---
title: Osvědčené postupy
icon: star
---
Tento dokument popisuje osvědčené postupy, které byste měli dodržovat při práci na frontend.
## Správa stavu
React a Jotai zajišťují správu stavu v kódu.
### Použijte atomy Jotai k ukládání stavu
Je dobrým zvykem vytvořit tolik atomů, kolik potřebujete ke správě stavu.
<Warning>
Je lepší použít více atomů než se snažit být příliš stručný s prop drilling.
</Warning>
```tsx
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
export const myAtomState = createAtomState<string>({
key: 'myAtomState',
defaultValue: 'default value',
});
export const MyComponent = () => {
const [myAtom, setMyAtom] = useAtomState(myAtomState);
return (
<div>
<input
value={myAtom}
onChange={(e) => setMyAtom(e.target.value)}
/>
</div>
);
}
```
### Nepoužívejte `useRef` k ukládání stavu
Vyhněte se používání `useRef` k ukládání stavu.
Pokud chcete ukládat stav, měli byste použít `useState` nebo atomy Jotai s `useAtomState`.
Podívejte se, jak spravovat překreslení, pokud máte pocit, že potřebujete `useRef`, abyste zabránili některým překreslením.
## Správa překreslení
Překreslení může být obtížné spravovat v Reactu.
Zde jsou některá pravidla, která je třeba dodržovat, abyste se vyhnuli zbytečnému překreslování.
Pamatujte, že můžete **vždy** zabránit opakovanému renderování pochopením jejich příčiny.
### Pracujte na úrovni kořene
Vyhýbání se překreslení v nových funkcích je nyní snadné tím, že je eliminujete na úrovni kořene.
Komponenta "PageChangeEffect" obsahuje pouze jeden "useEffect", který drží veškerou logiku pro provedení změny stránky.
Tímto způsobem víte, že existuje pouze jedno místo, které může spustit překreslování.
### Vždy si dvakrát rozmyslete před přidáním `useEffect` do vaší kódové databáze
Opakované renderování jsou často způsobeny zbytečným `useEffect`.
Měli byste si myslet, zda potřebujete `useEffect`, nebo zda můžete přesunout logiku ve funkci obsluhy událostí.
Pro vás je obecně snadné přesunout logiku do funkce `handleClick` nebo `handleChange`.
Můžete je také najít v knihovnách jako Apollo: `onCompleted`, `onError` atd.
### Použij sourozeneckou komponentu k extrakci `useEffect` nebo logiky načítání dat
Pokud máte pocit, že potřebujete přidat `useEffect` do základní komponenty, měli byste zvážit její extrakci v postranním vozíku.
Stejný postup můžete aplikovat na logiku získávání dat pomocí Apollo hooks.
```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] = useAtomState(dataState);
const [someDependency] = useAtomState(someDependencyState);
useEffect(() => {
if(someDependency !== data) {
setData(someDependency);
}
}, [someDependency]);
return <div>{data}</div>;
};
export const App = () => (
<PageComponent />
);
```
```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] = useAtomState(dataState);
return <div>{data}</div>;
};
export const PageData = () => {
const [data, setData] = useAtomState(dataState);
const [someDependency] = useAtomState(someDependencyState);
useEffect(() => {
if(someDependency !== data) {
setData(someDependency);
}
}, [someDependency]);
return <></>;
};
export const App = () => (
<>
<PageData />
<PageComponent />
</>
);
```
### Použijte rodiny atomů a selektory
Rodiny atomů a selektory jsou skvělým způsobem, jak se vyhnout překreslování.
Jsou užitečné, když potřebujete uložit seznam položek.
### Neměli byste používat `React.memo(MyComponent)`
Vyhněte se používání `React.memo()`, protože to neřeší příčinu překreslování, ale spíše přeruší řetězec překreslování, což může vést k neočekávanému chování a ztěžuje refaktorování kódu.
### Omezit použití `useCallback` nebo `useMemo`
Často nejsou nutné a kód ztěžují na čtení a údržbu pro nepodstatné zlepšení výkonu.
## Console.logs
Příkazy `console.log` jsou hodnotné při vývoji, protože poskytují pohled na hodnoty proměnných a průběh kódu v reálném čase. Ale, zanechání v produkčním kódu může vést k několika problémům:
1. **Výkon**: Přílišné logování může ovlivnit výkon za běhu, zejména u aplikací na straně klienta.
2. **Bezpečnost**: Logování citlivých dat může vystavit kritické informace komukoliv, kdo nahlédne do konzole prohlížeče.
3. **Čistota**: Naplnění konzole logy může zatížit důležitá varování nebo chyby, které je třeba vidět.
4. **Profesionalita**: Koneční uživatelé nebo klienti kontrolující konzolu a vidící množství logovacích příkazů mohou zpochybnit kvalitu a úroveň kódu.
Ujistěte se, že odstraníte všechny `console.logs`, než uvedete kód do produkce.
## Pojmenovávání
### Pojmenování proměnných
Jména proměnných by měla přesně zobrazovat účel nebo funkci proměnné.
#### Problém s generickými jmény
Generická jména v programování nejsou ideální, protože postrádají specifikaci, což vede k nejednoznačnosti a snižuje čitelnost kódu. Taková jména neposkytnou informace o účelu proměnné nebo funkce, čímž ztěžují vývojářům pochopení záměru kódu bez hlubšího zkoumání. To může vést ke zvýšené době ladění, vyšší náchylnosti k chybám a obtížím při údržbě a spolupráci. Mezitím, použití popisných jmen činí kód samozřejmým a snadněji navigovatelným, čímž se zvyšuje jeho kvalita a produktivita vývojáře.
```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('');
```
#### Některá slova, kterým se vyhnout v názvech proměnných
* dummy
### Obsluhovače událostí
Jména obsluhovačů událostí by měla začínat `handle`, zatímco `on` je prefix používaný k pojmenování událostí v komponentech props.
```tsx
// ❌ Bad
const onEmailChange = (val: string) => {
// ...
};
```
```tsx
// ✅ Good
const handleEmailChange = (val: string) => {
// ...
};
```
## Volitelné props
Vyhněte se tomu, abyste pro volitelný props předávali výchozí hodnotu.
**PŘÍKLAD**
Vezměte komponent `EmailField` definovanou níže:
```tsx
type EmailFieldProps = {
value: string;
disabled?: boolean;
};
const EmailField = ({ value, disabled = false }: EmailFieldProps) => (
<TextInput value={value} disabled={disabled} fullWidth />
);
```
**Použití**
```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" />;
```
## Komponenta jako props
Pokuste se co nejvíce předávat neinstancované komponenty jako props, aby si děti mohly samy rozhodnout, které props potřebují předat.
Nejčastější příklad je komponenta ikon:
```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>
)
};
```
Aby React pochopil, že komponenta je komponenta, musíte použít PascalCase, aby později ji bylo možné instancovat pomocí `<MyIcon>`
## Prop Drilling: Udržujte to minimální
Prop drilling, v kontextu React, odkazuje na praktiku předávání stavových proměnných a jejich setterů skrze mnoho vrstev komponent, i když mezilehlé komponenty je nepoužívají. Zatímco občas je to nutné, přehnané prop drilling může vést k:
1. **Snížená čitelnost**: Sledování původu nebo využití vlastnosti může být komplikované ve složitě vnořených strukturách komponent.
2. **Problémy s údržbou**: Změny v struktuře vlastností jedné komponenty mohou vyžadovat úpravy v některých komponentech, i když tyto vlastnosti přímo nepoužívají.
3. **Snížená znovupoužitelnost komponentů**: Komponent přijímající mnoho props pouze pro jejich předání, se stává méně univerzálním a obtížněji použitelným v různých kontextech.
Pokud máte pocit, že používáte přílišné prop drilling, podívejte se na osvědčené postupy správy stavu.
## Importy
Při importu, upřednostněte určené aliasy před upřesňováním úplných či relativních cest.
**Aliasy**
```js
{
alias: {
"~": path.resolve(__dirname, "src"),
"@": path.resolve(__dirname, "src/modules"),
"@testing": path.resolve(__dirname, "src/testing"),
},
}
```
**Použití**
```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';
```
## Validace schématu
[Zod](https://github.com/colinhacks/zod) je validátor schémat pro netypová data:
```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>;
```
## Zlomové změny
Vždy proveďte důkladné manuální testování, abyste zajistili, že úpravy nezpůsobily problémy jinde, zejména pokud testy zatím nebyly široce integrovány.

View File

@@ -0,0 +1,110 @@
---
title: Architektura složek
icon: folder-tree
info: Podrobný pohled na naši architekturu složek
---
V tomto průvodci prozkoumáte detaily struktury projektového adresáře a jak přispívá k organizaci a udržovatelnosti Twenty.
Následováním této konvence architektury složek je snazší najít soubory související s konkrétními funkcemi a zajistit rozšiřitelnost a udržovatelnost aplikace.
```
front
└───modules
│ └───module1
│ │ └───submodule1
│ └───module2
│ └───ui
│ │ └───display
│ │ └───inputs
│ │ │ └───buttons
│ │ └───...
└───pages
└───...
```
## Stránky
Zahrnuje komponenty nejvyšší úrovně definované aplikačními trasami. Importují více nízkoúrovňových komponent ze složky modulů (více podrobností níže).
## Moduly
Každý modul představuje funkci nebo skupinu funkcí s jejich specifickými komponenty, stavy a provozní logikou.
Všechny by měly dodržovat strukturu níže. Moduly můžete vnořovat do sebe (tzv. podmoduly) a platí pro ně stejná pravidla.
```
module1
└───components
│ └───component1
│ └───component2
└───constants
└───contexts
└───graphql
│ └───fragments
│ └───queries
│ └───mutations
└───hooks
│ └───internal
└───states
│ └───selectors
└───types
└───utils
```
### Kontexty
Kontext je způsob, jak předávat data skrz strom komponent, aniž by se musely na každé úrovni ručně předávat props.
Více podrobností naleznete v [React Context](https://react.dev/reference/react#context-hooks).
### GraphQL
Zahrnuje fragmenty, dotazy a mutace.
Více podrobností naleznete v [GraphQL](https://graphql.org/learn/).
* Fragmenty
Fragment je znovupoužitelný kus dotazu, který můžete použít na různých místech. Pomocí fragmentů je snazší vyhnout se duplikaci kódu.
Více podrobností naleznete v [GraphQL Fragments](https://graphql.org/learn/queries/#fragments).
* Dotazy
Více podrobností naleznete v [GraphQL Queries](https://graphql.org/learn/queries/).
* Mutace
Více podrobností naleznete v [GraphQL Mutations](https://graphql.org/learn/queries/#mutations).
### Hooky
Více podrobností naleznete v [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks).
### Stavy
Obsahuje logiku správy stavů. To řeší [Jotai](https://jotai.org).
* Selektory: Odvozené atomy (pomocí `createAtomSelector`) odvozují hodnoty z jiných atomů a jsou automaticky memoizovány.
Vestavěná správa stavů v Reactu stále spravuje stav uvnitř komponenty.
### Pomocné funkce
Měly by obsahovat pouze znovupoužitelné čisté funkce. V opačném případě vytvořte vlastní hooky ve složce `hooks`.
## UI
Obsahuje všechny znovupoužitelné komponenty UI použité v aplikaci.
Tato složka může obsahovat podsložky, jako jsou `data`, `display`, `feedback` a `input` pro specifické typy komponent. Každá komponenta by měla být samostatná a znovupoužitelná, takže ji můžete použít v různých částech aplikace.
Oddělením komponent UI od ostatních komponent ve složce `modules` je snazší udržovat konzistentní design a provádět změny v rozhraní, aniž by to ovlivnilo jiné části (obchodní logiku) kódové základny.
## Rozhraní a závislosti
Můžete importovat kód jiných modulů z jakéhokoliv modulu kromě složky `ui`. Díky tomu zůstane jeho kód snadno testovatelný.
### Interní
Každá část (hooky, stavy, ...) modulu může mít složku `internal`, která obsahuje části používané pouze v rámci modulu.

View File

@@ -0,0 +1,91 @@
---
title: Příkazy Frontend
icon: terminal
---
## Užitečné příkazy
### Spuštění aplikace
```bash
npx nx start twenty-front
```
### Regenerujte schéma GraphQL na základě API graphql schématu
```bash
npx nx run twenty-front:graphql:generate --configuration=metadata
```
NEBO
```bash
npx nx run twenty-front:graphql:generate
```
### Linter
```bash
npx nx run twenty-front:lint # pass --fix to fix lint errors
```
## Překlady
```bash
npx nx run twenty-front:lingui:extract
npx nx run twenty-front:lingui:compile
```
### Testovat
```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)
```
## Technologický stack
Projekt má čistý a jednoduchý stack s minimálním počtem šablonových kódů.
**Aplikace**
* [React](https://react.dev/)
* [Apollo](https://www.apollographql.com/docs/)
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
* [Jotai](https://jotai.org/)
* [TypeScript](https://www.typescriptlang.org/)
**Testování**
* [Jest](https://jestjs.io/)
* [Storybook](https://storybook.js.org/)
**Nástroje**
* [Yarn](https://yarnpkg.com/)
* [Craco](https://craco.js.org/docs/)
* [Oxlint](https://oxc.rs/docs/guide/usage/linter.html)
## Architektura
### Směrování
[React Router](https://reactrouter.com/) zajišťuje směrování.
Aby se předešlo zbytečné [re-renders](/l/cs/developers/contribute/capabilities/frontend-development/best-practices-front#managing-re-renders) ) je všechna směrovací logika v `useEffect` v `PageChangeEffect`.
### Správa stavu
[Jotai](https://jotai.org/) zajišťuje správu stavu.
Podívejte se na [osvědčené postupy](/l/cs/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) pro více informací o správě stavu.
## Testování
[Jest](https://jestjs.io/) slouží jako nástroj pro testování jednotek, zatímco [Storybook](https://storybook.js.org/) je pro testování komponent.
Jest je primárně určen pro testování pomocných funkcí, nikoli samotných komponent.
Storybook slouží k testování chování izolovaných komponent, stejně jako k zobrazování návrhového systému.

View File

@@ -0,0 +1,178 @@
---
title: Klávesové zkratky
---
## Úvod
Pokud potřebujete poslouchat klávesovou zkratku, obvykle použijete posluchač událostí `onKeyDown`.
Ve `twenty-front` však můžete mít konflikty mezi stejnými klávesovými zkratkami, které jsou použity v různých komponentách, nasazených současně.
Například, pokud máte stránku, která poslouchá klávesu Enter, a modal, který poslouchá klávesu Enter, s komponentou Select uvnitř tohoto modalu, která poslouchá klávesu Enter, můžete mít konflikt, když jsou všechny nasazeny současně.
## Funkce hook `useScopedHotkeys`
K řešení tohoto problému máme vlastní hook, který umožňuje poslouchat klávesové zkratky bez jakéhokoliv konfliktu.
Umístíte ho do komponenty a bude poslouchat klávesové zkratky pouze když je komponenta nasazena A když je aktivní specifikovaný **hotkey scope**.
## Jak v praxi poslouchat klávesové zkratky?
Jsou potřebné dva kroky k nastavení poslouchání klávesových zkratek :
1. Nastavte [hotkey scope](#what-is-a-hotkey-scope-), který bude poslouchat klávesové zkratky
2. Použijte hook `useScopedHotkeys` k poslouchání klávesových zkratek
Nastavení oblastí klávesových zkratek je potřebné i na jednoduchých stránkách, protože jiné UI prvky jako levé menu nebo příkazové menu mohou také poslouchat klávesové zkratky.
## Použití klávesových zkratek
Obecně budete mít dva případy použití, které vyžadují klávesové zkratky :
1. Na stránce nebo v komponentě nasazené na stránce
2. V komponentě typu modal, která přebírá fokus kvůli akci uživatele
Druhý případ použití se může stát rekurzivně: například rozbalovací seznam v modalu.
### Poslouchání klávesových zkratek na stránce
Příklad :
```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>;
};
```
### Poslouchání klávesových zkratek v komponentě typu modal
V tomto příkladu použijeme komponentu typu modal, která poslouchá klávesu Escape, aby svému nadřazenému komponentu řekla, že se má zavřít.
Zde interakce uživatele mění rozsah.
```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>;
};
```
Pak v komponentě modalu :
```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>;
};
```
Je důležité použít tento vzor, když si nejste jisti, že pouhé použití useEffect s připojením/odpojením bude stačit k tomu, aby se předešlo konfliktům.
Tyto konflikty mohou být těžko laditelné a může se to stát častěji než s useEffects.
## Co je to hotkey scope?
Rozsah klávesových zkratek je řetězec, který představuje kontext, ve kterém jsou klávesové zkratky aktivní. Obecně je kódován jako enum.
Když změníte rozsah klávesových zkratek, klávesové zkratky, které poslouchají tento rozsah, budou povolené a klávesové zkratky, které poslouchají jiné rozsahy, budou zakázané.
Můžete nastavit pouze jeden rozsah najednou.
Například rozsahy klávesových zkratek pro každou stránku jsou definovány v `PageHotkeyScope` enumu:
```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',
}
```
Interně je aktuálně vybraný rozsah uložen v Jotai atomu, který je sdílen napříč aplikací :
```tsx
export const currentHotkeyScopeState = createState<HotkeyScope>({
key: 'currentHotkeyScopeState',
defaultValue: INITIAL_HOTKEYS_SCOPE,
});
```
Ale tento atom by se nikdy neměl spravovat ručně ! Ukážeme si, jak jej používat v příští sekci.
## Jak to funguje interně?
Vytvořili jsme tenkou vrstvu nad [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro), která je výkonnější a vyhýbá se zbytečným překreslením.
Také vytváříme Jotai atom, abychom mohli řídit stav rozsahu klávesových zkratek a učinit jej dostupným kdekoli v aplikaci.

View File

@@ -0,0 +1,8 @@
---
title: Storybook
description: Prozkoumejte knihovnu komponent UI na Twenty
---
Prohlédněte si naši kompletní knihovnu komponent a dokumentaci ve Storybooku.
[Otevřít Storybook →](https://storybook.twenty.com)

View File

@@ -0,0 +1,291 @@
---
title: Stylová příručka
icon: paintbrush
---
Tento dokument obsahuje pravidla pro psaní kódu.
Cílem zde je mít konzistentní kódovou základnu, která je snadno čitelná a snadno udržovatelná.
Pro toto je lepší být trochu více rozvláčný než být příliš stručný.
Vždy mějte na paměti, že lidé čtou kód častěji než ho píší, zejména u projektu s otevřeným zdrojovým kódem, kde může kdokoli přispět.
Existuje mnoho pravidel, která zde nejsou definována, ale která jsou automaticky kontrolována lintery.
## React
### Používejte funkcionální komponenty
Vždy používejte funkcionální komponenty TSX.
Nepoužívejte implicitní `import` s `const`, protože je obtížnější číst a importovat s automatickým dokončováním kódu.
```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>;
};
```
### Vlastnosti
Vytvořte typ rekvizit a pojmenujte jej `(ComponentName)Props`, pokud není potřeba jej exportovat.
Použijte destrukturalizaci rekvizit.
```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>;
```
#### Upusťte od používání `React.FC` nebo `React.FunctionComponent` k definování typů rekvizit
```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 />
);
```
#### Nepoužívejte rozbalení jediného objektu rekvizit v prvcích JSX
Vyhněte se používání rozbalení jediného objektu rekvizit v prvcích JSX, například `{...props}`. Tato praxe často vede k tomu, že kód je méně čitelný a obtížnější udržovat, protože není jasné, které rekvizity komponenta přijímá.
```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 }} />;
};
```
Odůvodnění:
* Na první pohled je jasné, které prop kód předává, čímž je snazší pochopit a udržovat.
* Pomáhá to předcházet těsnému provázání mezi komponentami prostřednictvím jejich rekvizit.
* Lintovací nástroje usnadňují identifikaci překlepů nebo nepoužívaných rekvizit, když rekvizity uvádíte explicitně.
## JavaScript
### Používejte operátor nullish-coalescing `??`
```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';
```
### Používejte volitelné zřetězení `?.`
```tsx
// ❌ Bad
onClick && onClick();
// ✅ Good
onClick?.();
```
## TypeScript
### Používejte `type` místo `interface`
Vždy používejte `type` místo `interface`, protože se téměř vždy překrývají a `type` je flexibilnější.
```tsx
// ❌ Bad
interface MyInterface {
name: string;
}
// ✅ Good
type MyType = {
name: string;
};
```
### Používejte textové literály místo výčtů
[Textové literály](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) jsou preferovaný způsob pro zpracování hodnot podobných výčtům v TypeScriptu. Snadněji se rozšiřují pomocí Pick a Omit a nabízejí lepší vývojářskou zkušenost, zejména s automatickým dokončováním kódu.
Proč TypeScript doporučuje vyhnout se výčtům zjistíte [zde](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 a interní knihovny
Měli byste používat výčty, které generuje kód generátor GraphQL.
Je také lepší používat výčet při používání interní knihovny, aby interní knihovna nemusela vystavovat textový typ neusouvisející s interním API.
Příklad:
```TSX
const {
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
setHotkeyScopeAndMemorizePreviousScope(
RelationPickerHotkeyScope.RelationPicker,
);
```
## Styling
### Používejte StyledComponents
Stylujte komponenty pomocí [Linaria styled](https://github.com/callstack/linaria).
```tsx
// ❌ Bad
<div className="my-class">Hello World</div>
```
```tsx
// ✅ Good
const StyledTitle = styled.div`
color: red;
`;
```
Prefixujte stylizované komponenty "Styled", abyste je odlišili od "skutečných" komponent.
```tsx
// ❌ Bad
const Title = styled.div`
color: red;
`;
```
```tsx
// ✅ Good
const StyledTitle = styled.div`
color: red;
`;
```
### Theming
Využití tématu pro většinu stylování komponent je preferovaný přístup.
#### Jednotky měření
Vyhýbejte se používání hodnot `px` nebo `rem` přímo ve stylizovaných komponentách. Potřebné hodnoty jsou obvykle již definovány v tématu, takže se doporučuje využívat je pro tyto účely.
#### Barvy
Zdržte se zavádění nových barev; místo toho použijte existující paletu z tématu. Pokud by došlo k tomu, že paleta neodpovídá, prosím nechte komentář, aby to tým mohl napravit.
```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};
`;
```
## Prosazování Zákazu Importů Typů
Vyhýbejte se typovým importům. K prosazení tohoto standardu pravidlo Oxlint kontroluje a hlásí jakékoli typové importy. To pomáhá udržovat konzistenci a čitelnost v TypeScript kódu.
```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';
```
### Proč Zákaz Importů Typů
* **Konzistence**: Vyhýbáním se importům typů a použitím jednotného přístupu pro importy typů i hodnot zůstává kódová základna konzistentní ve svém stylu importů modulů.
* **Čitelnost**: Importy bez type zlepšují čitelnost kódu tím, že je jasné, zda importujete hodnoty nebo typy. Tím se snižuje dvojznačnost a usnadňuje pochopení účelu importovaných symbolů.
* **Udržovatelnost**: Zvyšuje udržovatelnost kódové základny, protože vývojáři mohou při revizi nebo úpravách kódu identifikovat a najít importy pouze typů.
### Pravidlo Oxlint
Pravidlo Oxlint, `typescript/consistent-type-imports`, prosazuje standard zákazu importů typů. Toto pravidlo generuje chyby nebo varování pro jakékoli porušení typového importu.
Upozorňujeme, že toto pravidlo konkrétně řeší vzácné okrajové případy, kdy dochází k neúmyslným typovým importům. TypeScript sám odrazuje tuto praxi, jak je uvedeno v [poznámkách k verzi TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). Ve většině případů byste neměli potřebovat používat pouze typové importy.
Aby váš kód splňoval toto pravidlo, spusťte Oxlint jako součást svého vývojového pracovního postupu.

View File

@@ -0,0 +1,61 @@
---
title: Práce s Figma
info: Zjistěte, jak můžete spolupracovat s Figmou Twenty
---
Figma je nástroj pro návrh uživatelského rozhraní, který pomáhá překlenout komunikační bariéru mezi návrháři a vývojáři.
Tento průvodce vysvětluje, jak můžete spolupracovat s Figma.
## Přístup
1. **Přístup ke sdílenému odkazu:** K Figma souboru projektu můžete přistoupit [zde](https://www.figma.com/file/xt8O9mFeLl46C5InWwoMrN/Twenty).
2. **Přihlásit se:** Pokud ještě nejste přihlášeni, Figma vás k tomu vyzve.
Klíčové funkce jsou dostupné pouze přihlášeným uživatelům, jako je režim pro vývojáře a možnost výběru dedikovaného rámce.
<Warning>
Nebudete moci účinně spolupracovat bez účtu.
</Warning>
## Struktura Figma
Na levém postranním panelu můžete přistupovat k různým stránkám Figmy společnosti Twenty. Takto jsou organizovány:
* **Stránka komponentů:** Toto je první stránka. Návrhář ji používá k vytváření a organizování znovupoužitelných návrhových prvků použitých v celém návrhovém souboru. Například tlačítka, ikony, symboly nebo jakékoli jiné znovupoužitelné komponenty. Slouží k zajištění konzistence v celém návrhu.
* **Hlavní stránka:** Druhá stránka je hlavní stránka, která zobrazuje kompletní uživatelské rozhraní projektu. Můžete stisknout **"Přehrát"**, abyste použili kompletní prototyp aplikace.
* **Stránky funkcí:** Ostatní stránky jsou obvykle věnovány funkcím ve vývoji. Obsahují návrh specifických funkcí nebo modulů aplikace či webu. Typicky se stále vyvíjejí.
## Užitečné tipy
S přístupem pouze pro čtení nemůžete návrh upravovat, ale máte přístup ke všem funkcím užitečným pro přeměnu návrhu na kód.
### Použití režimu pro vývojáře
Dev Mode Figma zvyšuje produktivitu vývojářů díky snadné navigaci designem, efektivnímu spravování prvků, efektivním komunikačním nástrojům, integracím do nástrojů, rychlým částem kódu a klíčovým informacím o vrstvě, čímž překonává mezeru mezi návrhem a vývojem. O Dev Mode se můžete dozvědět více [zde](https://www.figma.com/dev-mode/).
Přepněte na režim „Vývojář“ v pravé části nástrojové lišty, kde si můžete prohlédnout specifikace návrhu, kopírovat CSS a přistupovat k prvkům.
### Použití prototypu
Klikněte na libovolný prvek na plátně a stiskněte tlačítko „Přehrát“ v pravém horním rohu rozhraní k zobrazení prototypu. Režim prototypu vám umožňuje interakci s návrhem, jakoby to byl finální produkt. Ukazuje tok mezi obrazovkami a jak se prvky uživatelského rozhraní jako tlačítka, odkazy nebo menu chovají při interakci.
1. **Pochopení přechodů a animací:** V prototypovém režimu můžete vidět libovolné přechody nebo animace, které návrhář přidal mezi obrazovky nebo prvky UI, což poskytuje jasné vizuální instrukce vývojářům o zamýšleném chování a stylu.
2. **Objasnění implementace:** Prototyp může také pomoci snížit nejasnosti. Vývojáři s ním mohou interagovat pro lepší pochopení funkčnosti či vzhledu konkrétních prvků.
Pro podrobnější detaily a pokyny k Figma platformě můžete navštívit oficiální [Figma Documentation](https://help.figma.com/hc/en-us).
### Měření vzdálenosti
Vyberte prvek, podržte klávesu `Option` (Mac) nebo `Alt` (Windows) a pak přejeďte kurzorem nad jiným prvkem, abyste viděli vzdálenost mezi nimi.
### Rozšíření Figma pro VSCode (doporučeno)
[Figma pro VS Code](https://marketplace.visualstudio.com/items?itemName=figma.figma-vscode-extension)
vám umožňuje procházet a zkoumat návrhové soubory, spolupracovat s návrháři, sledovat změny a zrychlit implementaci – vše bez opuštění vašeho textového editoru.
Je součástí našich doporučených rozšíření.
## Spolupráce
1. **Použití komentářů:** Jste vítáni použít funkci komentářů kliknutím na bublinu vlevo na nástrojové liště.
2. **Rozhovor prostřednictvím kurzoru:** Hezkou funkcí Figma je Rozhovor prostřednictvím kurzoru. Stačí stisknout `;` na Macu a `/` ve Windows a odeslat zprávu, pokud vidíte, že někdo jiný používá Figma současně s vámi.

View File

@@ -0,0 +1,317 @@
---
title: Místní nastavení
icon: laptop-code
description: Průvodce pro přispěvatele (nebo zvídavé vývojáře), kteří chtějí spustit Twenty lokálně.
---
## Předpoklady
<Tabs>
<Tab title="Linux a macOS">
Než nainstalujete a použijete Twenty, ujistěte se, že máte na svém počítači nainstalovány následující balíčky:
* [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* [Node v24.5.0](https://nodejs.org/en/download)
* [yarn v4](https://yarnpkg.com/getting-started/install)
* [nvm](https://github.com/nvm-sh/nvm/blob/master/README.md)
<Warning>
`npm` nebude fungovat, měli byste místo něj použít `yarn`. Yarn je nyní součástí Node.js, takže jej nemusíte instalovat samostatně.
Musíte pouze spustit `corepack enable`, abyste povolili Yarn, pokud jste to ještě neudělali.
</Warning>
</Tab>
<Tab title="Windows (WSL)">
1. Nainstalujte WSL
Otevřete PowerShell jako správce a spusťte:
```powershell
wsl --install
```
Nyní byste měli vidět výzvu k restartování počítače. Pokud ne, restartujte jej ručně.
Při restartu se otevře okno PowerShellu a nainstaluje Ubuntu. Tento proces může chvíli trvat.
Zobrazí se výzva k vytvoření uživatelského jména a hesla pro vaši instalaci Ubuntu.
2. Nainstalujte a nastavte git
```bash
sudo apt-get install git
git config --global user.name "Your Name"
git config --global user.email "youremail@domain.com"
```
3. Nainstalujte nvm, node.js a yarn
<Warning>
Použijte `nvm` pro instalaci správné verze `node`. `nvmrc` zajišťuje, že všichni přispěvatelé používají stejnou verzi.
</Warning>
```bash
sudo apt-get install curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
```
Zavřete a znovu otevřete terminál, abyste použili nvm. Potom spusťte následující příkazy.
```bash
nvm install # installs recommended node version
nvm use # use recommended node version
corepack enable
```
</Tab>
</Tabs>
---
## Krok 1: Git Clone
V terminálu spusťte následující příkaz.
<Tabs>
<Tab title="SSH (Doporučeno)">
Pokud jste ještě nenastavili SSH klíče, můžete se naučit, jak to udělat, [zde](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/about-ssh).
```bash
git clone git@github.com:twentyhq/twenty.git
```
</Tab>
<Tab title="HTTPS">
```bash
git clone https://github.com/twentyhq/twenty.git
```
</Tab>
</Tabs>
## Krok 2: Umístěte se na kořen
```bash
cd twenty
```
Všechny příkazy v následujících krocích byste měli provádět z kořene projektu.
## Krok 3: Nastavení PostgreSQL databáze
<Tabs>
<Tab title="Linux">
**Možnost 1 (doporučeno):** Pro lokální vytvoření databáze:
Použijte následující odkaz pro instalaci PostgreSQL na vašem linuxovém stroji: [Instalace PostgreSQL](https://www.postgresql.org/download/linux/)
```bash
psql postgres -c "CREATE DATABASE \"default\";" -c "CREATE DATABASE test;"
```
Poznámka: Možná budete potřebovat přidat `sudo -u postgres` k příkazu před `psql`, abyste předešli chybám s oprávněními.
**Možnost 2:** Pokud máte nainstalován docker:
```bash
make -C packages/twenty-docker postgres-on-docker
```
</Tab>
<Tab title="Mac OS">
**Možnost 1 (doporučeno):** Pro lokalní vytvoření databáze pomocí `brew`:
```bash
brew install postgresql@16
export PATH="/opt/homebrew/opt/postgresql@16/bin:$PATH"
brew services start postgresql@16
psql postgres -c "CREATE DATABASE \"default\";" -c "CREATE DATABASE test;"
```
Můžete zjistit, zda PostgreSQL server běží, spuštěním:
```bash
brew services list
```
Instalátor nemusí ve výchozím nastavení vytvořit uživatele `postgres` při instalaci
přes Homebrew na macOS. Místo toho vytvoří PostgreSQL roli, která odpovídá vašemu uživatelskému jménu v MacOS (např. "john").
Pro zkontrolování a vytvoření uživatele `postgres`, pokud je to nutné, postupujte takto:
```bash
# Connect to PostgreSQL
psql postgres
or
psql -U $(whoami) -d postgres
```
Po zobrazení výzvy psql (postgres=#) spusťte:
```bash
# List existing PostgreSQL roles
\du
```
Zobrazí se výstup podobný tomuto:
```bash
Role name | Attributes | Member of
-----------+-------------+-----------
john | Superuser | {}
```
Pokud nevidíte roli `postgres`, pokračujte na další krok.
Vytvořte uživatelskou roli `postgres` ručně:
```bash
CREATE ROLE postgres WITH SUPERUSER LOGIN;
```
Tím vytvoříte superuživatelskou roli pojmenovanou `postgres` s přístupovými právy.
```bash
Role name | Attributes | Member of
-----------+-------------+-----------
postgres | Superuser | {}
john | Superuser | {}
```
**Možnost 2:** Pokud máte nainstalován docker:
```bash
make -C packages/twenty-docker postgres-on-docker
```
</Tab>
<Tab title="Windows (WSL)">
Všechny následující kroky je třeba provádět v terminálu WSL (v rámci vaší virtuálního stroje).
**Možnost 1:** Pro lokální zprovoznění PostgreSQL:
Použijte následující odkaz pro instalaci PostgreSQL na vašem linuxovém virtuálním stroji: [Instalace PostgreSQL](https://www.postgresql.org/download/linux/)
```bash
psql postgres -c "CREATE DATABASE \"default\";" -c "CREATE DATABASE test;"
```
Poznámka: Možná budete potřebovat přidat `sudo -u postgres` k příkazu před `psql`, abyste předešli chybám s oprávněními.
**Možnost 2:** Pokud máte nainstalován docker:
Používání Dockeru na WSL přidává další vrstvu složitosti.
Použijte tuto možnost pouze pokud si jste jisti extra kroky včetně zapnutí [Docker Desktop WSL2](https://docs.docker.com/desktop/wsl).
```bash
make -C packages/twenty-docker postgres-on-docker
```
</Tab>
</Tabs>
Nyní můžete přistupovat k databázi na adrese `localhost:5432`.
Pokud jste použili výše uvedenou možnost Dockeru, výchozí přihlašovací údaje jsou uživatelské jméno `postgres` a heslo `postgres`. U nativních instalací PostgreSQL použijte přihlašovací údaje a role nakonfigurované na vašem počítači.
## Krok 4: Nastavení Redis databáze (cache)
Twenty vyžaduje ke svému provozu Redis cache pro zajištění nejlepšího výkonu.
<Tabs>
<Tab title="Linux">
**Možnost 1:** Pro lokalní vytvoření Redis:
Použijte následující odkaz pro instalaci Redis na vašem Linuxovém stroji: [Instalace Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/)
**Možnost 2:** Pokud máte nainstalován docker:
```bash
make -C packages/twenty-docker redis-on-docker
```
</Tab>
<Tab title="Mac OS">
**Možnost 1 (doporučeno):** Pro lokalní vytvoření Redis pomocí `brew`:
```bash
brew install redis
```
Spusťte svůj server Redis:
```bash
brew services start redis
```
**Možnost 2:** Pokud máte nainstalován docker:
```bash
make -C packages/twenty-docker redis-on-docker
```
</Tab>
<Tab title="Windows (WSL)">
**Možnost 1:** Pro lokalní vytvoření Redis:
Použijte následující odkaz pro instalaci Redis na vašem Linuxovém virtuálním stroji: [Instalace Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/)
**Možnost 2:** Pokud máte nainstalován docker:
```bash
make -C packages/twenty-docker redis-on-docker
```
</Tab>
</Tabs>
Pokud potřebujete GUI klienta, doporučujeme [Redis Insight](https://redis.io/insight/) (k dispozici je bezplatná verze).
## Krok 5: Nastavení proměnných prostředí
Použijte proměnné prostředí nebo `.env` soubory, abyste nakonfigurovali váš projekt. Více informací [zde](/l/cs/developers/self-host/capabilities/setup).
Zkopírujte soubory `.env.example` v `/front` a `/server`:
```bash
cp ./packages/twenty-front/.env.example ./packages/twenty-front/.env
cp ./packages/twenty-server/.env.example ./packages/twenty-server/.env
```
<Info>
**Režim více pracovních prostorů:** Ve výchozím nastavení běží Twenty v režimu jednoho pracovního prostoru, ve kterém lze vytvořit pouze jeden pracovní prostor. Chcete-li povolit podporu více pracovních prostorů (užitečné pro testování funkcí založených na subdoménách), nastavte v serverovém souboru `.env` hodnotu `IS_MULTIWORKSPACE_ENABLED=true`. Podrobnosti viz [Režim více pracovních prostorů](/l/cs/developers/self-host/capabilities/setup#multi-workspace-mode).
</Info>
## Krok 6: Instalace závislostí
Pro sestavení Twenty serveru a zavedení některých dat do vaší databáze spusťte následující příkaz:
```bash
yarn
```
Všimněte si, že `npm` nebo `pnpm` nebudou fungovat.
## Krok 7: Spuštění projektu
<Tabs>
<Tab title="Linux">
V závislosti na vaší Linuxové distribuci mohl být Redis server spuštěn automaticky.
Pokud ne, zkontrolujte [instalační průvodce Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) pro vaši distribuci.
</Tab>
<Tab title="Mac OS">
Redis by již měl být spuštěn. Pokud ne, spusťte:
```bash
brew services start redis
```
</Tab>
<Tab title="Windows (WSL)">
V závislosti na vaší Linuxové distribuci mohl být Redis server spuštěn automaticky.
Pokud ne, zkontrolujte [instalační průvodce Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) pro vaši distribuci.
</Tab>
</Tabs>
Nastavte svou databázi pomocí následujícího příkazu:
```bash
npx nx database:reset twenty-server
```
Spusťte server, pracovní proces a frontendové služby:
```bash
npx nx start twenty-server
npx nx worker twenty-server
npx nx start twenty-front
```
Alternativně můžete spustit všechny služby najednou:
```bash
npx nx start
```
## Krok 8: Použijte Twenty
**Frontend**
Frontend Twenty bude spuštěný na [http://localhost:3001](http://localhost:3001).
Můžete se přihlásit pomocí výchozího demo účtu: `tim@apple.dev` (heslo: `tim@apple.dev`)
**Backend**
* Server Twenty poběží na [http://localhost:3000](http://localhost:3000)
* K GraphQL API se dostanete na [http://localhost:3000/graphql](http://localhost:3000/graphql)
* K REST API je přístup na [http://localhost:3000/rest](http://localhost:3000/rest)
## Řešení potíží
Pokud narazíte na jakýkoli problém, zkontrolujte sekci [Řešení potíží](/l/cs/developers/self-host/capabilities/troubleshooting) pro možná řešení.