ebee7d71b9
Created by Github action <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22715?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> Co-authored-by: github-actions <github-actions@twenty.com>
626 lines
28 KiB
Plaintext
626 lines
28 KiB
Plaintext
---
|
||
title: Ön uç bileşenleri
|
||
description: Twenty'nin UI'si içinde, korumalı alan (sandbox) izolasyonu ile görüntülenen React bileşenleri oluşturun.
|
||
icon: window-maximize
|
||
---
|
||
|
||
Ön uç bileşenler, Twenty'nin UI'si içinde doğrudan görüntülenen React bileşenleridir. Remote DOM kullanan izole bir Web Worker içinde çalışırlar — kodunuz izole bir ortamda (sandbox) çalışır ancak bir iframe içinde değil, sayfada yerel olarak işlenir.
|
||
|
||
## Ön uç bileşenlerinin kullanılabileceği yerler
|
||
|
||
Ön uç bileşenler, Twenty içinde iki konumda işlenebilir:
|
||
|
||
* **Yan panel** — Headless olmayan ön uç bileşenler, sağ taraftaki yan panelde açılır. Bir ön uç bileşeni komut menüsünden tetiklendiğinde varsayılan davranış budur.
|
||
* **Widget'lar (panolar ve kayıt sayfaları)** — Ön uç bileşenler, [sayfa düzenleri](/l/tr/developers/extend/apps/layout/page-layouts) içinde widget olarak gömülebilir. Bir pano veya kayıt sayfası düzeni yapılandırılırken kullanıcılar bir ön uç bileşen widget'ı ekleyebilir.
|
||
|
||
Tek başına bir ön uç bileşenine kullanıcı arayüzünden erişilemez — onu görünür hâle getirmeniz gerekir. Bunu yapmanın iki yolu vardır:
|
||
|
||
* **Onu bir [komut menüsü öğesi](/l/tr/developers/extend/apps/layout/command-menu-items) ile eşleştirin** — komut menüsüne (Cmd+K) ve isteğe bağlı olarak sabitlenmiş hızlı işlem olarak kaydeder.
|
||
* **Onu bir [sayfa düzeni](/l/tr/developers/extend/apps/layout/page-layouts) içinde widget olarak gömün** — bir kaydın ayrıntı sayfasına veya panosuna yerleştirir.
|
||
|
||
## Basit örnek
|
||
|
||
Bir ön uç bileşenini çalışır halde görmenin en hızlı yolu, onu [`defineCommandMenuItem`](/l/tr/developers/extend/apps/layout/command-menu-items) ile eşleştirmektir; böylece sayfanın sağ üst köşesinde bir hızlı işlem düğmesi olarak görünür:
|
||
|
||
```tsx src/front-components/hello-world.tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
|
||
const HelloWorld = () => {
|
||
return (
|
||
<div style={{ padding: '20px', fontFamily: 'sans-serif' }}>
|
||
<h1>Hello from my app!</h1>
|
||
<p>This component renders inside Twenty.</p>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: '74c526eb-cb68-4cf7-b05c-0dd8c288d948',
|
||
name: 'hello-world',
|
||
description: 'A simple front component',
|
||
component: HelloWorld,
|
||
});
|
||
```
|
||
|
||
```ts src/command-menu-items/hello-world.command-menu-item.ts
|
||
import { defineCommandMenuItem } from 'twenty-sdk/define';
|
||
|
||
export default defineCommandMenuItem({
|
||
universalIdentifier: 'd4e5f6a7-b8c9-0123-defa-456789012345',
|
||
shortLabel: 'Hello',
|
||
label: 'Hello World',
|
||
isPinned: true,
|
||
availabilityType: 'GLOBAL',
|
||
frontComponentUniversalIdentifier: '74c526eb-cb68-4cf7-b05c-0dd8c288d948',
|
||
});
|
||
```
|
||
|
||
`yarn twenty dev` ile senkronize ettikten sonra (veya tek seferlik bir `yarn twenty apply` çalıştırdıktan sonra), hızlı işlem sayfanın sağ üst köşesinde görünür:
|
||
|
||
<div style={{textAlign: 'center'}}>
|
||
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Sağ üst köşedeki hızlı işlem düğmesi" />
|
||
</div>
|
||
|
||
Bileşeni satır içi işlemek için üzerine tıklayın.
|
||
|
||
## Yapılandırma alanları
|
||
|
||
| Alan | Zorunlu | Açıklama |
|
||
| --------------------- | ------- | ------------------------------------------------------------------------------------- |
|
||
| `universalIdentifier` | Evet | Bu bileşen için kalıcı benzersiz kimlik |
|
||
| `component` | Evet | Bir React bileşen fonksiyonu |
|
||
| `name` | Hayır | Görünen Ad |
|
||
| `description` | Hayır | Bileşenin ne yaptığına dair açıklama |
|
||
| `isHeadless` | Hayır | Bileşenin görünür bir kullanıcı arayüzü yoksa `true` olarak ayarlayın (aşağıya bakın) |
|
||
|
||
## Bir ön uç bileşenini bir sayfaya yerleştirme
|
||
|
||
Komutların ötesinde, bir ön uç bileşenini bir **sayfa düzeninde** widget olarak ekleyerek doğrudan bir kayıt sayfasına gömebilirsiniz. Ayrıntılar için [Sayfa Düzenleri](/l/tr/developers/extend/apps/layout/page-layouts) bölümüne bakın.
|
||
|
||
## Headless ve headless olmayan
|
||
|
||
Ön uç bileşenler, `isHeadless` seçeneğiyle kontrol edilen iki işleme kipiyle gelir:
|
||
|
||
**Headless olmayan (varsayılan)** — Bileşen görünür bir kullanıcı arayüzü (UI) oluşturur. Komut menüsünden tetiklendiğinde yan panelde açılır. `isHeadless` `false` olduğunda veya belirtilmediğinde bu varsayılan davranıştır.
|
||
|
||
**Headless (`isHeadless: true`)** — Bileşen arka planda görünmez şekilde bağlanır. Yan paneli açmaz. Headless bileşenler, mantığı çalıştırıp ardından kendilerini kaldıran eylemler için tasarlanmıştır — örneğin, bir async görevi çalıştırma, bir sayfaya gitme veya bir onay modalı gösterme. Aşağıda açıklanan SDK Command bileşenleriyle doğal olarak eşleşirler.
|
||
|
||
```tsx src/front-components/sync-tracker.tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
import { useSelectedRecordIds, enqueueSnackbar } from 'twenty-sdk/front-component';
|
||
import { useEffect } from 'react';
|
||
|
||
const SyncTracker = () => {
|
||
const [recordId] = useSelectedRecordIds();
|
||
|
||
useEffect(() => {
|
||
enqueueSnackbar({ message: `Tracking record ${recordId}`, variant: 'info' });
|
||
}, [recordId]);
|
||
|
||
return null;
|
||
};
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: '...',
|
||
name: 'sync-tracker',
|
||
description: 'Tracks record views silently',
|
||
isHeadless: true,
|
||
component: SyncTracker,
|
||
});
|
||
```
|
||
|
||
Bileşen `null` döndürdüğü için, Twenty bunun için bir kapsayıcı oluşturmayı atlar — düzende boş alan görünmez. Bileşen yine de tüm hook'lara ve host iletişim API'sine erişime sahiptir.
|
||
|
||
## SDK Command bileşenleri
|
||
|
||
`twenty-sdk` paketi, headless ön uç bileşenler için tasarlanmış dört Command yardımcı bileşeni sağlar. Her bileşen bağlandığında bir eylem yürütür, hataları bir snackbar bildirimi göstererek ele alır ve tamamlandığında ön bileşeni otomatik olarak kaldırır.
|
||
|
||
Bunları `twenty-sdk/front-component` içinden içe aktarın:
|
||
|
||
* **`Command`** — `execute` prop'u aracılığıyla async bir geri çağrıyı çalıştırır.
|
||
* **`CommandLink`** — Bir uygulama yoluna gider. Props: `to`, `params`, `queryParams`, `options`.
|
||
* **`CommandModal`** — Bir onay modalı açar. Kullanıcı onaylarsa `execute` geri çağrısını yürütür. Props: `title`, `subtitle`, `execute`, `confirmButtonText`, `confirmButtonAccent`.
|
||
* **`CommandOpenSidePanelPage`** — Bir yan panel sayfasını açar. Props, `page`'e bağlıdır — örneğin `ViewRecord`, `recordId` + `objectNameSingular` alır, diğer sayfalar `pageTitle` + `pageIcon` alır.
|
||
|
||
`Command` kullanarak komut menüsünden bir eylem çalıştıran headless bir ön uç bileşenin tam örneği:
|
||
|
||
```tsx src/front-components/run-action.tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
import { Command } from 'twenty-sdk/front-component';
|
||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||
|
||
const RunAction = () => {
|
||
const execute = async () => {
|
||
const client = new CoreApiClient();
|
||
|
||
await client.mutation({
|
||
createTask: {
|
||
__args: { data: { title: 'Created by my app' } },
|
||
id: true,
|
||
},
|
||
});
|
||
};
|
||
|
||
return <Command execute={execute} />;
|
||
};
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
|
||
name: 'run-action',
|
||
description: 'Creates a task from the command menu',
|
||
component: RunAction,
|
||
isHeadless: true,
|
||
});
|
||
```
|
||
|
||
```ts src/command-menu-items/run-action.command-menu-item.ts
|
||
import { defineCommandMenuItem } from 'twenty-sdk/define';
|
||
|
||
export default defineCommandMenuItem({
|
||
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
|
||
label: 'Run my action',
|
||
frontComponentUniversalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
|
||
});
|
||
```
|
||
|
||
Ve yürütmeden önce onay istemek için `CommandModal` kullanan bir örnek:
|
||
|
||
```tsx src/front-components/delete-draft.tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
import { CommandModal } from 'twenty-sdk/front-component';
|
||
|
||
const DeleteDraft = () => {
|
||
const execute = async () => {
|
||
// perform the deletion
|
||
};
|
||
|
||
return (
|
||
<CommandModal
|
||
title="Delete draft?"
|
||
subtitle="This action cannot be undone."
|
||
execute={execute}
|
||
confirmButtonText="Delete"
|
||
confirmButtonAccent="danger"
|
||
/>
|
||
);
|
||
};
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: 'a7b8c9d0-e1f2-3456-abcd-567890123456',
|
||
name: 'delete-draft',
|
||
description: 'Deletes a draft with confirmation',
|
||
component: DeleteDraft,
|
||
isHeadless: true,
|
||
});
|
||
```
|
||
|
||
## Bir mantık işlevini çağırma
|
||
|
||
Ön bileşenler, tarayıcı tarafında izole bir Web Worker içinde çalışırken, [mantık işlevleri](/l/tr/developers/extend/apps/logic/logic-functions) sunucu tarafında çalışır. İkisi arasında doğrudan, işlem içi bir çağrı yoktur — bunun yerine, bir ön bileşen bir mantık işlevine HTTP üzerinden erişir.
|
||
|
||
`httpRouteTriggerSettings` ile bildirilen bir mantık işlevi, rota yolunda HTTP üzerinden erişilebilir durumdadır. Twenty, işlevlerinizin sunulduğu temel URL’yi, çağrıyı kimlik doğrulayan `TWENTY_APP_ACCESS_TOKEN` ile birlikte, worker’a `TWENTY_FUNCTIONS_URL` olarak enjekte eder. Kendi işlevlerinizi çağırmak için henüz özel bir SDK istemcisi yoktur, bu yüzden onları basit bir `fetch` ile çağırın:
|
||
|
||
> **Twenty Cloud üzerinde, HTTP ile tetiklenen mantık işlevleri, çalışma alanı başına ayrılmış özel bir etki alanında** `https://\<your-workspace-subdomain>.withtwenty.com\<path>` adresinde sunulur — bu, `TWENTY_FUNCTIONS_URL`'ün tam olarak çözümlendiği değerdir. Harici çağrıcılar için, tam URL’yi işlevin **HTTP trigger** ayarlarından veya uygulamanın **Settings** sekmesinden kopyalayın.
|
||
|
||
<Warning>
|
||
Eski `/s/` fonksiyon rotası **kullanımdan kaldırılmıştır (deprecated)** ve **2026-07-24 tarihinde devre dışı bırakılacaktır**. Bunun yerine yukarıdaki `TWENTY_FUNCTIONS_URL` değerini kullanın ve o tarihten önce sabit (hard-coded) tüm `/s/` URL’lerini taşıyın. `/s/` rotası, self-hosting için kullanılabilir olmaya devam eder.
|
||
</Warning>
|
||
|
||
Başsız bir ön bileşen, çağrıyı `Command` bileşeni aracılığıyla mount sırasında çalıştırabilir ve ardından otomatik olarak unmount olabilir:
|
||
|
||
```tsx src/front-components/sync-prs.tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
import { Command } from 'twenty-sdk/front-component';
|
||
|
||
const SyncPrs = () => {
|
||
const execute = async () => {
|
||
await fetch(`${process.env.TWENTY_FUNCTIONS_URL}/github/fetch-prs`, {
|
||
method: 'POST',
|
||
headers: {
|
||
Authorization: `Bearer ${process.env.TWENTY_APP_ACCESS_TOKEN}`,
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({ owner: 'twentyhq', repo: 'twenty' }),
|
||
});
|
||
};
|
||
|
||
return <Command execute={execute} />;
|
||
};
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: '...',
|
||
name: 'sync-prs',
|
||
description: 'Triggers the fetch-prs logic function',
|
||
isHeadless: true,
|
||
component: SyncPrs,
|
||
});
|
||
```
|
||
|
||
`TWENTY_FUNCTIONS_URL` değerine eklenen yol (path), mantık fonksiyonunun `httpRouteTriggerSettings.path` değeridir. `isAuthRequired: true` ayarını koruyun; bileşeniniz için Twenty'nin oluşturduğu `TWENTY_APP_ACCESS_TOKEN` isteği kimlik doğrular:
|
||
|
||
```ts src/logic-functions/fetch-prs.logic-function.ts
|
||
import { defineLogicFunction } from 'twenty-sdk/define';
|
||
import type { RoutePayload } from 'twenty-sdk/logic-function';
|
||
|
||
const handler = async (event: RoutePayload) => {
|
||
const { owner, repo } = (event.body ?? {}) as { owner: string; repo: string };
|
||
// ...fetch from GitHub and persist records...
|
||
return { ok: true };
|
||
};
|
||
|
||
export default defineLogicFunction({
|
||
universalIdentifier: '...',
|
||
name: 'fetch-prs',
|
||
handler,
|
||
httpRouteTriggerSettings: {
|
||
path: '/github/fetch-prs',
|
||
httpMethod: 'POST',
|
||
isAuthRequired: true,
|
||
},
|
||
});
|
||
```
|
||
|
||
<Note>
|
||
`TWENTY_FUNCTIONS_URL` ve `TWENTY_APP_ACCESS_TOKEN` otomatik olarak enjekte edilir — bkz. [Uygulama değişkenleri](#application-variables). Gizli uygulama değişkenleri asla ön bileşenlere açığa çıkarılmadığından, API anahtarlarını ve diğer hassas mantığı ön bileşende değil, mantık işlevinin içinde tutun.
|
||
</Note>
|
||
|
||
### Twenty REST API'sini çağırma
|
||
|
||
Bir front bileşeninden Twenty kayıtlarını okumak veya yazmak için, `twenty-client-sdk/rest` paketinden `RestApiClient` kullanın. `CoreApiClient` ve `MetadataApiClient` ile aynı istemci ailesine aittir, ancak GraphQL API yerine Twenty REST API'sini (`/rest/...`) hedefler ve temel URL'sini `TWENTY_API_URL` değerinden okur.
|
||
|
||
| Yöntem | Açıklama |
|
||
| --------------------------------- | ---------------------------------------- |
|
||
| `get(path, options?)` | Bir `GET` isteği gönderir |
|
||
| `post(path, body?, options?)` | Bir `POST` isteği gönderir |
|
||
| `put(path, body?, options?)` | Bir `PUT` isteği gönderir |
|
||
| `patch(path, body?, options?)` | Bir `PATCH` isteği gönderir |
|
||
| `delete(path, options?)` | Bir `DELETE` isteği gönderir |
|
||
| `request(method, path, options?)` | Herhangi bir HTTP yöntemiyle genel istek |
|
||
|
||
`options`, `headers`, `query` (sorgu dizesi parametrelerinin kaydı; null benzeri değerler atlanır) ve `signal` aracılığıyla bir `AbortSignal` kabul eder. `FormData` olmayan bir `body` nesnesi otomatik olarak JSON’a serileştirilir. `401` durumunda, istemci erişim jetonunu bir kez ana makine (host) üzerinden yeniler ve isteği yeniden dener.
|
||
|
||
Temel URL ve jeton varsayılan olarak ortamdan çözümlenir. Gerektiğinde — örneğin testlerde — kurucuya (constructor) geçersiz kılmalar (override) iletin:
|
||
|
||
```ts
|
||
const client = new RestApiClient({
|
||
baseUrl: 'https://myworkspace.twenty.com',
|
||
token: 'my-token',
|
||
});
|
||
```
|
||
|
||
Başarısız istekler, `status`, `statusText`, `url` ve ayrıştırılmış `body` değerlerini açığa çıkaran bir `RestApiClientError` fırlatır:
|
||
|
||
```tsx
|
||
import { RestApiClient, RestApiClientError } from 'twenty-client-sdk/rest';
|
||
|
||
const client = new RestApiClient();
|
||
|
||
try {
|
||
const people = await client.get('/rest/people', {
|
||
query: { limit: 10 },
|
||
});
|
||
} catch (error) {
|
||
if (error instanceof RestApiClientError) {
|
||
console.error(error.status, error.body);
|
||
}
|
||
}
|
||
```
|
||
|
||
## Çalışma zamanı bağlamına erişme
|
||
|
||
Bileşeninizin içinde, geçerli kullanıcıya, kayda ve bileşen örneğine erişmek için SDK hook'larını kullanın:
|
||
|
||
```tsx src/front-components/record-info.tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
import {
|
||
useUserId,
|
||
useSelectedRecordIds,
|
||
useFrontComponentId,
|
||
} from 'twenty-sdk/front-component';
|
||
|
||
const RecordInfo = () => {
|
||
const userId = useUserId();
|
||
const [recordId] = useSelectedRecordIds();
|
||
const componentId = useFrontComponentId();
|
||
|
||
return (
|
||
<div>
|
||
<p>User: {userId}</p>
|
||
<p>Record: {recordId ?? 'No record context'}</p>
|
||
<p>Component: {componentId}</p>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: 'b2c3d4e5-f6a7-8901-bcde-f23456789012',
|
||
name: 'record-info',
|
||
component: RecordInfo,
|
||
});
|
||
```
|
||
|
||
Kullanılabilir hook'lar:
|
||
|
||
| Hook | Döndürür | Açıklama |
|
||
| --------------------------------------------- | ----------------------- | --------------------------------------------------------------------------------- |
|
||
| `useUserId()` | `string` veya `null` | Geçerli kullanıcının ID'si |
|
||
| `useSelectedRecordIds()` | `string[]` | Tüm seçili kayıt kimlikleri (hiçbiri seçilmediyse boş dizi) |
|
||
| `useRecordId()` | `string` veya `null` | **Kullanımdan kaldırıldı.** Bunun yerine `useSelectedRecordIds()` kullanın |
|
||
| `useFrontComponentId()` | `string` | Bu bileşen örneğinin ID'si |
|
||
| `useColorScheme()` | `'light'` veya `'dark'` | Ana makine kullanıcı arayüzünün etkin renk şeması (`System` zaten çözümlenmiştir) |
|
||
| `useFrontComponentExecutionContext(selector)` | değişir | Bir seçici işlevle tam yürütme bağlamına erişin |
|
||
|
||
## Uygulama değişkenleri
|
||
|
||
`isSecret: false` ile [`defineApplication()`](/l/tr/developers/extend/apps/config/application) içinde tanımlanan uygulama değişkenleri, `getApplicationVariable` yardımcı işlevi aracılığıyla ön uç bileşenleri içinde kullanılabilir:
|
||
|
||
```tsx src/front-components/greeting.tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
import { getApplicationVariable } from 'twenty-sdk/front-component';
|
||
|
||
const Greeting = () => {
|
||
const recipientName = getApplicationVariable('DEFAULT_RECIPIENT_NAME') ?? 'World';
|
||
|
||
return <p>Hello, {recipientName}!</p>;
|
||
};
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: '...',
|
||
name: 'greeting',
|
||
component: Greeting,
|
||
});
|
||
```
|
||
|
||
<Warning>
|
||
Gizli değişkenler (`isSecret: true`) ön uç bileşenlere açıklanmaz. Bunlar yalnızca sunucu tarafında çalışan [mantık işlevlerinde](/l/tr/developers/extend/apps/logic/logic-functions) kullanılabilir. Bu, API anahtarları gibi hassas değerlerin tarayıcıya gönderilmesini engeller.
|
||
</Warning>
|
||
|
||
`getApplicationVariable`, değişkenin bildirilen `type` değerinden bağımsız olarak her zaman bir **string** (veya `undefined`) döndürür. String, türe göre tutarlı bir şekilde serileştirilir (boolean değerler `"true"` / `"false"`, sayılar ondalık dizeler olarak, diziler/nesneler JSON olarak) ve bu, `process.env` mantık işlevi için kullanılan formatla aynıdır — veriyi kendiniz ayrıştırın (`Number(...)`, `JSON.parse(...)`, `=== 'true'`). [Değişken türleri](/l/tr/developers/extend/apps/config/application#variable-types) bölümüne bakın.
|
||
|
||
Aşağıdaki sistem değişkenleri her zaman `process.env` aracılığıyla kullanılabilir:
|
||
|
||
| Değişken | Açıklama |
|
||
| ------------------------- | -------------------------------------------------------------- |
|
||
| `TWENTY_FUNCTIONS_URL` | Uygulamanızın HTTP mantık fonksiyonlarının sunulduğu temel URL |
|
||
| `TWENTY_API_URL` | Twenty çekirdek API'sinin temel URL'si |
|
||
| `TWENTY_APP_ACCESS_TOKEN` | Uygulamanızın rolüyle sınırlanan kısa ömürlü bir belirteç |
|
||
|
||
## Host iletişim API'si
|
||
|
||
Ön uç bileşenleri, `twenty-sdk`'deki işlevleri kullanarak gezinmeyi, modalları ve bildirimleri tetikleyebilir:
|
||
|
||
| Fonksiyon | Açıklama |
|
||
| ----------------------------------------------- | ---------------------------------- |
|
||
| `navigate(to, params?, queryParams?, options?)` | Uygulamada bir sayfaya git |
|
||
| `openSidePanelPage(params)` | Bir yan panel aç |
|
||
| `closeSidePanel()` | Yan paneli kapat |
|
||
| `openCommandConfirmationModal(params)` | Bir onay iletişim kutusu göster |
|
||
| `enqueueSnackbar(params)` | Bir toast bildirimi göster |
|
||
| `unmountFrontComponent()` | Bileşeni kaldır (unmount) |
|
||
| `updateProgress(progress)` | Bir ilerleme göstergesini güncelle |
|
||
|
||
Bir eylem tamamlandıktan sonra bir snackbar göstermek ve yan paneli kapatmak için host API'sini kullanan bir örnek:
|
||
|
||
```tsx src/front-components/archive-record.tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
import { enqueueSnackbar, closeSidePanel, useSelectedRecordIds } from 'twenty-sdk/front-component';
|
||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||
|
||
const ArchiveRecord = () => {
|
||
const [recordId] = useSelectedRecordIds();
|
||
|
||
const handleArchive = async () => {
|
||
const client = new CoreApiClient();
|
||
|
||
await client.mutation({
|
||
updateTask: {
|
||
__args: { id: recordId, data: { status: 'ARCHIVED' } },
|
||
id: true,
|
||
},
|
||
});
|
||
|
||
await enqueueSnackbar({
|
||
message: 'Record archived',
|
||
variant: 'success',
|
||
});
|
||
|
||
await closeSidePanel();
|
||
};
|
||
|
||
return (
|
||
<div style={{ padding: '20px' }}>
|
||
<p>Archive this record?</p>
|
||
<button onClick={handleArchive}>Archive</button>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: 'c9d0e1f2-a3b4-5678-cdef-789012345678',
|
||
name: 'archive-record',
|
||
description: 'Archives the current record',
|
||
component: ArchiveRecord,
|
||
});
|
||
```
|
||
|
||
### Birden çok kayıtla çalışma
|
||
|
||
Birden çok seçili kaydı yönetmek için `useSelectedRecordIds()` kullanın. Bu, toplu işlemler için kullanışlıdır:
|
||
|
||
```tsx src/front-components/bulk-export.tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
import { useSelectedRecordIds } from 'twenty-sdk/front-component';
|
||
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
|
||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||
|
||
const BulkExport = () => {
|
||
const selectedRecordIds = useSelectedRecordIds();
|
||
|
||
const handleExport = async () => {
|
||
const client = new CoreApiClient();
|
||
|
||
for (const recordId of selectedRecordIds) {
|
||
await client.mutation({
|
||
updateTask: {
|
||
__args: { id: recordId, data: { exported: true } },
|
||
id: true,
|
||
},
|
||
});
|
||
}
|
||
|
||
await enqueueSnackbar({
|
||
message: `Exported ${selectedRecordIds.length} records`,
|
||
variant: 'success',
|
||
});
|
||
|
||
await closeSidePanel();
|
||
};
|
||
|
||
return (
|
||
<div style={{ padding: '20px' }}>
|
||
<p>Export {selectedRecordIds.length} selected record(s)?</p>
|
||
<button onClick={handleExport}>Export</button>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: 'd0e1f2a3-b4c5-6789-defa-012345678901',
|
||
name: 'bulk-export',
|
||
description: 'Export selected records',
|
||
component: BulkExport,
|
||
});
|
||
```
|
||
|
||
Bunu, kayıt seçimleriyle kısıtlanmış bir [komut menüsü öğesi](/l/tr/developers/extend/apps/layout/command-menu-items) ile yüzeye çıkarın:
|
||
|
||
```ts src/command-menu-items/bulk-export.command-menu-item.ts
|
||
import { defineCommandMenuItem } from 'twenty-sdk/define';
|
||
|
||
export default defineCommandMenuItem({
|
||
universalIdentifier: 'd0e1f2a3-b4c5-6789-defa-012345678902',
|
||
label: 'Bulk Export',
|
||
availabilityType: 'RECORD_SELECTION',
|
||
frontComponentUniversalIdentifier: 'd0e1f2a3-b4c5-6789-defa-012345678901',
|
||
});
|
||
```
|
||
|
||
## Genel varlıklar
|
||
|
||
Ön uç bileşenleri, `getPublicAssetUrl` kullanarak uygulamanın `public/` dizinindeki dosyalara erişebilir:
|
||
|
||
```tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
import { getPublicAssetUrl } from 'twenty-sdk/utils';
|
||
|
||
const Logo = () => <img src={getPublicAssetUrl('logo.png')} alt="Logo" />;
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: '...',
|
||
name: 'logo',
|
||
component: Logo,
|
||
});
|
||
```
|
||
|
||
Ayrıntılar için [genel varlıklar bölümüne](/l/tr/developers/extend/apps/config/public-assets) bakın.
|
||
|
||
## Stil
|
||
|
||
Ön uç bileşenleri birden fazla biçimlendirme yaklaşımını destekler. Şunları kullanabilirsiniz:
|
||
|
||
* **Satır içi stiller** — `style={{ color: 'red' }}`
|
||
* **Twenty UI bileşenleri** — Twenty'nin kendi bileşen kitaplığı; aşağıda [Twenty UI bileşenlerini kullanma](#using-twenty-ui-components) bölümüne bakın
|
||
* **Emotion** — `@emotion/react` ile CSS-in-JS
|
||
* **Styled-components** — `styled.div` kalıpları
|
||
* **Tailwind CSS** — yardımcı sınıflar
|
||
* **React ile uyumlu herhangi bir CSS-in-JS kitaplığı**
|
||
|
||
## Twenty UI bileşenlerini kullanma
|
||
|
||
Twenty, bileşen kitaplığını [`twenty-ui`](https://www.npmjs.com/package/twenty-ui/v/1.0.0-alpha.1) paketi olarak sunar. Ön uç bileşenleri bunu, çalışma alanının açık ve koyu temasıyla otomatik olarak eşleşen düğmeler, etiketler, durum rozetleri, çipler, avatarlar, simgeler, tipografi ve tema belirteçleri için kullanabilir.
|
||
|
||
### Kurulum
|
||
|
||
Paketi, Twenty örneğinizle birlikte gelen sürüme sabitleyerek uygulamanıza ekleyin:
|
||
|
||
```bash
|
||
yarn add twenty-ui@1.0.0-alpha.1
|
||
```
|
||
|
||
`twenty-ui`, derleme zamanında ön uç bileşeninize paketlenir, bu nedenle yalnızca uygulamanızın bir bağımlılığı olması gerekir — çalışma zamanında yapılandırmanız gereken hiçbir şey yoktur.
|
||
|
||
### Bileşenleri içe aktarma
|
||
|
||
Kullandığınız bileşenlerin yalnızca paketinizde yer alması için, paket kökü yerine eşleşen alt yoldan içe aktarın:
|
||
|
||
| Alt yol | Dışa aktardıkları |
|
||
| --------------------------- | -------------------------------------------------------- |
|
||
| `twenty-ui/input` | `Button` ve form girdileri |
|
||
| `twenty-ui/data-display` | `Tag`, `Status`, `Chip`, `Avatar` ve daha fazlası |
|
||
| `twenty-ui/feedback` | `Callout`, `Banner`, `Info` ve daha fazlası |
|
||
| `twenty-ui/typography` | `H1Title`, `H2Title`, `H3Title`, `Label` ve daha fazlası |
|
||
| `twenty-ui/icon` | `Icon*` bileşenleri (ör. `IconCheck`) |
|
||
| `twenty-ui/theme-constants` | `ThemeProvider`, `themeCssVariables` |
|
||
|
||
```tsx
|
||
import { defineFrontComponent } from 'twenty-sdk/define';
|
||
import { Status, Tag } from 'twenty-ui/data-display';
|
||
import { Button } from 'twenty-ui/input';
|
||
|
||
const StyledWidget = () => {
|
||
return (
|
||
<div style={{ padding: '16px', display: 'flex', gap: '8px' }}>
|
||
<Button title="Click me" onClick={() => alert('Clicked!')} />
|
||
<Tag text="Active" color="green" />
|
||
<Status color="green" text="Online" />
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default defineFrontComponent({
|
||
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-567890123456',
|
||
name: 'styled-widget',
|
||
component: StyledWidget,
|
||
});
|
||
```
|
||
|
||
### İkonlar
|
||
|
||
Tek tek simgeleri `twenty-ui/icon` içinden içe aktarın:
|
||
|
||
```tsx
|
||
import { IconBox, IconCheck } from 'twenty-ui/icon';
|
||
```
|
||
|
||
Her adlandırılmış simge ağaç sallama optimizasyonuna tabidir; bu nedenle birkaç tanesini içe aktarmak paket boyutunuza çok az şey ekler. `IconsProvider`, `useIcons` ve `iconsState` kullanmaktan kaçının — bunlar, birkaç MB'lık Tabler simge setinin tamamını içeri çeker.
|
||
|
||
### Temalandırma ve tema belirteçleri
|
||
|
||
Twenty UI bileşenleri, çalışma alanının açık ve koyu temasıyla otomatik olarak eşleşir — oluşturucu etkin renk şemasını barındırıcıda uygular ve bileşenler renklerini buna göre belirler.
|
||
|
||
Kendi satır içi stillerinizde aynı tasarım belirteçlerini kullanmak için `useTheme()` kancasını çağırın. Bu kanca, etkin temaya bağlı Twenty tema belirteçlerini (boşluklandırma, renkler, köşe yarıçapları, yazı tipleri) döndürür; bileşeninizde `ThemeProvider` kurulumuna gerek yoktur:
|
||
|
||
```tsx
|
||
import { useTheme } from 'twenty-ui/theme-constants';
|
||
|
||
const Card = () => {
|
||
const theme = useTheme();
|
||
|
||
return (
|
||
<div
|
||
style={{
|
||
padding: theme.spacing[4],
|
||
background: theme.background.secondary,
|
||
color: theme.font.color.primary,
|
||
}}
|
||
>
|
||
Themed card
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
`useTheme()` bir kanca olduğundan, belirteçleri bileşen gövdesinin içinde okursunuz; böylece değerler her zaman etkin temayı yansıtır. Aynı belirteç haritası, `themeCssVariables` sabiti olarak da dışa aktarılır; ancak ön uç bileşenlerinde `useTheme()` kullanmayı tercih edin — `themeCssVariables` öğesini dolaylı olarak kullanan modül düzeyinde bir sabit, uygulama manifesti çıkarılırken tanımsız olabilir.
|
||
|
||
Etkin şemaya açıkça dallanmak için, `twenty-sdk/front-component` içindeki `useColorScheme()` ile okuyun; bu kanca `'light'` veya `'dark'` döndürür.
|