i18n - docs translations (#16779)

Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
github-actions[bot]
2025-12-23 17:06:38 +01:00
committed by GitHub
parent 1bc344c6fa
commit e3757f300a
1080 changed files with 89730 additions and 9944 deletions
+63 -63
View File
@@ -471,7 +471,7 @@
"language": "fr",
"tabs": [
{
"tab": "Guide de l'utilisateur",
"tab": "User Guide",
"groups": [
{
"group": "Discover Twenty",
@@ -497,7 +497,7 @@
]
},
{
"group": "Modèle de données",
"group": "Data Model",
"icon": "database",
"pages": [
"l/fr/user-guide/data-model/overview",
@@ -579,7 +579,7 @@
]
},
{
"group": "Flux de travail",
"group": "Workflows",
"icon": "bolt",
"pages": [
"l/fr/user-guide/workflows/overview",
@@ -750,7 +750,7 @@
]
},
{
"group": "Paramètres",
"group": "Settings",
"icon": "gear",
"pages": [
"l/fr/user-guide/settings/overview",
@@ -776,10 +776,10 @@
]
},
{
"tab": "Développeurs",
"tab": "Developers",
"groups": [
{
"group": "Développeurs",
"group": "Developers",
"pages": [
"l/fr/developers/introduction"
]
@@ -827,7 +827,7 @@
"l/fr/developers/contribute/capabilities/local-setup",
"l/fr/developers/contribute/capabilities/bug-and-requests",
{
"group": "veloppement du frontend",
"group": "Frontend Development",
"pages": [
"l/fr/developers/contribute/capabilities/frontend-development/storybook",
{
@@ -835,7 +835,7 @@
"pages": [
"l/fr/twenty-ui/introduction",
{
"group": "Afficher",
"group": "Display",
"pages": [
"l/fr/twenty-ui/display/checkmark",
"l/fr/twenty-ui/display/chip",
@@ -846,7 +846,7 @@
]
},
{
"group": "Vos commentaires",
"group": "Feedback",
"pages": [
"l/fr/twenty-ui/progress-bar"
]
@@ -888,7 +888,7 @@
]
},
{
"group": "veloppement du backend",
"group": "Backend Development",
"pages": [
"l/fr/developers/contribute/capabilities/backend-development/server-commands",
"l/fr/developers/contribute/capabilities/backend-development/feature-flags",
@@ -2257,7 +2257,7 @@
]
},
{
"group": "Modelo de datos",
"group": "Data Model",
"icon": "database",
"pages": [
"l/es/user-guide/data-model/overview",
@@ -2339,7 +2339,7 @@
]
},
{
"group": "Flujos de trabajo",
"group": "Workflows",
"icon": "bolt",
"pages": [
"l/es/user-guide/workflows/overview",
@@ -2399,7 +2399,7 @@
]
},
{
"group": "IA",
"group": "AI",
"icon": "robot",
"pages": [
"l/es/user-guide/ai/overview",
@@ -2450,7 +2450,7 @@
]
},
{
"group": "Tableros",
"group": "Dashboards",
"icon": "chart-bar",
"pages": [
"l/es/user-guide/dashboards/overview",
@@ -2490,7 +2490,7 @@
]
},
{
"group": "Facturación",
"group": "Billing",
"icon": "credit-card",
"pages": [
"l/es/user-guide/billing/overview",
@@ -2510,7 +2510,7 @@
]
},
{
"group": "Configuración",
"group": "Settings",
"icon": "gear",
"pages": [
"l/es/user-guide/settings/overview",
@@ -2536,10 +2536,10 @@
]
},
{
"tab": "Desarrolladores",
"tab": "Developers",
"groups": [
{
"group": "Desarrolladores",
"group": "Developers",
"pages": [
"l/es/developers/introduction"
]
@@ -2587,7 +2587,7 @@
"l/es/developers/contribute/capabilities/local-setup",
"l/es/developers/contribute/capabilities/bug-and-requests",
{
"group": "Desarrollo Frontend",
"group": "Frontend Development",
"pages": [
"l/es/developers/contribute/capabilities/frontend-development/storybook",
{
@@ -2595,7 +2595,7 @@
"pages": [
"l/es/twenty-ui/introduction",
{
"group": "Mostrar",
"group": "Display",
"pages": [
"l/es/twenty-ui/display/checkmark",
"l/es/twenty-ui/display/chip",
@@ -2606,13 +2606,13 @@
]
},
{
"group": "Retroalimentación",
"group": "Feedback",
"pages": [
"l/es/twenty-ui/progress-bar"
]
},
{
"group": "Entrada",
"group": "Input",
"pages": [
"l/es/twenty-ui/input/buttons",
"l/es/twenty-ui/input/color-scheme",
@@ -2627,7 +2627,7 @@
]
},
{
"group": "Navegación",
"group": "Navigation",
"pages": [
"l/es/twenty-ui/navigation",
"l/es/twenty-ui/navigation/breadcrumb",
@@ -2648,7 +2648,7 @@
]
},
{
"group": "Desarrollo Backend",
"group": "Backend Development",
"pages": [
"l/es/developers/contribute/capabilities/backend-development/server-commands",
"l/es/developers/contribute/capabilities/backend-development/feature-flags",
@@ -3111,7 +3111,7 @@
"language": "ja",
"tabs": [
{
"tab": "ユーザーガイド",
"tab": "User Guide",
"groups": [
{
"group": "Discover Twenty",
@@ -3137,7 +3137,7 @@
]
},
{
"group": "データモデル",
"group": "Data Model",
"icon": "database",
"pages": [
"l/ja/user-guide/data-model/overview",
@@ -3219,7 +3219,7 @@
]
},
{
"group": "ワークフロー",
"group": "Workflows",
"icon": "bolt",
"pages": [
"l/ja/user-guide/workflows/overview",
@@ -3390,7 +3390,7 @@
]
},
{
"group": "設定",
"group": "Settings",
"icon": "gear",
"pages": [
"l/ja/user-guide/settings/overview",
@@ -3416,10 +3416,10 @@
]
},
{
"tab": "開発者",
"tab": "Developers",
"groups": [
{
"group": "開発者",
"group": "Developers",
"pages": [
"l/ja/developers/introduction"
]
@@ -3467,7 +3467,7 @@
"l/ja/developers/contribute/capabilities/local-setup",
"l/ja/developers/contribute/capabilities/bug-and-requests",
{
"group": "フロントエンド開発",
"group": "Frontend Development",
"pages": [
"l/ja/developers/contribute/capabilities/frontend-development/storybook",
{
@@ -3475,7 +3475,7 @@
"pages": [
"l/ja/twenty-ui/introduction",
{
"group": "表示",
"group": "Display",
"pages": [
"l/ja/twenty-ui/display/checkmark",
"l/ja/twenty-ui/display/chip",
@@ -3486,7 +3486,7 @@
]
},
{
"group": "フィードバック",
"group": "Feedback",
"pages": [
"l/ja/twenty-ui/progress-bar"
]
@@ -3528,7 +3528,7 @@
]
},
{
"group": "バックエンド開発",
"group": "Backend Development",
"pages": [
"l/ja/developers/contribute/capabilities/backend-development/server-commands",
"l/ja/developers/contribute/capabilities/backend-development/feature-flags",
@@ -3577,7 +3577,7 @@
]
},
{
"group": "데이터 모델",
"group": "Data Model",
"icon": "database",
"pages": [
"l/ko/user-guide/data-model/overview",
@@ -3830,7 +3830,7 @@
]
},
{
"group": "설정",
"group": "Settings",
"icon": "gear",
"pages": [
"l/ko/user-guide/settings/overview",
@@ -3856,10 +3856,10 @@
]
},
{
"tab": "개발자",
"tab": "Developers",
"groups": [
{
"group": "개발자",
"group": "Developers",
"pages": [
"l/ko/developers/introduction"
]
@@ -3907,7 +3907,7 @@
"l/ko/developers/contribute/capabilities/local-setup",
"l/ko/developers/contribute/capabilities/bug-and-requests",
{
"group": "프론트엔드 개발",
"group": "Frontend Development",
"pages": [
"l/ko/developers/contribute/capabilities/frontend-development/storybook",
{
@@ -3915,7 +3915,7 @@
"pages": [
"l/ko/twenty-ui/introduction",
{
"group": "표시",
"group": "Display",
"pages": [
"l/ko/twenty-ui/display/checkmark",
"l/ko/twenty-ui/display/chip",
@@ -3926,13 +3926,13 @@
]
},
{
"group": "피드백",
"group": "Feedback",
"pages": [
"l/ko/twenty-ui/progress-bar"
]
},
{
"group": "입력",
"group": "Input",
"pages": [
"l/ko/twenty-ui/input/buttons",
"l/ko/twenty-ui/input/color-scheme",
@@ -3947,7 +3947,7 @@
]
},
{
"group": "네비게이션",
"group": "Navigation",
"pages": [
"l/ko/twenty-ui/navigation",
"l/ko/twenty-ui/navigation/breadcrumb",
@@ -3968,7 +3968,7 @@
]
},
{
"group": "백엔드 개발",
"group": "Backend Development",
"pages": [
"l/ko/developers/contribute/capabilities/backend-development/server-commands",
"l/ko/developers/contribute/capabilities/backend-development/feature-flags",
@@ -3991,7 +3991,7 @@
"language": "pt",
"tabs": [
{
"tab": "Manual do Usuário",
"tab": "User Guide",
"groups": [
{
"group": "Discover Twenty",
@@ -4017,7 +4017,7 @@
]
},
{
"group": "Modelo de Dados",
"group": "Data Model",
"icon": "database",
"pages": [
"l/pt/user-guide/data-model/overview",
@@ -4270,7 +4270,7 @@
]
},
{
"group": "Configurações",
"group": "Settings",
"icon": "gear",
"pages": [
"l/pt/user-guide/settings/overview",
@@ -4296,10 +4296,10 @@
]
},
{
"tab": "Desenvolvedores",
"tab": "Developers",
"groups": [
{
"group": "Desenvolvedores",
"group": "Developers",
"pages": [
"l/pt/developers/introduction"
]
@@ -4347,7 +4347,7 @@
"l/pt/developers/contribute/capabilities/local-setup",
"l/pt/developers/contribute/capabilities/bug-and-requests",
{
"group": "Desenvolvimento Frontend",
"group": "Frontend Development",
"pages": [
"l/pt/developers/contribute/capabilities/frontend-development/storybook",
{
@@ -4355,7 +4355,7 @@
"pages": [
"l/pt/twenty-ui/introduction",
{
"group": "Exibição",
"group": "Display",
"pages": [
"l/pt/twenty-ui/display/checkmark",
"l/pt/twenty-ui/display/chip",
@@ -4408,7 +4408,7 @@
]
},
{
"group": "Desenvolvimento de backend",
"group": "Backend Development",
"pages": [
"l/pt/developers/contribute/capabilities/backend-development/server-commands",
"l/pt/developers/contribute/capabilities/backend-development/feature-flags",
@@ -5777,7 +5777,7 @@
]
},
{
"group": "數據模型",
"group": "Data Model",
"icon": "database",
"pages": [
"l/zh/user-guide/data-model/overview",
@@ -5859,7 +5859,7 @@
]
},
{
"group": "Workflow",
"group": "Workflows",
"icon": "bolt",
"pages": [
"l/zh/user-guide/workflows/overview",
@@ -6030,7 +6030,7 @@
]
},
{
"group": "設置",
"group": "Settings",
"icon": "gear",
"pages": [
"l/zh/user-guide/settings/overview",
@@ -6056,10 +6056,10 @@
]
},
{
"tab": "開發人員",
"tab": "Developers",
"groups": [
{
"group": "開發人員",
"group": "Developers",
"pages": [
"l/zh/developers/introduction"
]
@@ -6107,7 +6107,7 @@
"l/zh/developers/contribute/capabilities/local-setup",
"l/zh/developers/contribute/capabilities/bug-and-requests",
{
"group": "前端開發",
"group": "Frontend Development",
"pages": [
"l/zh/developers/contribute/capabilities/frontend-development/storybook",
{
@@ -6115,7 +6115,7 @@
"pages": [
"l/zh/twenty-ui/introduction",
{
"group": "顯示",
"group": "Display",
"pages": [
"l/zh/twenty-ui/display/checkmark",
"l/zh/twenty-ui/display/chip",
@@ -6126,13 +6126,13 @@
]
},
{
"group": "反饋",
"group": "Feedback",
"pages": [
"l/zh/twenty-ui/progress-bar"
]
},
{
"group": "輸入",
"group": "Input",
"pages": [
"l/zh/twenty-ui/input/buttons",
"l/zh/twenty-ui/input/color-scheme",
@@ -6147,7 +6147,7 @@
]
},
{
"group": "導航",
"group": "Navigation",
"pages": [
"l/zh/twenty-ui/navigation",
"l/zh/twenty-ui/navigation/breadcrumb",
@@ -6168,7 +6168,7 @@
]
},
{
"group": "後端開發",
"group": "Backend Development",
"pages": [
"l/zh/developers/contribute/capabilities/backend-development/server-commands",
"l/zh/developers/contribute/capabilities/backend-development/feature-flags",
@@ -21,12 +21,12 @@ 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();
@@ -34,7 +34,7 @@ class CustomWorker {
async initWorker() {
await this.queue.work(async ({ id, data }) => {
//منطق العامل
//worker logic
});
}
}
@@ -40,7 +40,7 @@ export const MyComponent = () => {
تجنب استخدام `useRef` لتخزين الحالة.
إذا كنت ترغب في تخزين الحالة، يجب أن تستخدم `useState` أو `useRecoilState`.
If you want to store state, you should use `useState` or `useRecoilState`.
انظر [كيفية إدارة إعادة العرض](#managing-re-renders) إذا شعرت أنك بحاجة إلى `useRef` لمنع بعض إعادة العرض من الحدوث.
@@ -56,23 +56,23 @@ export const MyComponent = () => {
تجنب إعادة العرض في الميزات الجديدة أصبح سهلاً الآن عن طريق إزالتها على المستوى الجذري.
مكون الجانب `PageChangeEffect` يحتوي فقط على `useEffect` واحد يقوم بعقد جميع المنطق لتنفيذه عند تغيير الصفحة.
The `PageChangeEffect` sidecar component contains just one `useEffect` that holds all the logic to execute on a page change.
بهذه الطريقة، تعرف أن هناك مكان واحد فقط يمكنه تحفيز إعادة العرض.
### فكر جيدًا قبل إضافة `useEffect` في قاعدة التعليمات البرمجية الخاصة بك
### Always think twice before adding `useEffect` in your codebase
غالبًا ما تكون إعادة العرض ناجمة عن `useEffect` غير ضروري.
Re-renders are often caused by unnecessary `useEffect`.
يجب أن تفكر في ما إذا كنت بحاجة إلى `useEffect`، أو ما إذا كان بإمكانك نقل المنطق إلى وظيفة معالج الحدث.
You should think whether you need `useEffect`, or if you can move the logic in a event handler function.
ستجد أنه من السهل عمومًا نقل المنطق إلى وظيفة `handleClick` أو `handleChange`.
You'll find it generally easy to move the logic in a `handleClick` or `handleChange` function.
يمكنك أيضًا العثور عليها في المكتبات مثل Apollo: `onCompleted`، `onError`، إلخ.
### استخدم مكونًا متماثلاً لاستخراج `useEffect` أو منطق استدعاء البيانات
### Use a sibling component to extract `useEffect` or data fetching logic
إذا شعرت أنك بحاجة إلى إضافة `useEffect` في مكون الجذر الخاص بك، يجب أن تفكر في استخراجه في مكون الجانب.
If you feel like you need to add a `useEffect` in your root component, you should consider extracting it in a sidecar component.
يمكنك تطبيق نفس الشيء على منطق جلب البيانات، مع الخُطافات Apollo.
@@ -69,7 +69,7 @@ title: أوامر الواجهة الأمامية
"[React Router](https://reactrouter.com/) يتعامل مع التوجيه."
"لتجنب [إعادة العرض](/l/ar/developers/contribute/capabilities/frontend-development/best-practices-front#managing-re-renders) غير الضرورية، يوجد منطق التوجيه في `useEffect` في `PageChangeEffect`."
To avoid unnecessary [re-renders](/l/ar/developers/contribute/capabilities/frontend-development/best-practices-front#managing-re-renders) all the routing logic is in a `useEffect` in `PageChangeEffect`.
### "إدارة الحالة"
@@ -45,29 +45,29 @@ const PageListeningEnter = () => {
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
// 1. تعيين نطاق المفتاح في استخدام التأثير
// 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. استخدام خطاف useScopedHotkeys
// 2. Use the useScopedHotkeys hook
useScopedHotkeys(
Key.Enter,
() => {
// بعض المنطق المنفذ في هذه الصفحة عند ضغط المستخدم على Enter
// Some logic executed on this page when the user presses Enter
// ...
},
ExampleHotkeyScopes.ExampleEnterPage,
);
return <div>صفحتي التي تستمع لمفتاح Enter</div>;
return <div>My page that listens for Enter</div>;
};
```
@@ -87,7 +87,7 @@ const ExamplePageWithModal = () => {
} = usePreviousHotkeyScope();
const handleOpenModalClick = () => {
// 1. تعيين نطاق المفتاح عند فتح المستخدم المودال
// 1. Set the hotkey scope when user opens the modal
setShowModal(true);
setHotkeyScopeAndMemorizePreviousScope(
ExampleHotkeyScopes.ExampleModal,
@@ -95,14 +95,14 @@ const ExamplePageWithModal = () => {
};
const handleModalClose = () => {
// 1. العودة إلى نطاق المفتاح السابق عند إغلاق المودال
// 1. Revert to the previous hotkey scope when the modal is closed
setShowModal(false);
goBackToPreviousHotkeyScope();
};
return <div>
<h1>صفحتي التي تحتوي على مودال</h1>
<button onClick={handleOpenModalClick}>فتح المودال</button>
<h1>My page with a modal</h1>
<button onClick={handleOpenModalClick}>Open modal</button>
{showModal && <MyModalComponent onClose={handleModalClose} />}
</div>;
};
@@ -112,9 +112,9 @@ const ExamplePageWithModal = () => {
```tsx
const MyDropdownComponent = ({ onClose }: { onClose: () => void }) => {
// 2. استخدام خطاف useScopedHotkeys للاستماع لمفتاح Escape.
// لاحظ أن مفتاح Escape هو مفتاح اختصار شائع يمكن استخدامه من قبل مكونات أخرى كثيرة.
// لذلك من المهم استخدام نطاق مفتاح لتجنب التعارضات.
// 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,
() => {
@@ -123,13 +123,13 @@ const MyDropdownComponent = ({ onClose }: { onClose: () => void }) => {
ExampleHotkeyScopes.ExampleModal,
);
return <div>مكون المودال الخاص بي</div>;
return <div>My modal component</div>;
};
```
من المهم استخدام هذا النمط عندما لست متأكدًا من أن استخدام useEffect مع التركيب/إلغاء التركيب يكفي لتجنب التعارضات.
It's important to use this pattern when you're not sure that just using a useEffect with mount/unmount will be enough to avoid conflicts.
تلك التعارضات يمكن أن تكون صعبة التصحيح، وربما تحدث بشكل متكرر مع useEffects.
Those conflicts can be hard to debug, and it might happen more often than not with useEffects.
## ما هو نطاق المفتاح؟
@@ -21,14 +21,14 @@ The goal here is to have a consistent codebase, which is easy to read and easy t
لا تستخدم `import` الافتراضي مع `const`، لأنه أصعب من حيث القراءة والدمج باستخدام إكمال التعليمات البرمجية.
```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>;
};
@@ -41,10 +41,10 @@ export function MyComponent() {
استخدام تفكيك الخصائص.
```tsx
// ❌ سيئ، لا يوجد نوع
// ❌ Bad, no type
export const MyComponent = (props) => <div>Hello {props.name}</div>;
// ✅ جيد، النوع
// ✅ Good, type
type MyComponentProps = {
name: string;
};
@@ -55,11 +55,11 @@ export const MyComponent = ({ name }: MyComponentProps) => <div>Hello {name}</di
#### امتنع عن استخدام `React.FC` أو `React.FunctionComponent` لتحديد أنواع الخصائص
```tsx
/* ❌ - سيئ، يحدد أنماط المكون باستخدام `FC`
* - باستخدام `React.FC`، يقبل المكون ضمنيًا خاصية `children`
* حتى لو لم تكن محددة في نوع الخاصية. قد لا يكون هذا دائمًا
* مرغوبًا فيه، خاصةً إذا لم يكن المكون ينوي عرض
* الأطفال.
/* ❌ - 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;
@@ -86,7 +86,7 @@ const EmailField = ({ value }: EmailFieldProps) => (
تجنب استخدام انتشار متغير فردي للخصائص في عناصر JSX، مثل `{...props}`. غالبًا ما تؤدي هذه الممارسة إلى شكل تعليمي أقل قابلية للقراءة وأصعب في الصيانة لأنه من غير الواضح أي الخصائص يتلقاها المكون.
```tsx
/* ❌ - سيء، ينثر متغير فردي للخصائص في المكون الأساسي
/* ❌ - Bad, spreads a single variable prop into the underlying component
*/
const MyComponent = (props: OwnProps) => {
return <OtherComponent {...props} />;
@@ -137,12 +137,12 @@ onClick?.();
استخدم دائمًا `type` بدلاً من `interface`، لأنهما تقريبًا دائمًا متداخلين، و `type` أكثر مرونة.
```tsx
// ❌ سيء
// ❌ Bad
interface MyInterface {
name: string;
}
// ✅ جيد
// ✅ Good
type MyType = {
name: string;
};
@@ -155,7 +155,7 @@ type MyType = {
يمكنك معرفة السبب في أن TypeScript توصي بتجنب الأعداد [هنا](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).
```tsx
// ❌ سيء، يستخدم عدد مخصص
// ❌ Bad, utilizes an enum
enum Color {
Red = "red",
Green = "green",
@@ -263,13 +263,13 @@ const StyledButton = styled.button`
تجنب استيراد الأنواع. للحد من هذه الممارسة، تتحقق قاعدة ESLint وتبلغ عن أي استيرادات من هذا النوع. يساعد هذا على الحفاظ على الاتساق وقابلية القراءة في كود 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';
```
@@ -12,10 +12,10 @@ image: /images/user-guide/objects/objects.png
<Tabs>
<Tab title="استخدام">
```jsx
27332A4A31272F { 2A2F2E4A44 274435483129 } 4546 "@/ui/input/components/ImageInput";
import { ImageInput } from "@/ui/input/components/ImageInput";
27352F31 45434852464A 27442E2735 = () => {
39482F 2A2F2E44 274435483129/>
export const MyComponent = () => {
return <ImageInput/>;
};
```
</Tab>
@@ -17,10 +17,10 @@ Renders a breadcrumb navigation bar.
export const MyComponent = () => {
const breadcrumbLinks = [
{ children: "الصفحة الرئيسية", href: "/" },
{ children: "الفئة", href: "/category" },
{ children: "الفئة الفرعية", href: "/category/subcategory" },
{ children: "الصفحة الحالية" },
{ children: "Home", href: "/" },
{ children: "Category", href: "/category" },
{ children: "Subcategory", href: "/category/subcategory" },
{ children: "Current Page" },
];
return (
@@ -71,13 +71,13 @@ image: /images/user-guide/kanban-views/kanban.png
export const MyComponent = () => {
const handleCommandClick = () => {
console.log("تم النقر على الأمر!");
console.log("Command clicked!");
};
return (
<MenuItemCommand
LeftIcon={IconBell}
text="الخيار الأول"
text="First Option"
firstHotKey="⌘"
secondHotKey="1"
isSelected={true}
@@ -115,7 +115,7 @@ image: /images/user-guide/kanban-views/kanban.png
export const MyComponent = () => {
const handleMenuItemClick = (event) => {
console.log("تم النقر على عنصر القائمة!", event);
console.log("Menu item clicked!", event);
};
return (
@@ -125,7 +125,7 @@ image: /images/user-guide/kanban-views/kanban.png
iconButtons={[{ Icon: IconAlertCircle, onClick: handleButtonClick }]}
isTooltipOpen={false}
onClick={handleMenuItemClick}
text="عنصر القائمة القابل للسحب"
text="Menu item draggable"
isDragDisabled={false}
className
/>
@@ -163,7 +163,7 @@ image: /images/user-guide/kanban-views/kanban.png
return (
<MenuItemMultiSelect
LeftIcon={IconBell}
text="الخيار الأول"
text="First Option"
selected={false}
className
/>
@@ -198,8 +198,8 @@ image: /images/user-guide/kanban-views/kanban.png
return (
<MenuItemMultiSelectAvatar
avatar={<img src={imageUrl} alt="الصورة الرمزبية" />}
text="الخيار الأول"
avatar={<img src={imageUrl} alt="Avatar" />}
text="First Option"
selected={false}
className
/>
@@ -231,13 +231,13 @@ A menu item featuring an optional left icon, textual content, and a right-chevro
export const MyComponent = () => {
const handleNavigation = () => {
console.log("التنقل إلى صفحة أخرى");
console.log("Navigate to another page");
};
return (
<MenuItemNavigate
LeftIcon={IconBell}
text="الخيار الأول"
text="First Option"
onClick={handleNavigation}
className
/>
@@ -268,13 +268,13 @@ A menu item featuring an optional left icon, textual content, and a right-chevro
export const MyComponent = () => {
const handleSelection = () => {
console.log("تم اختيار عنصر القائمة");
console.log("Menu item selected");
};
return (
<MenuItemSelect
LeftIcon={IconBell}
text="الخيار الأول"
text="First Option"
selected={true}
disabled={false}
hovered={false}
@@ -354,20 +354,20 @@ A selectable menu item with a color sample for scenarios where you want users to
<Tabs>
<Tab title="الاستخدام">
```jsx
استيراد {MenuItemSelectColor} من "twenty-ui/display";
import { MenuItemSelectColor } from "twenty-ui/display";
تصدير المكون الخاص بي = () => {
export const MyComponent = () => {
const handleSelection = () => {
console.log("تم اختيار عنصر القائمة");
console.log("Menu item selected");
};
return (
<MenuItemSelectColor
color="أخضر"
color="green"
selected={true}
disabled={false}
hovered={true}
variant="افتراضي"
variant="default"
onClick={handleSelection}
className
/>
@@ -396,18 +396,18 @@ A selectable menu item with a color sample for scenarios where you want users to
<Tabs>
<Tab title="الاستخدام">
```jsx
استيراد {IconBell} من '@tabler/icons-react';
import { IconBell } from '@tabler/icons-react';
استيراد {MenuItemToggle} من 'twenty-ui/display';
import { MenuItemToggle } from 'twenty-ui/display';
تصدير المكون الخاص بي = () => {
export const MyComponent = () => {
return (
<MenuItemToggle
LeftIcon={IconBell}
text="الخيار الأول"
text="First Option"
toggled={true}
toggleSize="صغير"
toggleSize="small"
className
/>
);
@@ -12,30 +12,30 @@ image: /images/user-guide/table-views/table.png
<Tabs>
<Tab title="استخدام">
```jsx
استيراد { IconHome, IconUser, IconSettings } من '@tabler/icons-react';
استيراد { NavigationBar } من "@/ui/navigation/navigation-bar/components/NavigationBar";
import { IconHome, IconUser, IconSettings } from '@tabler/icons-react';
import { NavigationBar } from "@/ui/navigation/navigation-bar/components/NavigationBar";
export const MyComponent = () => {
const navigationItems = [
{
name: "الصفحة الرئيسية",
name: "Home",
Icon: IconHome,
onClick: () => console.log("تم النقر على الصفحة الرئيسية"),
onClick: () => console.log("Home clicked"),
},
{
name: "الملف الشخصي",
name: "Profile",
Icon: IconUser,
onClick: () => console.log("تم النقر على الملف الشخصي"),
onClick: () => console.log("Profile clicked"),
},
{
name: "الإعدادات",
name: "Settings",
Icon: IconSettings,
onClick: () => console.log("تم النقر على الإعدادات"),
onClick: () => console.log("Settings clicked"),
},
];
return <NavigationBar activeItemName="الصفحة الرئيسية" items={navigationItems}/>;
return <NavigationBar activeItemName="Home" items={navigationItems}/>;
};
```
</Tab>
@@ -17,9 +17,9 @@ image: /images/user-guide/api/api.png
export const MyComponent = () => {
return (
<StepBar activeStep={2}>
<StepBar.Step>الخطوة 1</StepBar.Step>
<StepBar.Step>الخطوة 2</StepBar.Step>
<StepBar.Step>الخطوة 3</StepBar.Step>
<StepBar.Step>Step 1</StepBar.Step>
<StepBar.Step>Step 2</StepBar.Step>
<StepBar.Step>Step 3</StepBar.Step>
</StepBar>
);
};
@@ -1,6 +1,6 @@
---
title: الفوترة
description: Understand Twenty pricing and manage your subscription.
description: تعرّف على تسعير Twenty وأدِر اشتراكك.
image: /images/user-guide/setup/pricing.png
---
@@ -8,38 +8,38 @@ image: /images/user-guide/setup/pricing.png
<img src="/images/user-guide/setup/pricing.png" alt="الفوترة" />
</Frame>
Twenty offers flexible pricing plans to fit your team's needs. Manage your subscription, track workflow credits, and access invoices all from **Settings → Billing**.
تقدّم Twenty خطط تسعير مرنة لتلبية احتياجات فريقك. أدِر اشتراكك، وتتبع أرصدة سير العمل، واطّلع على الفواتير — وكل ذلك من **Settings → Billing**.
## What's in this section
## ما الذي يتضمنه هذا القسم
<CardGroup cols={٢}>
<Card title="Pricing Plans" icon="tags" href="/l/ar/user-guide/billing/capabilities/pricing-plans">
Learn about Twenty's pricing plans and what's included.
<Card title="خطط التسعير" icon="tags" href="/l/ar/user-guide/billing/capabilities/pricing-plans">
تعرّف على خطط تسعير Twenty وما تتضمنه.
</Card>
<Card title="FAQ" icon="circle-question" href="/l/ar/user-guide/billing/how-tos/billing-faq">
Frequently asked questions about pricing and billing.
<Card title="الأسئلة الشائعة" icon="circle-question" href="/l/ar/user-guide/billing/how-tos/billing-faq">
أسئلة شائعة حول التسعير والفوترة.
</Card>
</CardGroup>
## At a glance
## نظرة سريعة
| الخطة | Key Features |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Free (Self-Hosted)** | All Pro features, community support |
| **Pro (Cloud)** | Everything apart from the Premium features (SSO and row-level permissions), standard support |
| **Organization (Cloud)** | All from Pro + the Premium features (SSO and row-level permissions), priority support |
| **Organization (Self-Hosted)** | All from Pro + the Premium features (SSO, row-level permissions), Twenty team support, not required to publish your custom code as open-source before distributing |
| الخطة | الميزات الرئيسية |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| **مجانًا (مستضاف ذاتيًا)** | جميع ميزات Pro، ودعم المجتمع |
| **Pro (سحابي)** | كل شيء باستثناء ميزات Premium (SSO وأذونات على مستوى الصف)، دعم قياسي |
| **المؤسسة (سحابي)** | كل ما في Pro + ميزات Premium (SSO وأذونات على مستوى الصف)، دعم ذو أولوية |
| **المؤسسة (مستضاف ذاتيًا)** | كل ما في Pro + ميزات Premium (SSO وأذونات على مستوى الصف)، دعم فريق Twenty، ولا يُشترط نشر شيفرتك المخصصة كمصدر مفتوح قبل التوزيع |
## Quick answers
## إجابات سريعة
**Where do I manage billing?**
Go to **Settings → Billing** to view your plan, update payment methods, and access invoices.
**أين أدير الفوترة؟**
انتقل إلى **Settings → Billing** لعرض خطتك، وتحديث طرق الدفع، والوصول إلى الفواتير.
**Can I use Twenty for free?**
Yes! Self-host Twenty and get all Pro features at no cost.
**هل يمكنني استخدام Twenty مجانًا؟**
نعم! استضف Twenty ذاتيًا واحصل على جميع ميزات Pro دون تكلفة.
**How do I upgrade?**
Go to **Settings → Billing** and click **Switch to Organization** or **Switch to Yearly**.
**كيف أقوم بالترقية؟**
انتقل إلى **Settings → Billing** ثم انقر **Switch to Organization** أو **Switch to Yearly**.
For more questions, see the [Billing FAQ](/l/ar/user-guide/billing/how-tos/billing-faq).
لمزيد من الأسئلة، راجع [الأسئلة الشائعة حول الفوترة](/l/ar/user-guide/billing/how-tos/billing-faq).
@@ -1,19 +1,19 @@
---
title: تقويم
description: Understanding calendar integration features in Twenty.
description: فهم ميزات تكامل التقويم في Twenty.
---
**Note**: To connect your calendar and configure sync settings, visit [Email & Calendar Setup](/l/ar/user-guide/calendar-emails/overview).
**ملاحظة**: لربط تقويمك وتكوين إعدادات المزامنة، قم بزيارة [إعدادات البريد الإلكتروني والتقويم](/l/ar/user-guide/calendar-emails/overview).
## How Calendar Integration Works
## كيف يعمل تكامل التقويم
Twenty automatically syncs your calendar events and links them to the relevant CRM records, giving you a complete view of your meeting history with contacts and companies.
يقوم Twenty بمزامنة أحداث تقويمك تلقائيًا وربطها بسجلات CRM ذات الصلة، ما يمنحك عرضًا كاملاً لسجل اجتماعاتك مع جهات الاتصال والشركات.
## علامة تبويب التقويم
Next to the Emails tab on records, you'll find a `Calendar` tab that contains the history of meetings scheduled with the record.
بجانب علامة تبويب البريد الإلكتروني في السجلات، ستجد علامة تبويب `التقويم` التي تحتوي على سجلّ الاجتماعات المجدولة المرتبطة بذلك السجل.
### Available For
### متاح لـ
* **الأشخاص**: عرض جميع الاجتماعات المجدولة مع جهة اتصال محددة
* **الشركات**: راجع جميع الاجتماعات المتعلقة بشركة وموظفيها
@@ -26,18 +26,18 @@ Next to the Emails tab on records, you'll find a `Calendar` tab that contains th
3. **تصفح تاريخ الاجتماعات**: عرض جميع الاجتماعات المجدولة وتفاصيلها
4. **الوصول إلى سياق الاجتماع**: شاهد المشاركين في الاجتماع، الأوقات، والمعلومات ذات الصلة
## Visibility Settings
## إعدادات الرؤية
Calendar data follows the same visibility settings as emails, ensuring consistent privacy controls across both communication channels.
تتبع بيانات التقويم نفس إعدادات الرؤية الخاصة بالبريد الإلكتروني، مما يضمن ضوابط خصوصية متسقة عبر كلتا قناتي التواصل.
## What Gets Synced
## ما الذي يتم مزامنته
* **External Meetings**: All meetings with contacts outside your organization
* **Automatic Linking**: Meetings connect to existing People and Company records based on attendee email addresses
* **Meeting Details**: Subject, time, duration, and participants
* **Updates**: New calendar events sync automatically
* **الاجتماعات الخارجية**: جميع الاجتماعات مع جهات الاتصال خارج مؤسستك
* **الربط التلقائي**: ترتبط الاجتماعات بسجلات الأشخاص والشركات الحالية بناءً على عناوين البريد الإلكتروني للحضور
* **تفاصيل الاجتماع**: الموضوع، الوقت، المدة، والمشاركون
* **التحديثات**: تتم مزامنة أحداث التقويم الجديدة تلقائيًا
## ما لا يتم مزامنته
* **Internal Meetings**: Meetings with only colleagues (same domain) remain private
* **Private Events**: Events marked as private in your calendar
* **الاجتماعات الداخلية**: تبقى الاجتماعات مع الزملاء فقط (نفس النطاق) خاصة
* **الأحداث الخاصة**: الأحداث المعلَّمة كخاصة في تقويمك
@@ -1,59 +1,59 @@
---
title: Dashboards FAQ
description: Frequently asked questions about dashboards in Twenty.
description: أسئلة شائعة حول لوحات القيادة في Twenty.
---
<AccordionGroup>
<Accordion title="Can I create private dashboards?">
No, dashboards are currently visible to everyone with access to your Twenty workspace. Private dashboards are not yet available.
<Accordion title="هل يمكنني إنشاء لوحات قيادة خاصة؟">
لا، لوحات القيادة مرئية حاليًا لجميع من لديهم صلاحية الوصول إلى مساحة العمل الخاصة بك على Twenty. لوحات القيادة الخاصة غير متاحة بعد.
</Accordion>
<Accordion title="Why do my metrics look different from my colleague's?">
Dashboards currently display data based on the viewer's timezone. If you're in different regions (e.g., APAC vs. US), you may see slightly different numbers for the same dashboard. We're working on adding a timezone setting per dashboard to ensure consistent data across teams.
<Accordion title="لماذا تبدو مقاييسي مختلفة عن مقاييس زميلي؟">
تعرض لوحات القيادة حاليًا البيانات بناءً على المنطقة الزمنية للعارض. إذا كنتم في مناطق مختلفة (على سبيل المثال، APAC مقابل US)، فقد ترون أرقامًا مختلفة قليلًا للوحة القيادة نفسها. نعمل على إضافة إعداد للمنطقة الزمنية لكل لوحة قيادة لضمان اتساق البيانات عبر الفرق.
</Accordion>
<Accordion title="Can I export my dashboard?">
Exporting dashboards is not available at the moment. This feature is on our roadmap.
<Accordion title="هل يمكنني تصدير لوحة القيادة الخاصة بي؟">
تصدير لوحات القيادة غير متاح في الوقت الحالي. هذه الميزة مدرَجة على خارطة الطريق لدينا.
</Accordion>
<Accordion title="Can I share dashboards with external users?">
No, sharing dashboards with users outside your Twenty workspace (non-Twenty users) is not currently supported.
<Accordion title="هل يمكنني مشاركة لوحات القيادة مع مستخدمين خارجيين؟">
لا، مشاركة لوحات القيادة مع المستخدمين خارج مساحة العمل الخاصة بك على Twenty (غير مستخدمي Twenty) غير مدعومة حاليًا.
</Accordion>
<Accordion title="How do I add a dashboard to my favorites?">
Open the dashboard you want to favorite, then click the star icon. Favorites are personal—they won't affect other users.
<Accordion title="كيف أضيف لوحة قيادة إلى المفضلة لدي؟">
افتح لوحة القيادة التي تريد إضافتها إلى المفضلة، ثم انقر على أيقونة النجمة. المفضلة شخصية — ولن تؤثر في المستخدمين الآخرين.
</Accordion>
<Accordion title="What's the difference between tabs and widgets?">
* **Tabs** organize your dashboard into sections (like pages within the dashboard)
* **Widgets** are the individual visualizations (charts, numbers, iFrames) within each tab
<Accordion title="ما الفرق بين علامات التبويب وعناصر واجهة المستخدم؟">
* **علامات التبويب** تنظّم لوحة القيادة إلى أقسام (مثل صفحات داخل لوحة القيادة)
* **عناصر واجهة المستخدم** هي التصورات الفردية (مخططات، أرقام، وإطارات iFrame) داخل كل علامة تبويب
Structure: Dashboard → Tabs → Widgets
البنية: لوحة القيادة → علامات التبويب → عناصر واجهة المستخدم
</Accordion>
<Accordion title="Why do I see 'Undisplayed data' warning on my bar chart?">
Bar charts have display limits: 100 bars for horizontal charts, 50 for vertical. If your data exceeds this, add filters to narrow down the results or change the grouping (e.g., group by week instead of day).
<Accordion title="لماذا أرى تحذير 'بيانات غير معروضة' على مخطط الأعمدة الخاص بي؟">
لمخططات الأعمدة حدود عرض: 100 عمود للمخططات الأفقية، و50 للعمودية. إذا تجاوزت بياناتك ذلك، فأضِف عوامل تصفية لحصر النتائج أو غيّر أسلوب التجميع (على سبيل المثال، التجميع حسب الأسبوع بدلًا من اليوم).
</Accordion>
<Accordion title="Can I filter an entire dashboard at once?">
Dashboard-level filters are not available yet, but this feature is on our roadmap. Currently, you need to apply filters to each widget individually.
<Accordion title="هل يمكنني تصفية لوحة القيادة بالكامل دفعة واحدة؟">
عوامل التصفية على مستوى لوحة القيادة غير متاحة بعد، لكن هذه الميزة مدرَجة على خارطة الطريق لدينا. حاليًا، تحتاج إلى تطبيق عوامل التصفية على كل عنصر واجهة مستخدم على حدة.
</Accordion>
<Accordion title="Are gauge charts or tables available?">
ليس بعد. Gauge charts and tables are on our roadmap and will be added in a future release.
<Accordion title="هل مخططات العدّاد أو الجداول متاحة؟">
ليس بعد. مخططات العدّاد والجداول مدرَجة على خارطة الطريق لدينا وسيتم إضافتها في إصدار لاحق.
</Accordion>
<Accordion title="How do I duplicate a dashboard?">
1. Make sure you're in view mode (not editing)
2. Open the command bar with **Cmd + K** (or **Ctrl + K** on Windows)
3. Select **Duplicate dashboard**
<Accordion title="كيف أُكرّر لوحة قيادة؟">
1. تأكد من أنك في وضع العرض (وليس التحرير)
2. افتح شريط الأوامر باستخدام **Cmd + K** (أو **Ctrl + K** على Windows)
3. اختر **تكرار لوحة القيادة**
</Accordion>
<Accordion title="How often does dashboard data refresh?">
Widgets update automatically as your CRM data changes:
<Accordion title="ما مدى تكرار تحديث بيانات لوحة القيادة؟">
تتحدّث عناصر واجهة المستخدم تلقائيًا مع تغيّر بيانات نظام إدارة علاقات العملاء (CRM):
* Real-time updates for most metrics
* Use the refresh button for a manual update if needed
* Historical data is preserved for trend analysis
* تحديثات فورية لمعظم المقاييس
* استخدم زر التحديث لإجراء تحديث يدوي عند الحاجة
* تُحفَظ البيانات التاريخية لتحليل الاتجاهات
</Accordion>
</AccordionGroup>
@@ -1,176 +1,176 @@
---
title: Field Mapping
description: How field mapping works during data import.
title: تعيين الحقول
description: كيف يعمل تعيين الحقول أثناء استيراد البيانات.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## How Field Mapping Works
## كيف يعمل تعيين الحقول
When you upload a file, Twenty analyzes your columns and attempts to match them to existing fields.
عند تحميل ملف، يقوم Twenty بتحليل أعمدتك ومحاولة مطابقتها مع الحقول الموجودة.
### Automatic Mapping
### التعيين التلقائي
Twenty tries to match columns based on:
يحاول Twenty مطابقة الأعمدة استنادًا إلى:
* Column header names (exact or similar matches)
* Data type detection (dates, numbers, emails)
* Common field patterns
* أسماء رؤوس الأعمدة (مطابقات دقيقة أو متشابهة)
* اكتشاف نوع البيانات (تواريخ، أرقام، عناوين بريد إلكتروني)
* أنماط الحقول الشائعة
<Note>**Quick tip:** Export a few rows from the object you want to import. The exported file will have the exact column names Twenty expects, making automatic mapping seamless during import.</Note>
<Note>**نصيحة سريعة:** صدِّر بضعة صفوف من الكائن الذي تريد استيراده. سيحتوي الملف المصدَّر على أسماء الأعمدة الدقيقة التي يتوقعها Twenty، مما يجعل التعيين التلقائي سلسًا أثناء الاستيراد.</Note>
### Manual Mapping Options
### خيارات التعيين اليدوي
For each column, you can:
لكل عمود، يمكنك:
* **Map to a field**: Select the matching Twenty field from a dropdown
* **Do not map**: Skip the column entirely (data won't be imported)
* **تعيين إلى حقل**: اختر الحقل المطابق في Twenty من قائمة منسدلة
* **عدم التعيين**: تخطَّ العمود بالكامل (لن يتم استيراد البيانات)
<Note>**Fields must exist before import.** The import creates records, not fields. Create custom fields under **Settings → Data Model** before importing.</Note>
<Note>**يجب أن تكون الحقول موجودة قبل الاستيراد.** الاستيراد يُنشئ السجلات، لا الحقول. أنشئ الحقول المخصصة ضمن **الإعدادات → نموذج البيانات** قبل الاستيراد.</Note>
## Field Type Compatibility
## توافق أنواع الحقول
All field types available in the Data Model are supported for import.
جميع أنواع الحقول المتاحة في نموذج البيانات مدعومة للاستيراد.
You can also import `id` values to either assign a specific ID to new records or update existing ones.
يمكنك أيضًا استيراد قيم `id` إما لتعيين معرّف محدد للسجلات الجديدة أو لتحديث السجلات القائمة.
<img src="/images/user-guide/fields/all-field-types.png" style={{width:'100%'}} />
## Data Format Requirements
## متطلبات تنسيق البيانات
<Note>**Some fields have special syntax.** We recommend downloading the sample file before preparing your import to see the expected syntax for each field type.</Note>
<Note>**لبعض الحقول صياغة خاصة.** نوصي بتنزيل الملف النموذجي قبل إعداد عملية الاستيراد للاطلاع على الصياغة المتوقعة لكل نوع حقل.</Note>
### Address Fields
### حقول العنوان
Address is a nested field with multiple columns. Some can be left empty.
العنوان حقل متداخل يضم عدة أعمدة. يمكن ترك بعضِها فارغًا.
* **Address / Address 1**: Street address line 1
* **Address / Address 2**: Street address line 2
* **Address / City**: City name
* **Address / State**: State or province
* **Address / Country**: Country name
* **Address / Post Code**: Postal/ZIP code
* **Address / Address 1**: سطر عنوان الشارع 1
* **Address / Address 2**: سطر عنوان الشارع 2
* **Address / City**: اسم المدينة
* **Address / State**: الولاية أو المقاطعة
* **Address / Country**: اسم الدولة
* **Address / Post Code**: الرمز البريدي/ZIP
### Array Fields
### حقول المصفوفة
Use the following format:
استخدم التنسيق التالي:
```
["value1","value2"]
[\"value1\",\"value2\"]
```
### Boolean Fields
### حقول القيم المنطقية
Use `TRUE` or `FALSE` (uppercase) - not `true` or `false`
استخدم `TRUE` أو `FALSE` (أحرف كبيرة) - وليس `true` أو `false`
### Currency Fields
### حقول العملة
Currency is a nested field with two columns that **both must be filled**:
العملة حقل متداخل يحتوي على عمودين يجب **ملؤهما كلاهما**:
* **Amount / Amount**: The numeric value (e.g., `1234.56`)
* **Amount / Currency**: The currency code (e.g., `USD`, `EUR`)
* **Amount / Amount**: القيمة الرقمية (مثال: `1234.56`)
* **Amount / Currency**: رمز العملة (مثال: `USD`، `EUR`)
### Date Fields
### حقول التاريخ
Supported formats:
التنسيقات المدعومة:
* `YYYY-MM-DD` (recommended)
* `YYYY-MM-DD` (موصى به)
* `MM/DD/YYYY`
* `DD/MM/YYYY`
* ISO 8601 format
* تنسيق ISO 8601
### Domain Fields
### حقول النطاق
* It is recommended to use the format `https://domain.com` to avoid creating duplicates, as this is the format used for Companies created by the mailbox and calendar synchronizations
* A `Domain Label` and `Domain URL` can be filled: best practice is to fill `domain.com` in the label and `https://domain.com` in the url
* Domains must be unique within the Companies object
* **Domains must be unique within the file to import**
* يُوصى باستخدام التنسيق `https://domain.com` لتجنب إنشاء التكرارات، إذ إن هذا هو التنسيق المستخدم للشركات التي يتم إنشاؤها عبر مزامنة صندوق البريد والتقويم
* يمكن ملء حقلي `Domain Label` و`Domain URL`: وأفضل ممارسة هي وضع `domain.com` في التسمية و`https://domain.com` في عنوان URL
* يجب أن تكون النطاقات فريدة داخل كائن الشركات
* **يجب أن تكون النطاقات فريدة داخل الملف المُراد استيراده**
### Email Fields
### حقول البريد الإلكتروني
* Must be valid email format
* Emails must be unique within the People object
* **Emails must be unique within the file to import**
* For additional emails: use **Emails / Primary Email** for the main email, and **Emails / Additional Emails** with this format:
* يجب أن تكون بتنسيق بريد إلكتروني صحيح
* يجب أن تكون عناوين البريد الإلكتروني فريدة داخل كائن الأشخاص
* **يجب أن تكون عناوين البريد الإلكتروني فريدة داخل الملف المُراد استيراده**
* للبريد الإلكتروني الإضافي: استخدم **Emails / Primary Email** للبريد الرئيسي، و**Emails / Additional Emails** بهذا التنسيق:
```
["jane@twenty.com","jane.doe@twenty.com"]
[\"jane@twenty.com\",\"jane.doe@twenty.com\"]
```
### Id Fields
### حقول المعرّف
Specifying an `id` during import is optional. Twenty auto-generates one if not provided.
تحديد `id` أثناء الاستيراد اختياري. يقوم Twenty بإنشاء واحد تلقائيًا إذا لم يتم توفيره.
Use cases for mapping an `id` column:
حالات استخدام لتعيين عمود `id`:
* **Set a specific ID**: Choose the UUID for newly created records
* **Update existing records**: Match against existing records to update them instead of creating duplicates. In that case, it is recommended to not map the other unique fields: mapping only one unique field ensures a smoother import.
* **تعيين معرّف محدد**: اختر UUID للسجلات التي سيتم إنشاؤها
* **تحديث السجلات الحالية**: طابِق السجلات الحالية لتحديثها بدلاً من إنشاء تكرارات. في هذه الحالة، يُنصح بعدم تعيين الحقول الفريدة الأخرى: فاقتصار التعيين على حقل فريد واحد يضمن عملية استيراد أكثر سلاسة.
<Note>If you provide an `id`, it must be in UUID format (e.g., `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`).</Note>
<Note>إذا قدّمت قيمة `id`، فيجب أن تكون بتنسيق UUID (مثال: `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`).</Note>
### JSON Fields
### حقول JSON
Use valid JSON format:
استخدم تنسيق JSON صالحًا:
```
{"key":"value","key2":"value2"}
```
### Links Fields
### حقول الروابط
Similar to Domain fields:
مشابه لحقول النطاق:
* Fill both the label and URL columns: **Links / Link URL** and **Links / Link Label**
* Use full URL format: `https://example.com`
* For secondary links, use **Links / Secondary Links** column with this format:
* املأ عمودي التسمية والرابط معًا: **Links / Link URL** و**Links / Link Label**
* استخدم تنسيق الرابط الكامل: `https://example.com`
* للروابط الثانوية، استخدم عمود **Links / Secondary Links** بهذا التنسيق:
```
[{"url":"https://twenty.com","label":"Twenty"}]
[{\"url\":\"https://twenty.com\",\"label\":\"Twenty\"}]
```
### Multi-Select Fields
### حقول التحديد المتعدد
Use the **API names** (not the display labels) in the following format:
استخدم **أسماء واجهة برمجة التطبيقات (API)** (وليس تسميات العرض) بالتنسيق التالي:
```
["VALUE1","VALUE2"]
[\"VALUE1\",\"VALUE2\"]
```
See [here](#finding-api-names-for-select-fields) where to find the API names.
اطّلع [هنا](#finding-api-names-for-select-fields) لمعرفة مكان العثور على أسماء واجهة برمجة التطبيقات.
<Note>New select options will not be created automatically by the import. They must be added under **Settings → Data Model** before importing.</Note>
<Note>لن يتم إنشاء خيارات التحديد الجديدة تلقائيًا بواسطة الاستيراد. يجب إضافتها ضمن **الإعدادات → نموذج البيانات** قبل الاستيراد.</Note>
<Warning>
**Import overwrites, it does not add.**
**الاستيراد يستبدل، لا يضيف.**
If a record already has `VALUE2` and `VALUE3` selected, and you import `["VALUE1"]`, the record will only have `VALUE1` after import. The previous selections are replaced, not merged.
إذا كان السجل يحتوي بالفعل على `VALUE2` و`VALUE3` محدّدين، ثم استوردت `[\"VALUE1\"]`، فسيحتوي السجل على `VALUE1` فقط بعد الاستيراد. يتم استبدال التحديدات السابقة، وليس دمجها.
</Warning>
### Number Fields
### حقول الأرقام
* Numbers only
* Decimals use period: `1234.56`
* No thousands separators
* أرقام فقط
* تُكتب الكسور العشرية بنقطة: `1234.56`
* من دون فواصل آلاف
### Phone Fields
### حقول الهاتف
Phone is a nested field with multiple columns that **must be filled**
الهاتف حقل متداخل يضم عدة أعمدة يجب **ملؤها**
* **Phones / Primary Phone Number**: The phone number (e.g., `4159095555`)
* **Phones / Primary Phone Country Code**: Country code (e.g., `US`)
* **Phones / Primary Phone Calling Code**: Dialing code (e.g., `+1`)
* **Phones / Primary Phone Number**: رقم الهاتف (مثال: `4159095555`)
* **Phones / Primary Phone Country Code**: رمز الدولة (مثال: `US`)
* **Phones / Primary Phone Calling Code**: رمز الاتصال (مثال: `+1`)
### Rating Fields
### حقول التقييم
Use the API name format: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4`, `RATING_5`
استخدم تنسيق اسم واجهة برمجة التطبيقات: `RATING_1`، `RATING_2`، `RATING_3`، `RATING_4`، `RATING_5`
### حقول العلاقات
Please see our dedicated article: [Import Relations Between Objects](/l/ar/user-guide/data-migration/capabilities/import-relations)
يرجى الاطّلاع على مقالتنا المخصّصة: [استيراد العلاقات بين الكائنات](/l/ar/user-guide/data-migration/capabilities/import-relations)
### حقول الاختيار
Use the **API name** of the option (not the display label):
استخدم **اسم واجهة برمجة التطبيقات** للخيار (وليس تسمية العرض):
```
VALUE1
@@ -1,5 +1,5 @@
---
title: التحويل من أنظمة إدارة علاقات العملاء الأخرى},{
title: Migrating from Other CRMs
description: Step-by-step guide to migrate your data from any CRM to Twenty.
---
@@ -1,5 +1,5 @@
---
title: حضِّر ملفات CSV الخاصة بك},{
title: Prepare Your CSV Files
description: دليل كامل خطوة بخطوة لتنسيق بياناتك لاستيرادها إلى Twenty.
---
@@ -87,114 +87,114 @@ description: دليل كامل خطوة بخطوة لتنسيق بياناتك
| **Phones / Primary Phone Country Code** | `US` |
| **Phones / Primary Phone Calling Code** | `+1` |
### Address Fields
### حقول العنوان
Address is a **nested field** with multiple columns (some can be left empty):
العنوان هو **حقل متداخل** يحتوي على أعمدة متعددة (يمكن ترك بعضها فارغًا):
* **Address / Address 1**: Street address line 1
* **Address / Address 2**: Street address line 2 (optional)
* **Address / City**: City name
* **Address / State**: State or province
* **Address / Country**: Country name
* **Address / Post Code**: Postal/ZIP code
* **العنوان / العنوان 1**: السطر الأول لعنوان الشارع
* **العنوان / العنوان 2**: السطر الثاني لعنوان الشارع (اختياري)
* **العنوان / المدينة**: اسم المدينة
* **العنوان / الولاية**: ولاية أو مقاطعة
* **العنوان / البلد**: اسم البلد
* **العنوان / الرمز البريدي**: رمز بريدي/ZIP
### Date Fields
### حقول التاريخ
Use consistent formatting throughout your file:
استخدم تنسيقًا موحدًا في كامل ملفك:
* `YYYY-MM-DD` (recommended): `2024-03-15`
* `YYYY-MM-DD` (مُوصى به): `2024-03-15`
* `MM/DD/YYYY`: `03/15/2024`
* `DD/MM/YYYY`: `15/03/2024`
* ISO 8601: `2024-03-15T10:30:00Z`
### Number Fields
### حقول الأرقام
* Numbers only (no text)
* Use period for decimals: `1234.56`
* No thousands separators (not `1,234.56`)
* أرقام فقط (بدون نص)
* استخدم النقطة للفواصل العشرية: `1234.56`
* بدون فواصل لآلاف الأرقام (ليس `1,234.56`)
### Currency Fields
### حقول العملة
Currency is a **nested field** requiring two columns that **both must be filled**:
العملة هي **حقل متداخل** يتطلب عمودين يجب **ملؤهما كليهما**:
| Column | مثال |
| --------------------- | --------- |
| **Amount / Amount** | `1234.56` |
| **Amount / Currency** | `USD` |
| العمود | مثال |
| ------------------- | --------- |
| **المبلغ / المبلغ** | `1234.56` |
| **المبلغ / العملة** | `USD` |
### Boolean Fields
### حقول منطقية
Use uppercase: `TRUE` or `FALSE`
استخدم أحرفًا كبيرة: `TRUE` أو `FALSE`
<Warning>Lowercase `true` or `false` will not work.</Warning>
<Warning>الأحرف الصغيرة `true` أو `false` لن تعمل.</Warning>
### اختر الحقول
Use the **API name** of the option, not the display label.
استخدم **اسم واجهة برمجة التطبيقات (API)** للخيار، وليس اسم العرض.
**How to find API names:**
**كيفية العثور على أسماء واجهة برمجة التطبيقات (API):**
1. Go to **Settings → Data Model**
2. Select the object and field
3. Enable **Advanced mode** (toggle at bottom right)
4. Copy the API name (e.g., `OPTION_1`, not "Option 1")
1. انتقل إلى **الإعدادات → نموذج البيانات**
2. اختر الكائن والحقل
3. فعّل **الوضع المتقدم** (المبدّل في أسفل اليمين)
4. انسخ اسم واجهة برمجة التطبيقات (مثال: `OPTION_1`، وليس "Option 1")
<Note>New select options are not created automatically. Add them in **Settings → Data Model** before importing.</Note>
<Note>خيارات الاختيار الجديدة لا يتم إنشاؤها تلقائيًا. أضِفها في **الإعدادات → نموذج البيانات** قبل الاستيراد.</Note>
### Multi-Select Fields
### حقول متعددة الاختيار
Use API names in array format:
استخدم أسماء واجهة برمجة التطبيقات بصيغة المصفوفة:
```
["VALUE1","VALUE2"]
```
### Array Fields
### حقول المصفوفة
Use JSON array format:
استخدم صيغة مصفوفة JSON:
```
["value1","value2"]
```
### Rating Fields
### حقول التقييم
Use the format: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4`, or `RATING_5`
استخدم الصيغة: `RATING_1` و`RATING_2` و`RATING_3` و`RATING_4` أو `RATING_5`
### Links/URL Fields
### حقول الروابط/عناوين URL
Fill both columns:
املأ كلا العمودين:
* **Links / Link Label**: `Twenty`
* **Links / Link URL**: `https://twenty.com`
* **الروابط / تسمية الرابط**: `Twenty`
* **الروابط / عنوان URL للرابط**: `https://twenty.com`
For secondary links, use the **Links / Secondary Links** column:
بالنسبة للروابط الثانوية، استخدم عمود **الروابط / الروابط الثانوية**:
```
[{"url":"https://twenty.com","label":"Twenty"}]
```
### JSON Fields
### حقول JSON
Use valid JSON format:
استخدم تنسيق JSON صالحًا:
```
{"key":"value","key2":"value2"}
```
### ID Fields
### حقول المعرّف
* **Optional**: Twenty auto-generates IDs if not provided
* **Format**: UUID (e.g., `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`)
* **Use case**: Include ID to update existing records instead of creating new ones
* **اختياري**: يقوم Twenty بإنشاء المعرّفات تلقائيًا إذا لم تُوفَّر
* **التنسيق**: UUID (مثلًا: `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`)
* **حالة الاستخدام**: تضمين المعرّف لتحديث السجلات الموجودة بدلًا من إنشاء سجلات جديدة
## Step 5: Add Relation Columns (If Linking Records)
## الخطوة 5: إضافة أعمدة العلاقات (إذا كنت تربط السجلات)
To link records to other objects (e.g., People to Companies), add a column with the unique identifier of the related record.
لربط السجلات بكائنات أخرى (مثل الأشخاص بالشركات)، أضِف عمودًا يحتوي على المعرّف الفريد للسجل المرتبط.
**Example**: Linking People to Companies
**مثال**: ربط الأشخاص بالشركات
Add a column to your People CSV:
أضِف عمودًا إلى ملف CSV الخاص بالأشخاص:
```
firstName,lastName,email,companyDomain
@@ -202,69 +202,69 @@ John,Smith,john@acme.com,https://acme.com
Jane,Doe,jane@widgets.co,https://widgets.co
```
**Important rules for relations:**
**قواعد مهمة للعلاقات:**
* The parent record must already exist in Twenty
* Use the **Domain URL** format (`https://domain.com`), not the label
* Map only ONE unique identifier (don't include both `companyId` AND `companyDomain`)
* For Workspace Members, use their **email** (not name)
* يجب أن يكون السجل الأب موجودًا مسبقًا في Twenty
* استخدم صيغة **عنوان المجال (Domain URL)** (`https://domain.com`) وليس التسمية
* قم بربط مُعرّف فريد واحد فقط (لا تُدرج كلاً من `companyId` و`companyDomain`)
* بالنسبة لأعضاء مساحة العمل، استخدم **البريد الإلكتروني** الخاص بهم (وليس الاسم)
<Warning>
**Import Order Matters!**
**ترتيب الاستيراد مهم!**
Import the "one" side before the "many" side:
استورد طرف "الواحد" قبل طرف "الكثير":
1. **Companies** first
2. **People** second (with company reference)
3. **Opportunities** third
1. **الشركات** أولاً
2. **الأشخاص** ثانيًا (مع مرجع الشركة)
3. **الفرص** ثالثًا
The parent record must exist before you can reference it.
يجب أن يوجد السجل الأب قبل أن تتمكن من الإشارة إليه.
</Warning>
See [How to Import Relations](/l/ar/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) for detailed instructions.
اطلع على [كيفية استيراد العلاقات](/l/ar/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) للحصول على تعليمات مفصلة.
## Step 6: Ensure Fields Exist in Twenty
## الخطوة 6: تأكد من وجود الحقول في Twenty
The import creates **records**, not **fields**. All fields you want to import must already exist in your data model.
تقوم عملية الاستيراد بإنشاء **سجلات**، وليس **حقولًا**. يجب أن تكون جميع الحقول التي تريد استيرادها موجودة مسبقًا في نموذج البيانات لديك.
**Before importing:**
**قبل الاستيراد:**
1. Go to **Settings → Data Model**
2. Select your object
3. Create any custom fields you need
4. Note the exact field names (they must match your column headers)
1. انتقل إلى **الإعدادات → نموذج البيانات**
2. اختر الكائن الخاص بك
3. أنشئ أي حقول مخصصة تحتاجها
4. دوّن أسماء الحقول بدقة (يجب أن تتطابق مع عناوين أعمدتك)
## Step 7: Final Checklist
## الخطوة 7: قائمة التحقق النهائية
Before uploading your file, verify:
قبل رفع ملفك، تحقّق مما يلي:
<Check>File is CSV, XLSX, or XLS format</Check>
<Check>File has fewer than 10,000 records</Check>
<Check>Encoding is UTF-8</Check>
<Check>No duplicate emails (for People) or domains (for Companies)</Check>
<Check>Dates use consistent format throughout</Check>
<Check>Domains use `https://domain.com` format</Check>
<Check>Boolean fields use `TRUE` or `FALSE` (uppercase)</Check>
<Check>Select fields use API names, not display labels</Check>
<Check>All custom fields exist in Settings → Data Model</Check>
<Check>Parent records imported before child records</Check>
<Check>Relation columns reference existing records</Check>
<Check>الملف بصيغة CSV أو XLSX أو XLS</Check>
<Check>يحتوي الملف على أقل من 10,000 سجل</Check>
<Check>الترميز UTF-8</Check>
<Check>لا توجد رسائل بريد إلكتروني مكررة (للأشخاص) أو نطاقات (للشركات)</Check>
<Check>التواريخ تستخدم تنسيقًا موحدًا طوال الملف</Check>
<Check>النطاقات تستخدم الصيغة `https://domain.com`</Check>
<Check>الحقول المنطقية تستخدم `TRUE` أو `FALSE` (أحرف كبيرة)</Check>
<Check>حقول الاختيار تستخدم أسماء واجهة برمجة التطبيقات، وليس أسماء العرض</Check>
<Check>جميع الحقول المخصصة موجودة في الإعدادات → نموذج البيانات</Check>
<Check>تم استيراد السجلات الأصلية قبل السجلات الفرعية</Check>
<Check>أعمدة العلاقات تشير إلى سجلات موجودة</Check>
## Common Mistakes to Avoid
## أخطاء شائعة يجب تجنبها
| Mistake | Solution |
| -------------------------------------------- | ------------------------------------- |
| Using `true` instead of `TRUE` | Boolean values must be uppercase |
| Using display labels for Select fields | Find and use API names in Settings |
| Importing People before Companies | Always import parent objects first |
| Missing currency code for Currency fields | Fill both Amount and Currency columns |
| Wrong domain format | Use `https://domain.com` consistently |
| Mapping multiple unique fields for relations | Map only ONE (domain OR id, not both) |
| الخطأ | الحل |
| ---------------------------------- | ----------------------------------------------------------- |
| استخدام `true` بدلًا من `TRUE` | يجب أن تكون القيم المنطقية بأحرف كبيرة |
| استخدام أسماء العرض لحقول الاختيار | اعثر على أسماء واجهة برمجة التطبيقات في الإعدادات واستخدمها |
| استيراد الأشخاص قبل الشركات | احرص دائمًا على استيراد الكائنات الأصل أولًا |
| رمز العملة مفقود لحقول العملة | املأ عمودي المبلغ والعملة معًا |
| تنسيق نطاق غير صحيح | استخدم `https://domain.com` بصورة متسقة |
| ربط عدة حقول فريدة للعلاقات | اربط حقلًا واحدًا فقط (النطاق أو المعرّف، وليس كليهما) |
## الخطوات التالية
Your file is ready! Now:
ملفك جاهز! الآن:
* [Import Companies](/l/ar/user-guide/data-migration/how-tos/import-companies-via-csv) (import these first)
* [Import Contacts](/l/ar/user-guide/data-migration/how-tos/import-contacts-via-csv)
* [Fix any import errors](/l/ar/user-guide/data-migration/how-tos/fix-import-errors)
* [استيراد الشركات](/l/ar/user-guide/data-migration/how-tos/import-companies-via-csv) (قم باستيرادها أولًا)
* [استيراد جهات الاتصال](/l/ar/user-guide/data-migration/how-tos/import-contacts-via-csv)
* [إصلاح أي أخطاء في الاستيراد](/l/ar/user-guide/data-migration/how-tos/fix-import-errors)
@@ -1,5 +1,5 @@
---
title: ترحيل البيانات},{
title: Data Migration
description: استيراد وتصدير بيانات CRM عبر ملفات CSV أو عبر API.
image: /images/user-guide/import-export-data/cloud.png
---
@@ -1,60 +1,60 @@
---
title: Create Relation Fields
description: Step-by-step guide to connecting objects with relation fields.
description: دليل خطوة بخطوة لربط الكائنات باستخدام حقول العلاقة.
---
Relation fields connect records from different objects—for example, linking People to Companies.
تربط حقول العلاقة السجلات من كائنات مختلفة—على سبيل المثال، ربط الأشخاص بالشركات.
<Note>
**Relation names cannot be changed after creation** (they affect the API). Plan your names carefully.
**لا يمكن تغيير أسماء العلاقات بعد إنشائها** (إذ تؤثر في واجهة برمجة التطبيقات API). خطط لأسماء العلاقات بعناية.
</Note>
## قبل أن تبدأ
Decide:
قرّر:
* Which objects are you connecting? (e.g., People → Companies)
* Which is the "one" side? (e.g., Company)
* Which is the "many" side? (e.g., People — many people work at one company)
* What should the field be named on each side?
* ما الكائنات التي تقوم بربطها؟ (مثال: الأشخاص → الشركات)
* أيّهما جانب "الواحد"؟ (مثال: شركة)
* أيّهما جانب "المتعدد"؟ (مثال: الأشخاص — يعمل العديد من الأشخاص في شركة واحدة)
* ما الاسم الذي يجب أن يحمله الحقل في كل جانب؟
See [Relation Fields](/l/ar/user-guide/data-model/capabilities/relation-fields) for relation types explained.
راجع [حقول العلاقة](/l/ar/user-guide/data-model/capabilities/relation-fields) لشرح أنواع العلاقات.
## Steps
## الخطوات
1. Go to **Settings → Data Model**
2. Select the object where you want the relation (typically the "many" side)
3. Click **+ Add Field**
4. Select **Relation** as the field type
5. Choose the **target object**
6. Select **One-to-Many** or **Many-to-One**
7. Enter field names for **both sides** of the relation
1. اذهب إلى **الإعدادات → نموذج البيانات**
2. حدّد الكائن الذي تريد فيه العلاقة (عادةً جانب "المتعدد")
3. انقر **+ إضافة حقل**
4. اختر **علاقة** كنوع الحقل
5. اختر **الكائن المستهدف**
6. اختر **واحد إلى متعدد** أو **متعدد إلى واحد**
7. أدخل أسماء الحقول ل**كلا الجانبين** من العلاقة
8. انقر على **حفظ**
## Example: People → Companies
## مثال: الأشخاص → الشركات
* Go to **Settings → Data Model → People**
* Add a Relation field
* Target: **Companies**
* Type: **Many-to-One**
* Field on People: **Company**
* Field on Companies: **Employees**
* اذهب إلى **الإعدادات → نموذج البيانات → الأشخاص**
* أضف حقل علاقة
* الهدف: **الشركات**
* النوع: **متعدد إلى واحد**
* الحقل في الأشخاص: **الشركة**
* الحقل في الشركات: **الموظفون**
Now each Person can be linked to a Company, and each Company shows its People.
يمكن الآن ربط كل شخص بشركة، وتعرض كل شركة موظفيها.
## Deleting a Relation
## حذف علاقة
1. Go to **Settings → Data Model**
2. Find the relation field
3. Click **⋮ → Deactivate**
1. اذهب إلى **الإعدادات → نموذج البيانات**
2. اعثر على حقل العلاقة
3. انقر **⋮ → إلغاء التنشيط**
Links are preserved but hidden. Reactivate to restore.
تظل الروابط محفوظة لكنها مخفية. أعد التنشيط لاستعادتها.
<Note>
**Deleting a relation doesn't delete records.** Only the link between them is removed.
**حذف العلاقة لا يحذف السجلات.** تتم إزالة الرابط بينهما فقط.
</Note>
## Related
## ذات صلة
* [Relation Fields](/l/ar/user-guide/data-model/capabilities/relation-fields) — types and limitations
* [How to Import Relations](/l/ar/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) — bulk import linked records
* [حقول العلاقة](/l/ar/user-guide/data-model/capabilities/relation-fields) — الأنواع والقيود
* [كيفية استيراد العلاقات](/l/ar/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) — الاستيراد الدفعي للسجلات المرتبطة
@@ -1,5 +1,5 @@
---
title: تخصيص نموذج البيانات الخاص بك},{
title: Customize Your Data Model
description: نظرة عامة على خيارات تخصيص نموذج البيانات.
---
@@ -1,5 +1,5 @@
---
title: إظهار المبلغ المتوقع في خط سير المبيعات لديك},{
title: Show Expected Amount in Your Pipeline
description: احسب واعرض قيم الصفقات الموزونة استنادًا إلى احتمال المرحلة.
---
@@ -1,92 +1,92 @@
---
title: عمليات تشغيل سير العمل
description: Monitor and manage workflow executions.
description: راقِب وأدِر عمليات تنفيذ سير العمل.
image: /images/user-guide/workflows/workflow.png
---
## About Runs
## حول عمليات التشغيل
A **Run** is a record of a workflow execution. Every time a workflow is triggered—whether by a record event, schedule, manual action, or webhook—a new run is created.
**تشغيل** هو سجل لتنفيذ سير العمل. في كل مرة يتم فيها تشغيل سير عمل—سواءً بواسطة حدث سجل، أو جدول زمني، أو إجراء يدوي، أو خطاف ويب—يتم إنشاء عملية تشغيل جديدة.
## Viewing Runs
## عرض عمليات التشغيل
### From the Workflow Editor
### من محرر سير العمل
1. Open the workflow you want to monitor
2. Click the **Runs** panel on the right side
3. See a list of recent runs with their status
1. افتح سير العمل الذي تريد مراقبته
2. انقر على لوحة **التشغيل** في الجانب الأيمن
3. اطلع على قائمة بأحدث عمليات التشغيل مع حالتها
### From the Workflow Runs View
### من عرض عمليات تشغيل سير العمل
1. Go to **Workflow Runs** in the sidebar
2. View runs across all workflows
3. Filter by status, workflow, or date
1. انتقل إلى **عمليات تشغيل سير العمل** في الشريط الجانبي
2. اعرض عمليات التشغيل عبر جميع سير العمل
3. رشّح حسب الحالة أو سير العمل أو التاريخ
## Run Statuses
## حالات التشغيل
| الحالة | الوصف |
| ---------------- | ------------------------------------------------------------------------ |
| **جارٍ التنفيذ** | Workflow is currently executing |
| **Completed** | Workflow finished successfully |
| **Failed** | Workflow encountered an error and stopped |
| **Waiting** | Workflow is paused (e.g., waiting for a Delay action or Form submission) |
| الحالة | الوصف |
| ---------------- | ----------------------------------------------------------------- |
| **جارٍ التنفيذ** | سير العمل قيد التنفيذ حاليًا |
| **مكتمل** | انتهى سير العمل بنجاح |
| **فشل** | واجه سير العمل خطأً وتوقّف |
| **في انتظار** | سير العمل متوقف مؤقتًا (مثال: ينتظر إجراء التأخير أو إرسال نموذج) |
## Run Details
## تفاصيل عملية التشغيل
Click on any run to see:
انقر على أي عملية تشغيل للاطلاع على:
* **Status**: Current state of the run
* **Started at**: When the run began
* **Duration**: How long the run took
* **Trigger data**: The input that started the workflow
* **Step outputs**: Data returned by each step
* **Error messages**: If the run failed, what went wrong
* **الحالة**: الوضع الحالي لعملية التشغيل
* **وقت البدء**: وقت بدء عملية التشغيل
* **المدة**: الوقت الذي استغرقته عملية التشغيل
* **بيانات المُشغِّل**: المُدخل الذي بدأ سير العمل
* **مخرجات الخطوة**: البيانات التي ترجعها كل خطوة
* **رسائل الخطأ**: إذا فشلت عملية التشغيل، ما الخطأ الذي حدث
## Step-by-Step Execution
## تنفيذ خطوة بخطوة
Each run shows the progression through your workflow:
تعرض كل عملية تشغيل التقدم خلال سير عملك:
1. See which steps completed successfully
2. Identify where failures occurred
3. View the data passed between steps
4. Debug issues by examining step inputs and outputs
1. اطلع على الخطوات التي اكتملت بنجاح
2. حدّد مواضع حدوث الفشل
3. اعرض البيانات الممررة بين الخطوات
4. استكشف المشكلات وأصلحها بفحص مدخلات الخطوات ومخرجاتها
## Error Handling
## التعامل مع الأخطاء
When a run fails:
عند فشل عملية تشغيل:
1. Open the failed run
2. Find the step that caused the failure
3. Check the error message for details
4. Common issues:
* Missing required fields
1. افتح عملية التشغيل الفاشلة
2. حدّد الخطوة التي تسببت في الفشل
3. تحقق من رسالة الخطأ للتفاصيل
4. مشكلات شائعة:
* حقول مطلوبة مفقودة
* تنسيق بيانات غير صالح
* External API errors
* Permission issues
* أخطاء واجهة برمجة التطبيقات الخارجية
* مشكلات الأذونات
## Re-running Workflows
## إعادة تشغيل سير العمل
If a run fails, you can:
إذا فشلت عملية تشغيل، يمكنك:
* Fix the underlying issue and wait for the next trigger
* For manual workflows, trigger again with the same or updated data
* Review the workflow logic to prevent future failures
* أصلح المشكلة الأساسية وانتظر المُشغِّل التالي
* بالنسبة لسير العمل اليدوي، شغّل مرة أخرى باستخدام البيانات نفسها أو بيانات محدَّثة
* راجع منطق سير العمل لمنع حالات الفشل المستقبلية
## Performance Tips
## نصائح الأداء
### Managing Run History
### إدارة محفوظات التشغيل
* Runs are retained for historical reference
* Very old runs may be archived automatically
* Export run data if you need to keep records
* تُحتفظ بعمليات التشغيل كمرجع تاريخي
* قد تُؤرشف عمليات التشغيل القديمة جدًا تلقائيًا
* صدّر بيانات التشغيل إذا كنت بحاجة إلى الاحتفاظ بسجلات
### Monitoring Best Practices
### أفضل ممارسات المراقبة
* Check runs regularly after activating new workflows
* Review failed runs to identify patterns
* تحقق بانتظام من عمليات التشغيل بعد تفعيل سير عمل جديدة
* راجع عمليات التشغيل الفاشلة لتحديد الأنماط
## Related
## ذات صلة
* [Workflow Triggers](/l/ar/user-guide/workflows/capabilities/workflow-triggers)
* [Workflow Actions](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [Workflow Troubleshooting](/l/ar/user-guide/workflows/how-tos/need-more-help/workflow-troubleshooting)
* [مشغلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers)
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [استكشاف مشكلات سير العمل وإصلاحها](/l/ar/user-guide/workflows/how-tos/need-more-help/workflow-troubleshooting)
@@ -1,15 +1,15 @@
---
title: Professional Services
description: Get professional help building complex workflows and automations from Twenty's team and certified partners.
title: خدمات احترافية
description: احصل على مساعدة احترافية لبناء مسارات عمل وأتمتة معقدة من فريق Twenty وشركائه المعتمدين.
---
## متى تحتاج إلى مساعدة احترافية؟
Consider professional services for:
فكّر في الاستفادة من الخدمات الاحترافية من أجل:
* تكامل أنظمة متعددة ومعقدة
* منطق الأعمال المتقدم وقواعد الأتمتة
* Large-scale data processing workflows
* مسارات عمل لمعالجة البيانات على نطاق واسع
* تطوير واجهة برمجة التطبيقات المخصصة
* تدريب الفريق وتحسين سير العمل
* عندما تكون الموارد الداخلية غير متوفرة
@@ -18,7 +18,7 @@ Consider professional services for:
### حزم الانضمام
Get help from our core team with our 4-hour [Onboarding packs](https://twenty.com/onboarding-packages):
احصل على مساعدة من فريقنا الأساسي باستخدام [حزم الانضمام](https://twenty.com/onboarding-packages) لمدة 4 ساعات:
* **إنشاء سير العمل**: بناء سير عمل مخصصة لعمليات عملك
* **تصميم نموذج البيانات**: تحسين هيكل البيانات الخاصة بك لأتمتة سير العمل
@@ -26,4 +26,4 @@ Get help from our core team with our 4-hour [Onboarding packs](https://twenty.co
### شركاء التنفيذ
Work with certified partners for advanced customizations. Contact us at contact@twenty.com to connect with our [implementation partners](https://twenty.com/partners).
اعمل مع شركاء معتمدين من أجل تخصيصات متقدمة. تواصل معنا عبر contact@twenty.com للتواصل مع [شركائنا في التنفيذ](https://twenty.com/partners).
@@ -18,7 +18,7 @@ Také jej přidejte do výčtu v `feature-flag.entity.ts`:
```ts
enum FeatureFlagKeys {
IsFeatureNameEnabled = 'IS_FUNKCEPOVOLENA',
IsFeatureNameEnabled = 'IS_FEATURENAME_ENABLED',
...
}
```
@@ -19,7 +19,7 @@ Je dobrým zvykem vytvořit tolik atomů, kolik potřebujete ke správě stavu.
```tsx
export const myAtomState = atom({
key: 'myAtomState',
výchozí: 'výchozí hodnota',
default: 'default value',
});
export const MyComponent = () => {
@@ -40,7 +40,7 @@ export const MyComponent = () => {
Vyhněte se používání `useRef` k ukládání stavu.
Pokud chcete ukládat stav, měli byste použít `useState` nebo `useRecoilState`.
If you want to store state, you should use `useState` or `useRecoilState`.
Podívejte se, jak spravovat překreslení, pokud máte pocit, že potřebujete `useRef`, abyste zabránili některým překreslením.
@@ -56,23 +56,23 @@ Pamatujte, že můžete **vždy** zabránit opakovanému renderování pochopen
Vyhýbání se překreslení v nových funkcích je nyní snadné tím, že je eliminujete na úrovni kořene.
Komponenta sidecar `PageChangeEffect` obsahuje pouze jedno `useEffect`, kde drží veškerou logiku vykonávanou při změně stránky.
The `PageChangeEffect` sidecar component contains just one `useEffect` that holds all the logic to execute on a page change.
Tímto způsobem víte, že existuje pouze jedno místo, které může spustit překreslování.
### Vždy přemýšlejte dvakrát, než přidáte `useEffect` do svého kódu
### Always think twice before adding `useEffect` in your codebase
Překreslování je často způsobeno zbytečným `useEffect`.
Re-renders are often caused by unnecessary `useEffect`.
Měli byste přemýšlet, zda potřebujete `useEffect`, nebo jestli můžete logiku přesunout do funkce obsluhy událostí.
You should think whether you need `useEffect`, or if you can move the logic in a event handler function.
Obecně budete snadno moci přesunout logiku do funkce `handleClick` nebo `handleChange`.
You'll find it generally easy to move the logic in a `handleClick` or `handleChange` function.
Můžete je také najít v knihovnách jako Apollo: `onCompleted`, `onError` atd.
### Použijte sourozenou komponentu k extrakci logiky `useEffect` nebo získávání dat
### Use a sibling component to extract `useEffect` or data fetching logic
Pokud máte pocit, že potřebujete přidat `useEffect` do svého základního komponentu, měli byste zvážit jeho extrakci do sidecar komponenty.
If you feel like you need to add a `useEffect` in your root component, you should consider extracting it in a sidecar component.
Stejný postup můžete aplikovat na logiku získávání dat pomocí Apollo hooks.
@@ -168,12 +168,13 @@ Jména proměnných by měla přesně zobrazovat účel nebo funkci proměnné.
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
// ❌ Špatně, používá generický název, který jasně nekomunikuje svůj účel ani obsah
// ❌ Bad, uses a generic name that doesn't communicate its
// purpose or content clearly
const [value, setValue] = useState('');
```
```tsx
// ✅ Dobře, používá popisný název
// ✅ Good, uses a descriptive name
const [email, setEmail] = useState('');
```
@@ -186,14 +187,14 @@ const [email, setEmail] = useState('');
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
// ❌ Špatně
// ❌ Bad
const onEmailChange = (val: string) => {
// ...
};
```
```tsx
// ✅ Dobře
// ✅ Good
const handleEmailChange = (val: string) => {
// ...
};
@@ -221,12 +222,12 @@ const EmailField = ({ value, disabled = false }: EmailFieldProps) => (
**Použití**
```tsx
// ❌ Špatně, předání stejné hodnoty jako výchozí nepřidává žádnou hodnotu
// ❌ Bad, passing in the same value as the default value adds no value
const Form = () => <EmailField value="username@email.com" disabled={false} />;
```
```tsx
// ✅ Dobře, předpokládá výchozí hodnotu
// ✅ Good, assumes the default value
const Form = () => <EmailField value="username@email.com" />;
```
@@ -284,7 +285,7 @@ Při importu, upřednostněte určené aliasy před upřesňováním úplných
**Použití**
```tsx
// ❌ Špatně, specifikuje celou relativní cestu
// ❌ Bad, specifies the entire relative path
import {
CatalogDecorator
} from '../../../../../testing/decorators/CatalogDecorator';
@@ -309,10 +310,10 @@ const validationSchema = z
exist: z.boolean(),
email: z
.string()
.email('Email musí být platný email'),
.email('Email must be a valid email'),
password: z
.string()
.regex(PASSWORD_REGEX, 'Heslo musí obsahovat alespoň 8 znaků'),
.regex(PASSWORD_REGEX, 'Password must contain at least 8 characters'),
})
.required();
@@ -73,7 +73,7 @@ Projekt má čistý a jednoduchý stack s minimálním počtem šablonových kó
[React Router](https://reactrouter.com/) zajišťuje směrování.
Aby se předešlo zbytečnému [překreslování](/l/cs/developers/contribute/capabilities/frontend-development/best-practices-front#managing-re-renders) je veškerá logika směrování v `useEffect` v `PageChangeEffect`.
To avoid unnecessary [re-renders](/l/cs/developers/contribute/capabilities/frontend-development/best-practices-front#managing-re-renders) all the routing logic is in a `useEffect` in `PageChangeEffect`.
### Správa stavu
@@ -45,29 +45,29 @@ const PageListeningEnter = () => {
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
// 1. Nastavte rozsah klávesových zkratek v useEffect
// 1. Set the hotkey scope in a useEffect
useEffect(() => {
setHotkeyScopeAndMemorizePreviousScope(
ExampleHotkeyScopes.ExampleEnterPage,
);
// Vraťte se k předchozímu rozsahu klávesových zkratek, když se komponenta odpojí
// Revert to the previous hotkey scope when the component is unmounted
return () => {
goBackToPreviousHotkeyScope();
};
}, [goBackToPreviousHotkeyScope, setHotkeyScopeAndMemorizePreviousScope]);
// 2. Použijte hook useScopedHotkeys
// 2. Use the useScopedHotkeys hook
useScopedHotkeys(
Key.Enter,
() => {
// Nějaká logika vykonaná na této stránce, když uživatel stiskne Enter
// Some logic executed on this page when the user presses Enter
// ...
},
ExampleHotkeyScopes.ExampleEnterPage,
);
return <div>Moje stránka, která poslouchá Enter</div>;
return <div>My page that listens for Enter</div>;
};
```
@@ -87,7 +87,7 @@ const ExamplePageWithModal = () => {
} = usePreviousHotkeyScope();
const handleOpenModalClick = () => {
// 1. Nastavte rozsah klávesových zkratek, když uživatel otevře modal
// 1. Set the hotkey scope when user opens the modal
setShowModal(true);
setHotkeyScopeAndMemorizePreviousScope(
ExampleHotkeyScopes.ExampleModal,
@@ -95,14 +95,14 @@ const ExamplePageWithModal = () => {
};
const handleModalClose = () => {
// 1. Vraťte se k předchozímu rozsahu klávesových zkratek, když se modal zavře
// 1. Revert to the previous hotkey scope when the modal is closed
setShowModal(false);
goBackToPreviousHotkeyScope();
};
return <div>
<h1>Moje stránka s modálem</h1>
<button onClick={handleOpenModalClick}>Otevřít modal</button>
<h1>My page with a modal</h1>
<button onClick={handleOpenModalClick}>Open modal</button>
{showModal && <MyModalComponent onClose={handleModalClose} />}
</div>;
};
@@ -112,9 +112,9 @@ Pak v komponentě modalu :
```tsx
const MyDropdownComponent = ({ onClose }: { onClose: () => void }) => {
// 2. Použijte hook useScopedHotkeys k poslouchání Escape.
// Všimněte si, že escape je běžná klávesová zkratka, kterou může použít mnoho jiných komponent
// Je tedy důležité používat rozsah klávesových zkratek, aby se předešlo konfliktům
// 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,
() => {
@@ -123,13 +123,13 @@ const MyDropdownComponent = ({ onClose }: { onClose: () => void }) => {
ExampleHotkeyScopes.ExampleModal,
);
return <div>Moje komponenta modalu</div>;
return <div>My modal component</div>;
};
```
Je důležité používat tento vzor, když si nejste jisti, že samotné použití useEffect pro nastavení a odebrání bude dostatečné k zabránění konfliktům.
It's important to use this pattern when you're not sure that just using a useEffect with mount/unmount will be enough to avoid conflicts.
Tyto konflikty mohou být těžké ladit a mohou se vyskytovat častěji než ne u useEffects.
Those conflicts can be hard to debug, and it might happen more often than not with useEffects.
## Co je to hotkey scope?
@@ -143,20 +143,20 @@ Například rozsahy klávesových zkratek pro každou stránku jsou definovány
```tsx
export enum PageHotkeyScope {
Nastavení = 'settings',
VytvořitPracovníProstor = 'create-workspace',
PřihlášeníRegistrace = 'sign-in-up',
VytvořitProfil = 'create-profile',
PožadovánoPlán = 'plan-required',
ZobrazitStránku = 'show-page',
OsobníZobrazitStránku = 'person-show-page',
FiremníZobrazitStránku = 'company-show-page',
FirmyStránka = 'companies-page',
LidéStránka = 'people-page',
PříležitostiStránka = 'opportunities-page',
ProfilStránka = 'profile-page',
ČlenPracovníhoProstoruStránka = 'workspace-member-page',
ÚkolStránka = 'task-page',
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',
}
```
@@ -21,16 +21,16 @@ 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
// ❌ Špatné, obtížnější číst a importovat s automatickým doplňkem kódu
// ❌ Bad, harder to read, harder to import with code completion
const MyComponent = () => {
return <div>Ahoj světe</div>;
return <div>Hello World</div>;
};
export default MyComponent;
// ✅ Dobré, snadné čtení a import s automatickým dokončováním kódu
// ✅ Good, easy to read, easy to import with code completion
export function MyComponent() {
return <div>Ahoj světe</div>;
return <div>Hello World</div>;
};
```
@@ -41,25 +41,25 @@ Create the type of the props and call it `(ComponentName)Props` if there's no ne
Use props destructuring.
```tsx
// ❌ Špatné, žádný typ
export const MyComponent = (props) => <div>Ahoj {props.name}</div>;
// ❌ Bad, no type
export const MyComponent = (props) => <div>Hello {props.name}</div>;
// ✅ Dobré, typ
// ✅ Good, type
type MyComponentProps = {
name: string;
};
export const MyComponent = ({ name }: MyComponentProps) => <div>Ahoj {name}</div>;
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
/* ❌ - Špatné, definuje anotace typů komponent s `FC`
* - S `React.FC` komponent implicitně přijímá rekvizitu `children`
* i když není definována v typu rekvizity. To nemusí být vždy
* žádoucí, zejména pokud komponenta nemá v úmyslu vykreslovat
* podřízené komponenty.
/* ❌ - 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;
@@ -86,7 +86,7 @@ const EmailField = ({ value }: EmailFieldProps) => (
Avoid using single variable prop spreading in JSX elements, like `{...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
/* ❌ - Špatné, šíří jedinou proměnnou prop do základní komponenty
/* ❌ - Bad, spreads a single variable prop into the underlying component
*/
const MyComponent = (props: OwnProps) => {
return <OtherComponent {...props} />;
@@ -137,12 +137,12 @@ onClick?.();
Vždy používejte `type` místo `interface`, protože se téměř vždy překrývají a `type` je flexibilnější.
```tsx
// ❌ Špatné
// ❌ Bad
interface MyInterface {
name: string;
}
// ✅ Dobré
// ✅ Good
type MyType = {
name: string;
};
@@ -155,7 +155,7 @@ type MyType = {
Proč TypeScript doporučuje vyhnout se výčtům zjistíte [zde](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).
```tsx
// ❌ Špatné, využívá výčet
// ❌ Bad, utilizes an enum
enum Color {
Red = "red",
Green = "green",
@@ -263,13 +263,13 @@ const StyledButton = styled.button`
Vyhýbejte se typovým importům. K prosazení tohoto standardu pravidlo ESLint kontroluje a hlásí jakékoli typové importy. To pomáhá udržovat konzistenci a čitelnost v TypeScript kódu.
```tsx
// ❌ Špatné
// ❌ Bad
import { type Meta, type StoryObj } from '@storybook/react';
// ❌ Špatné
// ❌ Bad
import type { Meta, StoryObj } from '@storybook/react';
// ✅ Dobré
// ✅ Good
import { Meta, StoryObj } from '@storybook/react';
```
@@ -15,17 +15,17 @@ Používané, když uživatel potřebuje vybrat více hodnot z několika možnos
import { Checkbox } from "twenty-ui/display";
export const MyComponent = () => {
return (
<Checkbox
checked={true}
indeterminate={false}
onChange={() => console.log("onChange function fired")}
onCheckedChange={() => console.log("onCheckedChange function fired")}
variant="primary"
size="small"
shape="squared"
/>
);
return (
<Checkbox
checked={true}
indeterminate={false}
onChange={() => console.log("onChange function fired")}
onCheckedChange={() => console.log("onCheckedChange function fired")}
variant="primary"
size="small"
shape="squared"
/>
);
};
```
</Tab>
@@ -17,10 +17,10 @@ Zobrazuje drobečkovou navigační lištu.
export const MyComponent = () => {
const breadcrumbLinks = [
{ children: "Domů", href: "/" },
{ children: "Kategorie", href: "/category" },
{ children: "Podkategorie", href: "/category/subcategory" },
{ children: "Aktuální stránka" },
{ children: "Home", href: "/" },
{ children: "Category", href: "/category" },
{ children: "Subcategory", href: "/category/subcategory" },
{ children: "Current Page" },
];
return (
@@ -19,21 +19,21 @@ Stylizovaná komponenta odkazu pro zobrazení kontaktních informací.
import { ContactLink } from 'twenty-ui/navigation';
export const MyComponent = () => {
const handleLinkClick = (event) => {
console.log('Odkaz na kontakt kliknut!', event);
};
const handleLinkClick = (event) => {
console.log('Contact link clicked!', event);
};
return (
<Router>
<ContactLink
className
href="mailto:example@example.com"
onClick={handleLinkClick}
>
example@example.com
</ContactLink>
</Router>
);
return (
<Router>
<ContactLink
className
href="mailto:example@example.com"
onClick={handleLinkClick}
>
example@example.com
</ContactLink>
</Router>
);
};
```
</Tab>
@@ -59,18 +59,19 @@ Stylizovaná komponenta odkazu pro zobrazení odkazů.
import { BrowserRouter as Router } from "react-router-dom";
export const MyComponent = () => {
const handleLinkClick = (event) => {
console.log("Odkaz na kontakt kliknut!", event);
};
const handleLinkClick = (event) => {
console.log("Contact link clicked!", event);
};
return (
<Router>
<RawLink className href="/contact" onClick={handleLinkClick}>
Kontaktujte nás
</RawLink>
</Router>
);
return (
<Router>
<RawLink className href="/contact" onClick={handleLinkClick}>
Contact Us
</RawLink>
</Router>
);
};
```
</Tab>
@@ -95,17 +96,17 @@ Zaobleně stylizovaný odkaz s komponentou Chip pro odkazy.
import { BrowserRouter as Router } from "react-router-dom";
export const MyComponent = () => {
const handleLinkClick = (event) => {
console.log("Odkaz na kontakt kliknut!", event);
};
const handleLinkClick = (event) => {
console.log("Contact link clicked!", event);
};
return (
<Router>
<RoundedLink href="/contact" onClick={handleLinkClick}>
Kontaktujte nás
</RoundedLink>
</Router>
);
return (
<Router>
<RoundedLink href="/contact" onClick={handleLinkClick}>
Contact Us
</RoundedLink>
</Router>
);
};
```
</Tab>
@@ -130,14 +131,14 @@ Stylizované sociální odkazy s podporou různých typů sociálních odkazů,
import { BrowserRouter as Router } from "react-router-dom";
export const MyComponent = () => {
return (
<Router>
<SocialLink
type="twitter"
href="https://twitter.com/twentycrm"
></SocialLink>
</Router>
);
return (
<Router>
<SocialLink
type="twitter"
href="https://twitter.com/twentycrm"
></SocialLink>
</Router>
);
};
```
</Tab>
@@ -199,7 +199,7 @@ A multi-select menu item with an avatar, a checkbox for selection, and textual c
return (
<MenuItemMultiSelectAvatar
avatar={<img src={imageUrl} alt="Avatar" />}
text="První možnost"
text="First Option"
selected={false}
className
/>
@@ -231,13 +231,13 @@ Položka menu s volitelnou levou ikonou, textovým obsahem a ikonou šipky vprav
export const MyComponent = () => {
const handleNavigation = () => {
console.log("Přejít na jinou stránku");
console.log("Navigate to another page");
};
return (
<MenuItemNavigate
LeftIcon={IconBell}
text="První možnost"
text="First Option"
onClick={handleNavigation}
className
/>
@@ -268,13 +268,13 @@ Výběrová položka menu, s volitelným levým obsahem (ikonou a textem) a indi
export const MyComponent = () => {
const handleSelection = () => {
console.log("Položka menu byla vybrána");
console.log("Menu item selected");
};
return (
<MenuItemSelect
LeftIcon={IconBell}
text="První možnost"
text="First Option"
selected={true}
disabled={false}
hovered={false}
@@ -313,13 +313,13 @@ Výběrová položka menu s avatarem, s volitelným levým obsahem (avatar a tex
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAYABgAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABgAAAAAQAAAGAAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAABSgAwAEAAAAAQAAABQAAAAA/8AAEQgAFAAUAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMACwgICggHCwoJCg0MCw0RHBIRDw8RIhkaFBwpJCsqKCQnJy0yQDctMD0wJyc4TDk9Q0VISUgrNk9VTkZUQEdIRf/bAEMBDA0NEQ8RIRISIUUuJy5FRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRf/dAAQAAv/aAAwDAQACEQMRAD8Ava1q728otYY98joSCTgZrnbXWdTtrhrfVZXWLafmcAEkdgR/hVltQku9Q8+OIEBcGOT+ID0PY1ka1KH2u8ToqnPLbmIqG7u6LtbQ7RXBRec4Uck9eKXcPWsKDWVnhWSL5kYcFelSf2m3901POh8jP//QoyIAnTuKpXsY82NsksUyWPU5q/L9z8RVK++/F/uCsVsaEURwgA4HtT9x9TUcf3KfUGh//9k=";
const handleSelection = () => {
console.log("Položka menu vybrána");
console.log("Menu item selected");
};
return (
<MenuItemSelectAvatar
avatar={<img src={imageUrl} alt="Avatar" />}
text="První možnost"
text="First Option"
selected={true}
disabled={false}
hovered={false}
@@ -358,7 +358,7 @@ Volitelná položka menu s ukázkou barvy pro situace, kdy chcete, aby uživatel
export const MyComponent = () => {
const handleSelection = () => {
console.log("Položka menu vybrána");
console.log("Menu item selected");
};
return (
@@ -405,7 +405,7 @@ Položka menu s přidruženým přepínačem k umožnění nebo zakázání urč
return (
<MenuItemToggle
LeftIcon={IconBell}
text="První možnost"
text="First Option"
toggled={true}
toggleSize="small"
className
@@ -21,17 +21,17 @@ Zobrazuje navigační panel, který obsahuje více komponent `NavigationBarItem`
{
name: "Home",
Icon: IconHome,
onClick: () => console.log("Domů kliknuto"),
onClick: () => console.log("Home clicked"),
},
{
name: "Profile",
Icon: IconUser,
onClick: () => console.log("Profil kliknuto"),
onClick: () => console.log("Profile clicked"),
},
{
name: "Settings",
Icon: IconSettings,
onClick: () => console.log("Nastavení kliknuto"),
onClick: () => console.log("Settings clicked"),
},
];
@@ -17,9 +17,9 @@ Zobrazuje postup přes sekvenci číslovaných kroků zvýrazněním aktuálníh
export const MyComponent = () => {
return (
<StepBar activeStep={2}>
<StepBar.Step>Krok 1</StepBar.Step>
<StepBar.Step>Krok 2</StepBar.Step>
<StepBar.Step>Krok 3</StepBar.Step>
<StepBar.Step>Step 1</StepBar.Step>
<StepBar.Step>Step 2</StepBar.Step>
<StepBar.Step>Step 3</StepBar.Step>
</StepBar>
);
};
@@ -1,6 +1,6 @@
---
title: Fakturace
description: Understand Twenty pricing and manage your subscription.
description: Seznamte se s cenami Twenty a spravujte své předplatné.
image: /images/user-guide/setup/pricing.png
---
@@ -8,38 +8,38 @@ image: /images/user-guide/setup/pricing.png
<img src="/images/user-guide/setup/pricing.png" alt="Fakturace" />
</Frame>
Twenty offers flexible pricing plans to fit your team's needs. Manage your subscription, track workflow credits, and access invoices all from **Settings → Billing**.
Twenty nabízí flexibilní cenové plány, které vyhoví potřebám vašeho týmu. Spravujte své předplatné, sledujte kredity pracovních postupů a přistupujte k fakturám — to vše v **Nastavení → Fakturace**.
## What's in this section
## Co najdete v této sekci
<CardGroup cols={2}>
<Card title="Pricing Plans" icon="tags" href="/l/cs/user-guide/billing/capabilities/pricing-plans">
Learn about Twenty's pricing plans and what's included.
<Card title="Cenové plány" icon="tags" href="/l/cs/user-guide/billing/capabilities/pricing-plans">
Zjistěte více o cenových plánech Twenty a o tom, co je zahrnuto.
</Card>
<Card title="FAQ" icon="circle-question" href="/l/cs/user-guide/billing/how-tos/billing-faq">
Frequently asked questions about pricing and billing.
<Card title="Časté dotazy" icon="circle-question" href="/l/cs/user-guide/billing/how-tos/billing-faq">
Nejčastější dotazy k cenám a fakturaci.
</Card>
</CardGroup>
## At a glance
## Stručný přehled
| Plán | Key Features |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Free (Self-Hosted)** | All Pro features, community support |
| **Pro (Cloud)** | Everything apart from the Premium features (SSO and row-level permissions), standard support |
| **Organization (Cloud)** | All from Pro + the Premium features (SSO and row-level permissions), priority support |
| **Organization (Self-Hosted)** | All from Pro + the Premium features (SSO, row-level permissions), Twenty team support, not required to publish your custom code as open-source before distributing |
| Plán | Klíčové funkce |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Zdarma (vlastní hosting)** | Všechny funkce Pro, podpora komunity |
| **Pro (Cloud)** | Vše kromě funkcí Premium (SSO a oprávnění na úrovni řádků), standardní podpora |
| **Organizace (Cloud)** | Vše z Pro + funkce Premium (SSO a oprávnění na úrovni řádků), prioritní podpora |
| **Organizace (vlastní hosting)** | Vše z Pro + funkce Premium (SSO, oprávnění na úrovni řádků), podpora týmu Twenty, není vyžadováno publikování vašeho vlastního kódu jako open-source před distribu |
## Quick answers
## Rychlé odpovědi
**Where do I manage billing?**
Go to **Settings → Billing** to view your plan, update payment methods, and access invoices.
**Kde spravuji fakturaci?**
Přejděte do **Nastavení → Fakturace**, kde uvidíte svůj plán, aktualizujete platební metody a získáte přístup k fakturám.
**Can I use Twenty for free?**
Yes! Self-host Twenty and get all Pro features at no cost.
**Mohu používat Twenty zdarma?**
Ano! Hostujte Twenty sami a získejte všechny funkce Pro zdarma.
**How do I upgrade?**
Go to **Settings → Billing** and click **Switch to Organization** or **Switch to Yearly**.
**Jak provedu upgrade?**
Přejděte do **Nastavení → Fakturace** a klikněte na **Přepnout na Organizaci** nebo **Přepnout na Roční**.
For more questions, see the [Billing FAQ](/l/cs/user-guide/billing/how-tos/billing-faq).
Další otázky najdete v [FAQ k fakturaci](/l/cs/user-guide/billing/how-tos/billing-faq).
@@ -1,19 +1,19 @@
---
title: Kalendář
description: Understanding calendar integration features in Twenty.
description: Přehled funkcí integrace kalendáře v Twenty.
---
**Note**: To connect your calendar and configure sync settings, visit [Email & Calendar Setup](/l/cs/user-guide/calendar-emails/overview).
**Poznámka**: Chcete-li připojit svůj kalendář a konfigurovat nastavení synchronizace, navštivte [Nastavení Emailu a Kalendáře](/l/cs/user-guide/calendar-emails/overview).
## How Calendar Integration Works
## Jak funguje integrace kalendáře
Twenty automatically syncs your calendar events and links them to the relevant CRM records, giving you a complete view of your meeting history with contacts and companies.
Twenty automaticky synchronizuje vaše události v kalendáři a propojuje je s příslušnými záznamy v CRM, čímž poskytuje úplný přehled o historii vašich schůzek s kontakty a společnostmi.
## Záložka kalendáře
Next to the Emails tab on records, you'll find a `Calendar` tab that contains the history of meetings scheduled with the record.
Vedle záložky Emailů na záznamech najdete záložku `Kalendář`, která obsahuje historii naplánovaných schůzek se záznamem.
### Available For
### Dostupné pro
* **Osoby**: Prohlédněte si všechny naplánované schůzky s konkrétním kontaktem
* **Společnosti**: Zobrazte si všechny schůzky týkající se společnosti a jejích zaměstnanců
@@ -26,18 +26,18 @@ Next to the Emails tab on records, you'll find a `Calendar` tab that contains th
3. **Procházení historie schůzek**: Zobrazte si všechny naplánované schůzky a jejich detaily
4. **Přístup k detailům schůzek**: Zobrazte si účastníky schůzek, časy a související informace
## Visibility Settings
## Nastavení viditelnosti
Calendar data follows the same visibility settings as emails, ensuring consistent privacy controls across both communication channels.
Údaje kalendáře se řídí stejným nastavením viditelnosti jako emaily, což zajišťuje konzistentní kontrolu soukromí napříč oběma komunikačními kanály.
## Co se synchronizuje
* **External Meetings**: All meetings with contacts outside your organization
* **Automatic Linking**: Meetings connect to existing People and Company records based on attendee email addresses
* **Meeting Details**: Subject, time, duration, and participants
* **Updates**: New calendar events sync automatically
* **Externí schůzky**: Všechny schůzky s kontakty mimo vaši organizaci
* **Automatické propojení**: Schůzky se propojí s existujícími záznamy Osoby a Společnosti na základě emailových adres účastníků
* **Podrobnosti schůzky**: Předmět, čas, délka a účastníci
* **Aktualizace**: Nové události v kalendáři se synchronizují automaticky
## Co se nesynchronizuje
* **Internal Meetings**: Meetings with only colleagues (same domain) remain private
* **Private Events**: Events marked as private in your calendar
* **Interní schůzky**: Schůzky pouze s kolegy (stejná doména) zůstávají soukromé
* **Soukromé události**: Události označené jako soukromé ve vašem kalendáři
@@ -1,59 +1,59 @@
---
title: Dashboards FAQ
description: Frequently asked questions about dashboards in Twenty.
title: Nejčastější dotazy k panelům
description: Nejčastější dotazy k panelům v Twenty.
---
<AccordionGroup>
<Accordion title="Can I create private dashboards?">
No, dashboards are currently visible to everyone with access to your Twenty workspace. Private dashboards are not yet available.
<Accordion title="Mohu vytvářet soukromé panely?">
Ne, panely jsou nyní viditelné pro všechny, kteří mají přístup do vašeho pracovního prostoru Twenty. Soukromé panely zatím nejsou k dispozici.
</Accordion>
<Accordion title="Why do my metrics look different from my colleague's?">
Dashboards currently display data based on the viewer's timezone. If you're in different regions (e.g., APAC vs. US), you may see slightly different numbers for the same dashboard. We're working on adding a timezone setting per dashboard to ensure consistent data across teams.
<Accordion title="Proč moje metriky vypadají jinak než metriky mého kolegy?">
Panely v současnosti zobrazují data podle časového pásma uživatele, který je prohlíží. Pokud jste v různých regionech (např. APAC vs. USA), můžete u stejného panelu vidět mírně odlišná čísla. Pracujeme na přidání nastavení časového pásma pro každý panel, aby byla data napříč týmy konzistent.
</Accordion>
<Accordion title="Can I export my dashboard?">
Exporting dashboards is not available at the moment. This feature is on our roadmap.
<Accordion title="Mohu exportovat svůj panel?">
Export panelů není v tuto chvíli k dispozici. Tato funkce je v našem plánu.
</Accordion>
<Accordion title="Can I share dashboards with external users?">
No, sharing dashboards with users outside your Twenty workspace (non-Twenty users) is not currently supported.
<Accordion title="Mohu sdílet panely s externími uživateli?">
Ne, sdílení panelů s uživateli mimo váš pracovní prostor Twenty (uživatelé mimo Twenty) zatím není podporováno.
</Accordion>
<Accordion title="How do I add a dashboard to my favorites?">
Open the dashboard you want to favorite, then click the star icon. Favorites are personal—they won't affect other users.
<Accordion title="Jak přidám panel mezi oblíbené?">
Otevřete panel, který chcete přidat mezi oblíbené, a klikněte na ikonu hvězdy. Oblíbené jsou osobní — neovlivní ostatní uživatele.
</Accordion>
<Accordion title="What's the difference between tabs and widgets?">
* **Tabs** organize your dashboard into sections (like pages within the dashboard)
* **Widgets** are the individual visualizations (charts, numbers, iFrames) within each tab
<Accordion title="Jaký je rozdíl mezi kartami a widgety?">
* **Karty** organizují váš panel do sekcí (jako stránky v rámci panelu)
* **Widgety** jsou jednotlivé vizualizace (grafy, čísla, iFramy) v rámci každé karty
Structure: Dashboard → Tabs → Widgets
Struktura: Panel → Karty → Widgety
</Accordion>
<Accordion title="Why do I see 'Undisplayed data' warning on my bar chart?">
Bar charts have display limits: 100 bars for horizontal charts, 50 for vertical. If your data exceeds this, add filters to narrow down the results or change the grouping (e.g., group by week instead of day).
<Accordion title="Proč vidím upozornění 'Nezobrazená data' ve svém sloupcovém grafu?">
Sloupcové grafy mají limity zobrazení: 100 sloupců pro vodorovné grafy, 50 pro svislé. Pokud vaše data tento limit překročí, přidejte filtry pro zúžení výsledků nebo změňte seskupení (např. seskupovat podle týdne namísto dne).
</Accordion>
<Accordion title="Can I filter an entire dashboard at once?">
Dashboard-level filters are not available yet, but this feature is on our roadmap. Currently, you need to apply filters to each widget individually.
<Accordion title="Mohu filtrovat celý panel najednou?">
Filtry na úrovni panelu zatím nejsou k dispozici, ale tato funkce je v našem plánu. Momentálně musíte filtry aplikovat na každý widget zvlášť.
</Accordion>
<Accordion title="Are gauge charts or tables available?">
Ještě ne. Gauge charts and tables are on our roadmap and will be added in a future release.
<Accordion title="Jsou k dispozici ukazatelové grafy nebo tabulky?">
Ještě ne. Ukazatelové grafy a tabulky jsou v našem plánu a budou přidány v některé z budoucích verzí.
</Accordion>
<Accordion title="How do I duplicate a dashboard?">
1. Make sure you're in view mode (not editing)
2. Open the command bar with **Cmd + K** (or **Ctrl + K** on Windows)
3. Select **Duplicate dashboard**
<Accordion title="Jak duplikovat panel?">
1. Ujistěte se, že jste v režimu zobrazení (nikoli v režimu úprav)
2. Otevřete příkazovou lištu pomocí **Cmd + K** (nebo **Ctrl + K** ve Windows)
3. Vyberte **Duplikovat panel**
</Accordion>
<Accordion title="How often does dashboard data refresh?">
Widgets update automatically as your CRM data changes:
<Accordion title="Jak často se data panelu obnovují?">
Widgety se aktualizují automaticky, jakmile se změní vaše data v CRM:
* Real-time updates for most metrics
* Use the refresh button for a manual update if needed
* Historical data is preserved for trend analysis
* Aktualizace v reálném čase pro většinu metrik
* V případě potřeby použijte tlačítko pro obnovení k ruční aktualizaci
* Historic data jsou zachována pro analýzu trendů
</Accordion>
</AccordionGroup>
@@ -1,176 +1,176 @@
---
title: Field Mapping
description: How field mapping works during data import.
title: Mapování polí
description: Jak funguje mapování polí při importu dat.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## How Field Mapping Works
## Jak funguje mapování polí
When you upload a file, Twenty analyzes your columns and attempts to match them to existing fields.
Když nahrajete soubor, Twenty analyzuje vaše sloupce a pokusí se je spárovat s existujícími poli.
### Automatic Mapping
### Automatické mapování
Twenty tries to match columns based on:
Twenty se snaží spárovat sloupce na základě:
* Column header names (exact or similar matches)
* Data type detection (dates, numbers, emails)
* Common field patterns
* Názvů záhlaví sloupců (přesné nebo podobné shody)
* Detekce typů dat (datumů, čísel, emailů)
* Běžné vzory polí
<Note>**Quick tip:** Export a few rows from the object you want to import. The exported file will have the exact column names Twenty expects, making automatic mapping seamless during import.</Note>
<Note>**Rychlý tip:** Exportujte několik řádků z objektu, který chcete importovat. Exportovaný soubor bude mít přesně takové názvy sloupců, jaké Twenty očekává, což při importu usnadní automatic mapování.</Note>
### Manual Mapping Options
### Možnosti ručního mapování
For each column, you can:
U každého sloupce můžete:
* **Map to a field**: Select the matching Twenty field from a dropdown
* **Do not map**: Skip the column entirely (data won't be imported)
* **Namapovat na pole**: Vyberte odpovídající pole Twenty z rozbalovací nabídky
* **Nemapovat**: Sloupec úplně přeskočte (data nebudou importována)
<Note>**Fields must exist before import.** The import creates records, not fields. Create custom fields under **Settings → Data Model** before importing.</Note>
<Note>**Pole musí existovat před importem.** Import vytváří záznamy, nikoli pole. Vytvořte vlastní pole v **Nastavení → Datový model** před importem.</Note>
## Field Type Compatibility
## Kompatibilita typů polí
All field types available in the Data Model are supported for import.
Všechny typy polí dostupné v Datovém modelu jsou pro import podporovány.
You can also import `id` values to either assign a specific ID to new records or update existing ones.
Můžete také importovat hodnoty `id` a přiřadit konkrétní ID novým záznamům nebo aktualizovat stávající.
<img src="/images/user-guide/fields/all-field-types.png" style={{width:'100%'}} />
## Data Format Requirements
## Požadavky na formát dat
<Note>**Some fields have special syntax.** We recommend downloading the sample file before preparing your import to see the expected syntax for each field type.</Note>
<Note>**Některá pole mají speciální syntaxi.** Před přípravou importu doporučujeme stáhnout ukázkový soubor, abyste viděli očekávanou syntaxi pro každý typ pole.</Note>
### Address Fields
### Adresová pole
Address is a nested field with multiple columns. Some can be left empty.
Adresa je vnořené pole s více sloupci. Některé lze ponechat prázdné.
* **Address / Address 1**: Street address line 1
* **Address / Address 2**: Street address line 2
* **Address / City**: City name
* **Address / State**: State or province
* **Address / Country**: Country name
* **Address / Post Code**: Postal/ZIP code
* **Adresa / Adresa 1**: První řádek adresy (ulice)
* **Adresa / Adresa 2**: Druhý řádek adresy (ulice)
* **Adresa / Město**: Název města
* **Adresa / Stát**: Stát nebo provincie
* **Adresa / Země**: Název země
* **Adresa / PSČ**: Poštovní směrovací číslo
### Array Fields
### Pole typu Array
Use the following format:
Použijte následující formát:
```
["value1","value2"]
[\"value1\",\"value2\"]
```
### Boolean Fields
### Booleovská pole
Use `TRUE` or `FALSE` (uppercase) - not `true` or `false`
Použijte `TRUE` nebo `FALSE` (velkými písmeny) ne `true` ani `false`
### Currency Fields
### Měnová pole
Currency is a nested field with two columns that **both must be filled**:
Měna je vnořené pole se dvěma sloupci, které je nutné **vyplnit obě**:
* **Amount / Amount**: The numeric value (e.g., `1234.56`)
* **Amount / Currency**: The currency code (e.g., `USD`, `EUR`)
* **Částka / Částka**: Číselná hodnota (např. `1234.56`)
* **Částka / Měna**: Kód měny (např. `USD`, `EUR`)
### Date Fields
### Datumová pole
Supported formats:
Podporované formáty:
* `YYYY-MM-DD` (recommended)
* `YYYY-MM-DD` (doporučeno)
* `MM/DD/YYYY`
* `DD/MM/YYYY`
* ISO 8601 format
* Formát ISO 8601
### Domain Fields
### Doménová pole
* It is recommended to use the format `https://domain.com` to avoid creating duplicates, as this is the format used for Companies created by the mailbox and calendar synchronizations
* A `Domain Label` and `Domain URL` can be filled: best practice is to fill `domain.com` in the label and `https://domain.com` in the url
* Domains must be unique within the Companies object
* **Domains must be unique within the file to import**
* Doporučujeme používat formát `https://domain.com`, abyste předešli vytváření duplicit, protože tento formát se používá u Společností vytvořených synchronizací poštovní schránky a kalendáře
* Lze vyplnit `Domain Label` a `Domain URL`: osvědčený postup je zadat do popisku `domain.com` a do URL `https://domain.com`
* Domény musí být v objektu Společnosti jedinečné
* **Domény musí být jedinečné v rámci importovaného souboru**
### Email Fields
### Emailová pole
* Must be valid email format
* Emails must be unique within the People object
* **Emails must be unique within the file to import**
* For additional emails: use **Emails / Primary Email** for the main email, and **Emails / Additional Emails** with this format:
* Musí mít platný formát emailu
* Emaily musí být v objektu Osoby jedinečné
* **Emaily musí být jedinečné v rámci importovaného souboru**
* Pro další emaily: použijte **Emaily / Primární email** pro hlavní email a **Emaily / Další emaily** v tomto formátu:
```
["jane@twenty.com","jane.doe@twenty.com"]
[\"jane@twenty.com\",\"jane.doe@twenty.com\"]
```
### Id Fields
### Pole ID
Specifying an `id` during import is optional. Twenty auto-generates one if not provided.
Zadání `id` při importu je volitelné. Pokud není uvedeno, Twenty jej automaticky vygeneruje.
Use cases for mapping an `id` column:
Příklady použití mapování sloupce `id`:
* **Set a specific ID**: Choose the UUID for newly created records
* **Update existing records**: Match against existing records to update them instead of creating duplicates. In that case, it is recommended to not map the other unique fields: mapping only one unique field ensures a smoother import.
* **Nastavit konkrétní ID**: Zvolte UUID pro nově vytvářené záznamy
* **Aktualizovat existující záznamy**: Spárujte je s existujícími záznamy, abyste je aktualizovali místo vytváření duplicit. V takovém případě doporučujeme nemapovat další jedinečná pole: mapování pouze jednoho jedinečného pole zajistí hladší import.
<Note>If you provide an `id`, it must be in UUID format (e.g., `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`).</Note>
<Note>Pokud zadáte `id`, musí být ve formátu UUID (např. `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`).</Note>
### JSON Fields
### Pole JSON
Use valid JSON format:
Použijte platný formát JSON:
```
{"key":"value","key2":"value2"}
```
### Links Fields
### Pole odkazů
Similar to Domain fields:
Podobně jako u doménových polí:
* Fill both the label and URL columns: **Links / Link URL** and **Links / Link Label**
* Use full URL format: `https://example.com`
* For secondary links, use **Links / Secondary Links** column with this format:
* Vyplňte oba sloupce s popiskem a adresou URL: **Odkazy / URL odkazu** a **Odkazy / Popisek odkazu**
* Použijte úplný formát URL: `https://example.com`
* Pro sekundární odkazy použijte sloupec **Odkazy / Sekundární odkazy** v tomto formátu:
```
[{"url":"https://twenty.com","label":"Twenty"}]
[{\"url\":\"https://twenty.com\",\"label\":\"Twenty\"}]
```
### Multi-Select Fields
### Pole s vícenásobným výběrem
Use the **API names** (not the display labels) in the following format:
Použijte **názvy API** (nikoli zobrazované popisky) v následujícím formátu:
```
["VALUE1","VALUE2"]
[\"VALUE1\",\"VALUE2\"]
```
See [here](#finding-api-names-for-select-fields) where to find the API names.
Viz [zde](#finding-api-names-for-select-fields), kde najdete názvy API.
<Note>New select options will not be created automatically by the import. They must be added under **Settings → Data Model** before importing.</Note>
<Note>Nové možnosti výběru se importem automaticky nevytvoří. Před importem je musíte přidat v **Nastavení → Datový model**.</Note>
<Warning>
**Import overwrites, it does not add.**
**Import přepisuje, nepřidává.**
If a record already has `VALUE2` and `VALUE3` selected, and you import `["VALUE1"]`, the record will only have `VALUE1` after import. The previous selections are replaced, not merged.
Pokud má záznam již vybrány `VALUE2` a `VALUE3` a vy importujete `[\"VALUE1\"]`, bude mít po importu pouze `VALUE1`. Předchozí výběry se nahrazují, neslučují.
</Warning>
### Number Fields
### Číselná pole
* Numbers only
* Decimals use period: `1234.56`
* No thousands separators
* Pouze čísla
* Desetinná místa se oddělují tečkou: `1234.56`
* Bez oddělovačů tisíců
### Phone Fields
### Telefonní pole
Phone is a nested field with multiple columns that **must be filled**
Telefon je vnořené pole s více sloupci, které je **nutné vyplnit**
* **Phones / Primary Phone Number**: The phone number (e.g., `4159095555`)
* **Phones / Primary Phone Country Code**: Country code (e.g., `US`)
* **Phones / Primary Phone Calling Code**: Dialing code (e.g., `+1`)
* **Telefony / Primární telefonní číslo**: Telefonní číslo (např. `4159095555`)
* **Telefony / Kód země primárního telefonu**: Kód země (např. `US`)
* **Telefony / Mezinárodní předvolba primárního telefonu**: Volací kód (např. `+1`)
### Rating Fields
### Hodnoticí pole
Use the API name format: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4`, `RATING_5`
Použijte název API ve formátu: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4`, `RATING_5`
### Relační pole
Please see our dedicated article: [Import Relations Between Objects](/l/cs/user-guide/data-migration/capabilities/import-relations)
Podívejte se prosím na náš samostatný článek: [Import relací mezi objekty](/l/cs/user-guide/data-migration/capabilities/import-relations)
### Výběrová Pole
Use the **API name** of the option (not the display label):
Použijte **název API** možnosti (nikoli zobrazovaný popisek):
```
VALUE1
@@ -87,114 +87,114 @@ Telefon je **vnořené pole**, které vyžaduje více sloupců:
| **Telefony / Kód země hlavního telefonu** | `US` |
| **Telefony / Mezinárodní předvolba hlavního telefonu** | `+1` |
### Address Fields
### Adresní pole
Address is a **nested field** with multiple columns (some can be left empty):
Adresa je **vnořené pole** s více sloupci (některé mohou zůstat prázdné):
* **Address / Address 1**: Street address line 1
* **Address / Address 2**: Street address line 2 (optional)
* **Address / City**: City name
* **Address / State**: State or province
* **Address / Country**: Country name
* **Address / Post Code**: Postal/ZIP code
* **Adresa / Adresa 1**: Řádek adresy 1
* **Adresa / Adresa 2**: Řádek adresy 2 (volitelné)
* **Adresa / Město**: Název města
* **Adresa / Stát**: Stát nebo provincie
* **Adresa / Země**: Název země
* **Adresa / PSČ**: Poštovní/ZIP kód
### Date Fields
### Datumová pole
Use consistent formatting throughout your file:
Používejte jednotný formát v celém souboru:
* `YYYY-MM-DD` (recommended): `2024-03-15`
* `YYYY-MM-DD` (doporučeno): `2024-03-15`
* `MM/DD/YYYY`: `03/15/2024`
* `DD/MM/YYYY`: `15/03/2024`
* ISO 8601: `2024-03-15T10:30:00Z`
### Number Fields
### Číselná pole
* Numbers only (no text)
* Use period for decimals: `1234.56`
* No thousands separators (not `1,234.56`)
* Pouze čísla (bez textu)
* Pro desetinná místa použijte tečku: `1234.56`
* Bez oddělovačů tisíců (ne `1,234.56`)
### Currency Fields
### Měnová pole
Currency is a **nested field** requiring two columns that **both must be filled**:
Měna je **vnořené pole** vyžadující dva sloupce, které musí být oba vyplněny:
| Column | Příklad |
| --------------------- | --------- |
| **Amount / Amount** | `1234.56` |
| **Amount / Currency** | `USD` |
| Sloupec | Příklad |
| ------------------- | --------- |
| **Částka / Částka** | `1234.56` |
| **Částka / Měna** | `USD` |
### Boolean Fields
### Booleovská pole
Use uppercase: `TRUE` or `FALSE`
Používejte velká písmena: `TRUE` nebo `FALSE`
<Warning>Lowercase `true` or `false` will not work.</Warning>
<Warning>Malá písmena `true` nebo `false` nebudou fungovat.</Warning>
### Výběrová Pole
Use the **API name** of the option, not the display label.
Použijte název API možnosti, nikoli zobrazovaný štítek.
**How to find API names:**
**Jak najít názvy API:**
1. Go to **Settings → Data Model**
2. Select the object and field
3. Enable **Advanced mode** (toggle at bottom right)
4. Copy the API name (e.g., `OPTION_1`, not "Option 1")
1. Přejděte na **Nastavení → Datový model**
2. Vyberte objekt a pole
3. Zapněte **Pokročilý režim** (přepínač vpravo dole)
4. Zkopírujte název API (např. `OPTION_1`, nikoli "Option 1")
<Note>New select options are not created automatically. Add them in **Settings → Data Model** before importing.</Note>
<Note>Nové možnosti výběru se nevytvářejí automaticky. Přidejte je v **Nastavení → Datový model** před importem.</Note>
### Multi-Select Fields
### Pole s vícenásobným výběrem
Use API names in array format:
Použijte názvy API ve formátu pole:
```
["VALUE1","VALUE2"]
```
### Array Fields
### Pole typu array
Use JSON array format:
Použijte formát JSON pole:
```
["value1","value2"]
```
### Rating Fields
### Hodnoticí pole
Use the format: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4`, or `RATING_5`
Použijte formát: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4` nebo `RATING_5`
### Links/URL Fields
### Pole odkazů/URL
Fill both columns:
Vyplňte oba sloupce:
* **Links / Link Label**: `Twenty`
* **Links / Link URL**: `https://twenty.com`
* **Odkazy / Štítek odkazu**: `Twenty`
* **Odkazy / URL odkazu**: `https://twenty.com`
For secondary links, use the **Links / Secondary Links** column:
Pro sekundární odkazy použijte sloupec **Odkazy / Sekundární odkazy**:
```
[{"url":"https://twenty.com","label":"Twenty"}]
```
### JSON Fields
### JSON pole
Use valid JSON format:
Použijte platný formát JSON:
```
{"key":"value","key2":"value2"}
```
### ID Fields
### ID pole
* **Optional**: Twenty auto-generates IDs if not provided
* **Format**: UUID (e.g., `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`)
* **Use case**: Include ID to update existing records instead of creating new ones
* **Volitelné**: Twenty automaticky generuje ID, pokud nejsou zadána
* **Formát**: UUID (např. `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`)
* **Využití**: Zahrňte ID pro aktualizaci existujících záznamů místo vytváření nových
## Step 5: Add Relation Columns (If Linking Records)
## Krok 5: Přidejte relační sloupce (pokud propojujete záznamy)
To link records to other objects (e.g., People to Companies), add a column with the unique identifier of the related record.
Chcete-li propojit záznamy s jinými objekty (např. lidi se společnostmi), přidejte sloupec s jedinečným identifikátorem souvisejícího záznamu.
**Example**: Linking People to Companies
**Příklad**: Propojení lidí se společnostmi
Add a column to your People CSV:
Přidejte do svého souboru CSV s lidmi sloupec:
```
firstName,lastName,email,companyDomain
@@ -202,69 +202,69 @@ John,Smith,john@acme.com,https://acme.com
Jane,Doe,jane@widgets.co,https://widgets.co
```
**Important rules for relations:**
**Důležitá pravidla pro relace:**
* The parent record must already exist in Twenty
* Use the **Domain URL** format (`https://domain.com`), not the label
* Map only ONE unique identifier (don't include both `companyId` AND `companyDomain`)
* For Workspace Members, use their **email** (not name)
* Nadřazený záznam musí v Twenty již existovat
* Použijte formát **Domain URL** (`https://domain.com`), nikoli štítek
* Mapujte pouze JEDEN jedinečný identifikátor (nezahrnujte zároveň `companyId` i `companyDomain`)
* U členů pracovního prostoru použijte jejich **e-mail** (ne jméno)
<Warning>
**Import Order Matters!**
**Pořadí importu je důležité!**
Import the "one" side before the "many" side:
Importujte stranu "one" před stranou "many":
1. **Companies** first
2. **People** second (with company reference)
3. **Opportunities** third
1. **Společnosti** jako první
2. **Lidé** jako druzí (s odkazem na společnost)
3. **Příležitosti** jako třetí
The parent record must exist before you can reference it.
Nadřazený záznam musí existovat dříve, než na něj můžete odkazovat.
</Warning>
See [How to Import Relations](/l/cs/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) for detailed instructions.
Podrobné pokyny najdete v [Jak importovat relace](/l/cs/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv).
## Step 6: Ensure Fields Exist in Twenty
## Krok 6: Ujistěte se, že pole v Twenty existují
The import creates **records**, not **fields**. All fields you want to import must already exist in your data model.
Import vytváří záznamy, nikoli pole. Všechna pole, která chcete importovat, musí již existovat ve vašem datovém modelu.
**Before importing:**
**Před importem:**
1. Go to **Settings → Data Model**
2. Select your object
3. Create any custom fields you need
4. Note the exact field names (they must match your column headers)
1. Přejděte na **Nastavení → Datový model**
2. Vyberte požadovaný objekt
3. Vytvořte všechna vlastní pole, která potřebujete
4. Poznamenejte si přesné názvy polí (musí odpovídat názvům sloupců)
## Step 7: Final Checklist
## Krok 7: Závěrečný kontrolní seznam
Before uploading your file, verify:
Před nahráním souboru ověřte:
<Check>File is CSV, XLSX, or XLS format</Check>
<Check>File has fewer than 10,000 records</Check>
<Check>Encoding is UTF-8</Check>
<Check>No duplicate emails (for People) or domains (for Companies)</Check>
<Check>Dates use consistent format throughout</Check>
<Check>Domains use `https://domain.com` format</Check>
<Check>Boolean fields use `TRUE` or `FALSE` (uppercase)</Check>
<Check>Select fields use API names, not display labels</Check>
<Check>All custom fields exist in Settings → Data Model</Check>
<Check>Parent records imported before child records</Check>
<Check>Relation columns reference existing records</Check>
<Check>Soubor je ve formátu CSV, XLSX nebo XLS</Check>
<Check>Soubor obsahuje méně než 10 000 záznamů</Check>
<Check>Kódování je UTF-8</Check>
<Check>Žádné duplicitní e-maily (pro lidi) nebo domény (pro společnosti)</Check>
<Check>Data používají jednotný formát v celém souboru</Check>
<Check>Domény používají formát `https://domain.com`</Check>
<Check>Booleovská pole používají `TRUE` nebo `FALSE` (velká písmena)</Check>
<Check>Výběrová pole používají názvy API, nikoli zobrazované štítky</Check>
<Check>Všechna vlastní pole existují v Nastavení → Datový model</Check>
<Check>Nadřazené záznamy byly importovány před podřízenými</Check>
<Check>Relační sloupce odkazují na existující záznamy</Check>
## Common Mistakes to Avoid
## Časté chyby, kterým se vyhnout
| Mistake | Solution |
| -------------------------------------------- | ------------------------------------- |
| Using `true` instead of `TRUE` | Boolean values must be uppercase |
| Using display labels for Select fields | Find and use API names in Settings |
| Importing People before Companies | Always import parent objects first |
| Missing currency code for Currency fields | Fill both Amount and Currency columns |
| Wrong domain format | Use `https://domain.com` consistently |
| Mapping multiple unique fields for relations | Map only ONE (domain OR id, not both) |
| Chyba | Řešení |
| ---------------------------------------------- | ---------------------------------------------- |
| Použití `true` místo `TRUE` | Booleovské hodnoty musí být velkými písmeny |
| Použití zobrazovaných štítků u výběrových polí | V Nastavení najděte a používejte názvy API |
| Importování lidí před společnostmi | Vždy nejprve importujte nadřazené objekty |
| Chybějící kód měny u měnových polí | Vyplňte sloupce Částka i Měna |
| Nesprávný formát domény | Používejte konzistentně `https://domain.com` |
| Mapování více jedinečných polí pro relace | Mapujte pouze JEDNO (doména NEBO id, ne obojí) |
## Další kroky
Your file is ready! Now:
Váš soubor je připraven! Nyní:
* [Import Companies](/l/cs/user-guide/data-migration/how-tos/import-companies-via-csv) (import these first)
* [Import Contacts](/l/cs/user-guide/data-migration/how-tos/import-contacts-via-csv)
* [Fix any import errors](/l/cs/user-guide/data-migration/how-tos/fix-import-errors)
* [Importovat společnosti](/l/cs/user-guide/data-migration/how-tos/import-companies-via-csv) (importujte je jako první)
* [Importovat kontakty](/l/cs/user-guide/data-migration/how-tos/import-contacts-via-csv)
* [Opravit chyby importu](/l/cs/user-guide/data-migration/how-tos/fix-import-errors)
@@ -1,60 +1,60 @@
---
title: Create Relation Fields
description: Step-by-step guide to connecting objects with relation fields.
title: Vytvoření relačních polí
description: Návod krok za krokem k propojení objektů pomocí relačních polí.
---
Relation fields connect records from different objects—for example, linking People to Companies.
Relační pole propojují záznamy z různých objektů — například propojení lidí se společnostmi.
<Note>
**Relation names cannot be changed after creation** (they affect the API). Plan your names carefully.
**Názvy relací nelze po vytvoření změnit** (ovlivňují rozhraní API). Názvy si pečlivě naplánujte.
</Note>
## Než začnete
Decide:
Rozhodněte se:
* Which objects are you connecting? (e.g., People → Companies)
* Which is the "one" side? (e.g., Company)
* Which is the "many" side? (e.g., People — many people work at one company)
* What should the field be named on each side?
* Které objekty propojujete? (např. Lidé → Společnosti)
* Která strana je „jedna“? (např. Společnost)
* Která strana je „mnoho“? (např. Lidé — mnoho lidí pracuje v jedné společnosti)
* Jak se má pole jmenovat na každé straně?
See [Relation Fields](/l/cs/user-guide/data-model/capabilities/relation-fields) for relation types explained.
Viz [Relační pole](/l/cs/user-guide/data-model/capabilities/relation-fields) s vysvětlením typů relací.
## Steps
## Postup
1. Go to **Settings → Data Model**
2. Select the object where you want the relation (typically the "many" side)
3. Click **+ Add Field**
4. Select **Relation** as the field type
5. Choose the **target object**
6. Select **One-to-Many** or **Many-to-One**
7. Enter field names for **both sides** of the relation
1. Přejděte do **Nastavení → Datový model**
2. Vyberte objekt, ve kterém chcete relaci (obvykle strana „mnoho“)
3. Klikněte na **+ Přidat pole**
4. Vyberte jako typ pole **Relace**
5. Vyberte **cílový objekt**
6. Vyberte **Jedna ku mnoha** nebo **Mnoho ku jedné**
7. Zadejte názvy polí pro **obě strany** relace
8. Klikněte na **Uložit**
## Example: People → Companies
## Příklad: Lidé → Společnosti
* Go to **Settings → Data Model → People**
* Add a Relation field
* Target: **Companies**
* Type: **Many-to-One**
* Field on People: **Company**
* Field on Companies: **Employees**
* Přejděte do **Nastavení → Datový model → Lidé**
* Přidejte relační pole
* Cíl: **Společnosti**
* Typ: **Mnoho ku jedné**
* Pole u lidí: **Společnost**
* Pole u společností: **Zaměstnanci**
Now each Person can be linked to a Company, and each Company shows its People.
Nyní lze každou osobu propojit se společností a každá společnost zobrazuje své lidi.
## Deleting a Relation
## Smazání relace
1. Go to **Settings → Data Model**
2. Find the relation field
3. Click **⋮ → Deactivate**
1. Přejděte do **Nastavení → Datový model**
2. Najděte relační pole
3. Klikněte na **⋮ → Deaktivovat**
Links are preserved but hidden. Reactivate to restore.
Propojení se zachovají, ale jsou skrytá. Znovu aktivujte pro obnovení.
<Note>
**Deleting a relation doesn't delete records.** Only the link between them is removed.
**Smazání relace nemaže záznamy.** Odstraní se pouze propojení mezi nimi.
</Note>
## Related
## Související
* [Relation Fields](/l/cs/user-guide/data-model/capabilities/relation-fields) — types and limitations
* [How to Import Relations](/l/cs/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) — bulk import linked records
* [Relační pole](/l/cs/user-guide/data-model/capabilities/relation-fields) — typy a omezení
* [Jak importovat relace](/l/cs/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) — hromadný import propojených záznamů
@@ -1,5 +1,5 @@
---
title: Omezte přístup ke svému zobrazení},{
title: Restrict Access to Your View
description: Ovládejte, kdo může vidět vaše vlastní zobrazení.
---
@@ -23,7 +23,7 @@ Zobrazení jsou uložená nastavení, která určují, jak se vaše data zobrazu
### Zobrazení tabulky
Výchozí zobrazení podobné tabulkovému procesoru zobrazující záznamy v řádcích spřizpůsobitelnými sloupci.
Výchozí zobrazení podobné tabulkovému procesoru zobrazující záznamy v řádcích s přizpůsobitelnými sloupci.
### Zobrazení Kanban
@@ -1,92 +1,92 @@
---
title: Běhy průběhu práce
description: Monitor and manage workflow executions.
description: Sledujte a spravujte běhy pracovních postupů.
image: /images/user-guide/workflows/workflow.png
---
## About Runs
## O bězích
A **Run** is a record of a workflow execution. Every time a workflow is triggered—whether by a record event, schedule, manual action, or webhook—a new run is created.
**Běh** je záznam provedení pracovního postupu. Při každém spuštění pracovního postupu—ať už událostí záznamu, plánem, ruční akcí nebo webhookem—se vytvoří nový běh.
## Viewing Runs
## Zobrazení běhů
### From the Workflow Editor
### Z editoru pracovních postupů
1. Open the workflow you want to monitor
2. Click the **Runs** panel on the right side
3. See a list of recent runs with their status
1. Otevřete pracovní postup, který chcete sledovat
2. Klikněte na panel **Běhů** na pravé straně
3. Zobrazte seznam nedávných běhů s jejich stavem
### From the Workflow Runs View
### Ze zobrazení běhů pracovních postupů
1. Go to **Workflow Runs** in the sidebar
2. View runs across all workflows
3. Filter by status, workflow, or date
1. V postranním panelu přejděte na **Běhy pracovních postupů**
2. Zobrazte běhy napříč všemi pracovními postupy
3. Filtrujte podle stavu, pracovního postupu nebo data
## Run Statuses
## Stavy běhů
| Stav | Popis |
| ------------- | ------------------------------------------------------------------------ |
| **Běží** | Workflow is currently executing |
| **Completed** | Workflow finished successfully |
| **Failed** | Workflow encountered an error and stopped |
| **Waiting** | Workflow is paused (e.g., waiting for a Delay action or Form submission) |
| Stav | Popis |
| ------------- | ----------------------------------------------------------------------------------- |
| **Běží** | Pracovní postup se právě provádí |
| **Dokončeno** | Pracovní postup byl úspěšně dokončen |
| **Selhalo** | Pracovní postup narazil na chybu a zastavil se |
| **Čekání** | Pracovní postup je pozastaven (např. čeká na akci Zpoždění nebo odeslání formuláře) |
## Run Details
## Podrobnosti běhu
Click on any run to see:
Kliknutím na libovolný běh zobrazíte:
* **Status**: Current state of the run
* **Started at**: When the run began
* **Duration**: How long the run took
* **Trigger data**: The input that started the workflow
* **Step outputs**: Data returned by each step
* **Error messages**: If the run failed, what went wrong
* **Stav**: Aktuální stav běhu
* **Zahájeno**: Kdy běh začal
* **Doba trvání**: Jak dlouho běh trval
* **Data spouštěče**: Vstup, který spustil pracovní postup
* **Výstupy kroků**: Data vrácená jednotlivými kroky
* **Chybové zprávy**: Pokud běh selhal, co se pokazilo
## Step-by-Step Execution
## Provádění krok za krokem
Each run shows the progression through your workflow:
Každý běh ukazuje průchod vaším pracovním postupem:
1. See which steps completed successfully
2. Identify where failures occurred
3. View the data passed between steps
4. Debug issues by examining step inputs and outputs
1. Zjistěte, které kroky byly úspěšně dokončeny
2. Zjistěte, kde došlo k selhání
3. Zobrazte data předávaná mezi kroky
4. Laděte problémy zkoumáním vstupů a výstupů kroků
## Error Handling
## Zpracování chyb
When a run fails:
Když běh selže:
1. Open the failed run
2. Find the step that caused the failure
3. Check the error message for details
4. Common issues:
* Missing required fields
1. Otevřete neúspěšný běh
2. Najděte krok, který selhání způsobil
3. Zkontrolujte podrobnosti v chybové zprávě
4. Běžné problémy:
* Chybí povinná pole
* Neplatný formát dat
* External API errors
* Permission issues
* Chyby externího rozhraní API
* Problémy s oprávněními
## Re-running Workflows
## Opětovné spuštění pracovních postupů
If a run fails, you can:
Pokud běh selže, můžete:
* Fix the underlying issue and wait for the next trigger
* For manual workflows, trigger again with the same or updated data
* Review the workflow logic to prevent future failures
* Odstraňte základní problém a počkejte na další spuštění
* U ručních pracovních postupů spusťte znovu se stejnými nebo aktualizovanými daty
* Zkontrolujte logiku pracovního postupu, abyste předešli budoucím selháním
## Performance Tips
## Tipy k výkonu
### Managing Run History
### Správa historie běhů
* Runs are retained for historical reference
* Very old runs may be archived automatically
* Export run data if you need to keep records
* Běhy jsou uchovávány pro historické účely
* Velmi staré běhy mohou být automaticky archivovány
* Exportujte data běhů, pokud potřebujete uchovávat záznamy
### Monitoring Best Practices
### Osvědčené postupy pro monitorování
* Check runs regularly after activating new workflows
* Review failed runs to identify patterns
* Po aktivaci nových pracovních postupů pravidelně kontrolujte běhy
* Prohlédněte si neúspěšné běhy a hledejte opakující se vzorce
## Related
## Související
* [Workflow Triggers](/l/cs/user-guide/workflows/capabilities/workflow-triggers)
* [Workflow Actions](/l/cs/user-guide/workflows/capabilities/workflow-actions)
* [Workflow Troubleshooting](/l/cs/user-guide/workflows/how-tos/need-more-help/workflow-troubleshooting)
* [Spouštěče pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-triggers)
* [Akce pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-actions)
* [Odstraňování problémů s pracovními postupy](/l/cs/user-guide/workflows/how-tos/need-more-help/workflow-troubleshooting)
@@ -1,5 +1,5 @@
---
title: Verze pracovního postupu},{
title: Workflow Versions
description: Spravujte verze a koncepty pracovních postupů.
image: /images/user-guide/workflows/workflow.png
---
@@ -26,7 +26,7 @@ class Resolver {
}
}
// async-WorKer
//async worker
class CustomWorker {
constructor(@Inject(MESSAGE_QUEUES.custom) private queue: MessageQueueService) {
this.initWorker();
@@ -18,21 +18,21 @@ Es ist eine gute Praxis, so viele Atome zu erstellen, wie Sie benötigen, um Ihr
```tsx
export const myAtomState = atom({
key: 'myAtomState',
default: 'Standardwert',
key: 'myAtomState',
default: 'default value',
});
export const MyComponent = () => {
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
return (
<div>
<input
value={myAtom}
onChange={(e) => setMyAtom(e.target.value)}
/>
</div>
);
return (
<div>
<input
value={myAtom}
onChange={(e) => setMyAtom(e.target.value)}
/>
</div>
);
}
```
@@ -40,7 +40,7 @@ export const MyComponent = () => {
Vermeiden Sie die Verwendung von `useRef`, um den Zustand zu speichern.
Wenn Sie den Zustand speichern möchten, sollten Sie `useState` oder `useRecoilState` verwenden.
If you want to store state, you should use `useState` or `useRecoilState`.
Sehen Sie sich [an, wie Re-Renderings verwaltet werden können](#managing-re-renders), falls Sie das Gefühl haben, dass Sie `useRef` benötigen, um einige Re-Renderings zu verhindern.
@@ -56,23 +56,23 @@ Beachten Sie, dass Sie **immer** Re-Renderings vermeiden können, indem Sie dere
Das Vermeiden von Re-Renderings in neuen Funktionen wird jetzt erleichtert, indem sie auf Root-Ebene eliminiert werden.
Die `PageChangeEffect`-Sidecar-Komponente enthält nur einen `useEffect`-Hook, der die gesamte Logik für den Seitenwechsel enthält.
The `PageChangeEffect` sidecar component contains just one `useEffect` that holds all the logic to execute on a page change.
Auf diese Weise wissen Sie, dass es nur einen Ort gibt, der ein Re-Rendering auslösen kann.
### Denken Sie immer zweimal nach, bevor Sie `useEffect` in Ihre Codebasis aufnehmen.
### Always think twice before adding `useEffect` in your codebase
Re-Renderings werden oft durch unnötige `useEffect`-Verwendungen verursacht.
Re-renders are often caused by unnecessary `useEffect`.
Sie sollten überlegen, ob Sie `useEffect` benötigen oder ob Sie die Logik in eine Event-Handler-Funktion verschieben können.
You should think whether you need `useEffect`, or if you can move the logic in a event handler function.
Es ist in der Regel einfach, die Logik in eine `handleClick` oder `handleChange`-Funktion zu verschieben.
You'll find it generally easy to move the logic in a `handleClick` or `handleChange` function.
Sie können sie auch in Bibliotheken wie Apollo finden: `onCompleted`, `onError`, usw.
### Verwenden Sie eine Geschwisterkomponente, um `useEffect`- oder Datenabruf-Logik auszulagern.
### Use a sibling component to extract `useEffect` or data fetching logic
Wenn Sie das Gefühl haben, Ihrer Root-Komponente einen `useEffect` hinzufügen zu müssen, sollten Sie erwägen, ihn in eine Sidecar-Komponente auszulagern.
If you feel like you need to add a `useEffect` in your root component, you should consider extracting it in a sidecar component.
Dasselbe können Sie auch für die Datenabruflogik mit Apollo-Hooks anwenden.
@@ -187,16 +187,16 @@ const [email, setEmail] = useState('');
Ereignis-Handler-Namen sollten mit `handle` beginnen, während `on` als Präfix dient, um Ereignisse in Komponenten-Props zu benennen.
```tsx
// ❌ Schlecht
// ❌ Bad
const onEmailChange = (val: string) => {
// ...
// ...
};
```
```tsx
// ✅ Gut
// ✅ Good
const handleEmailChange = (val: string) => {
// ...
// ...
};
```
@@ -210,24 +210,24 @@ Betrachten Sie die unten definierte `EmailField`-Komponente:
```tsx
type EmailFieldProps = {
value: string;
disabled?: boolean;
value: string;
disabled?: boolean;
};
const EmailField = ({ value, disabled = false }: EmailFieldProps) => (
<TextInput value={value} disabled={disabled} fullWidth />
<TextInput value={value} disabled={disabled} fullWidth />
);
```
**Verwendung**
```tsx
// ❌ Schlecht, den gleichen Wert wie den Standardwert übergeben, fügt keinen Wert hinzu
// ❌ Bad, passing in the same value as the default value adds no value
const Form = () => <EmailField value="username@email.com" disabled={false} />;
```
```tsx
// ✅ Gut, nimmt den Standardwert an
// ✅ Good, assumes the default value
const Form = () => <EmailField value="username@email.com" />;
```
@@ -242,13 +242,13 @@ const SomeParentComponent = () => <MyComponent Icon={MyIcon} />;
// In MyComponent
const MyComponent = ({ MyIcon }: { MyIcon: IconComponent }) => {
const theme = useTheme();
const theme = useTheme();
return (
<div>
<MyIcon size={theme.icon.size.md}>
</div>
)
return (
<div>
<MyIcon size={theme.icon.size.md}>
</div>
)
};
```
@@ -274,28 +274,28 @@ Beim Importieren sollten Sie die vorgesehenen Aliase anstelle der vollständigen
```js
{
alias: {
"~": path.resolve(__dirname, "src"),
"@": path.resolve(__dirname, "src/modules"),
"@testing": path.resolve(__dirname, "src/testing"),
},
alias: {
"~": path.resolve(__dirname, "src"),
"@": path.resolve(__dirname, "src/modules"),
"@testing": path.resolve(__dirname, "src/testing"),
},
}
```
**Verwendung**
```tsx
// ❌ Schlecht, gibt den vollständigen relativen Pfad an
// ❌ Bad, specifies the entire relative path
import {
CatalogDecorator
CatalogDecorator
} from '../../../../../testing/decorators/CatalogDecorator';
import {
ComponentDecorator
ComponentDecorator
} from '../../../../../testing/decorators/ComponentDecorator';
```
```tsx
// ✅ Gut, nutzt die vorgesehenen Aliase
// ✅ Good, utilises the designated aliases
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
import { ComponentDecorator } from 'twenty-ui/testing';
```
@@ -306,16 +306,16 @@ import { ComponentDecorator } from 'twenty-ui/testing';
```js
const validationSchema = z
.object({
exist: z.boolean(),
email: z
.string()
.email('Email muss eine gültige E-Mail sein'),
password: z
.string()
.regex(PASSWORD_REGEX, 'Passwort muss mindestens 8 Zeichen enthalten'),
})
.required();
.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>;
```
@@ -73,7 +73,7 @@ Das Projekt hat einen sauberen und einfachen Stack mit minimalem Boilerplate-Cod
[React Router](https://reactrouter.com/) übernimmt das Routing.
Um unnötige [Re-Renders](/l/de/developers/contribute/capabilities/frontend-development/best-practices-front#managing-re-renders) zu vermeiden, befindet sich die gesamte Routing-Logik in einem `useEffect` in `PageChangeEffect`.
To avoid unnecessary [re-renders](/l/de/developers/contribute/capabilities/frontend-development/best-practices-front#managing-re-renders) all the routing logic is in a `useEffect` in `PageChangeEffect`.
### Zustandsverwaltung
@@ -45,29 +45,29 @@ const PageListeningEnter = () => {
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
// 1. Setze den Tastenkombinationsbereich in einem useEffect
// 1. Set the hotkey scope in a useEffect
useEffect(() => {
setHotkeyScopeAndMemorizePreviousScope(
ExampleHotkeyScopes.ExampleEnterPage,
);
// Zurückkehren zum vorherigen Tastenkombinationsbereich, wenn die Komponente entfernt wird
// Revert to the previous hotkey scope when the component is unmounted
return () => {
goBackToPreviousHotkeyScope();
};
}, [goBackToPreviousHotkeyScope, setHotkeyScopeAndMemorizePreviousScope]);
// 2. Verwenden Sie den useScopedHotkeys Hook
// 2. Use the useScopedHotkeys hook
useScopedHotkeys(
Key.Enter,
() => {
// Eine Logik, die auf dieser Seite ausgeführt wird, wenn der Benutzer Enter drückt
// Some logic executed on this page when the user presses Enter
// ...
},
ExampleHotkeyScopes.ExampleEnterPage,
);
return <div>Meine Seite, die auf Enter hört</div>;
return <div>My page that listens for Enter</div>;
};
```
@@ -87,7 +87,7 @@ const ExamplePageWithModal = () => {
} = usePreviousHotkeyScope();
const handleOpenModalClick = () => {
// 1. Setze den Tastenkombinationsbereich, wenn der Benutzer das Modal öffnet
// 1. Set the hotkey scope when user opens the modal
setShowModal(true);
setHotkeyScopeAndMemorizePreviousScope(
ExampleHotkeyScopes.ExampleModal,
@@ -95,14 +95,14 @@ const ExamplePageWithModal = () => {
};
const handleModalClose = () => {
// 1. Zurückkehren zum vorherigen Tastenkombinationsbereich, wenn das Modal geschlossen wird
// 1. Revert to the previous hotkey scope when the modal is closed
setShowModal(false);
goBackToPreviousHotkeyScope();
};
return <div>
<h1>Meine Seite mit einem Modal</h1>
<button onClick={handleOpenModalClick}>Modal öffnen</button>
<h1>My page with a modal</h1>
<button onClick={handleOpenModalClick}>Open modal</button>
{showModal && <MyModalComponent onClose={handleModalClose} />}
</div>;
};
@@ -112,9 +112,9 @@ Dann in der Modalkomponente:
```tsx
const MyDropdownComponent = ({ onClose }: { onClose: () => void }) => {
// 2. Verwenden Sie den useScopedHotkeys Hook, um auf Escape zu hören.
// Beachten Sie, dass Escape eine gängige Tastenkombination ist, die von vielen anderen Komponenten verwendet werden könnte
// Daher ist es wichtig, einen Tastenkombinationsbereich zu verwenden, um Konflikte zu vermeiden
// 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,
() => {
@@ -123,13 +123,13 @@ const MyDropdownComponent = ({ onClose }: { onClose: () => void }) => {
ExampleHotkeyScopes.ExampleModal,
);
return <div>Meine Modalkomponente</div>;
return <div>My modal component</div>;
};
```
Es ist wichtig, dieses Muster zu verwenden, wenn Sie sich nicht sicher sind, ob das einfache Benutzen eines useEffect bei Ein-/Ausbindung ausreicht, um Konflikte zu vermeiden.
It's important to use this pattern when you're not sure that just using a useEffect with mount/unmount will be enough to avoid conflicts.
Diese Konflikte können schwer zu debuggen sein und treten möglicherweise häufiger auf, als man denkt, mit useEffects.
Those conflicts can be hard to debug, and it might happen more often than not with useEffects.
## Was ist ein Tastenkombinationsbereich?
@@ -21,16 +21,16 @@ Verwenden Sie immer TSX-Funktionskomponenten.
Vermeiden Sie `import` mit `const`, da es schwieriger zu lesen und schwerer mit Code-Vervollständigung zu importieren ist.
```tsx
// ❌ Schlecht, schwerer zu lesen, schwerer zu importieren mit Code-Vervollständigung
const MeineKomponente = () => {
return <div>Hallo Welt</div>;
// ❌ Bad, harder to read, harder to import with code completion
const MyComponent = () => {
return <div>Hello World</div>;
};
export default MeineKomponente;
export default MyComponent;
// ✅ Gut, leicht zu lesen, leicht zu importieren mit Code-Vervollständigung
export function MeineKomponente() {
return <div>Hallo Welt</div>;
// ✅ Good, easy to read, easy to import with code completion
export function MyComponent() {
return <div>Hello World</div>;
};
```
@@ -41,26 +41,27 @@ Erstellen Sie den Typ der Eigenschaften (props) und nennen Sie ihn `(ComponentNa
Verwenden Sie Destrukturierung der Props.
```tsx
// ❌ Schlecht, ohne Typ
export const MeineKomponente = (props) => <div>Hallo {props.name}</div>;
// ❌ Bad, no type
export const MyComponent = (props) => <div>Hello {props.name}</div>;
// ✅ Gut, mit Typ
type MeineKomponenteProps = {
// ✅ Good, type
type MyComponentProps = {
name: string;
};
export const MeineKomponente = ({ name }: MeineKomponenteProps) => <div>Hallo {name}</div>;
export const MyComponent = ({ name }: MyComponentProps) => <div>Hello {name}</div>;
```
#### Vermeiden Sie die Verwendung von `React.FC` oder `React.FunctionComponent`, um Prop-Typen zu definieren
```tsx
/* ❌ - Schlecht, definiert die Komponententyp-Anmerkungen mit `FC`
* - Mit `React.FC` akzeptiert die Komponente implizit ein `children`-Prop,
* selbst wenn es nicht im Prop-Typ definiert ist. Dies ist nicht immer gewünscht,
* insbesondere wenn die Komponente nicht beabsichtigt, Kinder zu rendern.
/* ❌ - 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 EmailFeld: React.FC<{
const EmailField: React.FC<{
value: string;
}> = ({ value }) => <TextInput value={value} disabled fullWidth />;
```
@@ -85,10 +86,10 @@ const EmailField = ({ value }: EmailFieldProps) => (
Vermeiden Sie das Propspreading einzelner Variablen in JSX-Elementen, wie `{...props}`. Diese Praxis führt oft zu weniger lesbarem und schwer wartbarem Code, da unklar ist, welche Props die Komponente erhält.
```tsx
/* ❌ - Schlecht, spreadet ein einzelnes Variablen-Prop in die darunterliegende Komponente
/* ❌ - Bad, spreads a single variable prop into the underlying component
*/
const MeineKomponente = (props: EigeneProps) => {
return <AndereKomponente {...props} />;
const MyComponent = (props: OwnProps) => {
return <OtherComponent {...props} />;
}
```
@@ -136,13 +137,13 @@ onClick?.();
Verwenden Sie immer `type` anstelle von `interface`, da sie fast immer überlappen und `type` flexibler ist.
```tsx
// ❌ Schlecht
interface MeinInterface {
// ❌ Bad
interface MyInterface {
name: string;
}
// ✅ Gut
type MeinTyp = {
// ✅ Good
type MyType = {
name: string;
};
```
@@ -154,14 +155,14 @@ type MeinTyp = {
Warum TypeScript empfiehlt, Enums zu vermeiden, sehen Sie [hier](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).
```tsx
// ❌ Schlecht, verwendet ein Enum
enum Farbe {
Rot = "red",
Grün = "green",
Blau = "blue",
// ❌ Bad, utilizes an enum
enum Color {
Red = "red",
Green = "green",
Blue = "blue",
}
let farbe = Farbe.Rot;
let color = Color.Red;
```
```tsx
@@ -262,13 +263,13 @@ const StyledButton = styled.button`
Vermeiden Sie Typ-Importe. Um diesen Standard durchzusetzen, überprüft eine ESLint-Regel alle Typ-Importe und meldet sie. Dies trägt zur Konsistenz und Lesbarkeit des TypeScript-Codes bei.
```tsx
// ❌ Schlecht
// ❌ Bad
import { type Meta, type StoryObj } from '@storybook/react';
// ❌ Schlecht
// ❌ Bad
import type { Meta, StoryObj } from '@storybook/react';
// ✅ Gut
// ✅ Good
import { Meta, StoryObj } from '@storybook/react';
```
@@ -20,7 +20,7 @@ A dropdown-based icon picker that allows users to select an icon from a list.
const [selectedIcon, setSelectedIcon] = useState("");
const handleIconChange = ({ iconKey, Icon }) => {
console.log("Gewähltes Symbol:", iconKey);
console.log("Selected Icon:", iconKey);
setSelectedIcon(iconKey);
};
@@ -17,10 +17,10 @@ Erstellt eine Navigationsleiste mit Brotkrumen.
export const MyComponent = () => {
const breadcrumbLinks = [
{ children: "Startseite", href: "/" },
{ children: "Kategorie", href: "/category" },
{ children: "Unterkategorie", href: "/category/subcategory" },
{ children: "Aktuelle Seite" },
{ children: "Home", href: "/" },
{ children: "Category", href: "/category" },
{ children: "Subcategory", href: "/category/subcategory" },
{ children: "Current Page" },
];
return (
@@ -20,7 +20,7 @@ A stylized link component for displaying contact information.
export const MyComponent = () => {
const handleLinkClick = (event) => {
console.log('Kontaktlink geklickt!', event);
console.log('Contact link clicked!', event);
};
return (
@@ -60,13 +60,13 @@ A stylized link component for displaying links.
export const MyComponent = () => {
const handleLinkClick = (event) => {
console.log("Kontaktlink geklickt!", event);
console.log("Contact link clicked!", event);
};
return (
<Router>
<RawLink className href="/contact" onClick={handleLinkClick}>
Kontaktieren Sie uns
Contact Us
</RawLink>
</Router>
);
@@ -97,13 +97,13 @@ A rounded-styled link with a Chip component for links.
export const MyComponent = () => {
const handleLinkClick = (event) => {
console.log("Kontaktlink geklickt!", event);
console.log("Contact link clicked!", event);
};
return (
<Router>
<RoundedLink href="/contact" onClick={handleLinkClick}>
Kontaktieren Sie uns
Contact Us
</RoundedLink>
</Router>
);
@@ -18,18 +18,18 @@ Ein vielseitiger Menüpunkt, der in einem Menü oder einer Navigationsliste verw
export const MyComponent = () => {
const handleMenuItemClick = (event) => {
console.log("Menüpunkt angeklickt!", event);
console.log("Menu item clicked!", event);
};
const handleButtonClick = (event) => {
console.log("Symbolschaltfläche angeklickt!", event);
console.log("Icon button clicked!", event);
};
return (
<MenuItem
LeftIcon={IconBell}
accent="default"
text="Menüpunkttext"
text="Menu item text"
iconButtons={[{ Icon: IconAlertCircle, onClick: handleButtonClick }]}
isTooltipOpen={true}
testId="menu-item-1"
@@ -71,13 +71,13 @@ Ein befehlsartiger Menüpunkt innerhalb eines Menüs zur Anzeige von Tastaturkü
export const MyComponent = () => {
const handleCommandClick = () => {
console.log("Befehl geklickt!");
console.log("Command clicked!");
};
return (
<MenuItemCommand
LeftIcon={IconBell}
text="Erste Option"
text="First Option"
firstHotKey="⌘"
secondHotKey="1"
isSelected={true}
@@ -115,7 +115,7 @@ Ein verschiebbares Menüelement, das in einem Menü oder einer Liste verwendet w
export const MyComponent = () => {
const handleMenuItemClick = (event) => {
console.log("Menüelement geklickt!", event);
console.log("Menu item clicked!", event);
};
return (
@@ -125,7 +125,7 @@ Ein verschiebbares Menüelement, das in einem Menü oder einer Liste verwendet w
iconButtons={[{ Icon: IconAlertCircle, onClick: handleButtonClick }]}
isTooltipOpen={false}
onClick={handleMenuItemClick}
text="Menüelement verschiebbar"
text="Menu item draggable"
isDragDisabled={false}
className
/>
@@ -163,7 +163,7 @@ Bietet eine Möglichkeit, eine Mehrfachauswahl-Funktionalität mit einem zugehö
return (
<MenuItemMultiSelect
LeftIcon={IconBell}
text="Erste Option"
text="First Option"
selected={false}
className
/>
@@ -199,7 +199,7 @@ Ein Mehrfachauswahl-Menüelement mit einem Avatar, einem Kontrollkästchen zur A
return (
<MenuItemMultiSelectAvatar
avatar={<img src={imageUrl} alt="Avatar" />}
text="Erste Option"
text="First Option"
selected={false}
className
/>
@@ -231,13 +231,13 @@ Ein Menüelement mit einem optionalen linken Symbol, Textinhalt und einem nach r
export const MyComponent = () => {
const handleNavigation = () => {
console.log("Zu einer anderen Seite navigieren");
console.log("Navigate to another page");
};
return (
<MenuItemNavigate
LeftIcon={IconBell}
text="Erste Option"
text="First Option"
onClick={handleNavigation}
className
/>
@@ -268,13 +268,13 @@ Ein auswählbares Menüelement mit optionalem linken Inhalt (Symbol und Text) un
export const MyComponent = () => {
const handleSelection = () => {
console.log("Menüelement ausgewählt");
console.log("Menu item selected");
};
return (
<MenuItemSelect
LeftIcon={IconBell}
text="Erste Option"
text="First Option"
selected={true}
disabled={false}
hovered={false}
@@ -313,13 +313,13 @@ A selectable menu item with an avatar, featuring optional left content (avatar a
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAYABgAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABgAAAAAQAAAGAAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAABSgAwAEAAAAAQAAABQAAAAA/8AAEQgAFAAUAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/bAEMACwgICggHCwoJCg0MCw0RHBIRDw8RIhkaFBwpJCsqKCQnJy0yQDctMD0wJyc4TDk9Q0VISUgrNk9VTkZUQEdIRf/bAEMBDA0NEQ8RIRISIUUuJy5FRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRf/dAAQAAv/aAAwDAQACEQMRAD8Ava1q728otYY98joSCTgZrnbXWdTtrhrfVZXWLafmcAEkdgR/hVltQku9Q8+OIEBcGOT+ID0PY1ka1KH2u8ToqnPLbmIqG7u6LtbQ7RXBRec4Uck9eKXcPWsKDWVnhWSL5kYcFelSf2m3901POh8jP//QoyIAnTuKpXsY82NsksUyWPU5q/L9z8RVK++/F/uCsVsaEURwgA4HtT9x9TUcf3KfUGh//9k=";
const handleSelection = () => {
console.log("Menüpunkt ausgewählt");
console.log("Menu item selected");
};
return (
<MenuItemSelectAvatar
avatar={<img src={imageUrl} alt="Avatar" />}
text="Erste Option"
text="First Option"
selected={true}
disabled={false}
hovered={false}
@@ -358,7 +358,7 @@ Ein wählbares Menüelement mit Farbbeispiel für Situationen, in denen Benutzer
export const MyComponent = () => {
const handleSelection = () => {
console.log("Menüpunkt ausgewählt");
console.log("Menu item selected");
};
return (
@@ -405,7 +405,7 @@ Ein Menüelement mit einem zugehörigen Umschalter, mit dem Benutzer eine bestim
return (
<MenuItemToggle
LeftIcon={IconBell}
text="Erste Option"
text="First Option"
toggled={true}
toggleSize="small"
className
@@ -21,17 +21,17 @@ Rendert eine Navigationsleiste, die mehrere `NavigationBarItem`-Komponenten enth
{
name: "Home",
Icon: IconHome,
onClick: () => console.log("Home geklickt"),
onClick: () => console.log("Home clicked"),
},
{
name: "Profil",
name: "Profile",
Icon: IconUser,
onClick: () => console.log("Profil geklickt"),
onClick: () => console.log("Profile clicked"),
},
{
name: "Einstellungen",
name: "Settings",
Icon: IconSettings,
onClick: () => console.log("Einstellungen geklickt"),
onClick: () => console.log("Settings clicked"),
},
];
@@ -17,9 +17,9 @@ Zeigt den Fortschritt durch eine Folge von nummerierten Schritten, indem der akt
export const MyComponent = () => {
return (
<StepBar activeStep={2}>
<StepBar.Step>Schritt 1</StepBar.Step>
<StepBar.Step>Schritt 2</StepBar.Step>
<StepBar.Step>Schritt 3</StepBar.Step>
<StepBar.Step>Step 1</StepBar.Step>
<StepBar.Step>Step 2</StepBar.Step>
<StepBar.Step>Step 3</StepBar.Step>
</StepBar>
);
};
@@ -1,5 +1,5 @@
---
title: Berechtigungen & Zugriffskontrolle},{
title: Permissions & Access Control
description: Steuern Sie, auf welche Daten KI-Agenten in Ihrem Arbeitsbereich zugreifen und was sie dort ändern können.
---
@@ -1,6 +1,6 @@
---
title: Abrechnung
description: Understand Twenty pricing and manage your subscription.
description: Verstehen Sie die Preisgestaltung von Twenty und verwalten Sie Ihr Abonnement.
image: /images/user-guide/setup/pricing.png
---
@@ -8,38 +8,38 @@ image: /images/user-guide/setup/pricing.png
<img src="/images/user-guide/setup/pricing.png" alt="Abrechnung" />
</Frame>
Twenty offers flexible pricing plans to fit your team's needs. Manage your subscription, track workflow credits, and access invoices all from **Settings → Billing**.
Twenty bietet flexible Preispläne, die den Bedürfnissen Ihres Teams entsprechen. Verwalten Sie Ihr Abonnement, verfolgen Sie Workflow-Guthaben und greifen Sie auf Rechnungen zu alles über **Einstellungen → Abrechnung**.
## What's in this section
## Was enthält dieser Abschnitt
<CardGroup cols={2}>
<Card title="Pricing Plans" icon="tags" href="/l/de/user-guide/billing/capabilities/pricing-plans">
Learn about Twenty's pricing plans and what's included.
<Card title="Preispläne" icon="tags" href="/l/de/user-guide/billing/capabilities/pricing-plans">
Erfahren Sie mehr über die Preispläne von Twenty und was enthalten ist.
</Card>
<Card title="FAQ" icon="circle-question" href="/l/de/user-guide/billing/how-tos/billing-faq">
Frequently asked questions about pricing and billing.
Häufig gestellte Fragen zu Preisen und Abrechnung.
</Card>
</CardGroup>
## At a glance
## Auf einen Blick
| Plan | Key Features |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Free (Self-Hosted)** | All Pro features, community support |
| **Pro (Cloud)** | Everything apart from the Premium features (SSO and row-level permissions), standard support |
| **Organization (Cloud)** | All from Pro + the Premium features (SSO and row-level permissions), priority support |
| **Organization (Self-Hosted)** | All from Pro + the Premium features (SSO, row-level permissions), Twenty team support, not required to publish your custom code as open-source before distributing |
| Plan | Wichtige Funktionen |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Kostenlos (Selbstgehostet)** | Alle Pro-Funktionen, Community-Support |
| **Pro (Cloud)** | Alles außer den Premium-Funktionen (SSO und zeilenbezogene Berechtigungen), Standardsupport |
| **Organisation (Cloud)** | Alles aus Pro + die Premium-Funktionen (SSO und zeilenbezogene Berechtigungen), priorisierter Support |
| **Organisation (Selbstgehostet)** | Alles aus Pro + die Premium-Funktionen (SSO, zeilenbezogene Berechtigungen), Support durch das Twenty-Team, keine Pflicht, Ihren benutzerdefinierten Code vor der Verteilung als Open Source zu veröffentlichen |
## Quick answers
## Schnelle Antworten
**Where do I manage billing?**
Go to **Settings → Billing** to view your plan, update payment methods, and access invoices.
**Wo verwalte ich die Abrechnung?**
Gehen Sie zu **Einstellungen → Abrechnung**, um Ihren Plan anzusehen, Zahlungsmethoden zu aktualisieren und auf Rechnungen zuzugreifen.
**Can I use Twenty for free?**
Yes! Self-host Twenty and get all Pro features at no cost.
**Kann ich Twenty kostenlos nutzen?**
Ja! Hosten Sie Twenty selbst und erhalten Sie alle Pro-Funktionen kostenlos.
**How do I upgrade?**
Go to **Settings → Billing** and click **Switch to Organization** or **Switch to Yearly**.
**Wie führe ich ein Upgrade durch?**
Gehen Sie zu **Einstellungen → Abrechnung** und klicken Sie auf **Zu Organisation wechseln** oder **Zum Jahresplan wechseln**.
For more questions, see the [Billing FAQ](/l/de/user-guide/billing/how-tos/billing-faq).
Weitere Fragen finden Sie in den [Abrechnungs-FAQs](/l/de/user-guide/billing/how-tos/billing-faq).
@@ -1,23 +1,23 @@
---
title: Kalender
description: Understanding calendar integration features in Twenty.
description: Die Funktionen der Kalenderintegration in Twenty verstehen.
---
**Note**: To connect your calendar and configure sync settings, visit [Email & Calendar Setup](/l/de/user-guide/calendar-emails/overview).
**Hinweis**: Um Ihren Kalender zu verbinden und die Synchronisierungseinstellungen zu konfigurieren, besuchen Sie [E-Mail- & Kalendereinrichtung](/l/de/user-guide/calendar-emails/overview).
## How Calendar Integration Works
## Wie die Kalenderintegration funktioniert
Twenty automatically syncs your calendar events and links them to the relevant CRM records, giving you a complete view of your meeting history with contacts and companies.
Twenty synchronisiert Ihre Kalendertermine automatisch und verknüpft sie mit den entsprechenden CRM-Datensätzen, sodass Sie einen vollständigen Überblick über Ihre Meeting-Historie mit Kontakten und Unternehmen erhalten.
## Kalender-Reiter
Next to the Emails tab on records, you'll find a `Calendar` tab that contains the history of meetings scheduled with the record.
Neben dem Reiter E-Mails in Datensätzen finden Sie einen Reiter `Kalender`, der die Historie der mit dem Datensatz geplanten Meetings enthält.
### Available For
### Verfügbar für
* **Personen**: Alle mit einem bestimmten Kontakt geplanten Meetings anzeigen
* **Unternehmen**: Alle Meetings im Zusammenhang mit einem Unternehmen und seinen Mitarbeitern anzeigen
* **Opportunities**: Access meeting history related to the company linked to this opportunity
* **Chancen**: Zugriff auf die Meeting-Historie zur Firma, die mit dieser Chance verknüpft ist
### Meeting-Historie anzeigen
@@ -26,18 +26,18 @@ Next to the Emails tab on records, you'll find a `Calendar` tab that contains th
3. **Durchsuchen Sie die Meeting-Historie**: Alle geplanten Meetings und deren Details anzeigen
4. **Auf Meeting-Kontext zugreifen**: Teilnehmer, Zeiten und verwandte Informationen einsehen
## Visibility Settings
## Sichtbarkeitseinstellungen
Calendar data follows the same visibility settings as emails, ensuring consistent privacy controls across both communication channels.
Kalenderdaten folgen denselben Sichtbarkeitseinstellungen wie E-Mails und gewährleisten konsistente Datenschutzkontrollen in beiden Kommunikationskanälen.
## Was synchronisiert wird
* **External Meetings**: All meetings with contacts outside your organization
* **Automatic Linking**: Meetings connect to existing People and Company records based on attendee email addresses
* **Meeting Details**: Subject, time, duration, and participants
* **Updates**: New calendar events sync automatically
* **Externe Meetings**: Alle Meetings mit Kontakten außerhalb Ihrer Organisation
* **Automatische Verknüpfung**: Meetings werden basierend auf den E-Mail-Adressen der Teilnehmer mit bestehenden Personen- und Firmendatensätzen verknüpft
* **Meeting-Details**: Betreff, Uhrzeit, Dauer und Teilnehmer
* **Aktualisierungen**: Neue Kalendertermine werden automatisch synchronisiert
## Was nicht synchronisiert wird
* **Internal Meetings**: Meetings with only colleagues (same domain) remain private
* **Private Events**: Events marked as private in your calendar
* **Interne Meetings**: Meetings zwischen Kollegen (gleiche Domain) bleiben privat
* **Private Termine**: Termine, die in Ihrem Kalender als privat markiert sind
@@ -1,59 +1,59 @@
---
title: Dashboards FAQ
description: Frequently asked questions about dashboards in Twenty.
description: Häufig gestellte Fragen zu Dashboards in Twenty.
---
<AccordionGroup>
<Accordion title="Can I create private dashboards?">
No, dashboards are currently visible to everyone with access to your Twenty workspace. Private dashboards are not yet available.
<Accordion title="Kann ich private Dashboards erstellen?">
Nein, Dashboards sind derzeit für alle sichtbar, die Zugriff auf deinen Twenty-Arbeitsbereich haben. Private Dashboards sind noch nicht verfügbar.
</Accordion>
<Accordion title="Why do my metrics look different from my colleague's?">
Dashboards currently display data based on the viewer's timezone. If you're in different regions (e.g., APAC vs. US), you may see slightly different numbers for the same dashboard. We're working on adding a timezone setting per dashboard to ensure consistent data across teams.
<Accordion title="Warum sehen meine Kennzahlen anders aus als die meiner Kolleginnen und Kollegen?">
Dashboards zeigen derzeit Daten basierend auf der Zeitzone der betrachtenden Person. Befinden sich Personen in unterschiedlichen Regionen (z. B. APAC vs. USA), können für dasselbe Dashboard leicht unterschiedliche Zahlen angezeigt werden. Wir arbeiten daran, eine Zeitzonen-Einstellung pro Dashboard hinzuzufügen, um teamübergreifend konsistente Daten sicherzustellen.
</Accordion>
<Accordion title="Can I export my dashboard?">
Exporting dashboards is not available at the moment. This feature is on our roadmap.
<Accordion title="Kann ich mein Dashboard exportieren?">
Das Exportieren von Dashboards ist derzeit nicht verfügbar. Diese Funktion steht auf unserer Roadmap.
</Accordion>
<Accordion title="Can I share dashboards with external users?">
No, sharing dashboards with users outside your Twenty workspace (non-Twenty users) is not currently supported.
<Accordion title="Kann ich Dashboards mit externen Benutzerinnen und Benutzern teilen?">
Nein, das Teilen von Dashboards mit Benutzerinnen und Benutzern außerhalb deines Twenty-Arbeitsbereichs (Nicht-Twenty-Benutzer) wird derzeit nicht unterstützt.
</Accordion>
<Accordion title="How do I add a dashboard to my favorites?">
Open the dashboard you want to favorite, then click the star icon. Favorites are personal—they won't affect other users.
<Accordion title="Wie füge ich ein Dashboard zu meinen Favoriten hinzu?">
Öffne das Dashboard, das du zu den Favoriten hinzufügen möchtest, und klicke dann auf das Sternsymbol. Favoriten sind persönlich sie wirken sich nicht auf andere Benutzer aus.
</Accordion>
<Accordion title="What's the difference between tabs and widgets?">
* **Tabs** organize your dashboard into sections (like pages within the dashboard)
* **Widgets** are the individual visualizations (charts, numbers, iFrames) within each tab
<Accordion title="Was ist der Unterschied zwischen Tabs und Widgets?">
* **Tabs** organisieren dein Dashboard in Abschnitte (ähnlich wie Seiten innerhalb des Dashboards)
* **Widgets** sind die einzelnen Visualisierungen (Diagramme, Zahlen, iFrames) innerhalb jedes Tabs
Structure: Dashboard → Tabs → Widgets
Struktur: Dashboard → Tabs → Widgets
</Accordion>
<Accordion title="Why do I see 'Undisplayed data' warning on my bar chart?">
Bar charts have display limits: 100 bars for horizontal charts, 50 for vertical. If your data exceeds this, add filters to narrow down the results or change the grouping (e.g., group by week instead of day).
<Accordion title="Warum sehe ich die Warnung „Nicht angezeigte Daten“ in meinem Balkendiagramm?">
Balkendiagramme haben Anzeigegrenzen: 100 Balken bei horizontalen Diagrammen, 50 bei vertikalen. Wenn deine Daten darüber hinausgehen, füge Filter hinzu, um die Ergebnisse einzugrenzen, oder ändere die Gruppierung (z. B. nach Woche statt nach Tag gruppieren).
</Accordion>
<Accordion title="Can I filter an entire dashboard at once?">
Dashboard-level filters are not available yet, but this feature is on our roadmap. Currently, you need to apply filters to each widget individually.
<Accordion title="Kann ich ein gesamtes Dashboard auf einmal filtern?">
Filter auf Dashboard-Ebene sind noch nicht verfügbar, aber diese Funktion steht auf unserer Roadmap. Derzeit musst du Filter für jedes Widget einzeln anwenden.
</Accordion>
<Accordion title="Are gauge charts or tables available?">
Noch nicht. Gauge charts and tables are on our roadmap and will be added in a future release.
<Accordion title="Gibt es Tachometerdiagramme oder Tabellen?">
Noch nicht. Tachometerdiagramme und Tabellen stehen auf unserer Roadmap und werden in einer zukünftigen Version hinzugefügt.
</Accordion>
<Accordion title="How do I duplicate a dashboard?">
1. Make sure you're in view mode (not editing)
2. Open the command bar with **Cmd + K** (or **Ctrl + K** on Windows)
3. Select **Duplicate dashboard**
<Accordion title="Wie dupliziere ich ein Dashboard?">
1. Stelle sicher, dass du im Ansichtsmodus bist (nicht im Bearbeitungsmodus)
2. Öffne die Befehlspalette mit **Cmd + K** (oder **Strg + K** unter Windows)
3. Wähle **Dashboard duplizieren**
</Accordion>
<Accordion title="How often does dashboard data refresh?">
Widgets update automatically as your CRM data changes:
<Accordion title="Wie oft werden Dashboard-Daten aktualisiert?">
Widgets aktualisieren sich automatisch, wenn sich deine CRM-Daten ändern:
* Real-time updates for most metrics
* Use the refresh button for a manual update if needed
* Historical data is preserved for trend analysis
* Echtzeitaktualisierungen für die meisten Kennzahlen
* Verwende bei Bedarf die Schaltfläche zum Aktualisieren für eine manuelle Aktualisierung
* Historische Daten bleiben für Trendanalysen erhalten
</Accordion>
</AccordionGroup>
@@ -1,176 +1,176 @@
---
title: Field Mapping
description: How field mapping works during data import.
title: Feldzuordnung
description: Wie die Feldzuordnung beim Datenimport funktioniert.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## How Field Mapping Works
## Wie die Feldzuordnung funktioniert
When you upload a file, Twenty analyzes your columns and attempts to match them to existing fields.
Wenn Sie eine Datei hochladen, analysiert Twenty Ihre Spalten und versucht, sie bestehenden Feldern zuzuordnen.
### Automatic Mapping
### Automatische Zuordnung
Twenty tries to match columns based on:
Twenty versucht, Spalten anhand der folgenden Kriterien abzugleichen:
* Column header names (exact or similar matches)
* Data type detection (dates, numbers, emails)
* Common field patterns
* Spaltenüberschriften (genaue oder ähnliche Übereinstimmungen)
* Erkennung des Datentyps (Datum, Zahlen, E-Mails)
* Häufige Feldmuster
<Note>**Quick tip:** Export a few rows from the object you want to import. The exported file will have the exact column names Twenty expects, making automatic mapping seamless during import.</Note>
<Note>**Schneller Tipp:** Exportieren Sie ein paar Zeilen aus dem Objekt, das Sie importieren möchten. Die exportierte Datei enthält genau die Spaltennamen, die Twenty erwartet, sodass die automatische Zuordnung beim Import reibungslos funktioniert.</Note>
### Manual Mapping Options
### Optionen für die manuelle Zuordnung
For each column, you can:
Für jede Spalte können Sie:
* **Map to a field**: Select the matching Twenty field from a dropdown
* **Do not map**: Skip the column entirely (data won't be imported)
* **Einem Feld zuordnen**: Wählen Sie das passende Twenty-Feld aus einem Dropdown aus
* **Nicht zuordnen**: Überspringen Sie die Spalte vollständig (Daten werden nicht importiert)
<Note>**Fields must exist before import.** The import creates records, not fields. Create custom fields under **Settings → Data Model** before importing.</Note>
<Note>**Felder müssen vor dem Import existieren.** Der Import erzeugt Datensätze, nicht Felder. Erstellen Sie benutzerdefinierte Felder vor dem Import unter **Einstellungen → Datenmodell**.</Note>
## Field Type Compatibility
## Kompatibilität der Feldtypen
All field types available in the Data Model are supported for import.
Alle im Datenmodell verfügbaren Feldtypen werden für den Import unterstützt.
You can also import `id` values to either assign a specific ID to new records or update existing ones.
Sie können auch `id`-Werte importieren, um neuen Datensätzen eine bestimmte ID zuzuweisen oder vorhandene zu aktualisieren.
<img src="/images/user-guide/fields/all-field-types.png" style={{width:'100%'}} />
## Data Format Requirements
## Anforderungen an das Datenformat
<Note>**Some fields have special syntax.** We recommend downloading the sample file before preparing your import to see the expected syntax for each field type.</Note>
<Note>**Einige Felder haben eine spezielle Syntax.** Wir empfehlen, vor der Vorbereitung Ihres Imports die Beispieldatei herunterzuladen, um die erwartete Syntax für jeden Feldtyp zu sehen.</Note>
### Address Fields
### Adressfelder
Address is a nested field with multiple columns. Some can be left empty.
Adresse ist ein verschachteltes Feld mit mehreren Spalten. Einige können leer bleiben.
* **Address / Address 1**: Street address line 1
* **Address / Address 2**: Street address line 2
* **Address / City**: City name
* **Address / State**: State or province
* **Address / Country**: Country name
* **Address / Post Code**: Postal/ZIP code
* **Adresse / Adresszeile 1**: Adresszeile 1
* **Adresse / Adresszeile 2**: Adresszeile 2
* **Adresse / Stadt**: Stadtname
* **Adresse / Bundesland**: Bundesland oder Provinz
* **Adresse / Land**: Ländername
* **Adresse / Postleitzahl**: Postleitzahl/ZIP-Code
### Array Fields
### Array-Felder
Use the following format:
Verwenden Sie folgendes Format:
```
["value1","value2"]
```
### Boolean Fields
### Boolesche Felder
Use `TRUE` or `FALSE` (uppercase) - not `true` or `false`
Verwenden Sie `TRUE` oder `FALSE` (Großbuchstaben) nicht `true` oder `false`
### Currency Fields
### Währungsfelder
Currency is a nested field with two columns that **both must be filled**:
Währung ist ein verschachteltes Feld mit zwei Spalten, die **beide ausgefüllt werden müssen**:
* **Amount / Amount**: The numeric value (e.g., `1234.56`)
* **Amount / Currency**: The currency code (e.g., `USD`, `EUR`)
* **Betrag / Betrag**: Der Zahlenwert (z. B. `1234.56`)
* **Betrag / Währung**: Der Währungscode (z. B. `USD`, `EUR`)
### Date Fields
### Datumsfelder
Supported formats:
Unterstützte Formate:
* `YYYY-MM-DD` (recommended)
* `YYYY-MM-DD` (empfohlen)
* `MM/DD/YYYY`
* `DD/MM/YYYY`
* ISO 8601 format
* ISO-8601-Format
### Domain Fields
### Domain-Felder
* It is recommended to use the format `https://domain.com` to avoid creating duplicates, as this is the format used for Companies created by the mailbox and calendar synchronizations
* A `Domain Label` and `Domain URL` can be filled: best practice is to fill `domain.com` in the label and `https://domain.com` in the url
* Domains must be unique within the Companies object
* **Domains must be unique within the file to import**
* Es wird empfohlen, das Format `https://domain.com` zu verwenden, um Duplikate zu vermeiden, da dies das Format für Unternehmen ist, die durch die Postfach- und Kalender-Synchronisierungen erstellt werden.
* Es können ein `Domain Label` und eine `Domain URL` ausgefüllt werden: Best Practice ist, im Label `domain.com` und in der URL `https://domain.com` anzugeben
* Domains müssen im Objekt Unternehmen eindeutig sein
* **Domains müssen innerhalb der zu importierenden Datei eindeutig sein**
### Email Fields
### E-Mail-Felder
* Must be valid email format
* Emails must be unique within the People object
* **Emails must be unique within the file to import**
* For additional emails: use **Emails / Primary Email** for the main email, and **Emails / Additional Emails** with this format:
* Müssen ein gültiges E-Mail-Format haben
* E-Mails müssen im Objekt Personen eindeutig sein
* **E-Mails müssen innerhalb der zu importierenden Datei eindeutig sein**
* Für zusätzliche E-Mails: Verwenden Sie **E-Mails / Primäre E-Mail** für die Haupt-E-Mail und **E-Mails / Zusätzliche E-Mails** mit diesem Format:
```
["jane@twenty.com","jane.doe@twenty.com"]
```
### Id Fields
### ID-Felder
Specifying an `id` during import is optional. Twenty auto-generates one if not provided.
Die Angabe einer `id` während des Imports ist optional. Twenty erzeugt automatisch eine, wenn keine angegeben wird.
Use cases for mapping an `id` column:
Anwendungsfälle für die Zuordnung einer `id`-Spalte:
* **Set a specific ID**: Choose the UUID for newly created records
* **Update existing records**: Match against existing records to update them instead of creating duplicates. In that case, it is recommended to not map the other unique fields: mapping only one unique field ensures a smoother import.
* **Spezifische ID festlegen**: Wählen Sie die UUID für neu erstellte Datensätze
* **Vorhandene Datensätze aktualisieren**: Gegen vorhandene Datensätze abgleichen, um sie zu aktualisieren, anstatt Duplikate zu erstellen. In diesem Fall wird empfohlen, die anderen eindeutigen Felder nicht zuzuordnen: Die Zuordnung nur eines eindeutigen Feldes sorgt für einen reibungsloseren Import.
<Note>If you provide an `id`, it must be in UUID format (e.g., `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`).</Note>
<Note>Wenn Sie eine `id` angeben, muss sie im UUID-Format sein (z. B. `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`).</Note>
### JSON Fields
### JSON-Felder
Use valid JSON format:
Verwenden Sie gültiges JSON-Format:
```
{"key":"value","key2":"value2"}
```
### Links Fields
### Link-Felder
Similar to Domain fields:
Ähnlich wie Domain-Felder:
* Fill both the label and URL columns: **Links / Link URL** and **Links / Link Label**
* Use full URL format: `https://example.com`
* For secondary links, use **Links / Secondary Links** column with this format:
* Füllen Sie sowohl die Spalten für Label und URL aus: **Links / Link-URL** und **Links / Link-Label**
* Verwenden Sie das vollständige URL-Format: `https://example.com`
* Für sekundäre Links verwenden Sie die Spalte **Links / Sekundäre Links** mit diesem Format:
```
[{"url":"https://twenty.com","label":"Twenty"}]
```
### Multi-Select Fields
### Mehrfachauswahl-Felder
Use the **API names** (not the display labels) in the following format:
Verwenden Sie die **API-Namen** (nicht die Anzeigenamen) in folgendem Format:
```
["VALUE1","VALUE2"]
```
See [here](#finding-api-names-for-select-fields) where to find the API names.
Siehe [hier](#finding-api-names-for-select-fields), wo Sie die API-Namen finden.
<Note>New select options will not be created automatically by the import. They must be added under **Settings → Data Model** before importing.</Note>
<Note>Neue Auswahloptionen werden durch den Import nicht automatisch erstellt. Sie müssen vor dem Import unter **Einstellungen → Datenmodell** hinzugefügt werden.</Note>
<Warning>
**Import overwrites, it does not add.**
**Der Import überschreibt, er fügt nichts hinzu.**
If a record already has `VALUE2` and `VALUE3` selected, and you import `["VALUE1"]`, the record will only have `VALUE1` after import. The previous selections are replaced, not merged.
Wenn ein Datensatz bereits `VALUE2` und `VALUE3` ausgewählt hat und Sie `[\"VALUE1\"]` importieren, hat der Datensatz nach dem Import nur noch `VALUE1`. Die bisherigen Auswahlen werden ersetzt, nicht zusammengeführt.
</Warning>
### Number Fields
### Zahlenfelder
* Numbers only
* Decimals use period: `1234.56`
* No thousands separators
* Nur Zahlen
* Dezimalzahlen verwenden einen Punkt: `1234.56`
* Keine Tausendertrennzeichen
### Phone Fields
### Telefonfelder
Phone is a nested field with multiple columns that **must be filled**
Telefon ist ein verschachteltes Feld mit mehreren Spalten, die **ausgefüllt werden müssen**
* **Phones / Primary Phone Number**: The phone number (e.g., `4159095555`)
* **Phones / Primary Phone Country Code**: Country code (e.g., `US`)
* **Phones / Primary Phone Calling Code**: Dialing code (e.g., `+1`)
* **Telefone / Primäre Telefonnummer**: Die Telefonnummer (z. B. `4159095555`)
* **Telefone / Ländercode der primären Telefonnummer**: Ländercode (z. B. `US`)
* **Telefone / Vorwahl der primären Telefonnummer**: Vorwahl (z. B. `+1`)
### Rating Fields
### Bewertungsfelder
Use the API name format: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4`, `RATING_5`
Verwenden Sie das API-Namensformat: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4`, `RATING_5`
### Relationsfelder
Please see our dedicated article: [Import Relations Between Objects](/l/de/user-guide/data-migration/capabilities/import-relations)
Weitere Informationen finden Sie in unserem dedizierten Artikel: [Beziehungen zwischen Objekten importieren](/l/de/user-guide/data-migration/capabilities/import-relations)
### Auswahlfelder
Use the **API name** of the option (not the display label):
Verwenden Sie den **API-Namen** der Option (nicht den Anzeigenamen):
```
VALUE1
@@ -1,5 +1,5 @@
---
title: Bereiten Sie Ihre CSV-Dateien vor},{
title: Prepare Your CSV Files
description: Vollständige Schritt-für-Schritt-Anleitung zum Formatieren deiner Daten für den Import in Twenty.
---
@@ -87,114 +87,114 @@ Telefon ist ein **verschachteltes Feld**, das mehrere Spalten benötigt:
| **Phones / Primary Phone Country Code** | `US` |
| **Phones / Primary Phone Calling Code** | `+1` |
### Address Fields
### Adressfelder
Address is a **nested field** with multiple columns (some can be left empty):
Adresse ist ein **verschachteltes Feld** mit mehreren Spalten (einige können leer bleiben):
* **Address / Address 1**: Street address line 1
* **Address / Address 2**: Street address line 2 (optional)
* **Address / City**: City name
* **Address / State**: State or province
* **Address / Country**: Country name
* **Address / Post Code**: Postal/ZIP code
* **Adresse / Adresse 1**: Straßenadresse Zeile 1
* **Adresse / Adresse 2**: Straßenadresse Zeile 2 (optional)
* **Adresse / Stadt**: Stadtname
* **Adresse / Bundesland**: Bundesstaat oder Provinz
* **Adresse / Land**: Name des Landes
* **Adresse / Postleitzahl**: Postleitzahl/ZIP-Code
### Date Fields
### Datumsfelder
Use consistent formatting throughout your file:
Verwenden Sie in Ihrer Datei ein einheitliches Format:
* `YYYY-MM-DD` (recommended): `2024-03-15`
* `YYYY-MM-DD` (empfohlen): `2024-03-15`
* `MM/DD/YYYY`: `03/15/2024`
* `DD/MM/YYYY`: `15/03/2024`
* ISO 8601: `2024-03-15T10:30:00Z`
### Number Fields
### Zahlenfelder
* Numbers only (no text)
* Use period for decimals: `1234.56`
* No thousands separators (not `1,234.56`)
* Nur Zahlen (kein Text)
* Verwenden Sie den Punkt für Dezimalstellen: `1234.56`
* Keine Tausendertrennzeichen (nicht `1,234.56`)
### Currency Fields
### Währungsfelder
Currency is a **nested field** requiring two columns that **both must be filled**:
Währung ist ein **verschachteltes Feld** und erfordert zwei Spalten, die **beide ausgefüllt werden müssen**:
| Column | Beispiel |
| --------------------- | --------- |
| **Amount / Amount** | `1234.56` |
| **Amount / Currency** | `USD` |
| Spalte | Beispiel |
| -------------------- | --------- |
| **Betrag / Betrag** | `1234.56` |
| **Betrag / Währung** | `USD` |
### Boolean Fields
### Boolesche Felder
Use uppercase: `TRUE` or `FALSE`
Großschreibung verwenden: `TRUE` oder `FALSE`
<Warning>Lowercase `true` or `false` will not work.</Warning>
<Warning>Kleinschreibung `true` oder `false` funktioniert nicht.</Warning>
### Auswahlfelder
Use the **API name** of the option, not the display label.
Verwenden Sie den **API-Namen** der Option, nicht den Anzeigenamen.
**How to find API names:**
**So finden Sie API-Namen:**
1. Go to **Settings → Data Model**
2. Select the object and field
3. Enable **Advanced mode** (toggle at bottom right)
4. Copy the API name (e.g., `OPTION_1`, not "Option 1")
1. Gehen Sie zu **Einstellungen → Datenmodell**
2. Wählen Sie das Objekt und das Feld aus
3. Aktivieren Sie den **Erweiterten Modus** (Schalter unten rechts)
4. Kopieren Sie den API-Namen (z. B. `OPTION_1`, nicht "Option 1")
<Note>New select options are not created automatically. Add them in **Settings → Data Model** before importing.</Note>
<Note>Neue Auswahloptionen werden nicht automatisch erstellt. Fügen Sie sie vor dem Import unter **Einstellungen → Datenmodell** hinzu.</Note>
### Multi-Select Fields
### Mehrfachauswahlfelder
Use API names in array format:
Verwenden Sie API-Namen im Array-Format:
```
["VALUE1","VALUE2"]
```
### Array Fields
### Array-Felder
Use JSON array format:
Verwenden Sie das JSON-Array-Format:
```
["value1","value2"]
```
### Rating Fields
### Bewertungsfelder
Use the format: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4`, or `RATING_5`
Verwenden Sie das Format: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4` oder `RATING_5`
### Links/URL Fields
### Links/URL-Felder
Fill both columns:
Füllen Sie beide Spalten aus:
* **Links / Link Label**: `Twenty`
* **Links / Link URL**: `https://twenty.com`
* **Links / Link-Label**: `Twenty`
* **Links / Link-URL**: `https://twenty.com`
For secondary links, use the **Links / Secondary Links** column:
Für sekundäre Links verwenden Sie die Spalte **Links / Sekundäre Links**:
```
[{"url":"https://twenty.com","label":"Twenty"}]
```
### JSON Fields
### JSON-Felder
Use valid JSON format:
Verwenden Sie ein gültiges JSON-Format:
```
{"key":"value","key2":"value2"}
```
### ID Fields
### ID-Felder
* **Optional**: Twenty auto-generates IDs if not provided
* **Format**: UUID (e.g., `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`)
* **Use case**: Include ID to update existing records instead of creating new ones
* **Optional**: Twenty erstellt IDs automatisch, wenn sie nicht angegeben werden
* **Format**: UUID (z. B. `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`)
* **Anwendungsfall**: ID angeben, um bestehende Datensätze zu aktualisieren, statt neue zu erstellen
## Step 5: Add Relation Columns (If Linking Records)
## Schritt 5: Beziehungsspalten hinzufügen (bei Verknüpfung von Datensätzen)
To link records to other objects (e.g., People to Companies), add a column with the unique identifier of the related record.
Um Datensätze mit anderen Objekten zu verknüpfen (z. B. Personen mit Unternehmen), fügen Sie eine Spalte mit dem eindeutigen Bezeichner des zugehörigen Datensatzes hinzu.
**Example**: Linking People to Companies
**Beispiel**: Verknüpfung von Personen mit Unternehmen
Add a column to your People CSV:
Fügen Sie Ihrer Personen-CSV eine Spalte hinzu:
```
firstName,lastName,email,companyDomain
@@ -202,69 +202,69 @@ John,Smith,john@acme.com,https://acme.com
Jane,Doe,jane@widgets.co,https://widgets.co
```
**Important rules for relations:**
**Wichtige Regeln für Beziehungen:**
* The parent record must already exist in Twenty
* Use the **Domain URL** format (`https://domain.com`), not the label
* Map only ONE unique identifier (don't include both `companyId` AND `companyDomain`)
* For Workspace Members, use their **email** (not name)
* Der übergeordnete Datensatz muss bereits in Twenty vorhanden sein
* Verwenden Sie das **Domain-URL**-Format (`https://domain.com`), nicht die Bezeichnung
* Ordnen Sie nur EINEN eindeutigen Bezeichner zu (nicht sowohl `companyId` ALS AUCH `companyDomain`)
* Für Workspace-Mitglieder verwenden Sie deren **E-Mail** (nicht den Namen)
<Warning>
**Import Order Matters!**
**Die Importreihenfolge ist wichtig!**
Import the "one" side before the "many" side:
Importieren Sie die "One"-Seite vor der "Many"-Seite:
1. **Companies** first
2. **People** second (with company reference)
3. **Opportunities** third
1. **Unternehmen** zuerst
2. **Personen** als Zweites (mit Unternehmensreferenz)
3. **Opportunities** als Drittes
The parent record must exist before you can reference it.
Der übergeordnete Datensatz muss vorhanden sein, bevor Sie darauf verweisen können.
</Warning>
See [How to Import Relations](/l/de/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) for detailed instructions.
Siehe [Beziehungen importieren](/l/de/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) für detaillierte Anleitungen.
## Step 6: Ensure Fields Exist in Twenty
## Schritt 6: Sicherstellen, dass Felder in Twenty vorhanden sind
The import creates **records**, not **fields**. All fields you want to import must already exist in your data model.
Der Import erstellt **Datensätze**, nicht **Felder**. Alle Felder, die Sie importieren möchten, müssen bereits in Ihrem Datenmodell vorhanden sein.
**Before importing:**
**Vor dem Import:**
1. Go to **Settings → Data Model**
2. Select your object
3. Create any custom fields you need
4. Note the exact field names (they must match your column headers)
1. Gehen Sie zu **Einstellungen → Datenmodell**
2. Wählen Sie Ihr Objekt aus
3. Erstellen Sie alle benötigten benutzerdefinierten Felder
4. Notieren Sie die exakten Feldnamen (sie müssen mit Ihren Spaltenüberschriften übereinstimmen)
## Step 7: Final Checklist
## Schritt 7: Abschluss-Checkliste
Before uploading your file, verify:
Überprüfen Sie vor dem Hochladen Ihrer Datei:
<Check>File is CSV, XLSX, or XLS format</Check>
<Check>File has fewer than 10,000 records</Check>
<Check>Encoding is UTF-8</Check>
<Check>No duplicate emails (for People) or domains (for Companies)</Check>
<Check>Dates use consistent format throughout</Check>
<Check>Domains use `https://domain.com` format</Check>
<Check>Boolean fields use `TRUE` or `FALSE` (uppercase)</Check>
<Check>Select fields use API names, not display labels</Check>
<Check>All custom fields exist in Settings → Data Model</Check>
<Check>Parent records imported before child records</Check>
<Check>Relation columns reference existing records</Check>
<Check>Datei ist im CSV-, XLSX- oder XLS-Format</Check>
<Check>Datei enthält weniger als 10.000 Datensätze</Check>
<Check>Zeichencodierung ist UTF-8</Check>
<Check>Keine doppelten E-Mails (für Personen) oder Domains (für Unternehmen)</Check>
<Check>Datumsangaben verwenden durchgehend ein einheitliches Format</Check>
<Check>Domains verwenden das Format `https://domain.com`</Check>
<Check>Boolesche Felder verwenden `TRUE` oder `FALSE` (Großschreibung)</Check>
<Check>Auswahlfelder verwenden API-Namen, nicht Anzeigenamen</Check>
<Check>Alle benutzerdefinierten Felder existieren in Einstellungen → Datenmodell</Check>
<Check>Übergeordnete Datensätze vor untergeordneten Datensätzen importiert</Check>
<Check>Beziehungsspalten verweisen auf vorhandene Datensätze</Check>
## Common Mistakes to Avoid
## Häufige Fehler, die Sie vermeiden sollten
| Mistake | Solution |
| -------------------------------------------- | ------------------------------------- |
| Using `true` instead of `TRUE` | Boolean values must be uppercase |
| Using display labels for Select fields | Find and use API names in Settings |
| Importing People before Companies | Always import parent objects first |
| Missing currency code for Currency fields | Fill both Amount and Currency columns |
| Wrong domain format | Use `https://domain.com` consistently |
| Mapping multiple unique fields for relations | Map only ONE (domain OR id, not both) |
| Fehler | Lösung |
| ----------------------------------------------------- | -------------------------------------------------------------- |
| Verwendung von `true` statt `TRUE` | Boolesche Werte müssen in Großbuchstaben sein |
| Verwendung von Anzeigenamen für Auswahlfelder | API-Namen in den Einstellungen suchen und verwenden |
| Import von Personen vor Unternehmen | Importieren Sie stets zuerst die übergeordneten Objekte |
| Fehlender Währungscode für Währungsfelder | Sowohl die Spalte Betrag als auch die Spalte Währung ausfüllen |
| Falsches Domain-Format | `https://domain.com` konsequent verwenden |
| Zuordnung mehrerer eindeutiger Felder für Beziehungen | Nur EINES zuordnen (Domain ODER ID, nicht beides) |
## Nächste Schritte
Your file is ready! Now:
Ihre Datei ist bereit! Jetzt:
* [Import Companies](/l/de/user-guide/data-migration/how-tos/import-companies-via-csv) (import these first)
* [Import Contacts](/l/de/user-guide/data-migration/how-tos/import-contacts-via-csv)
* [Fix any import errors](/l/de/user-guide/data-migration/how-tos/fix-import-errors)
* [Unternehmen importieren](/l/de/user-guide/data-migration/how-tos/import-companies-via-csv) (diese zuerst importieren)
* [Kontakte importieren](/l/de/user-guide/data-migration/how-tos/import-contacts-via-csv)
* [Importfehler beheben](/l/de/user-guide/data-migration/how-tos/fix-import-errors)
@@ -1,60 +1,60 @@
---
title: Create Relation Fields
description: Step-by-step guide to connecting objects with relation fields.
title: Relationsfelder erstellen
description: Schritt-für-Schritt-Anleitung zum Verbinden von Objekten mit Relationsfeldern.
---
Relation fields connect records from different objects—for example, linking People to Companies.
Relationsfelder verbinden Datensätze aus verschiedenen Objekten — zum Beispiel Personen mit Unternehmen.
<Note>
**Relation names cannot be changed after creation** (they affect the API). Plan your names carefully.
**Relationsnamen können nach dem Erstellen nicht geändert werden** (sie wirken sich auf die API aus). Planen Sie Ihre Namen sorgfältig.
</Note>
## Bevor Sie beginnen
Decide:
Entscheiden Sie:
* Which objects are you connecting? (e.g., People → Companies)
* Which is the "one" side? (e.g., Company)
* Which is the "many" side? (e.g., People — many people work at one company)
* What should the field be named on each side?
* Welche Objekte verbinden Sie? (z. B. Personen → Unternehmen)
* Welche ist die "One"-Seite? (z. B. Unternehmen)
* Welche ist die "Many"-Seite? (z. B. Personen — viele Personen arbeiten bei einem Unternehmen)
* Wie soll das Feld auf beiden Seiten heißen?
See [Relation Fields](/l/de/user-guide/data-model/capabilities/relation-fields) for relation types explained.
Siehe [Relationsfelder](/l/de/user-guide/data-model/capabilities/relation-fields) für Erläuterungen zu Relationstypen.
## Steps
## Schritte
1. Go to **Settings → Data Model**
2. Select the object where you want the relation (typically the "many" side)
3. Click **+ Add Field**
4. Select **Relation** as the field type
5. Choose the **target object**
6. Select **One-to-Many** or **Many-to-One**
7. Enter field names for **both sides** of the relation
1. Gehen Sie zu **Einstellungen → Datenmodell**
2. Wählen Sie das Objekt aus, in dem Sie die Relation benötigen (typischerweise die "Many"-Seite)
3. Klicken Sie auf **+ Feld hinzufügen**
4. Wählen Sie **Relation** als Feldtyp aus
5. Wählen Sie das **Zielobjekt** aus
6. Wählen Sie **One-to-Many** oder **Many-to-One**
7. Geben Sie Feldnamen für **beide Seiten** der Relation ein
8. Klicken Sie auf **Speichern**
## Example: People → Companies
## Beispiel: Personen → Unternehmen
* Go to **Settings → Data Model → People**
* Add a Relation field
* Target: **Companies**
* Type: **Many-to-One**
* Field on People: **Company**
* Field on Companies: **Employees**
* Gehen Sie zu **Einstellungen → Datenmodell → Personen**
* Fügen Sie ein Relationsfeld hinzu
* Ziel: **Unternehmen**
* Typ: **Many-to-One**
* Feld bei Personen: **Unternehmen**
* Feld bei Unternehmen: **Mitarbeitende**
Now each Person can be linked to a Company, and each Company shows its People.
Jetzt kann jede Person mit einem Unternehmen verknüpft werden, und jedes Unternehmen zeigt seine Mitarbeitenden.
## Deleting a Relation
## Eine Relation löschen
1. Go to **Settings → Data Model**
2. Find the relation field
3. Click **⋮ → Deactivate**
1. Gehen Sie zu **Einstellungen → Datenmodell**
2. Suchen Sie das Relationsfeld
3. Klicken Sie auf **⋮ → Deaktivieren**
Links are preserved but hidden. Reactivate to restore.
Verknüpfungen bleiben erhalten, sind jedoch verborgen. Reaktivieren, um wiederherzustellen.
<Note>
**Deleting a relation doesn't delete records.** Only the link between them is removed.
**Das Löschen einer Relation löscht keine Datensätze.** Es wird nur die Verknüpfung zwischen ihnen entfernt.
</Note>
## Related
## Verwandt
* [Relation Fields](/l/de/user-guide/data-model/capabilities/relation-fields) — types and limitations
* [How to Import Relations](/l/de/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) — bulk import linked records
* [Relationsfelder](/l/de/user-guide/data-model/capabilities/relation-fields) — Typen und Einschränkungen
* [Relationen importieren](/l/de/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) — verknüpfte Datensätze im Stapel importieren
@@ -1,5 +1,5 @@
---
title: Zugriff auf Ihre Ansicht beschränken},{
title: Restrict Access to Your View
description: Steuern Sie, wer Ihre benutzerdefinierten Ansichten sehen kann.
---
@@ -1,5 +1,5 @@
---
title: Erwarteten Betrag in Ihrer Pipeline anzeigen},{
title: Show Expected Amount in Your Pipeline
description: Gewichtete DealWerte basierend auf der Phasenwahrscheinlichkeit berechnen und anzeigen.
---
@@ -45,7 +45,7 @@ Wenn Benutzer diese berechneten Felder nicht manuell bearbeiten sollen:
Dadurch können nur die Workflows diese Werte aktualisieren.
## Schritt 2: Workflow #1 erstellen — Probability bei Phasenwechsel aktualisieren
## Schritt 2: Workflow #1 erstellen — Probability bei Phasenwechsel aktualisieren
Dieser Workflow setzt die Probability automatisch, wenn eine Opportunity in eine neue Phase wechselt.
@@ -97,7 +97,7 @@ Nachdem die Verzweigungen wieder zusammengeführt wurden:
* Feld: Expected Amount
* Wert: Amount × Probability
## Schritt 3: Workflow #2 erstellen — Bei Änderung von Amount neu berechnen
## Schritt 3: Workflow #2 erstellen — Bei Änderung von Amount neu berechnen
Dieser Workflow aktualisiert den Expected Amount, wenn sich der Amount des Deals ändert.
@@ -138,8 +138,8 @@ Jede Spalte zeigt nun den insgesamt gewichteten PipelineWert für diese Phase
| -------------------------- | ----------------------------------------------------------------------------------------- |
| **Feld „Probability“** | Speichert die phasenbasierte Gewinnwahrscheinlichkeit |
| **Feld „Expected Amount“** | Speichert Amount × Probability |
| **Workflow #1** | Aktualisiert Probability bei Phasenwechsel und berechnet anschließend Expected Amount neu |
| **Workflow #2** | Berechnet Expected Amount neu, wenn sich Amount ändert |
| **Workflow #1** | Aktualisiert Probability bei Phasenwechsel und berechnet anschließend Expected Amount neu |
| **Workflow #2** | Berechnet Expected Amount neu, wenn sich Amount ändert |
| **Aggregation** | Zeigt die Summe des Expected Amount pro Phase an |
## Verwandt
@@ -1,92 +1,92 @@
---
title: Workflow-Läufe
description: Monitor and manage workflow executions.
description: Workflow-Ausführungen überwachen und verwalten.
image: /images/user-guide/workflows/workflow.png
---
## About Runs
## Über Läufe
A **Run** is a record of a workflow execution. Every time a workflow is triggered—whether by a record event, schedule, manual action, or webhook—a new run is created.
Ein **Lauf** ist ein Protokoll einer Workflow-Ausführung. Jedes Mal, wenn ein Workflow ausgelöst wird sei es durch ein Datensatzereignis, einen Zeitplan, eine manuelle Aktion oder einen Webhook wird ein neuer Lauf erstellt.
## Viewing Runs
## Läufe anzeigen
### From the Workflow Editor
### Im Workflow-Editor
1. Open the workflow you want to monitor
2. Click the **Runs** panel on the right side
3. See a list of recent runs with their status
1. Öffnen Sie den Workflow, den Sie überwachen möchten
2. Klicken Sie auf das **Läufe**-Panel auf der rechten Seite
3. Sehen Sie eine Liste der letzten Läufe mit ihrem Status
### From the Workflow Runs View
### In der Ansicht Workflow-Läufe
1. Go to **Workflow Runs** in the sidebar
2. View runs across all workflows
3. Filter by status, workflow, or date
1. Gehen Sie in der Seitenleiste zu **Workflow-Läufe**
2. Zeigen Sie Läufe über alle Workflows hinweg an
3. Filtern Sie nach Status, Workflow oder Datum
## Run Statuses
## Laufstatus
| Status | Beschreibung |
| ------------------- | ------------------------------------------------------------------------ |
| **Wird ausgeführt** | Workflow is currently executing |
| **Completed** | Workflow finished successfully |
| **Failed** | Workflow encountered an error and stopped |
| **Waiting** | Workflow is paused (e.g., waiting for a Delay action or Form submission) |
| Status | Beschreibung |
| ------------------- | ------------------------------------------------------------------------------------------------- |
| **Wird ausgeführt** | Workflow wird derzeit ausgeführt |
| **Abgeschlossen** | Workflow wurde erfolgreich abgeschlossen |
| **Fehlgeschlagen** | Beim Workflow ist ein Fehler aufgetreten und wurde angehalten |
| **Wartend** | Workflow ist angehalten (z. B. wartet auf eine Verzögerungsaktion oder eine Formularübermittlung) |
## Run Details
## Laufdetails
Click on any run to see:
Klicken Sie auf einen beliebigen Lauf, um Folgendes zu sehen:
* **Status**: Current state of the run
* **Started at**: When the run began
* **Duration**: How long the run took
* **Trigger data**: The input that started the workflow
* **Step outputs**: Data returned by each step
* **Error messages**: If the run failed, what went wrong
* **Status**: Aktueller Zustand des Laufs
* **Gestartet am**: Wann der Lauf begonnen hat
* **Dauer**: Wie lange der Lauf gedauert hat
* **Triggerdaten**: Die Eingabe, die den Workflow gestartet hat
* **Schrittausgaben**: Daten, die von jedem Schritt zurückgegeben wurden
* **Fehlermeldungen**: Falls der Lauf fehlgeschlagen ist was schiefgelaufen ist
## Step-by-Step Execution
## Ausführung Schritt für Schritt
Each run shows the progression through your workflow:
Jeder Lauf zeigt den Fortschritt in Ihrem Workflow:
1. See which steps completed successfully
2. Identify where failures occurred
3. View the data passed between steps
4. Debug issues by examining step inputs and outputs
1. Sehen Sie, welche Schritte erfolgreich abgeschlossen wurden
2. Ermitteln Sie, wo Fehler aufgetreten sind
3. Sehen Sie sich die zwischen den Schritten übergebenen Daten an
4. Beheben Sie Probleme, indem Sie die Eingaben und Ausgaben der Schritte untersuchen
## Error Handling
## Fehlerbehandlung
When a run fails:
Wenn ein Lauf fehlschlägt:
1. Open the failed run
2. Find the step that caused the failure
3. Check the error message for details
4. Common issues:
* Missing required fields
1. Öffnen Sie den fehlgeschlagenen Lauf
2. Finden Sie den Schritt, der den Fehler verursacht hat
3. Prüfen Sie die Fehlermeldung auf Details
4. Häufige Probleme:
* Fehlende erforderliche Felder
* Ungültiges Datenformat
* External API errors
* Permission issues
* Externe API-Fehler
* Berechtigungsprobleme
## Re-running Workflows
## Workflows erneut ausführen
If a run fails, you can:
Wenn ein Lauf fehlschlägt, können Sie:
* Fix the underlying issue and wait for the next trigger
* For manual workflows, trigger again with the same or updated data
* Review the workflow logic to prevent future failures
* Beheben Sie das zugrunde liegende Problem und warten Sie auf den nächsten Trigger
* Bei manuellen Workflows erneut auslösen mit denselben oder aktualisierten Daten
* Überprüfen Sie die Workflow-Logik, um künftige Fehler zu vermeiden
## Performance Tips
## Tipps zur Leistung
### Managing Run History
### Laufhistorie verwalten
* Runs are retained for historical reference
* Very old runs may be archived automatically
* Export run data if you need to keep records
* Läufe werden zu Referenzzwecken aufbewahrt
* Sehr alte Läufe können automatisch archiviert werden
* Exportieren Sie Laufdaten, wenn Sie Aufzeichnungen aufbewahren müssen
### Monitoring Best Practices
### Best Practices für das Monitoring
* Check runs regularly after activating new workflows
* Review failed runs to identify patterns
* Überprüfen Sie Läufe regelmäßig, nachdem Sie neue Workflows aktiviert haben
* Überprüfen Sie fehlgeschlagene Läufe, um Muster zu erkennen
## Related
## Verwandte Themen
* [Workflow Triggers](/l/de/user-guide/workflows/capabilities/workflow-triggers)
* [Workflow Actions](/l/de/user-guide/workflows/capabilities/workflow-actions)
* [Workflow Troubleshooting](/l/de/user-guide/workflows/how-tos/need-more-help/workflow-troubleshooting)
* [Workflow-Trigger](/l/de/user-guide/workflows/capabilities/workflow-triggers)
* [Workflow-Aktionen](/l/de/user-guide/workflows/capabilities/workflow-actions)
* [Workflow-Fehlerbehebung](/l/de/user-guide/workflows/how-tos/need-more-help/workflow-troubleshooting)
@@ -18,7 +18,7 @@ Erwägen Sie professionelle Dienstleistungen für:
### Einführungspakete
Get help from our core team with our 4-hour [Onboarding packs](https://twenty.com/onboarding-packages):
Holen Sie sich Unterstützung von unserem Kernteam mit unseren 4-stündigen [Einführungspaketen](https://twenty.com/onboarding-packages):
* **Workflow-Erstellung**: Erstellen Sie benutzerdefinierte Workflows für Ihre Geschäftsprozesse
* **Datenmodell-Design**: Optimieren Sie Ihre Datenstruktur für Workflow-Automatisierung
@@ -1,22 +1,22 @@
---
title: Mejores prácticas
title: Best Practices
---
Este documento describe las mejores prácticas que debe seguir al trabajar en el backend.
This document outlines the best practices you should follow when working on the backend.
## Siga un enfoque modular
## Follow a modular approach
El backend sigue un enfoque modular, que es un principio fundamental al trabajar con NestJS. Asegúrese de descomponer su código en módulos reutilizables para mantener una base de código limpia y organizada.
Cada módulo debe encapsular una característica o funcionalidad particular y tener un alcance bien definido. Este enfoque modular permite una clara separación de responsabilidades y elimina complejidades innecesarias.
The backend follows a modular approach, which is a fundamental principle when working with NestJS. Make sure you break down your code into reusable modules to maintain a clean and organized codebase.
Each module should encapsulate a particular feature or functionality and have a well-defined scope. This modular approach enables clear separation of concerns and removes unnecessary complexities.
## Exponer servicios para usar en módulos
## Expose services to use in modules
Siempre cree servicios que tengan una responsabilidad clara y única, lo que mejora la legibilidad y mantenibilidad del código. Nombre los servicios de manera descriptiva y consistente.
Always create services that have a clear and single responsibility, which enhances code readability and maintainability. Name the services descriptively and consistently.
También debe exponer servicios que desee usar en otros módulos. Exponer servicios a otros módulos es posible a través del poderoso sistema de inyección de dependencias de NestJS, y promueve un acoplamiento débil entre los componentes.
You should also expose services that you want to use in other modules. Exposing services to other modules is possible through NestJS's powerful dependency injection system, and promotes loose coupling between components.
## Evitar usar el tipo `any`
## Avoid using `any` type
Cuando declara una variable como `any`, el verificador de tipos de TypeScript no realiza ninguna comprobación de tipos, lo que hace posible asignar cualquier tipo de valores a la variable. TypeScript utiliza la inferencia de tipos para determinar el tipo de la variable a partir del valor. Al declararlo como `any`, TypeScript ya no puede inferir el tipo. Esto dificulta la captura de errores relacionados con el tipo durante el desarrollo, lo que lleva a errores en tiempo de ejecución y hace que el código sea menos mantenible, menos fiable y más difícil de entender para otros.
When you declare a variable as `any`, TypeScript's type checker doesn't perform any type checking, making it possible to assign any type of values to the variable. TypeScript uses type inference to determine the type of variable based on the value. By declaring it as `any`, TypeScript can no longer infer the type. This makes it hard to catch type-related errors during development, leading to runtime errors and makes the code less maintainable, less reliable, and harder to understand for others.
Por eso todo debe tener un tipo. Entonces, si crea un nuevo objeto con un nombre y apellido, debe crear una interfaz o tipo que contenga un nombre y apellido y defina la forma del objeto que está manipulando.
This is why everything should have a type. So if you create a new object with a first name and last name, you should create an interface or type that contains a first name and last name that defines the shape of the object you are manipulating.
@@ -1,39 +1,39 @@
---
title: Objetos personalizados
title: Custom Objects
---
Los objetos son estructuras que te permiten almacenar datos (registros, atributos y valores) específicos de una organización. Twenty proporciona tanto objetos estándar como personalizados.
Objects are structures that allow you to store data (records, attributes, and values) specific to an organization. Twenty provides both standard and custom objects.
Los objetos estándar son objetos incorporados con un conjunto de atributos disponibles para todos los usuarios. Ejemplos de objetos estándar en Twenty incluyen Empresa y Persona. Los objetos estándar tienen campos estándar que también están disponibles para todos los usuarios de Twenty, como Company.displayName.
Standard objects are in-built objects with a set of attributes available for all users. Examples of standard objects in Twenty include Company and Person. Standard objects have standard fields that are also available for all Twenty users, like Company.displayName.
Los objetos personalizados son objetos que puedes crear para almacenar información que es única para tu organización. No están incorporados; los miembros de tu espacio de trabajo pueden crear y personalizar objetos personalizados para albergar información para la cual los objetos estándar no son aptos.
Custom objects are objects that you can create to store information that is unique to your organization. They are not built-in; members of your workspace can create and customize custom objects to hold information that standard objects aren't suitable for.
## Esquema de alto nivel
## High-level schema
<div style={{textAlign: 'center'}}>
<img src="/images/docs/server/custom-object-schema.png" alt="Esquema de alto nivel" />
<img src="/images/docs/server/custom-object-schema.png" alt="High level schema" />
</div>
<br />
## Cómo funciona
## How it works
Los objetos personalizados provienen de tablas de metadatos que determinan la forma, el nombre y el tipo de los objetos. Toda esta información está presente en la base de datos del esquema de metadatos, que consta de tablas:
Custom objects come from metadata tables that determine the shape, name, and type of the objects. All this information is present in the metadata schema database, consisting of tables:
* **DataSource**: Detalles de dónde se encuentra la información.
* **Object**: Describe el objeto y lo vincula a un DataSource.
* **Field**: Describe los campos de un objeto y lo conecta al objeto.
* **DataSource**: Details where the data is present.
* **Object**: Describes the object and links to a DataSource.
* **Field**: Outlines an Object's fields and connects to the Object.
Para añadir un objeto personalizado, el workspaceMember consultará la API de /metadata. Esto actualiza los metadatos de acuerdo y calcula un esquema GraphQL basado en los metadatos, almacenándolo en un caché de GQL para su uso posterior.
To add a custom object, the workspaceMember will query the /metadata API. This updates the metadata accordingly and computes a GraphQL schema based on the metadata, storing it in a GQL cache for later use.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/server/add-custom-objects.jpeg" alt="Consultando la API de /metadata para añadir objetos personalizados" />
<img src="/images/docs/server/add-custom-objects.jpeg" alt="Query the /metadata API to add custom objects" />
</div>
<br />
Para obtener datos, el proceso implica hacer consultas a través del endpoint /graphql y pasarlos a través del Query Resolver.
To fetch data, the process involves making queries through the /graphql endpoint and passing them through the Query Resolver.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/server/custom-object-schema.png" alt="Consulta el endpoint /graphql para obtener datos" />
<img src="/images/docs/server/custom-object-schema.png" alt="Query the /graphql endpoint to fetch data" />
</div>
@@ -2,7 +2,7 @@
title: Feature Flags
---
Feature flags are used to hide experimental features. Para Twenty, se configuran a nivel de espacio de trabajo y no a nivel de usuario.
Feature flags are used to hide experimental features. For Twenty, they are set on workspace level and not on a user level.
## Adding a new feature flag
@@ -14,7 +14,7 @@ type FeatureFlagKey =
| ...;
```
También agrégalo al enum en `feature-flag.entity.ts`:
Also add it to the enum in `feature-flag.entity.ts`:
```ts
enum FeatureFlagKeys {
@@ -39,8 +39,8 @@ const isFeatureNameEnabled = useIsFeatureEnabled('IS_FEATURENAME_ENABLED');
## Configure feature flags for the deployment
Cambie el registro correspondiente en la Tabla `core.featureFlag`:
Change the corresponding record in the Table `core.featureFlag`:
| iD | clave | workspaceId | valor |
| --------- | ------------------------ | ------------------------- | ----------- |
| Aleatorio | `IS_FEATURENAME_ENABLED` | ID del espacio de trabajo | `verdadero` |
| id | key | workspaceId | value |
| ------ | ------------------------ | ----------- | ------ |
| Random | `IS_FEATURENAME_ENABLED` | WorkspaceID | `true` |
@@ -1,9 +1,9 @@
---
title: Arquitectura de Carpetas
info: Una mirada detallada a la arquitectura de carpetas de nuestro servidor
title: Folder Architecture
info: A detailed look into our server folder architecture
---
La estructura del directorio backend es la siguiente:
The backend directory structure is as follows:
```
server
@@ -23,35 +23,35 @@ server
## Ability
Define permisos e incluye gestores para cada entidad.
Defines permissions and includes handlers for each entity.
## Decoradores
## Decorators
Define decoradores personalizados en NestJS para funcionalidad adicional.
Defines custom decorators in NestJS for added functionality.
Ver [decoradores personalizados](https://docs.nestjs.com/custom-decorators) para más detalles.
See [custom decorators](https://docs.nestjs.com/custom-decorators) for more details.
## Filtros
## Filters
Incluye filtros de excepciones para manejar excepciones que puedan ocurrir en endpoints de GraphQL.
Includes exception filters to handle exceptions that might occur in GraphQL endpoints.
## Guardias
## Guards
Ver [guardias](https://docs.nestjs.com/guards) para más detalles.
See [guards](https://docs.nestjs.com/guards) for more details.
## Health
Incluye una API REST públicamente disponible (healthz) que devuelve un JSON para confirmar si la base de datos está funcionando como se esperaba.
Includes a publicly available REST API (healthz) that returns a JSON to confirm whether the database is working as expected.
## Metadatos
## Metadata
Define objetos personalizados y hace disponible una API de GraphQL (graphql/metadata).
Defines custom objects and makes available a GraphQL API (graphql/metadata).
## Espacio de trabajo
## Workspace
Genera y sirve un esquema GraphQL personalizado basado en los metadatos.
Generates and serves custom GraphQL schema based on the metadata.
### Estructura del Directorio de Espacio de Trabajo
### Workspace Directory Structure
```
workspace
@@ -83,43 +83,43 @@ workspace
└───workspace.factory.ts
```
La raíz del directorio de espacio de trabajo incluye el `espacio.trabajo.factory.ts`, un archivo que contiene la función `createGraphQLSchema`. Esta funcn genera un esquema específico para el espacio de trabajo utilizando los metadatos para adaptar un esquema para espacios de trabajo individuales. By separating the schema and resolver construction, we use the `makeExecutableSchema` function, which combines these discrete elements.
The root of the workspace directory includes the `workspace.factory.ts`, a file containing the `createGraphQLSchema` function. This function generates workspace-specific schema by using the metadata to tailor a schema for individual workspaces. By separating the schema and resolver construction, we use the `makeExecutableSchema` function, which combines these discrete elements.
Esta estrategia no solo se trata de organización, sino que también ayuda con la optimización, como el almacenamiento en caché de definiciones de tipos generados para mejorar el rendimiento y la escalabilidad.
This strategy is not just about organization, but also helps with optimization, such as caching generated type definitions to enhance performance and scalability.
### Constructor de Esquema de Espacio de Trabajo
### Workspace Schema builder
Genera el esquema GraphQL, e incluye:
Generates the GraphQL schema, and includes:
#### Fábricas:
#### Factories:
Constructores especializados para generar constructos relacionados con GraphQL.
Specialised constructors to generate GraphQL-related constructs.
* La fábrica de tipos traduce los metadatos de los campos en tipos GraphQL utilizando `TypeMapperService`.
* La fábrica de definiciones de tipos crea objetos de entrada o salida de GraphQL derivados de `objectMetadata`.
* The type.factory translates field metadata into GraphQL types using `TypeMapperService`.
* The type-definition.factory creates GraphQL input or output objects derived from `objectMetadata`.
#### Tipos GraphQL
#### GraphQL Types
Incluye enumeraciones, entradas, objetos y escalares, y sirve como bloques de construcción para la construcción del esquema.
Includes enumerations, inputs, objects, and scalars, and serves as the building blocks for the schema construction.
#### Interfaces y Definiciones de Objetos
#### Interfaces and Object Definitions
Contiene los planos para entidades GraphQL, e incluye tanto tipos predefinidos como personalizados como `MONEY` o `URL`.
Contains the blueprints for GraphQL entities, and includes both predefined and custom types like `MONEY` or `URL`.
#### Servicios
#### Services
Contiene el servicio responsable de asociar FieldMetadataType con su escalar de GraphQL apropiado o modificadores de consulta.
Contains the service responsible for associating FieldMetadataType with its appropriate GraphQL scalar or query modifiers.
#### Almacenamiento
#### Storage
Incluye la clase `TypeDefinitionsStorage` que contiene definiciones de tipos reutilizables, previniendo duplicación de tipos GraphQL.
Includes the `TypeDefinitionsStorage` class that contains reusable type definitions, preventing duplication of GraphQL types.
### Constructor de Resolver de Espacio de Trabajo
### Workspace Resolver Builder
Crea funciones de resolutor para consultar y modificar el esquema GraphQL.
Creates resolver functions for querying and mutating the GraphQL schema.
Cada fábrica en este directorio es responsable de producir un tipo de resolutor distinto, como el `FindManyResolverFactory`, diseñado para aplicación adaptable a través de varias tablas.
Each factory in this directory is responsible for producing a distinct resolver type, such as the `FindManyResolverFactory`, designed for adaptable application across various tables.
### Ejecutor de Consultas de Espacio de Trabajo
### Workspace Query Runner
Ejecuta las consultas generadas en la base de datos y analiza el resultado.
Runs the generated queries on the database and parses the result.
@@ -1,32 +1,32 @@
---
title: Cola de Mensajes
title: Message Queue
---
Las colas facilitan la realización de operaciones asíncronas. Se pueden utilizar para realizar tareas en segundo plano, como enviar un correo de bienvenida al registrarse.
Cada caso de uso tendrá su propia clase de cola extendida de `MessageQueueServiceBase`.
Queues facilitate async operations to be performed. They can be used for performing background tasks such as sending a welcome email on register.
Each use case will have its own queue class extended from `MessageQueueServiceBase`.
Actualmente, solo soportamos `bull-mq`[bull-mq](https://bullmq.io/) como el controlador de cola.
Currently, we only support `bull-mq`[bull-mq](https://bullmq.io/) as the queue driver.
## Pasos para crear y usar una nueva cola
## Steps to create and use a new queue
1. Agregue un nombre de cola para su nueva cola en la enumeración `MESSAGE_QUEUES`.
2. Proporcione la implementación de fábrica de la cola con el nombre de la cola como el token de dependencia.
3. Inyecte la cola que creó en el módulo/servicio requerido con el nombre de la cola como el token de dependencia.
4. Agregue una clase de trabajador con inyección basada en token, al igual que el productor.
1. Add a queue name for your new queue under enum `MESSAGE_QUEUES`.
2. Provide the factory implementation of the queue with the queue name as the dependency token.
3. Inject the queue that you created in the required module/service with the queue name as the dependency token.
4. Add worker class with token based injection just like producer.
### Ejemplo de uso
### Example usage
```ts
class Resolver {
constructor(@Inject(MESSAGE_QUEUES.custom) private queue: MessageQueueService) {}
async onSomeAction() {
//lógica de negocio
//business logic
await this.queue.add(someData);
}
}
//trabajador asíncrono
//async worker
class CustomWorker {
constructor(@Inject(MESSAGE_QUEUES.custom) private queue: MessageQueueService) {
this.initWorker();
@@ -34,7 +34,7 @@ class CustomWorker {
async initWorker() {
await this.queue.work(async ({ id, data }) => {
//lógica del trabajador
//worker logic
});
}
}
@@ -1,19 +1,19 @@
---
title: Comandos de Backend
title: Backend Commands
---
## Comandos útiles
## Useful commands
Estos comandos deben ejecutarse desde la carpeta packages/twenty-server.
These commands should be executed from packages/twenty-server folder.
From any other folder you can run `npx nx {command} twenty-server` (or `npx nx run twenty-server:{command}`).
### Configuración inicial
### First time setup
```
npx nx database:reset twenty-server # configurar la base de datos con semillas de desarrollo
npx nx database:reset twenty-server # setup the database with dev seeds
```
### Iniciando el servidor
### Starting the server
```
npx nx run twenty-server:start
@@ -22,55 +22,56 @@ npx nx run twenty-server:start
### Lint
```
npx nx run twenty-server:lint # pasar --fix para corregir errores de lint
npx nx run twenty-server:lint # pass --fix to fix lint errors
```
### Prueba
### Test
```
npx nx run twenty-server:test:unit # ejecutar pruebas unitarias
npx nx run twenty-server:test:integration # ejecutar pruebas de integración
npx nx run twenty-server:test:unit # run unit tests
npx nx run twenty-server:test:integration # run integration tests
```
Nota: puedes ejecutar `npx nx run twenty-server:test:integration:with-db-reset` en caso de que necesites restablecer la base de datos antes de ejecutar las pruebas de integración.
Note: you can run `npx nx run twenty-server:test:integration:with-db-reset` in case you need to reset the database before running the integration tests.
### Restablecer la base de datos
### Resetting the database
Si deseas restablecer y sembrar la base de datos, puedes ejecutar el siguiente comando:
If you want to reset and seed the database, you can run the following command:
```bash
npx nx run twenty-server:database:reset
```
### Migraciones
### Migrations
#### Para objetos en esquemas Core/Metadata (TypeORM)
#### For objects in Core/Metadata schemas (TypeORM)
```bash
npx nx run twenty-server:typeorm migration:generate src/database/typeorm/core/migrations/nameOfYourMigration -d src/database/typeorm/core/core.datasource.ts
```
#### Para objetos de Workspace
#### For Workspace objects
No hay archivos de migraciones, las migraciones se generan automáticamente para cada espacio de trabajo, se almacenan en la base de datos y se aplican con este comando
There are no migrations files, migration are generated automatically for each workspace,
stored in the database, and applied with this command
```bash
npx nx run twenty-server:command workspace:sync-metadata -f
```
<Warning>
Esto eliminará la base de datos y volverá a ejecutar las migraciones y semillas.
This will drop the database and re-run the migrations and seed.
Asegúrate de respaldar cualquier dato que desees conservar antes de ejecutar este comando.
Make sure to back up any data you want to keep before running this command.
</Warning>
## Stack Tecnológico
## Tech Stack
Twenty utiliza principalmente NestJS para el backend.
Twenty primarily uses NestJS for the backend.
Prisma fue el primer ORM que usamos. Pero para permitir a los usuarios crear campos y objetos personalizados, un nivel más bajo tenía más sentido ya que necesitamos tener un control detallado. El proyecto ahora usa TypeORM.
Prisma was the first ORM we used. But in order to allow users to create custom fields and custom objects, a lower-level made more sense as we need to have fine-grained control. The project now uses TypeORM.
Así es como se ve la pila tecnológica ahora.
Here's what the tech stack now looks like.
**Core**
@@ -78,23 +79,23 @@ Así es como se ve la pila tecnológica ahora.
* [TypeORM](https://typeorm.io/)
* [GraphQL Yoga](https://the-guild.dev/graphql/yoga-server)
**Base de datos**
**Database**
* [Postgres](https://www.postgresql.org/)
**Integraciones de terceros**
**Third-party integrations**
* [Sentry](https://sentry.io/welcome/) para rastrear errores
* [Sentry](https://sentry.io/welcome/) for tracking bugs
**Pruebas**
**Testing**
* [Jest](https://jestjs.io/)
**Herramientas**
**Tooling**
* [Yarn](https://yarnpkg.com/)
* [ESLint](https://eslint.org/)
**Desarrollo**
**Development**
* [AWS EKS](https://aws.amazon.com/eks/)
@@ -1,50 +1,52 @@
---
title: Aplicación Zapier
title: Zapier App
---
Sincroniza sin esfuerzo Twenty con más de 3000 aplicaciones usando [Zapier](https://zapier.com/). ¡Automatiza tareas, mejora la productividad y potencia tus relaciones con los clientes!
Effortlessly sync Twenty with 3000+ apps using [Zapier](https://zapier.com/). Automate tasks, boost productivity, and supercharge your customer relationships!
## Acerca de Zapier
## About Zapier
Zapier is a tool that allows you to automate workflows by connecting the apps that your team uses every day. El concepto fundamental de Zapier son los flujos de trabajo automatizados, llamados Zaps, que incluyen desencadenantes y acciones.
Zapier is a tool that allows you to automate workflows by connecting the apps that your team uses every day. The fundamental concept of Zapier is automation workflows, called Zaps, and include triggers and actions.
Puedes aprender más sobre cómo funciona Zapier [aquí](https://zapier.com/how-it-works).
You can learn more about how Zapier works [here](https://zapier.com/how-it-works).
## Configuración
## Setup
### Paso 1: Instalar paquetes de Zapier
### Step 1: Install Zapier packages
```bash
cd packages/twenty-zapier\n\nyarn
cd packages/twenty-zapier
yarn
```
### Paso 2: Iniciar sesión con la CLI
### Step 2: Login with the CLI
Utiliza tus credenciales de Zapier para iniciar sesión usando la CLI:
Use your Zapier credentials to log in using the CLI:
```bash
zapier login
```
### Paso 3: Configurar variables de entorno
### Step 3: Set environment variables
Desde la carpeta `packages/twenty-zapier`, ejecuta:
From the `packages/twenty-zapier` folder, run:
```bash
cp .env.example .env
```
Ejecuta la aplicación localmente, ve a [http://localhost:3000/settings/api-webhooks](http://localhost:3000/settings/api-webhooks) y genera una clave API.
Run the application locally, go to [http://localhost:3000/settings/api-webhooks](http://localhost:3000/settings/api-webhooks), and generate an API key.
Reemplaza el valor de **YOUR_API_KEY** en el archivo `.env` con la clave API que acabas de generar.
Replace the **YOUR_API_KEY** value in the `.env` file with the API key you just generated.
## Desarrollo
## Development
<Warning>
Asegúrate de ejecutar `yarn build` antes de cualquier comando `zapier`.
Make sure to run `yarn build` before any `zapier` command.
</Warning>
### Prueba
### Test
```bash
yarn test
@@ -56,25 +58,25 @@ yarn test
yarn format
```
### Observa y compila mientras editas el código
### Watch and compile as you edit code
```bash
yarn watch
```
### Valida tu aplicación Zapier
### Validate your Zapier app
```bash
yarn validate
```
### Despliega tu aplicación Zapier
### Deploy your Zapier app
```bash
yarn deploy
```
### Lista todos los comandos de Zapier CLI
### List all Zapier CLI commands
```bash
zapier
@@ -3,21 +3,21 @@ title: Bugs, Requests & Pull Requests
info: Report issues, request features, and contribute code
---
## Reportar errores
## Reporting Bugs
Para reportar un error, por favor [crea un problema en GitHub](https://github.com/twentyhq/twenty/issues/new).
To report a bug, please [create an issue on GitHub](https://github.com/twentyhq/twenty/issues/new).
También puedes pedir ayuda en [Discord](https://discord.gg/cx5n4Jzs57).
You can also ask for help on [Discord](https://discord.gg/cx5n4Jzs57).
## Solicitudes de funciones
## Feature Requests
Si no estás seguro de si es un error y sientes que está más cerca de una solicitud de función, entonces probablemente deberías [abrir una discusión en su lugar](https://github.com/twentyhq/twenty/discussions/new).
If you're not sure if it's a bug, and you feel it's closer to a feature request, then you should probably [open a discussion instead](https://github.com/twentyhq/twenty/discussions/new).
## Submit a Pull Request
Contributing code to Twenty starts with a pull request (PR).
### Antes de empezar
### Before You Start
1. Check [existing issues](https://github.com/twentyhq/twenty/issues) for related work
2. For new features, open an issue first to discuss
@@ -1,19 +1,19 @@
---
title: Mejores prácticas
title: Best Practices
---
Este documento describe las mejores prácticas que debes seguir al trabajar en el frontend.
This document outlines the best practices you should follow when working on the frontend.
## Gestión de estado
## State management
React y Recoil manejan la gestión de estado en la base de código.
React and Recoil handle state management in the codebase.
### Usa `useRecoilState` para almacenar el estado
### Use `useRecoilState` to store state
Es buena práctica crear tantos átomos como necesites para almacenar tu estado.
It's good practice to create as many atoms as you need to store your state.
<Warning>
Es mejor usar átomos adicionales que intentar ser demasiado concisos con la perforación de props.
It's better to use extra atoms than trying to be too concise with props drilling.
</Warning>
```tsx
@@ -36,45 +36,45 @@ export const MyComponent = () => {
}
```
### No uses `useRef` para almacenar el estado
### Do not use `useRef` to store state
Evita usar `useRef` para almacenar el estado.
Avoid using `useRef` to store state.
Si deseas almacenar el estado, deberías usar `useState` o `useRecoilState`.
If you want to store state, you should use `useState` or `useRecoilState`.
Consulta [cómo gestionar las re-renderizaciones](#managing-re-renders) si sientes que necesitas `useRef` para evitar algunas re-renderizaciones.
See [how to manage re-renders](#managing-re-renders) if you feel like you need `useRef` to prevent some re-renders from happening.
## Gestión de las re-renderizaciones
## Managing re-renders
Las re-renderizaciones pueden ser difíciles de gestionar en React.
Re-renders can be hard to manage in React.
Aquí hay algunas reglas a seguir para evitar re-renderizaciones innecesarias.
Here are some rules to follow to avoid unnecessary re-renders.
Ten en cuenta que siempre puedes evitar re-renderizaciones comprendiendo su causa.
Keep in mind that you can **always** avoid re-renders by understanding their cause.
### Trabaja a nivel de raíz
### Work at the root level
Ahora es fácil evitar re-renderizaciones en nuevas funciones eliminándolas a nivel de raíz.
Avoiding re-renders in new features is now made easy by eliminating them at the root level.
El componente acompañante `PageChangeEffect` contiene solo un `useEffect` que alberga toda la lógica para ejecutar en un cambio de página.
The `PageChangeEffect` sidecar component contains just one `useEffect` that holds all the logic to execute on a page change.
De esa manera, sabes que solo hay un lugar que puede desencadenar una re-renderización.
That way you know that there's just one place that can trigger a re-render.
### Siempre piensa dos veces antes de añadir `useEffect` en tu base de código.
### Always think twice before adding `useEffect` in your codebase
Las re-renderizaciones son a menudo causadas por `useEffect` innecesarios.
Re-renders are often caused by unnecessary `useEffect`.
Deberías pensar si necesitas `useEffect`, o si puedes mover la lógica a una función manejadora de eventos.
You should think whether you need `useEffect`, or if you can move the logic in a event handler function.
Por lo general, encontrarás fácil mover la lógica a una función `handleClick` o `handleChange`.
You'll find it generally easy to move the logic in a `handleClick` or `handleChange` function.
También puedes encontrarlas en bibliotecas como Apollo: `onCompleted`, `onError`, etc.
You can also find them in libraries like Apollo: `onCompleted`, `onError`, etc.
### Usa un componente hermano para extraer `useEffect` o lógica de obtención de datos
### Use a sibling component to extract `useEffect` or data fetching logic
Si sientes que necesitas añadir un `useEffect` en tu componente raíz, deberías considerar extraerlo en un componente acompañante.
If you feel like you need to add a `useEffect` in your root component, you should consider extracting it in a sidecar component.
Puedes aplicar lo mismo para la lógica de obtención de datos, con hooks de Apollo.
You can apply the same for data fetching logic, with Apollo hooks.
```tsx
// ❌ Bad, will cause re-renders even if data is not changing,
@@ -129,43 +129,43 @@ export const App = () => (
);
```
### Usa estados de familia de recoil y selectores de familia de recoil
### Use recoil family states and recoil family selectors
Los estados y selectores de familia de recoil son una gran manera de evitar re-renderizaciones.
Recoil family states and selectors are a great way to avoid re-renders.
Son útiles cuando necesitas almacenar una lista de elementos.
They are useful when you need to store a list of items.
### No deberías usar `React.memo(MyComponent)`
### You shouldn't use `React.memo(MyComponent)`
Evita usar `React.memo()` porque no resuelve la causa de la re-renderización, sino que rompe la cadena de re-renderización, lo que puede llevar a un comportamiento inesperado y hacer que el código sea muy difícil de refactorizar.
Avoid using `React.memo()` because it does not solve the cause of the re-render, but instead breaks the re-render chain, which can lead to unexpected behavior and make the code very hard to refactor.
### Limita el uso de `useCallback` o `useMemo`
### Limit `useCallback` or `useMemo` usage
A menudo no son necesarios y harán que el código sea más difícil de leer y mantener para una ganancia de rendimiento que es imperceptible.
They are often not necessary and will make the code harder to read and maintain for a gain of performance that is unnoticeable.
## Console.logs
Las declaraciones `console.log` son valiosas durante el desarrollo, ofreciendo información en tiempo real sobre los valores de las variables y el flujo de código. Pero, dejarlas en el código de producción puede llevar a varios problemas:
`console.log` statements are valuable during development, offering real-time insights into variable values and code flow. But, leaving them in production code can lead to several issues:
1. **Rendimiento**: El registro excesivo puede afectar el rendimiento en tiempo de ejecución, especialmente en aplicaciones del lado del cliente.
1. **Performance**: Excessive logging can affect the runtime performance, especially on client-side applications.
2. **Seguridad**: Registrar datos sensibles puede exponer información crítica a cualquier persona que inspeccione la consola del navegador.
2. **Security**: Logging sensitive data can expose critical information to anyone who inspects the browser's console.
3. **Limpieza**: Llenar la consola con registros puede oscurecer advertencias o errores importantes que los desarrolladores o herramientas necesitan ver.
3. **Cleanliness**: Filling up the console with logs can obscure important warnings or errors that developers or tools need to see.
4. **Profesionalismo**: Los usuarios finales o clientes que revisen la consola y vean una miríada de declaraciones de registros podrían cuestionar la calidad y el acabado del código.
4. **Professionalism**: End users or clients checking the console and seeing a myriad of log statements might question the code's quality and polish.
Asegúrate de eliminar todos los `console.logs` antes de enviar el código a producción.
Make sure you remove all `console.logs` before pushing the code to production.
## Nomenclatura
## Naming
### Nombres de variables
### Variable Naming
Los nombres de variables deben describir con precisión el propósito o función de la variable.
Variable names ought to precisely depict the purpose or function of the variable.
#### El problema con los nombres genéricos
#### The issue with generic names
Los nombres genéricos en programación no son ideales porque carecen de especificidad, lo que lleva a la ambigüedad y reduce la legibilidad del código. Tales nombres no transmiten el propósito de la variable o función, lo que dificulta a los desarrolladores entender la intención del código sin una investigación más profunda. Esto puede resultar en un aumento del tiempo de depuración, una mayor susceptibilidad a errores y dificultades en el mantenimiento y colaboración. Mientras tanto, la nomenclatura descriptiva hace que el código sea autoexplicativo y más fácil de navegar, mejorando la calidad del código y la productividad del desarrollador.
Generic names in programming are not ideal because they lack specificity, leading to ambiguity and reduced code readability. Such names fail to convey the variable or function's purpose, making it challenging for developers to understand the code's intent without deeper investigation. This can result in increased debugging time, higher susceptibility to errors, and difficulties in maintenance and collaboration. Meanwhile, descriptive naming makes the code self-explanatory and easier to navigate, enhancing code quality and developer productivity.
```tsx
// ❌ Bad, uses a generic name that doesn't communicate its
@@ -178,13 +178,13 @@ const [value, setValue] = useState('');
const [email, setEmail] = useState('');
```
#### Algunas palabras a evitar en los nombres de variables
#### Some words to avoid in variable names
* dummy
### Manejadores de eventos
### Event handlers
Los nombres de manejadores de eventos deben comenzar con `handle`, mientras que `on` es un prefijo usado para nombrar eventos en las props de los componentes.
Event handler names should start with `handle`, while `on` is a prefix used to name events in components props.
```tsx
// ❌ Bad
@@ -200,13 +200,13 @@ const handleEmailChange = (val: string) => {
};
```
## Props opcionales
## Optional Props
Evita pasar el valor predeterminado para una prop opcional.
Avoid passing the default value for an optional prop.
**EJEMPLO**
**EXAMPLE**
Toma el componente `EmailField` definido a continuación:
Take the`EmailField` component defined below:
```tsx
type EmailFieldProps = {
@@ -219,7 +219,7 @@ const EmailField = ({ value, disabled = false }: EmailFieldProps) => (
);
```
**Uso**
**Usage**
```tsx
// ❌ Bad, passing in the same value as the default value adds no value
@@ -231,11 +231,11 @@ const Form = () => <EmailField value="username@email.com" disabled={false} />;
const Form = () => <EmailField value="username@email.com" />;
```
## Componente como props
## Component as props
Intenta tanto como sea posible pasar componentes no instanciados como propiedades, para que los hijos puedan decidir por sí mismos qué propiedades necesitan pasar.
Try as much as possible to pass uninstantiated components as props, so children can decide on their own of what props they need to pass.
El ejemplo más común de esto son los componentes de icono:
The most common example for that is icon components:
```tsx
const SomeParentComponent = () => <MyComponent Icon={MyIcon} />;
@@ -252,25 +252,25 @@ const MyComponent = ({ MyIcon }: { MyIcon: IconComponent }) => {
};
```
Para que React entienda que el componente es un componente, necesitas usar PascalCase, para luego instanciarlo con `<MyIcon>`
For React to understand that the component is a component, you need to use PascalCase, to later instantiate it with `<MyIcon>`
## Prop Drilling: Mantenlo Minimalista
## Prop Drilling: Keep It Minimal
El prop drilling, en el contexto de React, se refiere a la práctica de pasar variables de estado y sus setters a través de muchas capas de componentes, incluso si los componentes intermedios no los usan. Aunque a veces es necesario, el exceso de prop drilling puede llevar a:
Prop drilling, in the React context, refers to the practice of passing state variables and their setters through many component layers, even if intermediary components don't use them. While sometimes necessary, excessive prop drilling can lead to:
1. **Readabilidad Reducida**: Rastrear de dónde proviene una propiedad o dónde se utiliza puede volverse complicado en una estructura de componentes muy anidada.
1. **Decreased Readability**: Tracing where a prop originates or where it's utilized can become convoluted in a deeply nested component structure.
2. **Desafíos de Mantenimiento**: Los cambios en la estructura de propiedades de un componente podrían requerir ajustes en varios componentes, incluso si no utilizan directamente la propiedad.
2. **Maintenance Challenges**: Changes in one component's prop structure might require adjustments in several components, even if they don't directly use the prop.
3. **Reducción de la Reusabilidad del Componente**: Un componente que recibe muchas propiedades solo para pasarlas se vuelve menos general y más difícil de reutilizar en diferentes contextos.
3. **Reduced Component Reusability**: A component receiving a lot of props solely for passing them down becomes less general-purpose and harder to reuse in different contexts.
Si sientes que estás usando en exceso el prop drilling, consulta [mejores prácticas de gestión de estado](#state-management).
If you feel that you are using excessive prop drilling, see [state management best practices](#state-management).
## Importar
## Imports
Al importar, opta por los alias designados en lugar de especificar rutas completas o relativas.
When importing, opt for the designated aliases rather than specifying complete or relative paths.
**Alias del identificador**
**The Aliases**
```js
{
@@ -282,7 +282,7 @@ Al importar, opta por los alias designados en lugar de especificar rutas complet
}
```
**Uso**
**Usage**
```tsx
// ❌ Bad, specifies the entire relative path
@@ -300,9 +300,9 @@ import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
import { ComponentDecorator } from 'twenty-ui/testing';
```
## Validación de Esquema
## Schema Validation
[Zod](https://github.com/colinhacks/zod) es el validador de esquemas para objetos no tipados:
[Zod](https://github.com/colinhacks/zod) is the schema validator for untyped objects:
```js
const validationSchema = z
@@ -320,6 +320,6 @@ const validationSchema = z
type Form = z.infer<typeof validationSchema>;
```
## Cambios Cruciales
## Breaking Changes
Siempre ejecuta pruebas manuales exhaustivas antes de proceder para garantizar que las modificaciones no hayan causado interrupciones en otras partes, dado que las pruebas aún no se han integrado extensivamente.
Always perform thorough manual testing before proceeding to guarantee that modifications havent caused disruptions elsewhere, given that tests have not yet been extensively integrated.
@@ -1,11 +1,11 @@
---
title: Arquitectura de Carpetas
title: Folder Architecture
info: A detailed look into our folder architecture
---
En esta guía, explorarás los detalles de la estructura del directorio del proyecto y cómo contribuye a la organización y mantenibilidad de Twenty.
In this guide, you will explore the details of the project directory structure and how it contributes to the organization and maintainability of Twenty.
Siguiendo esta convención de arquitectura de carpetas, es más fácil encontrar los archivos relacionados con funciones específicas y asegurar que la aplicación sea escalable y mantenible.
By following this folder architecture convention, it's easier to find the files related to specific features and ensure that the application is scalable and maintainable.
```
front
@@ -22,14 +22,14 @@ front
└───...
```
## Páginas
## Pages
Incluye los componentes de alto nivel definidos por las rutas de la aplicación. Importan más componentes de bajo nivel de la carpeta de módulos (más detalles abajo).
Includes the top-level components defined by the application routes. They import more low-level components from the modules folder (more details below).
## Módulos
## Modules
Cada módulo representa una función o un grupo de funciones, comprendiendo sus componentes específicos, estados y lógica operativa.
Todos deberían seguir la estructura siguiente. Puedes anidar módulos dentro de módulos (denominados submódulos) y se aplicarán las mismas reglas.
Each module represents a feature or a group of feature, comprising its specific components, states, and operational logic.
They should all follow the structure below. You can nest modules within modules (referred to as submodules) and the same rules will apply.
```
module1
@@ -50,60 +50,60 @@ module1
└───utils
```
### Contextos
### Contexts
Un contexto es una manera de pasar datos a través del árbol de componentes sin tener que pasar propiedades manualmente en cada nivel.
A context is a way to pass data through the component tree without having to pass props down manually at every level.
Ver [React Context](https://react.dev/reference/react#context-hooks) para más detalles.
See [React Context](https://react.dev/reference/react#context-hooks) for more details.
### GraphQL
Incluye fragmentos, consultas y mutaciones.
Includes fragments, queries, and mutations.
Ver [GraphQL](https://graphql.org/learn/) para más detalles.
See [GraphQL](https://graphql.org/learn/) for more details.
* Fragmentos
* Fragments
Un fragmento es una parte reutilizable de una consulta, que puedes usar en diferentes lugares. Usando fragmentos, es más fácil evitar la duplicación de código.
A fragment is a reusable piece of a query, which you can use in different places. By using fragments, it's easier to avoid duplicating code.
Ver [GraphQL Fragments](https://graphql.org/learn/queries/#fragments) para más detalles.
See [GraphQL Fragments](https://graphql.org/learn/queries/#fragments) for more details.
* Consultas
* Queries
Ver [GraphQL Queries](https://graphql.org/learn/queries/) para más detalles.
See [GraphQL Queries](https://graphql.org/learn/queries/) for more details.
* Mutaciones
* Mutations
Ver [GraphQL Mutations](https://graphql.org/learn/queries/#mutations) para más detalles.
See [GraphQL Mutations](https://graphql.org/learn/queries/#mutations) for more details.
### Hooks
Ver [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) para más detalles.
See [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) for more details.
### Estados
### States
Contiene la lógica de gestión de estado. [RecoilJS](https://recoiljs.org) maneja esto.
Contains the state management logic. [RecoilJS](https://recoiljs.org) handles this.
* Selectores: Ver [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) para más detalles.
* Selectors: See [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) for more details.
La gestión de estado incorporada de React todavía maneja el estado dentro de un componente.
React's built-in state management still handles state within a component.
### Utilidades
### Utils
Debería contener solo funciones puras reutilizables. De lo contrario, crea hooks personalizados en la carpeta `hooks`.
Should just contain reusable pure functions. Otherwise, create custom hooks in the `hooks` folder.
## Interfaz de usuario
## UI
Contiene todos los componentes de interfaz de usuario reutilizables utilizados en la aplicación.
Contains all the reusable UI components used in the application.
Esta carpeta puede contener subcarpetas, como `datos`, `visualización`, `retroalimentación` y `entrada` para tipos específicos de componentes. Cada componente debe ser autónomo y reutilizable, para que puedas usarlo en diferentes partes de la aplicación.
This folder can contain sub-folders, like `data`, `display`, `feedback`, and `input` for specific types of components. Each component should be self-contained and reusable, so that you can use it in different parts of the application.
Al separar los componentes de la interfaz de usuario de otros componentes en la carpeta `modules`, es más fácil mantener un diseño consistente y realizar cambios en la interfaz de usuario sin afectar otras partes (lógica de negocio) del código base.
By separating the UI components from the other components in the `modules` folder, it's easier to maintain a consistent design and to make changes to the UI without affecting other parts (business logic) of the codebase.
## Interfaz y dependencias
## Interface and dependencies
Puedes importar otro código de módulo desde cualquier módulo excepto desde la carpeta `ui`. Esto mantendrá su código fácil de probar.
You can import other module code from any module except for the `ui` folder. This will keep its code easy to test.
### Interno
### Internal
Cada parte (hooks, estados, ...) de un módulo puede tener una carpeta `internal`, que contiene partes que se usan solo dentro del módulo.
Each part (hooks, states, ...) of a module can have an `internal` folder, which contains parts that are just used within the module.
@@ -1,22 +1,22 @@
---
title: Comandos del Frontend
title: Frontend Commands
---
## Comandos útiles
## Useful commands
### Iniciando la aplicación
### Starting the app
```bash
npx nx start twenty-front
```
### Regenerar el esquema de graphql basado en el esquema API graphql
### Regenerate graphql schema based on API graphql schema
```bash
npx nx run twenty-front:graphql:generate --configuration=metadata
```
O
OR
```bash
npx nx run twenty-front:graphql:generate
@@ -28,14 +28,14 @@ npx nx run twenty-front:graphql:generate
npx nx run twenty-front:lint # pass --fix to fix lint errors
```
## Traducciones
## Translations
```bash
npx nx run twenty-front:lingui:extract
npx nx run twenty-front:lingui:compile
```
### Prueba
### Test
```bash
npx nx run twenty-front:test # run jest tests
@@ -44,11 +44,11 @@ npx nx run twenty-front:storybook:test # run tests # (needs yarn storybook:serve
npx nx run twenty-front:storybook:coverage # (needs yarn storybook:serve:dev to be running)
```
## Stack Tecnológico
## Tech Stack
The project has a clean and simple stack, with minimal boilerplate code.
**Aplicación**
**App**
* [React](https://react.dev/)
* [Apollo](https://www.apollographql.com/docs/)
@@ -56,35 +56,35 @@ The project has a clean and simple stack, with minimal boilerplate code.
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
* [TypeScript](https://www.typescriptlang.org/)
**Pruebas**
**Testing**
* [Jest](https://jestjs.io/)
* [Storybook](https://storybook.js.org/)
**Herramientas**
**Tooling**
* [Yarn](https://yarnpkg.com/)
* [Craco](https://craco.js.org/docs/)
* [ESLint](https://eslint.org/)
## Arquitectura
## Architecture
### Enrutamiento
### Routing
[React Router](https://reactrouter.com/) maneja el enrutamiento.
[React Router](https://reactrouter.com/) handles the routing.
Para evitar [re-renderizados](/l/es/developers/contribute/capabilities/frontend-development/best-practices-front#managing-re-renders) innecesarios toda la lógica de enrutamiento está en un `useEffect` en `PageChangeEffect`.
To avoid unnecessary [re-renders](/l/es/developers/contribute/capabilities/frontend-development/best-practices-front#managing-re-renders) all the routing logic is in a `useEffect` in `PageChangeEffect`.
### Gestión del Estado
### State Management
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) maneja la gestión del estado.
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) handles state management.
Ver [mejores prácticas](/l/es/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) para más información sobre la gestión del estado.
See [best practices](/l/es/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) for more information on state management.
## Pruebas
## Testing
[Jest](https://jestjs.io/) sirve como la herramienta para pruebas unitarias mientras [Storybook](https://storybook.js.org/) es para pruebas de componentes.
[Jest](https://jestjs.io/) serves as the tool for unit testing while [Storybook](https://storybook.js.org/) is for component testing.
Jest es principalmente para probar funciones utilitarias, y no los componentes en sí mismos.
Jest is mainly for testing utility functions, and not components themselves.
Storybook es para probar el comportamiento de componentes aislados, así como mostrar el sistema de diseño.
Storybook is for testing the behavior of isolated components, as well as displaying the design system.
@@ -1,178 +1,178 @@
---
title: Atajos de teclado
title: Hotkeys
---
## Introducción
## Introduction
Cuando necesitas escuchar una tecla de acceso rápido, normalmente usarías el evento `onKeyDown`.
When you need to listen to a hotkey, you would normally use the `onKeyDown` event listener.
En `twenty-front`, sin embargo, podrías tener conflictos entre los mismos atajos de teclado utilizados en diferentes componentes, montados al mismo tiempo.
In `twenty-front` however, you might have conflicts between same hotkeys that are used in different components, mounted at the same time.
Por ejemplo, si tienes una página que escucha la tecla Enter y un modal que escucha la tecla Enter, con un componente Select dentro de ese modal que también escucha la tecla Enter, podrías tener un conflicto cuando todos están montados al mismo tiempo.
For example, if you have a page that listens for the Enter key, and a modal that listens for the Enter key, with a Select component inside that modal that listens for the Enter key, you might have a conflict when all are mounted at the same time.
## El gancho `useScopedHotkeys`
## The `useScopedHotkeys` hook
Para manejar este problema, tenemos un gancho personalizado que hace posible escuchar atajos de teclado sin ningún conflicto.
To handle this problem, we have a custom hook that makes it possible to listen to hotkeys without any conflict.
Lo colocas en un componente, y escuchará los atajos de teclado solo cuando el componente está montado Y cuando el **ámbito del atajo de teclado** especificado está activo.
You place it in a component, and it will listen to the hotkeys only when the component is mounted AND when the specified **hotkey scope** is active.
## ¿Cómo escuchar atajos de teclado en la práctica?
## How to listen for hotkeys in practice?
Hay dos pasos involucrados en configurar la escucha de atajos de teclado:
There are two steps involved in setting up hotkey listening :
1. Establece el [ámbito del atajo de teclado](#qué-es-un-ambito-de-atajo-de-teclado-) que escuchará los atajos de teclado
2. Usa el gancho `useScopedHotkeys` para escuchar atajos de teclado
1. Set the [hotkey scope](#what-is-a-hotkey-scope-) that will listen to hotkeys
2. Use the `useScopedHotkeys` hook to listen to hotkeys
Configurar los ámbitos de atajos de teclado es necesario incluso en páginas simples, porque otros elementos de la interfaz de usuario como el menú lateral o el menú de comandos también podrían escuchar atajos de teclado.
Setting up hotkey scopes is required even in simple pages, because other UI elements like left menu or command menu might also listen to hotkeys.
## Casos de uso para atajos de teclado
## Use cases for hotkeys
En general, tendrás dos casos de uso que requieren atajos de teclado:
In general, you'll have two use cases that require hotkeys :
1. En una página o un componente montado en una página
2. En un componente tipo modal que toma el enfoque debido a la acción del usuario
1. In a page or a component mounted in a page
2. In a modal-type component that takes the focus due to a user action
El segundo caso de uso puede ocurrir recursivamente: un desplegable en un modal, por ejemplo.
The second use case can happen recursively : a dropdown in a modal for example.
### Escuchando atajos de teclado en una página
### Listening to hotkeys in a page
Ejemplo:
Example :
```tsx
const EscuchaEnterEnPagina = () => {
const PageListeningEnter = () => {
const {
estableceAmbitoDeAtajoYMemorizaAmbitoAnterior,
regresaAlAmbitoDeAtajoAnterior,
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
// 1. Establece el ámbito de atajo en un useEffect
// 1. Set the hotkey scope in a useEffect
useEffect(() => {
estableceAmbitoDeAtajoYMemorizaAmbitoAnterior(
EjemploAmbitosDeAtajo.EjemploEnterPagina,
setHotkeyScopeAndMemorizePreviousScope(
ExampleHotkeyScopes.ExampleEnterPage,
);
// Revertir al ámbito de atajo anterior cuando se desmonte el componente
// Revert to the previous hotkey scope when the component is unmounted
return () => {
regresaAlAmbitoDeAtajoAnterior();
goBackToPreviousHotkeyScope();
};
}, [regresaAlAmbitoDeAtajoAnterior, estableceAmbitoDeAtajoYMemorizaAmbitoAnterior]);
}, [goBackToPreviousHotkeyScope, setHotkeyScopeAndMemorizePreviousScope]);
// 2. Usa el gancho useScopedHotkeys
// 2. Use the useScopedHotkeys hook
useScopedHotkeys(
Key.Enter,
() => {
// Alguna lógica ejecutada en esta página cuando el usuario presiona Enter
// Some logic executed on this page when the user presses Enter
// ...
},
EjemploAmbitosDeAtajo.EjemploEnterPagina,
ExampleHotkeyScopes.ExampleEnterPage,
);
return <div>Mi página que escucha Enter</div>;
return <div>My page that listens for Enter</div>;
};
```
### Escuchando atajos de teclado en un componente tipo modal
### Listening to hotkeys in a modal-type component
Para este ejemplo utilizaremos un componente modal que escucha la tecla Escape para indicar a su padre que lo cierre.
For this example we'll use a modal component that listens for the Escape key to tell its parent to close it.
Aquí la interacción del usuario está cambiando el ámbito.
Here the user interaction is changing the scope.
```tsx
const PaginaEjemploConModal = () => {
const [mostrarModal, establecerMostrarModal] = useState(false);
const ExamplePageWithModal = () => {
const [showModal, setShowModal] = useState(false);
const {
estableceAmbitoDeAtajoYMemorizaAmbitoAnterior,
regresaAlAmbitoDeAtajoAnterior,
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
const manejarClicAbrirModal = () => {
// 1. Establece el ámbito de atajo cuando el usuario abre el modal
establecerMostrarModal(true);
estableceAmbitoDeAtajoYMemorizaAmbitoAnterior(
EjemploAmbitosDeAtajo.EjemploModal,
const handleOpenModalClick = () => {
// 1. Set the hotkey scope when user opens the modal
setShowModal(true);
setHotkeyScopeAndMemorizePreviousScope(
ExampleHotkeyScopes.ExampleModal,
);
};
const manejarCierreModal = () => {
// 1. Revertir al ámbito de atajo anterior cuando se cierra el modal
establecerMostrarModal(false);
regresaAlAmbitoDeAtajoAnterior();
const handleModalClose = () => {
// 1. Revert to the previous hotkey scope when the modal is closed
setShowModal(false);
goBackToPreviousHotkeyScope();
};
return <div>
<h1>Mi página con un modal</h1>
<button onClick={manejarClicAbrirModal}>Abrir modal</button>
{mostrarModal && <MiComponenteModal onClose={manejarCierreModal} />}
<h1>My page with a modal</h1>
<button onClick={handleOpenModalClick}>Open modal</button>
{showModal && <MyModalComponent onClose={handleModalClose} />}
</div>;
};
```
Luego, en el componente modal:
Then in the modal component :
```tsx
const MiComponenteDesplegable = ({ onClose }: { onClose: () => void }) => {
// 2. Usa el gancho useScopedHotkeys para escuchar la tecla Escape.
// Tenga en cuenta que Escape es una tecla de acceso rápido común que podría usarse en muchos otros componentes
// Por lo tanto, es importante usar un ámbito de atajo para evitar conflictos
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()
},
EjemploAmbitosDeAtajo.EjemploModal,
ExampleHotkeyScopes.ExampleModal,
);
return <div>Mi componente modal</div>;
return <div>My modal component</div>;
};
```
Es importante usar este patrón cuando no estás seguro de que solo usar un useEffect con mount/unmount será suficiente para evitar conflictos.
It's important to use this pattern when you're not sure that just using a useEffect with mount/unmount will be enough to avoid conflicts.
Esos conflictos pueden ser difíciles de depurar, y puede suceder más a menudo de lo que crees con useEffects.
Those conflicts can be hard to debug, and it might happen more often than not with useEffects.
## ¿Qué es un ámbito de atajo de teclado?
## What is a hotkey scope?
Un ámbito de atajo de teclado es una cadena que representa un contexto en el que los atajos de teclado están activos. Por lo general, se codifica como un enum.
A hotkey scope is a string that represents a context in which the hotkeys are active. It is generally encoded as an enum.
Cuando cambias el ámbito del atajo de teclado, se habilitarán los atajos que están escuchando este ámbito y se deshabilitarán los atajos que escuchan otros ámbitos.
When you change the hotkey scope, the hotkeys that are listening to this scope will be enabled and the hotkeys that are listening to other scopes will be disabled.
Solo puedes establecer un ámbito a la vez.
You can set only one scope at a time.
Como ejemplo, los ámbitos de atajos de teclado para cada página se definen en el enum `PageHotkeyScope`:
As an example, the hotkey scopes for each page are defined in the `PageHotkeyScope` enum:
```tsx
export enum PageHotkeyScope {
Configuración = 'configuración',
CrearEspacioTrabajo = 'crear-espacio-trabajo',
IniciarSesion = 'iniciar-sesión',
CrearPerfil = 'crear-perfil',
PlanRequerido = 'plan-requerido',
MostrarPagina = 'mostrar-pagina',
MostrarPersonaPagina = 'mostrar-persona-pagina',
MostrarEmpresaPagina = 'mostrar-empresa-pagina',
PaginaEmpresas = 'pagina-empresas',
PaginaPersonas = 'pagina-personas',
PaginaOportunidades = 'pagina-oportunidades',
PaginaPerfil = 'pagina-perfil',
PaginaMiembroEspacioTrabajo = 'pagina-miembro-espacio-trabajo',
PaginaTareas = 'pagina-tareas',
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',
}
```
Internamente, el ámbito seleccionado se almacena en un estado de Recoil que se comparte en toda la aplicación:
Internally, the currently selected scope is stored in a Recoil state that is shared across the application :
```tsx
export const estadoActualDeAmbitoDeAtajo = createState<HotkeyScope>({
key: 'estadoActualDeAmbitoDeAtajo',
defaultValue: AMBITO_INICIAL_ATAJOS,
export const currentHotkeyScopeState = createState<HotkeyScope>({
key: 'currentHotkeyScopeState',
defaultValue: INITIAL_HOTKEYS_SCOPE,
});
```
¡Pero este estado de Recoil nunca debe manejarse manualmente! Veremos cómo usarlo en la siguiente sección.
But this Recoil state should never be handled manually ! We'll see how to use it in the next section.
## ¿Cómo funciona internamente?
## How is it working internally?
Hicimos un contenedor delgado sobre [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) que lo hace más eficiente y evita renders innecesarios.
We made a thin wrapper on top of [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) that makes it more performant and avoids unnecessary re-renders.
También creamos un estado de Recoil para manejar el estado del ámbito de atajos de teclado y hacerlo disponible en toda la aplicación.
We also create a Recoil state to handle the hotkey scope state and make it available everywhere in the application.
@@ -1,8 +1,8 @@
---
title: Storybook
description: Navegar por la biblioteca de componentes de interfaz de Twenty
description: Browse Twenty's UI component library
---
Ver nuestra biblioteca completa de componentes y documentación en Storybook.
View our complete component library and documentation in Storybook.
[Abrir Storybook →](https://storybook.twenty.com)
[Open Storybook →](https://storybook.twenty.com)
@@ -1,64 +1,64 @@
---
title: Guía de Estilo
title: Style Guide
---
Este documento incluye las reglas a seguir al escribir código.
This document includes the rules to follow when writing code.
El objetivo aquí es tener una base de código coherente, que sea fácil de leer y de mantener.
The goal here is to have a consistent codebase, which is easy to read and easy to maintain.
Para esto, es mejor ser un poco más detallado que ser demasiado conciso.
For this, it's better to be a bit more verbose than to be too concise.
Ten siempre en cuenta que la gente lee código más a menudo de lo que lo escribe, especialmente en un proyecto de código abierto, donde cualquiera puede contribuir.
Always keep in mind that people read code more often than they write it, specially on an open source project, where anyone can contribute.
Hay muchas reglas que no están definidas aquí, pero que son verificadas automáticamente por linters.
There are a lot of rules that are not defined here, but that are automatically checked by linters.
## React
### Usar componentes funcionales
### Use functional components
Siempre usa componentes funcionales TSX.
Always use TSX functional components.
Do not use default `import` with `const`, because it's harder to read and harder to import with code completion.
```tsx
// ❌ Malo, más difícil de leer, más difícil de importar con autocompletación de código
// ❌ Bad, harder to read, harder to import with code completion
const MyComponent = () => {
return <div>Hola Mundo</div>;
return <div>Hello World</div>;
};
export default MyComponent;
// ✅ Bueno, fácil de leer, fácil de importar con autocompletación de código
// ✅ Good, easy to read, easy to import with code completion
export function MyComponent() {
return <div>Hola Mundo</div>;
return <div>Hello World</div>;
};
```
### "Props"
### Props
Crea el tipo de las props y llámalo `(NombreDelComponente)Props` si no hay necesidad de exportarlo.
Create the type of the props and call it `(ComponentName)Props` if there's no need to export it.
Usa la desestructuración de props.
Use props destructuring.
```tsx
// ❌ Malo, sin tipo
export const MyComponent = (props) => <div>Hola {props.name}</div>;
// ❌ Bad, no type
export const MyComponent = (props) => <div>Hello {props.name}</div>;
// ✅ Bueno, con tipo
// ✅ Good, type
type MyComponentProps = {
name: string;
};
export const MyComponent = ({ name }: MyComponentProps) => <div>Hola {name}</div>;
export const MyComponent = ({ name }: MyComponentProps) => <div>Hello {name}</div>;
```
#### Evita usar `React.FC` o `React.FunctionComponent` para definir tipos de props
#### Refrain from using `React.FC` or `React.FunctionComponent` to define prop types
```tsx
/* ❌ - Malo, define las anotaciones de tipo de componente con `FC`
* - Con `React.FC`, el componente acepta implícitamente una prop `children`
* incluso si no está definida en el tipo de prop. Esto podría no ser siempre
* deseable, especialmente si el componente no tiene la intención de renderizar
/* ❌ - 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<{
@@ -81,12 +81,12 @@ const EmailField = ({ value }: EmailFieldProps) => (
);
```
#### Sin Propagación de una sola variable de Props en Elementos JSX
#### No Single Variable Prop Spreading in JSX Elements
Evita usar la propagación de una sola variable de props en elementos JSX, como `{...props}`. Esta práctica a menudo resulta en un código que es menos legible y más difícil de mantener porque no está claro qué props está recibiendo el componente.
Avoid using single variable prop spreading in JSX elements, like `{...props}`. This practice often results in code that is less readable and harder to maintain because it's unclear which props the component is receiving.
```tsx
/* ❌ - Malo, propaga una sola variable de prop en el componente subyacente
/* ❌ - Bad, spreads a single variable prop into the underlying component
*/
const MyComponent = (props: OwnProps) => {
return <OtherComponent {...props} />;
@@ -102,25 +102,25 @@ const MyComponent = ({ prop1, prop2, prop3 }: MyComponentProps) => {
};
```
Razonamiento:
Rationale:
* A simple vista, es más claro qué props se está pasando, lo que hace que sea más fácil de entender y mantener.
* Ayuda a prevenir el acoplamiento estricto entre componentes mediante sus props.
* Las herramientas de linting facilitan la identificación de props mal escritas o sin uso al listar props explícitamente.
* At a glance, it's clearer which props the code passes down, making it easier to understand and maintain.
* It helps to prevent tight coupling between components via their props.
* Linting tools make it easier to identify misspelled or unused props when you list props explicitly.
## JavaScript
### Usar el operador de fusión nula `??`
### Use nullish-coalescing operator `??`
```tsx
// ❌ Malo, puede devolver "default" incluso si el valor es 0 o ''
// ❌ Bad, can return 'default' even if value is 0 or ''
const value = process.env.MY_VALUE || 'default';
// ✅ Bueno, devolverá "default" sólo si el valor es null o undefined
// ✅ Good, will return 'default' only if value is null or undefined
const value = process.env.MY_VALUE ?? 'default';
```
### Usar encadenamiento opcional `?.`
### Use optional chaining `?.`
```tsx
// ❌ Bad
@@ -132,30 +132,30 @@ onClick?.();
## TypeScript
### Usar `type` en lugar de `interface`
### Use `type` instead of `interface`
Siempre usa `type` en lugar de `interface`, porque casi siempre se superponen y `type` es más flexible.
Always use `type` instead of `interface`, because they almost always overlap, and `type` is more flexible.
```tsx
// ❌ Malo
// ❌ Bad
interface MyInterface {
name: string;
}
// ✅ Bueno
// ✅ Good
type MyType = {
name: string;
};
```
### Usar literales de cadena en lugar de enums
### Use string literals instead of enums
[Los literales de cadena](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) son la manera preferida para manejar valores tipo enum en TypeScript. Son más fáciles de extender con Pick y Omit, y ofrecen una mejor experiencia de desarrollo, especialmente con la autocompletación de código.
[String literals](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) are the go-to way to handle enum-like values in TypeScript. They are easier to extend with Pick and Omit, and offer a better developer experience, specially with code completion.
Puedes ver por qué TypeScript recomienda evitar enums [aquí](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).
You can see why TypeScript recommends avoiding enums [here](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums).
```tsx
// ❌ Malo, utiliza un enum
// ❌ Bad, utilizes an enum
enum Color {
Red = "red",
Green = "green",
@@ -166,18 +166,18 @@ let color = Color.Red;
```
```tsx
// ✅ Bueno, utiliza un literal de cadena
// ✅ Good, utilizes a string literal
let color: "red" | "green" | "blue" = "red";
```
#### GraphQL y bibliotecas internas
#### GraphQL and internal libraries
Deberías usar enums que genera el codegen de GraphQL.
You should use enums that GraphQL codegen generates.
También es mejor usar un enum al usar una biblioteca interna, para que la biblioteca interna no tenga que exponer un tipo de literal de cadena que no está relacionado con la API interna.
It's also better to use an enum when using an internal library, so the internal library doesn't have to expose a string literal type that is not related to the internal API.
Ejemplo:
Example:
```TSX
const {
@@ -190,54 +190,54 @@ setHotkeyScopeAndMemorizePreviousScope(
);
```
## Estilo
## Styling
### Usar StyledComponents
### Use StyledComponents
Estiliza los componentes con [styled-components](https://emotion.sh/docs/styled).
Style the components with [styled-components](https://emotion.sh/docs/styled).
```tsx
// ❌ Malo
<div className="my-class">Hola Mundo</div>
// ❌ Bad
<div className="my-class">Hello World</div>
```
```tsx
// ✅ Bueno
// ✅ Good
const StyledTitle = styled.div`
color: red;
`;
```
Prefija los componentes estilizados con "Styled" para diferenciarlos de los componentes "reales".
Prefix styled components with "Styled" to differentiate them from "real" components.
```tsx
// ❌ Malo
// ❌ Bad
const Title = styled.div`
color: red;
`;
```
```tsx
// ✅ Bueno
// ✅ Good
const StyledTitle = styled.div`
color: red;
`;
```
### Tematización
### Theming
Utilizar el tema para la mayor parte de la estilización de los componentes es el enfoque preferido.
Utilizing the theme for the majority of component styling is the preferred approach.
#### Unidades de medida
#### Units of measurement
Evita usar valores `px` o `rem` directamente dentro de los componentes estilizados. Los valores necesarios suelen estar ya definidos en el tema, por lo que se recomienda usar el tema para estos fines.
Avoid using `px` or `rem` values directly within the styled components. The necessary values are generally already defined in the theme, so its recommended to make use of the theme for these purposes.
#### Colores
#### Colors
Abstente de introducir nuevos colores; en su lugar, utiliza la paleta existente del tema. Si hay una situación en la que la paleta no se ajusta, deja un comentario para que el equipo pueda corregirlo.
Refrain from introducing new colors; instead, use the existing palette from the theme. Should there be a situation where the palette does not align, please leave a comment so that the team can rectify it.
```tsx
// ❌ Malo, especifica directamente los valores de estilo sin utilizar el tema
// ❌ Bad, directly specifies style values without utilizing the theme
const StyledButton = styled.button`
color: #333333;
font-size: 1rem;
@@ -248,7 +248,7 @@ const StyledButton = styled.button`
```
```tsx
// ✅ Bueno, utiliza el tema
// ✅ Good, utilizes the theme
const StyledButton = styled.button`
color: ${({ theme }) => theme.font.color.primary};
font-size: ${({ theme }) => theme.font.size.md};
@@ -258,33 +258,33 @@ const StyledButton = styled.button`
`;
```
## Aplicando No-Type Imports
## Enforcing No-Type Imports
Evita las importaciones de tipo. Para reforzar este estándar, una regla de ESLint verifica y reporta cualquier importación de tipo. Esto ayuda a mantener la consistencia y la legibilidad en el código TypeScript.
Avoid type imports. To enforce this standard, an ESLint rule checks for and reports any type imports. This helps maintain consistency and readability in the TypeScript code.
```tsx
// ❌ Malo
// ❌ Bad
import { type Meta, type StoryObj } from '@storybook/react';
// ❌ Malo
// ❌ Bad
import type { Meta, StoryObj } from '@storybook/react';
// ✅ Bueno
// ✅ Good
import { Meta, StoryObj } from '@storybook/react';
```
### Por qué No-Type Imports
### Why No-Type Imports
* **Consistencia**: Al evitar las importaciones de tipo y usar un solo enfoque tanto para las importaciones de tipo como de valor, la base de código se mantiene consistente en su estilo de importación de módulos.
* **Consistency**: By avoiding type imports and using a single approach for both type and value imports, the codebase remains consistent in its module import style.
* **Legibilidad**: Las no-importaciones de tipo mejoran la legibilidad del código al dejar claro cuándo se están importando valores o tipos. Esto reduce la ambigüedad y hace más fácil entender el propósito de los símbolos importados.
* **Readability**: No-type imports improve code readability by making it clear when you're importing values or types. This reduces ambiguity and makes it easier to understand the purpose of imported symbols.
* **Mantenibilidad**: Mejora la mantenibilidad de la base de código porque los desarrolladores pueden identificar y localizar importaciones solo de tipo al revisar o modificar el código.
* **Maintainability**: It enhances codebase maintainability because developers can identify and locate type-only imports when reviewing or modifying code.
### Regla de ESLint
### ESLint Rule
An ESLint rule, `@typescript-eslint/consistent-type-imports`, enforces the no-type import standard. Esta regla genera errores o advertencias sobre cualquier violación de importación de tipo.
An ESLint rule, `@typescript-eslint/consistent-type-imports`, enforces the no-type import standard. This rule will generate errors or warnings for any type import violations.
Por favor, ten en cuenta que esta regla específicamente aborda extraños casos límite donde ocurren importaciones de tipo no intencionadas. TypeScript en sí mismo desaconseja esta práctica, como se menciona en las [notas de lanzamiento de TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). En la mayoría de situaciones, no deberías necesitar usar importaciones solo de tipo.
Please note that this rule specifically addresses rare edge cases where unintentional type imports occur. TypeScript itself discourages this practice, as mentioned in the [TypeScript 3.8 release notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html). In most situations, you should not need to use type-only imports.
Para asegurarte de que tu código cumpla con esta regla, asegúrate de ejecutar ESLint como parte de tu flujo de trabajo de desarrollo.
To ensure your code complies with this rule, make sure to run ESLint as part of your development workflow.
@@ -1,59 +1,59 @@
---
title: Trabajar con Figma
info: Aprende cómo puedes colaborar con Twenty en Figma
title: Work with Figma
info: Learn how you can collaborate with Twenty's Figma
---
Figma es una herramienta de diseño de interfaces colaborativa que ayuda a superar la barrera de comunicación entre diseñadores y desarrolladores.
Esta guía explica cómo puedes colaborar con Figma.
Figma is a collaborative interface design tool that aids in bridging the communication barrier between designers and developers.
This guide explains how you can collaborate with Figma.
## Acceso
## Access
1. **Accede al enlace compartido:** Puedes acceder al archivo de Figma del proyecto [aquí](https://www.figma.com/file/xt8O9mFeLl46C5InWwoMrN/Twenty).
2. **Inicia sesión:** Si aún no has iniciado sesión, Figma te pedirá que lo hagas.
Las características clave solo están disponibles para usuarios registrados, como el modo desarrollador y la capacidad de seleccionar un marco dedicado.
1. **Access the shared link:** You can access the project's Figma file [here](https://www.figma.com/file/xt8O9mFeLl46C5InWwoMrN/Twenty).
2. **Sign in:** If you're not already signed in, Figma will prompt you to do so.
Key features are only available to logged-in users, such as the developer mode and the ability to select a dedicated frame.
<Warning>
No podrás colaborar efectivamente sin una cuenta.
You will not be able to collaborate effectively without an account.
</Warning>
## Estructura de Figma
## Figma structure
En la barra lateral izquierda, puedes acceder a las diferentes páginas del Figma de Twenty. Así es como están organizadas:
On the left sidebar, you can access the different pages of Twenty's Figma. This is how they're organized:
* **Página de componentes:** Esta es la primera página. El diseñador la utiliza para crear y organizar los elementos de diseño reutilizables que se usan en todo el archivo de diseño. Por ejemplo, botones, íconos, símbolos u otros componentes reutilizables. Sirve para mantener la consistencia a lo largo del diseño.
* **Página principal:** La segunda página es la página principal, que muestra la interfaz de usuario completa del proyecto. Puedes presionar ***Play*** para usar el prototipo completo de la aplicación.
* **Páginas de características:** Las otras páginas están típicamente dedicadas a características en progreso. Contienen el diseño de características específicas o módulos de la aplicación o sitio web. Normalmente, aún están en desarrollo.
* **Components page:** This is the first page. The designer uses it to create and organize the reusable design elements used throughout the design file. For example, buttons, icons, symbols, or any other reusable components. It serves to maintain consistency across the design.
* **Main page:** The second page is the main page, which shows the complete user interface of the project. You can press ***Play*** to use the full app prototype.
* **Features pages:** The other pages are typically dedicated to features in progress. They contain the design of specific features or modules of the application or website. They are typically still in progress.
## Consejos útiles
## Useful Tips
Con acceso de solo lectura, no puedes editar el diseño, pero puedes acceder a todas las características que serán útiles para convertir los diseños en código.
With read-only access, you can't edit the design, but you can access all features that will be useful to convert the designs into code.
### Usa el modo Dev
### Use the Dev mode
El Modo Dev de Figma mejora la productividad de los desarrolladores al proporcionar una navegación fácil por el diseño, una gestión eficaz de assets, herramientas de comunicación eficientes, integraciones de caja de herramientas, fragmentos de código rápidos e información clave de capas, superando la brecha entre diseño y desarrollo. Puedes aprender más sobre el Modo Dev [aquí](https://www.figma.com/dev-mode/).
Figma's Dev Mode enhances developers' productivity by providing easy design navigation, effective asset management, efficient communication tools, toolbox integrations, quick code snippets, and key layer information, bridging the gap between design and development. You can learn more about Dev Mode [here](https://www.figma.com/dev-mode/).
Cambia al modo "Desarrollador" en la parte derecha de la barra de herramientas para ver las especificaciones de diseño, copiar CSS y acceder a los assets.
Switch to the "Developer" mode in the right part of the toolbar to see design specs, copy CSS, and access assets.
### Usar el prototipo
### Use the Prototype
Haz clic en cualquier elemento del lienzo y presiona el botón "Play" en el extremo superior derecho de la interfaz para acceder a la vista del prototipo. El modo de prototipo te permite interactuar con el diseño como si fuera el producto final. Demuestra el flujo entre pantallas y cómo los elementos de la interfaz, como botones, enlaces o menús, se comportan al interactuar con ellos.
Click on any element on the canvas and press the “Play” button at the top right edge of the interface to access the prototype view. Prototype mode allows you to interact with the design as if it were the final product. It demonstrates the flow between screens and how interface elements like buttons, links, or menus behave when interacted with.
1. **Entendiendo las transiciones y animaciones:** En el modo Prototipo, puedes ver cualquier transición o animación añadida por un diseñador entre pantallas o elementos de UI, proporcionando instrucciones visuales claras a los desarrolladores sobre la conducta y el estilo intencionados.
2. **Aclaración de implementación:** Un prototipo también puede ayudar a reducir las ambigüedades. Los desarrolladores pueden interactuar con él para obtener una mejor comprensión de la funcionalidad o apariencia de elementos particulares.
1. **Understanding transitions and animations:** In the Prototype mode, you can view any transitions or animations added by a designer between screens or UI elements, providing clear visual instructions to developers on the intended behavior and style.
2. **Implementation clarification:** A prototype can also help reduce ambiguities. Developers can interact with it to gain a better understanding of the functionality or appearance of particular elements.
Para más detalles y orientación sobre el aprendizaje de la plataforma Figma, puedes visitar la [Documentación Oficial de Figma](https://help.figma.com/hc/en-us).
For more comprehensive details and guidance on learning the Figma platform, you can visit the official [Figma Documentation](https://help.figma.com/hc/en-us).
### Medir distancias
### Measure distances
Selecciona un elemento, mantén presionada la tecla `Option` (Mac) o `Alt` (Windows), luego pasa el cursor sobre otro elemento para ver la distancia entre ellos.
Select an element, hold `Option` key (Mac) or `Alt` key (Windows), then hover over another element to see the distance between them.
### Extensión Figma para VSCode (Recomendado)
### Figma extension for VSCode (Recommended)
[Figma para VS Code](https://marketplace.visualstudio.com/items?itemName=figma.figma-vscode-extension)
te permite navegar e inspeccionar archivos de diseño, colaborar con diseñadores, rastrear cambios y acelerar la implementación, todo sin salir de tu editor de texto.
Forma parte de nuestras extensiones recomendadas.
[Figma for VS Code](https://marketplace.visualstudio.com/items?itemName=figma.figma-vscode-extension)
lets you navigate and inspect design files, collaborate with designers, track changes, and speed up implementation - all without leaving your text editor.
It's part of our recommended extensions.
## Colaboración
## Collaboration
1. **Uso de Comentarios:** Puedes utilizar la función de comentarios haciendo clic en el ícono de burbuja en la parte izquierda de la barra de herramientas.
2. **Chat de Cursor:** Una característica agradable de Figma es el Chat de Cursor. Simplemente presiona `;` en Mac y `/` en Windows para enviar un mensaje si ves a alguien más usando Figma al mismo tiempo que tú.
1. **Using Comments:** You are welcome to use the comment feature by clicking on the bubble icon in the left part of the toolbar.
2. **Cursor chat:** A nice feature of Figma is the Cursor chat. Just press `;` on Mac and `/` on Windows to send a message if you see someone else using Figma as the same time as you.
@@ -1,13 +1,13 @@
---
title: Configuración Local
description: La guía para los colaboradores (o desarrolladores curiosos) que quieren ejecutar Twenty localmente.
title: Local Setup
description: The guide for contributors (or curious developers) who want to run Twenty locally.
---
## Prerrequisitos
## Prerequisites
<Tabs>
<Tab title="Linux y MacOS">
Antes de que puedas instalar y usar Twenty, asegúrate de instalar lo siguiente en tu computadora:
<Tab title="Linux and MacOS">
Before you can install and use Twenty, make sure you install the following on your computer:
* [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* [Node v24.5.0](https://nodejs.org/en/download)
@@ -15,38 +15,38 @@ description: La guía para los colaboradores (o desarrolladores curiosos) que qu
* [nvm](https://github.com/nvm-sh/nvm/blob/master/README.md)
<Warning>
`npm` no funcionará, deberías usar `yarn` en su lugar. Yarn ahora se envía con Node.js, por lo que no necesitas instalarlo por separado.
Solo tienes que ejecutar `corepack enable` para habilitar Yarn si aún no lo has hecho.
`npm` won't work, you should use `yarn` instead. Yarn is now shipped with Node.js, so you don't need to install it separately.
You only have to run `corepack enable` to enable Yarn if you haven't done it yet.
</Warning>
</Tab>
<Tab title="Windows (WSL)">
1. Instalar WSL
Abre PowerShell como Administrador y ejecuta:
1. Install WSL
Open PowerShell as Administrator and run:
```powershell
wsl --install
```
Ahora deberías ver un aviso para reiniciar tu computadora. Si no, reiníciala manualmente.
You should now see a prompt to restart your computer. If not, restart it manually.
Al reiniciar, se abrirá una ventana de PowerShell e instalará Ubuntu. Esto puede tomar algo de tiempo.
Verás un aviso para crear un nombre de usuario y contraseña para tu instalación de Ubuntu.
Upon restart, a powershell window will open and install Ubuntu. This may take up some time.
You'll see a prompt to create a username and password for your Ubuntu installation.
2. Instalar y configurar git
2. Install and configure git
```bash
sudo apt-get install git
git config --global user.name "Tu Nombre"
git config --global user.name "Your Name"
git config --global user.email "tuemail@dominio.com"
git config --global user.email "youremail@domain.com"
```
3. Instalar nvm, node.js y yarn
3. Install nvm, node.js and yarn
<Warning>
Usa `nvm` para instalar la versión correcta de `node`. El `.nvmrc` asegura que todos los colaboradores usen la misma versión.
Use `nvm` to install the correct `node` version. The `.nvmrc` ensures all contributors use the same version.
</Warning>
```bash
@@ -55,13 +55,13 @@ description: La guía para los colaboradores (o desarrolladores curiosos) que qu
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
```
Cierra y vuelve a abrir tu terminal para usar nvm. Luego ejecuta los siguientes comandos.
Close and reopen your terminal to use nvm. Then run the following commands.
```bash
nvm install # instala la versión recomendada de node
nvm install # installs recommended node version
nvm use # usa la versión recomendada de node
nvm use # use recommended node version
corepack enable
```
@@ -70,13 +70,13 @@ description: La guía para los colaboradores (o desarrolladores curiosos) que qu
---
## Paso 1: Clonar con Git
## Step 1: Git Clone
En tu terminal, ejecuta el siguiente comando.
In your terminal, run the following command.
<Tabs>
<Tab title="SSH (Recomendado)">
Si aún no has configurado claves SSH, puedes aprender cómo hacerlo [aquí](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/about-ssh).
<Tab title="SSH (Recommended)">
If you haven't already set up SSH keys, you can learn how to do so [here](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/about-ssh).
```bash
git clone git@github.com:twentyhq/twenty.git
@@ -90,28 +90,28 @@ En tu terminal, ejecuta el siguiente comando.
</Tab>
</Tabs>
## Paso 2: Ubícate en la raíz
## Step 2: Position yourself at the root
```bash
cd twenty
```
Debes ejecutar todos los comandos de los siguientes pasos desde la raíz del proyecto.
You should run all commands in the following steps from the root of the project.
## Paso 3: Configurar una Base de Datos PostgreSQL
## Step 3: Set up a PostgreSQL Database
<Tabs>
<Tab title="Linux">
**Opción 1 (preferido):** Para aprovisionar tu base de datos localmente:
Usa el siguiente enlace para instalar PostgreSQL en tu máquina Linux: [Instalación de PostgreSQL](https://www.postgresql.org/download/linux/)
**Option 1 (preferred):** To provision your database locally:
Use the following link to install Postgresql on your Linux machine: [Postgresql Installation](https://www.postgresql.org/download/linux/)
```bash
psql postgres -c "CREATE DATABASE \"default\";" -c "CREATE DATABASE test;"
```
Nota: Puede que necesites agregar `sudo -u postgres` antes del comando `psql` para evitar errores de permisos.
Note: You might need to add `sudo -u postgres` to the command before `psql` to avoid permission errors.
**Opción 2:** Si tienes Docker instalado:
**Option 2:** If you have docker installed:
```bash
make postgres-on-docker
@@ -119,7 +119,7 @@ Debes ejecutar todos los comandos de los siguientes pasos desde la raíz del pro
</Tab>
<Tab title="Mac OS">
**Opción 1 (preferido):** Para aprovisionar tu base de datos localmente con `brew`:
**Option 1 (preferred):** To provision your database locally with `brew`:
```bash
brew install postgresql@16
@@ -128,49 +128,49 @@ Debes ejecutar todos los comandos de los siguientes pasos desde la raíz del pro
psql postgres -c "CREATE DATABASE \"default\";" -c "CREATE DATABASE test;"
```
Puedes verificar si el servidor PostgreSQL está corriendo ejecutando:
You can verify if the PostgreSQL server is running by executing:
```bash
brew services list
```
El instalador puede que no cree el usuario `postgres` por defecto al instalar
vía Homebrew en macOS. En cambio, crea un rol de PostgreSQL que coincide con tu
nombre de usuario de macOS (por ejemplo, "john").
Para comprobar y crear el usuario `postgres` si es necesario, sigue estos pasos:
The installer might not create the `postgres` user by default when installing
via Homebrew on MacOS. Instead, it creates a PostgreSQL role that matches your macOS
username (e.g., "john").
To check and create the `postgres` user if necessary, follow these steps:
```bash
# Conectar a PostgreSQL
# Connect to PostgreSQL
psql postgres
o
or
psql -U $(whoami) -d postgres
```
Una vez en el comando psql (postgres=#), ejecuta:
Once at the psql prompt (postgres=#), run:
```bash
# Lista los roles de PostgreSQL existentes
# List existing PostgreSQL roles
\du
```
Verás una salida similar a:
You'll see output similar to:
```bash
Nombre del rol | Atributos | Miembro de
Role name | Attributes | Member of
-----------+-------------+-----------
john | Superuser | {}
```
Si no ves un rol `postgres` listado, procede al siguiente paso.
Crea el rol `postgres` manualmente:
If you do not see a `postgres` role listed, proceed to the next step.
Create the `postgres` role manually:
```bash
CREATE ROLE postgres WITH SUPERUSER LOGIN;
```
Esto crea un rol de superusuario llamado `postgres` con acceso de inicio de sesión.
This creates a superuser role named `postgres` with login access.
**Opción 2:** Si tienes Docker instalado:
**Option 2:** If you have docker installed:
```bash
make postgres-on-docker
@@ -178,20 +178,20 @@ Debes ejecutar todos los comandos de los siguientes pasos desde la raíz del pro
</Tab>
<Tab title="Windows (WSL)">
Todos los siguientes pasos deben ejecutarse en la terminal de WSL (dentro de tu máquina virtual)
All the following steps are to be run in the WSL terminal (within your virtual machine)
**Opción 1:** Para aprovisionar tu PostgreSQL localmente:
Usa el siguiente enlace para instalar PostgreSQL en tu máquina virtual Linux: [Instalación de PostgreSQL](https://www.postgresql.org/download/linux/)
**Option 1:** To provision your Postgresql locally:
Use the following link to install Postgresql on your Linux virtual machine: [Postgresql Installation](https://www.postgresql.org/download/linux/)
```bash
psql postgres -c "CREATE DATABASE \"default\";" -c "CREATE DATABASE test;"
```
Nota: Puede que necesites agregar `sudo -u postgres` antes del comando `psql` para evitar errores de permisos.
Note: You might need to add `sudo -u postgres` to the command before `psql` to avoid permission errors.
**Opción 2:** Si tienes Docker instalado:
Ejecutar Docker en WSL agrega una capa extra de complejidad.
Solo usa esta opción si estás cómodo con los pasos extras involucrados, incluyendo activar [Docker Desktop WSL2](https://docs.docker.com/desktop/wsl).
**Option 2:** If you have docker installed:
Running Docker on WSL adds an extra layer of complexity.
Only use this option if you are comfortable with the extra steps involved, including turning on [Docker Desktop WSL2](https://docs.docker.com/desktop/wsl).
```bash
make postgres-on-docker
@@ -199,18 +199,18 @@ Debes ejecutar todos los comandos de los siguientes pasos desde la raíz del pro
</Tab>
</Tabs>
Ahora puedes acceder a la base de datos en [localhost:5432](localhost:5432), con usuario `postgres` y contraseña `postgres`.
You can now access the database at [localhost:5432](localhost:5432), with user `postgres` and password `postgres` .
## Paso 4: Configurar una Base de Datos Redis (cache)
## Step 4: Set up a Redis Database (cache)
Twenty requiere un caché de redis para proporcionar el mejor rendimiento
Twenty requires a redis cache to provide the best performance
<Tabs>
<Tab title="Linux">
**Opción 1:** Para aprovisionar tu Redis localmente:
Usa el siguiente enlace para instalar Redis en tu máquina Linux: [Instalación de Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/)
**Option 1:** To provision your Redis locally:
Use the following link to install Redis on your Linux machine: [Redis Installation](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/)
**Opción 2:** Si tienes Docker instalado:
**Option 2:** If you have docker installed:
```bash
make redis-on-docker
@@ -218,16 +218,16 @@ Twenty requiere un caché de redis para proporcionar el mejor rendimiento
</Tab>
<Tab title="Mac OS">
**Opción 1 (preferido):** Para aprovisionar tu Redis localmente con `brew`:
**Option 1 (preferred):** To provision your Redis locally with `brew`:
```bash
brew install redis
```
Inicia tu servidor redis:
Start your redis server:
`brew services start redis`
**Opción 2:** Si tienes Docker instalado:
**Option 2:** If you have docker installed:
```bash
make redis-on-docker
@@ -235,10 +235,10 @@ Twenty requiere un caché de redis para proporcionar el mejor rendimiento
</Tab>
<Tab title="Windows (WSL)">
**Opción 1:** Para aprovisionar tu Redis localmente:
Usa el siguiente enlace para instalar Redis en tu máquina virtual Linux: [Instalación de Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/)
**Option 1:** To provision your Redis locally:
Use the following link to install Redis on your Linux virtual machine: [Redis Installation](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/)
**Opción 2:** Si tienes Docker instalado:
**Option 2:** If you have docker installed:
```bash
make redis-on-docker
@@ -248,11 +248,11 @@ Twenty requiere un caché de redis para proporcionar el mejor rendimiento
If you need a Client GUI, we recommend [redis insight](https://redis.io/insight/) (free version available)
## Paso 5: Configurar las variables de entorno
## Step 5: Setup environment variables
Usa variables de entorno o archivos `.env` para configurar tu proyecto. Más información [aquí](/l/es/developers/self-host/capabilities/setup)
Use environment variables or `.env` files to configure your project. More info [here](/l/es/developers/self-host/capabilities/setup)
Copia los archivos `.env.example` en `/front` y `/server`:
Copy the `.env.example` files in `/front` and `/server`:
```bash
cp ./packages/twenty-front/.env.example ./packages/twenty-front/.env
@@ -263,26 +263,26 @@ cp ./packages/twenty-server/.env.example ./packages/twenty-server/.env
**Multi-Workspace Mode:** By default, Twenty runs in single-workspace mode where only one workspace can be created. To enable multi-workspace support (useful for testing subdomain-based features), set `IS_MULTIWORKSPACE_ENABLED=true` in your server `.env` file. See [Multi-Workspace Mode](/l/es/developers/self-host/capabilities/setup#multi-workspace-mode) for details.
</Info>
## Paso 6: Instalación de dependencias
## Step 6: Installing dependencies
Para compilar el servidor de Twenty e ingresar algunos datos en tu base de datos, ejecuta el siguiente comando:
To build Twenty server and seed some data into your database, run the following command:
```bash
yarn
```
Ten en cuenta que `npm` o `pnpm` no funcionarán
Note that `npm` or `pnpm` won't work
## Paso 7: Ejecutar el proyecto
## Step 7: Running the project
<Tabs>
<Tab title="Linux">
Dependiendo de tu distribución de Linux, el servidor Redis podría iniciarse automáticamente.
Si no, revisa la [guía de instalación de Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) para tu distribución.
Depending on your Linux distribution, Redis server might be started automatically.
If not, check the [Redis installation guide](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) for your distro.
</Tab>
<Tab title="Mac OS">
Redis ya debería estar funcionando. Si no, ejecuta:
Redis should already be running. If not, run:
```bash
brew services start redis
@@ -290,18 +290,18 @@ Ten en cuenta que `npm` o `pnpm` no funcionarán
</Tab>
<Tab title="Windows (WSL)">
Dependiendo de tu distribución de Linux, el servidor Redis podría iniciarse automáticamente.
Si no es así, consulte la [guía de instalación de Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) para su distribución.
Depending on your Linux distribution, Redis server might be started automatically.
If not, check the [Redis installation guide](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) for your distro.
</Tab>
</Tabs>
Configure su base de datos con el siguiente comando:
Set up your database with the following command:
```bash
npx nx database:reset twenty-server
```
Inicie el servidor, el trabajador y los servicios frontend:
Start the server, the worker and the frontend services:
```bash
npx nx start twenty-server
@@ -309,25 +309,25 @@ npx nx worker twenty-server
npx nx start twenty-front
```
Alternativamente, puede iniciar todos los servicios a la vez:
Alternatively, you can start all services at once:
```bash
npx nx start
```
## Paso 8: Use Twenty
## Step 8: Use Twenty
**Frontend**
El frontend de Twenty estará ejecutándose en [http://localhost:3001](http://localhost:3001).
Puede iniciar sesión usando la cuenta demo por defecto: `tim@apple.dev` (contraseña: `tim@apple.dev`)
Twenty's frontend will be running at [http://localhost:3001](http://localhost:3001).
You can log in using the default demo account: `tim@apple.dev` (password: `tim@apple.dev`)
**Backend**
* El servidor de Twenty estará operativo en [http://localhost:3000](http://localhost:3000)
* La API GraphQL puede ser accedida en [http://localhost:3000/graphql](http://localhost:3000/graphql)
* La API REST puede ser alcanzada en [http://localhost:3000/rest](http://localhost:3000/rest)
* Twenty's server will be up and running at [http://localhost:3000](http://localhost:3000)
* The GraphQL API can be accessed at [http://localhost:3000/graphql](http://localhost:3000/graphql)
* The REST API can be reached at [http://localhost:3000/rest](http://localhost:3000/rest)
## Solución de Problemas
## Troubleshooting
Si encuentras algún problema, consulta [Solución de Problemas](/l/es/developers/self-host/capabilities/troubleshooting) para ver soluciones.
If you encounter any problem, check [Troubleshooting](/l/es/developers/self-host/capabilities/troubleshooting) for solutions.
@@ -4,10 +4,10 @@ description: Contribute to Twenty's open-source development.
---
<Frame>
<img src="/images/user-guide/github/github-header.png" alt="IA" />
<img src="/images/user-guide/github/github-header.png" alt="AI" />
</Frame>
## Resumen
## Overview
Twenty is open-source and welcomes contributions from the community. Whether you're fixing bugs, adding features, or improving documentation, your contributions help make Twenty better for everyone.
@@ -26,7 +26,7 @@ Twenty is open-source and welcomes contributions from the community. Whether you
Report issues or request features
</Card>
<Card title="Desarrollo Frontend" icon="browser" href="/l/es/developers/contribute/capabilities/frontend-development">
<Card title="Frontend Development" icon="browser" href="/l/es/developers/contribute/capabilities/frontend-development">
Contribute to the UI
</Card>
</CardGroup>
@@ -5,16 +5,16 @@ description: Query and modify your CRM data programmatically using REST or Graph
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
Twenty fue creado para ser amigable con los desarrolladores, ofreciendo APIs potentes que se adaptan a tu modelo de datos personalizado. Proveemos cuatro tipos de API distintos para satisfacer diferentes necesidades de integración.
Twenty was built to be developer-friendly, offering powerful APIs that adapt to your custom data model. We provide four distinct API types to meet different integration needs.
## Enfoque centrado en el desarrollador
## Developer-First Approach
Twenty generates APIs specifically for your data model:
* **No se requieren IDs largos**: Usa los nombres de tus objetos y campos directamente en los endpoints.
* **Objetos estándar y personalizados tratados por igual**: Tus objetos personalizados reciben el mismo tratamiento de API que los incorporados.
* **Endpoints dedicados**: Cada objeto y campo recibe su propio endpoint de API.
* **Documentación personalizada**: Generada específicamente para el modelo de datos de tu espacio de trabajo.
* **No long IDs required**: Use your object and field names directly in endpoints
* **Standard and custom objects treated equally**: Your custom objects get the same API treatment as built-in ones
* **Dedicated endpoints**: Each object and field gets its own API endpoint
* **Custom documentation**: Generated specifically for your workspace's data model
<Note>
Your personalized API documentation is available under **Settings → API & Webhooks** after creating an API key. Since Twenty generates APIs that match your custom data model, the documentation is unique to your workspace.
@@ -22,45 +22,45 @@ Twenty generates APIs specifically for your data model:
## The Two API Types
### API Principal
### Core API
Accesible en `/rest/` o `/graphql/`
Accessed on `/rest/` or `/graphql/`
Work with your actual **records** (the data):
* Create, read, update, delete People, Companies, Opportunities, etc.
* Query and filter data
* Gestionar relaciones de registros
* Manage record relationships
### API de Metadatos
### Metadata API
Accesible en `/rest/metadata/` o `/metadata/`
Accessed on `/rest/metadata/` or `/metadata/`
Manage your **workspace and data model**:
* Crear, modificar o eliminar objetos y campos
* Configurar ajustes del espacio de trabajo
* Create, modify, or delete objects and fields
* Configure workspace settings
* Define relationships between objects
## REST vs GraphQL
Both Core and Metadata APIs are available in REST and GraphQL formats:
| Formato | Available Operations |
| Format | Available Operations |
| ----------- | ---------------------------------------------------------- |
| **REST** | CRUD, batch operations, upserts |
| **GraphQL** | Same + **batch upserts**, relationship queries in one call |
Choose based on your needs — both formats access the same data.
## Puntos de Acceso de API
## API Endpoints
| Environment | Base URL |
| --------------- | ------------------------- |
| **Cloud** | `https://api.twenty.com/` |
| **Self-Hosted** | `https://{your-domain}/` |
## Autenticación
## Authentication
Every API request requires an API key in the header:
@@ -68,14 +68,14 @@ Every API request requires an API key in the header:
Authorization: Bearer YOUR_API_KEY
```
### Crear una Clave de API
### Create an API Key
1. Ve a **Configuración → APIs y Webhooks**
1. Go to **Settings → APIs & Webhooks**
2. Click **+ Create key**
3. Configurar:
3. Configure:
* **Name**: Descriptive name for the key
* **Expiration Date**: When the key expires
4. Haga clic en **Guardar**
4. Click **Save**
5. **Copy immediately** — the key is only shown once
<VimeoEmbed videoId="928786722" title="Creating API key" />
@@ -90,13 +90,13 @@ For better security, assign a specific role to limit access:
1. Go to **Settings → Roles**
2. Click on the role to assign
3. Abre la pestaña **Asignación**
3. Open the **Assignment** tab
4. Under **API Keys**, click **+ Assign to API key**
5. Select the API key
The key will inherit that role's permissions. See [Permissions](/l/es/user-guide/permissions-access/capabilities/permissions) for details.
### Gestionar Claves de API
### Manage API Keys
**Regenerate**: Settings → APIs & Webhooks → Click key → **Regenerate**
@@ -108,7 +108,7 @@ Test your APIs directly in the browser with our built-in playground — availabl
### Access the Playground
1. Ve a **Configuración → APIs y Webhooks**
1. Go to **Settings → APIs & Webhooks**
2. Create an API key (required)
3. Click on **REST API** or **GraphQL API** to open the playground
@@ -121,11 +121,11 @@ Test your APIs directly in the browser with our built-in playground — availabl
The playground reflects your custom objects and fields, so documentation is always accurate for your workspace.
## Operaciones por Lotes
## Batch Operations
Both REST and GraphQL support batch operations:
* **Tamaño del lote**: Hasta 60 registros por solicitud
* **Batch size**: Up to 60 records per request
* **Operations**: Create, update, delete multiple records
**GraphQL-only features:**
@@ -137,7 +137,7 @@ Both REST and GraphQL support batch operations:
API requests are throttled to ensure platform stability:
| Límite | Valor |
| Limit | Value |
| -------------- | -------------------- |
| **Requests** | 100 calls per minute |
| **Batch size** | 60 records per call |
@@ -21,7 +21,7 @@ Apps let you build and manage Twenty customizations **as code**. Instead of conf
* Custom UI layouts and components
## Prerrequisitos
## Prerequisites
* Node.js 24+ and Yarn 4
* A Twenty workspace and an API key (create one at https://app.twenty.com/settings/api-webhooks)
@@ -42,7 +42,7 @@ yarn auth
yarn dev
```
Desde aquí usted puede:
From here you can:
```bash filename="Terminal"
# Add a new entity to your application (guided)
@@ -115,7 +115,7 @@ Later commands will add more files and folders:
* `yarn generate` will create a `generated/` folder (typed Twenty client + workspace types).
* `yarn create-entity` will add entity definition files under `src/` for your custom objects.
## Autenticación
## Authentication
The first time you run `yarn auth`, you'll be prompted for:
@@ -124,7 +124,7 @@ The first time you run `yarn auth`, you'll be prompted for:
Your credentials are stored per-user in `~/.twenty/config.json`. You can maintain multiple profiles and switch using `--workspace <name>`.
Ejemplos:
Examples:
```bash filename="Terminal"
# Login interactively (recommended)
@@ -512,7 +512,7 @@ Then add scripts like these:
Now you can run the same commands via Yarn, e.g. `yarn dev`, `yarn sync`, etc.
## Solución de problemas
## Troubleshooting
* Authentication errors: run `yarn auth` and ensure your API key has the required permissions.
* Cannot connect to server: verify the API URL and that the Twenty server is reachable.
@@ -7,28 +7,28 @@ import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
Webhooks push data to your systems in real-time when events occur in Twenty — no polling required. Use them to keep external systems in sync, trigger automations, or send alerts.
## Crear un Webhook
## Create a Webhook
1. Ve a **Configuración → APIs y Webhooks → Webhooks**
2. Haga clic en **+ Crear webhook**
1. Go to **Settings → APIs & Webhooks → Webhooks**
2. Click **+ Create webhook**
3. Enter your webhook URL (must be publicly accessible)
4. Haga clic en **Guardar**
4. Click **Save**
The webhook activates immediately and starts sending notifications.
<VimeoEmbed videoId="928786708" title="Creating a webhook" />
### Gestionar Webhooks
### Manage Webhooks
**Edit**: Click the webhook → Update URL → **Save**
**Delete**: Click the webhook → **Delete** → Confirm
## Eventos
## Events
Twenty sends webhooks for these event types:
| Evento | Ejemplo |
| Event | Example |
| ------------------ | ---------------------------------------------------------- |
| **Record Created** | `person.created`, `company.created`, `note.created` |
| **Record Updated** | `person.updated`, `company.updated`, `opportunity.updated` |
@@ -55,23 +55,23 @@ Each webhook sends an HTTP POST with a JSON body:
}
```
| Campo | Descripción |
| ----------------- | ------------------------------------------------ |
| `evento` | What happened (e.g., `person.created`) |
| `datos` | The full record that was created/updated/deleted |
| `marca de tiempo` | When the event occurred (UTC) |
| Field | Description |
| ----------- | ------------------------------------------------ |
| `event` | What happened (e.g., `person.created`) |
| `data` | The full record that was created/updated/deleted |
| `timestamp` | When the event occurred (UTC) |
<Note>
Respond with a **2xx HTTP status** (200-299) to acknowledge receipt. Non-2xx responses are logged as delivery failures.
</Note>
## Validación de Webhook
## Webhook Validation
Twenty signs each webhook request for security. Validate signatures to ensure requests are authentic.
### Headers
| Encabezado | Descripción |
| Header | Description |
| ---------------------------- | --------------------- |
| `X-Twenty-Webhook-Signature` | HMAC SHA256 signature |
| `X-Twenty-Webhook-Timestamp` | Request timestamp |
@@ -103,7 +103,7 @@ const isValid = expectedSignature === req.headers["x-twenty-webhook-signature"];
## Webhooks vs Workflows
| Método | Dirección | Use Case |
| Method | Direction | Use Case |
| ---------------------------- | --------- | ---------------------------------------------------------- |
| **Webhooks** | OUT | Automatically notify external systems of any record change |
| **Workflow + HTTP Request** | OUT | Send data out with custom logic (filters, transformations) |
@@ -4,10 +4,10 @@ description: Extend Twenty's functionality with APIs, webhooks, and custom apps.
---
<Frame>
<img src="/images/user-guide/integrations/plug.png" alt="IA" />
<img src="/images/user-guide/integrations/plug.png" alt="AI" />
</Frame>
## Resumen
## Overview
Twenty is designed to be extensible. Use our APIs, webhooks, and app framework to integrate with your existing tools and build custom functionality.
@@ -20,7 +20,7 @@ Twenty is designed to be extensible. Use our APIs, webhooks, and app framework t
## Getting Started
<CardGroup cols={2}>
<Card title="APIs" icon="código" href="/l/es/developers/extend/capabilities/apis">
<Card title="APIs" icon="code" href="/l/es/developers/extend/capabilities/apis">
Connect to Twenty programmatically
</Card>
@@ -1,45 +1,45 @@
---
title: Otros métodos
title: Other methods
---
<Warning>
Este documento es mantenido por la comunidad. Podría contener problemas.
This document is maintained by the community. It might contain issues.
</Warning>
## Kubernetes vía Terraform y Manifests
## Kubernetes via Terraform and Manifests
Documentación comunitaria para la implementación de Kubernetes está disponible [aquí](https://github.com/twentyhq/twenty/tree/main/packages/twenty-docker/k8s)
Community-led documentation for Kubernetes deployment is available [here](https://github.com/twentyhq/twenty/tree/main/packages/twenty-docker/k8s)
### Coolify
Despliega Twenty en servidores usando Coolify. (la imagen oficial en Coolify estará disponible pronto)
Deploy Twenty on servers using Coolify. (official image on Coolify will be available soon)
[Documentación de Coolify](https://coolify.io/docs/get-started/introduction)
[Coolify documentation](https://coolify.io/docs/get-started/introduction)
### EasyPanel
Despliega Twenty en EasyPanel con la plantilla mantenida por la comunidad a continuación.
Deploy Twenty on EasyPanel with the community maintained template below.
[Desplegar en EasyPanel](https://easypanel.io/docs/templates/twenty)
[Deploy on EasyPanel](https://easypanel.io/docs/templates/twenty)
### Elest.io
Despliega Twenty en servidores con Elest.io utilizando el enlace a continuación.
Deploy Twenty on servers with Elest.io using link below.
[Desplegar en Elest.io](https://elest.io/open-source/twenty)
[Deploy on Elest.io](https://elest.io/open-source/twenty)
### Twenty en Railway
### Twenty on Railway
Despliega Twenty en Railway con la plantilla mantenida por la comunidad a continuación.
Deploy Twenty on Railway with the community maintained template below.
[![Desplegar en Railway](https://railway.com/button.svg)](https://railway.com/deploy/nAL3hA)
[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/nAL3hA)
### Twenty en Sealos
### Twenty on Sealos
Despliega Twenty en Sealos con la plantilla mantenida por la comunidad a continuación.
Deploy Twenty on Sealos with the community maintained template below.
[![Desplegar en Sealos](https://sealos.io/Deploy-on-Sealos.svg)](https://sealos.io/products/app-store/twenty)
[![Deploy on Sealos](https://sealos.io/Deploy-on-Sealos.svg)](https://sealos.io/products/app-store/twenty)
## Otros
## Others
Please feel free to Open a PR to add more Cloud Provider options.
@@ -1,207 +1,207 @@
---
title: 1-Clic con Docker Compose
title: 1-Click w/ Docker Compose
---
<Warning>
Los contenedores de Docker son para alojamiento en producción o autoalojamiento, para la contribución por favor revise la [Configuración Local](/l/es/developers/contribute/capabilities/local-setup).
Docker containers are for production hosting or self-hosting, for the contribution please check the [Local Setup](/l/es/developers/contribute/capabilities/local-setup).
</Warning>
## Resumen
## Overview
Esta guía proporciona instrucciones paso a paso para instalar y configurar la aplicación Twenty utilizando Docker Compose. El objetivo es simplificar el proceso y prevenir errores comunes que podrían arruinar tu configuración.
This guide provides step-by-step instructions to install and configure the Twenty application using Docker Compose. The aim is to make the process straightforward and prevent common pitfalls that could break your setup.
**Importante:** Solo modifica configuraciones explícitamente mencionadas en esta guía. Alterar otras configuraciones puede causar problemas.
**Important:** Only modify settings explicitly mentioned in this guide. Altering other configurations may lead to issues.
Consulta los documentos [Configurar Variables de Entorno](/l/es/developers/self-host/capabilities/setup) para configuraciones avanzadas. Todas las variables de entorno deben ser declaradas en el archivo docker-compose.yml en el nivel del servidor y/o trabajador dependiendo de la variable.
See docs [Setup Environment Variables](/l/es/developers/self-host/capabilities/setup) for advanced configuration. All environment variables must be declared in the docker-compose.yml file at the server and / or worker level depending on the variable.
## Requisitos del sistema
## System Requirements
* RAM: Asegúrate de que tu entorno tenga al menos 2GB de RAM. La memoria insuficiente puede causar que los procesos se bloqueen.
* Docker & Docker Compose: Asegúrate de que ambos estén instalados y actualizados.
* RAM: Ensure your environment has at least 2GB of RAM. Insufficient memory can cause processes to crash.
* Docker & Docker Compose: Make sure both are installed and up-to-date.
## Opción 1: Script de una línea
## Option 1: One-line script
Instala la última versión estable de Twenty con un solo comando:
Install the latest stable version of Twenty with a single command:
```bash
bash <(curl -sL https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/scripts/install.sh)
```
Para instalar una versión o rama específica:
To install a specific version or branch:
```bash
VERSION=vx.y.z BRANCH=branch-name bash <(curl -sL https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/scripts/install.sh)
```
* Reemplace x.y.z con el número de versión deseado.
* Reemplace branch-name con el nombre de la rama que desea instalar.
* Replace x.y.z with the desired version number.
* Replace branch-name with the name of the branch you want to install.
## Opción 2: Pasos manuales
## Option 2: Manual steps
Sigue estos pasos para una configuración manual.
Follow these steps for a manual setup.
### Paso 1: Configurar el archivo de entorno
### Step 1: Set Up the Environment File
1. **Create the .env File**
Copia el archivo de entorno de ejemplo a tu directorio de trabajo a un nuevo archivo .env:
Copy the example environment file to a new .env file in your working directory:
```bash
curl -o .env https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-docker/.env.example
```
2. **Generar tokens secretos**
2. **Generate Secret Tokens**
Ejecuta el siguiente comando para generar una cadena única aleatoria:
Run the following command to generate a unique random string:
```bash
openssl rand -base64 32
```
**Importante:** Mantén este valor en secreto / no lo compartas.
**Important:** Keep this value secret / do not share it.
3. **Actualiza el `.env`**
3. **Update the `.env`**
Reemplaza el valor de marcador de posición en tu archivo .env con el token generado:
Replace the placeholder value in your .env file with the generated token:
```ini
APP_SECRET=primera_cadena_aleatoria
APP_SECRET=first_random_string
```
4. **Establecer la contraseña de Postgres**
4. **Set the Postgres Password**
Actualiza el valor de `PG_DATABASE_PASSWORD` en el archivo .env con una contraseña fuerte sin caracteres especiales.
Update the `PG_DATABASE_PASSWORD` value in the .env file with a strong password without special characters.
```ini
PG_DATABASE_PASSWORD=mi_contraseña_fuerte
PG_DATABASE_PASSWORD=my_strong_password
```
### Paso 2: Obtener el archivo Docker Compose
### Step 2: Obtain the Docker Compose File
Descarga el archivo `docker-compose.yml` en tu directorio de trabajo:
Download the `docker-compose.yml` file to your working directory:
```bash
curl -o docker-compose.yml https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-docker/docker-compose.yml
```
### Paso 3: Lanza la aplicación
### Step 3: Launch the Application
Inicia los contenedores Docker:
Start the Docker containers:
```bash
docker compose up -d
```
### Paso 4: Acceder a la aplicación
### Step 4: Access the Application
Si alojas twentyCRM en tu propia computadora, abre tu navegador y navega a [http://localhost:3000](http://localhost:3000).
If you host twentyCRM on your own computer, open your browser and navigate to [http://localhost:3000](http://localhost:3000).
Si lo alojas en un servidor, verifica que el servidor esté en funcionamiento y que todo esté bien con
If you host it on a server, check that the server is running and that everything is ok with
```bash
curl http://localhost:3000
```
## Configuración
## Configuration
### Exponer Twenty para acceso externo
### Expose Twenty to External Access
Por defecto, Twenty se ejecuta en `localhost` en el puerto `3000`. Para acceder a él mediante un dominio externo o dirección IP, necesitas configurar `SERVER_URL` en tu archivo `.env`.
By default, Twenty runs on `localhost` at port `3000`. To access it via an external domain or IP address, you need to configure the `SERVER_URL` in your `.env` file.
#### Entendiendo `SERVER_URL`
#### Understanding `SERVER_URL`
* **Protocolo:** Usa `http` o `https` dependiendo de tu configuración.
* Usa `http` si no has configurado SSL.
* Usa `https` si tienes SSL configurado.
* **Dominio/IP:** Este es el nombre de dominio o dirección IP donde tu aplicación es accesible.
* **Puerto:** Incluye el número de puerto si no estás usando los puertos predeterminados (`80` para `http`, `443` para `https`).
* **Protocol:** Use `http` or `https` depending on your setup.
* Use `http` if you haven't set up SSL.
* Use `https` if you have SSL configured.
* **Domain/IP:** This is the domain name or IP address where your application is accessible.
* **Port:** Include the port number if you're not using the default ports (`80` for `http`, `443` for `https`).
### Requisitos de SSL
### SSL Requirements
SSL (HTTPS) es requerido para que ciertas características del navegador funcionen correctamente. Aunque estas características podrían funcionar durante el desarrollo local (ya que los navegadores tratan localhost de manera diferente), se requiere una configuración SSL adecuada al alojar Twenty en un dominio regular.
SSL (HTTPS) is required for certain browser features to work properly. While these features might work during local development (as browsers treat localhost differently), a proper SSL setup is needed when hosting Twenty on a regular domain.
Por ejemplo, es posible que la API del portapapeles requiera un contexto seguro: algunas características como los botones de copia en toda la aplicación pueden no funcionar sin HTTPS habilitado.
For example, the clipboard API might require a secure context - some features like copy buttons throughout the application might not work without HTTPS enabled.
Recomendamos encarecidamente configurar Twenty detrás de un proxy inverso con terminación SSL para una seguridad y funcionalidad óptimas.
We strongly recommend setting up Twenty behind a reverse proxy with SSL termination for optimal security and functionality.
#### Configurando `SERVER_URL`
#### Configuring `SERVER_URL`
1. **Determine su URL de acceso**
* **Sin proxy inverso (Acceso directo):**
1. **Determine Your Access URL**
* **Without Reverse Proxy (Direct Access):**
Si estás accediendo a la aplicación directamente sin un proxy inverso:
If you're accessing the application directly without a reverse proxy:
```ini
SERVER_URL=http://tu-dominio-o-ip:3000
SERVER_URL=http://your-domain-or-ip:3000
```
* **Con proxy inverso (Puertos estándar):**
* **With Reverse Proxy (Standard Ports):**
Si estás usando un proxy inverso como Nginx o Traefik y tienes SSL configurado:
If you're using a reverse proxy like Nginx or Traefik and have SSL configured:
```ini
SERVER_URL=https://tu-dominio-o-ip
SERVER_URL=https://your-domain-or-ip
```
* **Con proxy inverso (Puertos personalizados):**
* **With Reverse Proxy (Custom Ports):**
Si estás usando puertos no estándar:
If you're using non-standard ports:
```ini
SERVER_URL=https://tu-dominio-o-ip:puerto-personalizado
SERVER_URL=https://your-domain-or-ip:custom-port
```
2. **Actualiza el archivo `.env`**
2. **Update the `.env` File**
Abre tu archivo `.env` y actualiza el `SERVER_URL`:
Open your `.env` file and update the `SERVER_URL`:
```ini
SERVER_URL=http(s)://tu-dominio-o-ip:tu-puerto
SERVER_URL=http(s)://your-domain-or-ip:your-port
```
**Ejemplos:**
**Examples:**
* Acceso directo sin SSL:
* Direct access without SSL:
```ini
SERVER_URL=http://123.45.67.89:3000
```
* Acceso vía dominio con SSL:
* Access via domain with SSL:
```ini
SERVER_URL=https://miappdetwenty.com
SERVER_URL=https://mytwentyapp.com
```
3. **Reiniciar la aplicación**
3. **Restart the Application**
Para que los cambios surtan efecto, reinicia los contenedores Docker:
For changes to take effect, restart the Docker containers:
```bash
docker compose down
docker compose up -d
```
#### Consideraciones
#### Considerations
* **Configuración del Proxy Inverso:**
* **Reverse Proxy Configuration:**
Asegúrese de que su proxy inverso envíe las solicitudes al puerto interno correcto (`3000` por defecto). Configure la terminación SSL y cualquier cabecera necesaria.
Ensure your reverse proxy forwards requests to the correct internal port (`3000` by default). Configure SSL termination and any necessary headers.
* **Configuración del Cortafuegos:**
* **Firewall Settings:**
Abra los puertos necesarios en su cortafuegos para permitir el acceso externo.
Open necessary ports in your firewall to allow external access.
* **Consistencia:**
* **Consistency:**
La `SERVER_URL` debe coincidir con cómo los usuarios acceden a su aplicación en sus navegadores.
The `SERVER_URL` must match how users access your application in their browsers.
#### Persistencia
#### Persistence
* **Volúmenes de Datos:**
* **Data Volumes:**
La configuración de Docker Compose utiliza volúmenes para persistir datos para la base de datos y el almacenamiento del servidor.
The Docker Compose configuration uses volumes to persist data for the database and server storage.
* **Entornos Sin Estado:**
* **Stateless Environments:**
Si se despliega en un entorno sin estado (por ejemplo, ciertos servicios en la nube), configure un almacenamiento externo para persistir los datos.
If deploying to a stateless environment (e.g., certain cloud services), configure external storage to persist data.
## Backup and Restore
@@ -248,6 +248,6 @@ docker compose up -d
* **Encrypt sensitive data** — protect backups with encryption
* **Retain multiple copies** — keep daily, weekly, and monthly backups
## Solución de Problemas
## Troubleshooting
Si encuentras algún problema, consulta [Solución de Problemas](/l/es/developers/self-host/capabilities/troubleshooting) para ver soluciones.
If you encounter any problem, check [Troubleshooting](/l/es/developers/self-host/capabilities/troubleshooting) for solutions.
@@ -1,64 +1,64 @@
---
title: Configuración
title: Setup
---
# Gestión de Configuración
# Configuration Management
<Warning>
**¿Instalando por primera vez?** Siga la [guía de instalación de Docker Compose](/l/es/developers/self-host/capabilities/docker-compose) para ejecutar Twenty, luego regrese aquí para la configuración.
**First time installing?** Follow the [Docker Compose installation guide](/l/es/developers/self-host/capabilities/docker-compose) to get Twenty running, then return here for configuration.
</Warning>
Twenty ofrece **dos modos de configuración** para adaptarse a diferentes necesidades de implementación:
Twenty offers **two configuration modes** to suit different deployment needs:
**Acceso al panel de administración:** Solo los usuarios con privilegios de administrador (`canAccessFullAdminPanel: true`) pueden acceder a la interfaz de configuración.
**Admin panel access:** Only users with admin privileges (`canAccessFullAdminPanel: true`) can access the configuration interface.
## 1. Configuración del Panel de Administración (Predeterminado)
## 1. Admin Panel Configuration (Default)
```bash
IS_CONFIG_VARIABLES_IN_DB_ENABLED=true # predeterminado
IS_CONFIG_VARIABLES_IN_DB_ENABLED=true # default
```
**La mayoría de las configuraciones se realizan a través de la interfaz** después de la instalación:
**Most configuration happens through the UI** after installation:
1. Acceda a su instancia de Twenty (normalmente `http://localhost:3000`)
2. Vaya a **Configuración / Panel de Administración / Variables de Configuración**
3. Configure integraciones, correo electrónico, almacenamiento y más
4. Los cambios se aplican inmediatamente (dentro de 15 segundos para implementaciones multicontenedor)
1. Access your Twenty instance (usually `http://localhost:3000`)
2. Go to **Settings / Admin Panel / Configuration Variables**
3. Configure integrations, email, storage, and more
4. Changes take effect immediately (within 15 seconds for multi-container deployments)
<Warning>
**Implementaciones Multicontenedor:** Al usar la configuración de base de datos (`IS_CONFIG_VARIABLES_IN_DB_ENABLED=true`), tanto los contenedores del servidor como los de trabajo leen de la misma base de datos. Los cambios en el panel de administración afectan a ambos automáticamente, eliminando la necesidad de duplicar las variables de entorno entre contenedores (excepto para las variables de infraestructura).
**Multi-Container Deployments:** When using database configuration (`IS_CONFIG_VARIABLES_IN_DB_ENABLED=true`), both server and worker containers read from the same database. Admin panel changes affect both automatically, eliminating the need to duplicate environment variables between containers (except for infrastructure variables).
</Warning>
**Qué se puede configurar a través del panel de administración:**
**What you can configure through the admin panel:**
* **Autenticación** - OAuth de Google/Microsoft, configuración de contraseñas
* **Correo Electrónico** - Configuración de SMTP, plantillas, verificación
* **Almacenamiento** - Configuración S3, rutas de almacenamiento local
* **Integraciones** - Gmail, Google Calendar, servicios de Microsoft
* **Flujo de Trabajo y Limitación de Tasas** - Límites de ejecución, restricción de API
* **Y mucho más...**
* **Authentication** - Google/Microsoft OAuth, password settings
* **Email** - SMTP settings, templates, verification
* **Storage** - S3 configuration, local storage paths
* **Integrations** - Gmail, Google Calendar, Microsoft services
* **Workflow & Rate Limiting** - Execution limits, API throttling
* **And much more...**
![Variables de Configuración del Panel de Administración](/images/user-guide/setup/admin-panel-config-variables.png)
![Admin Panel Configuration Variables](/images/user-guide/setup/admin-panel-config-variables.png)
<Warning>
Cada variable está documentada con descripciones en su panel de administración en **Configuración → Panel de Administración → Variables de Configuración**.
Algunas configuraciones de infraestructura como las conexiones de base de datos (`PG_DATABASE_URL`), URLs del servidor (`SERVER_URL`), y secretos de la aplicación (`APP_SECRET`) solo se pueden configurar a través del archivo `.env`.
Each variable is documented with descriptions in your admin panel at **Settings → Admin Panel → Configuration Variables**.
Some infrastructure settings like database connections (`PG_DATABASE_URL`), server URLs (`SERVER_URL`), and app secrets (`APP_SECRET`) can only be configured via `.env` file.
[Referencia técnica completa →](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts)
[Complete technical reference →](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/twenty-config/config-variables.ts)
</Warning>
## 2. Configuración Solo de Entorno
## 2. Environment-Only Configuration
```bash
IS_CONFIG_VARIABLES_IN_DB_ENABLED=false
```
**Toda la configuración se gestiona a través de archivos `.env`:**
**All configuration managed through `.env` files:**
1. Establezca `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false` en su archivo `.env`
2. Agregue todas las variables de configuración a su archivo `.env`
3. Reinicie los contenedores para que los cambios tengan efecto
4. El panel de administración mostrará los valores actuales pero no podrá modificarlos
1. Set `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false` in your `.env` file
2. Add all configuration variables to your `.env` file
3. Restart containers for changes to take effect
4. Admin panel will show current values but cannot modify them
## Multi-Workspace Mode
@@ -116,31 +116,31 @@ IS_WORKSPACE_CREATION_LIMITED_TO_SERVER_ADMINS=true
When enabled, only users with `canAccessFullAdminPanel` can create additional workspaces. Users can still create their first workspace during initial signup.
## Integración con Gmail y Google Calendar
## Gmail & Google Calendar Integration
### Crear Proyecto en Google Cloud
### Create Google Cloud Project
1. Vaya a [Google Cloud Console](https://console.cloud.google.com/)
2. Cree un nuevo proyecto o seleccione uno existente
3. Habilite estas APIs:
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select existing one
3. Enable these APIs:
* [Gmail API](https://console.cloud.google.com/apis/library/gmail.googleapis.com)
* [Google Calendar API](https://console.cloud.google.com/apis/library/calendar-json.googleapis.com)
* [People API](https://console.cloud.google.com/apis/library/people.googleapis.com)
### Configurar OAuth
### Configure OAuth
1. Vaya a [Credenciales](https://console.cloud.google.com/apis/credentials)
2. Cree un ID de Cliente OAuth 2.0
3. Agregue estas URIs de redirección:
1. Go to [Credentials](https://console.cloud.google.com/apis/credentials)
2. Create OAuth 2.0 Client ID
3. Add these redirect URIs:
* `https://{your-domain}/auth/google/redirect` (for SSO)
* `https://{your-domain}/auth/google-apis/get-access-token` (for integrations)
### Configurar en Twenty
### Configure in Twenty
1. Vaya a **Configuración → Panel de Administración → Variables de Configuración**
2. Encuentre la sección **Google Auth**
3. Establezca estas variables:
1. Go to **Settings → Admin Panel → Configuration Variables**
2. Find the **Google Auth** section
3. Set these variables:
* `MESSAGING_PROVIDER_GMAIL_ENABLED=true`
* `CALENDAR_PROVIDER_GOOGLE_ENABLED=true`
* `AUTH_GOOGLE_CLIENT_ID={client-id}`
@@ -149,35 +149,35 @@ When enabled, only users with `canAccessFullAdminPanel` can create additional wo
* `AUTH_GOOGLE_APIS_CALLBACK_URL=https://{your-domain}/auth/google-apis/get-access-token`
<Warning>
**Modo solo de entorno:** Si establece `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`, agregue estas variables a su archivo `.env` en su lugar.
**Environment-only mode:** If you set `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`, add these variables to your `.env` file instead.
</Warning>
**Ámbitos requeridos** (configurados automáticamente):
[Ver código fuente relevante](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/auth/utils/get-google-apis-oauth-scopes.ts#L4-L10)
**Required scopes** (automatically configured):
[See relevant source code](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/auth/utils/get-google-apis-oauth-scopes.ts#L4-L10)
* `https://www.googleapis.com/auth/calendar.events`
* `https://www.googleapis.com/auth/gmail.readonly`
* `https://www.googleapis.com/auth/profile.emails.read`
### Si su aplicación está en modo de prueba
### If your app is in test mode
Si su aplicación está en modo de prueba, deberá agregar usuarios de prueba a su proyecto.
If your app is in test mode, you will need to add test users to your project.
En [Pantalla de consentimiento OAuth](https://console.cloud.google.com/apis/credentials/consent), agregue sus usuarios de prueba en la sección "Usuarios de prueba".
Under [OAuth consent screen](https://console.cloud.google.com/apis/credentials/consent), add your test users to the "Test users" section.
## Integración con Microsoft 365
## Microsoft 365 Integration
<Warning>
Los usuarios deben tener una [licencia de Microsoft 365](https://admin.microsoft.com/Adminportal/Home) para poder usar la API de Calendar y Messaging. No podrán sincronizar su cuenta en Twenty sin una.
Users must have a [Microsoft 365 Licence](https://admin.microsoft.com/Adminportal/Home) to be able to use the Calendar and Messaging API. They will not be able to sync their account on Twenty without one.
</Warning>
### Cree un proyecto en Microsoft Azure
### Create a project in Microsoft Azure
Necesitará crear un proyecto en [Microsoft Azure](https://portal.azure.com/#view/Microsoft_AAD_IAM/AppGalleryBladeV2) y obtener las credenciales.
You will need to create a project in [Microsoft Azure](https://portal.azure.com/#view/Microsoft_AAD_IAM/AppGalleryBladeV2) and get the credentials.
### Habilitar APIs
### Enable APIs
En la Consola de Microsoft Azure habilite las siguientes APIs en "Permisos":
On Microsoft Azure Console enable the following APIs in "Permissions":
* Microsoft Graph: Mail.ReadWrite
* Microsoft Graph: Mail.Send
@@ -188,20 +188,20 @@ En la Consola de Microsoft Azure habilite las siguientes APIs en "Permisos":
* Microsoft Graph: profile
* Microsoft Graph: offline_access
Nota: "Mail.ReadWrite" y "Mail.Send" solo son obligatorios si desea enviar correos electrónicos usando nuestras acciones de flujo de trabajo. Puede usar "Mail.Read" en su lugar si solo desea recibir correos electrónicos.
Note: "Mail.ReadWrite" and "Mail.Send" are only mandatory if you want to send emails using our workflow actions. You can use "Mail.Read" instead if you only want to receive emails.
### URIs de redirección autorizadas
### Authorized redirect URIs
Necesita agregar las siguientes URIs de redirección a su proyecto:
You need to add the following redirect URIs to your project:
* `https://{your-domain}/auth/microsoft/redirect` if you want to use Microsoft SSO
* `https://{your-domain}/auth/microsoft-apis/get-access-token`
### Configurar en Twenty
### Configure in Twenty
1. Vaya a **Configuración → Panel de Administración → Variables de Configuración**
2. Encuentre la sección **Microsoft Auth**
3. Establezca estas variables:
1. Go to **Settings → Admin Panel → Configuration Variables**
2. Find the **Microsoft Auth** section
3. Set these variables:
* `MESSAGING_PROVIDER_MICROSOFT_ENABLED=true`
* `CALENDAR_PROVIDER_MICROSOFT_ENABLED=true`
* `AUTH_MICROSOFT_ENABLED=true`
@@ -211,35 +211,35 @@ Necesita agregar las siguientes URIs de redirección a su proyecto:
* `AUTH_MICROSOFT_APIS_CALLBACK_URL=https://{your-domain}/auth/microsoft-apis/get-access-token`
<Warning>
**Modo solo de entorno:** Si establece `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`, agregue estas variables a su archivo `.env` en su lugar.
**Environment-only mode:** If you set `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`, add these variables to your `.env` file instead.
</Warning>
### Configurar ámbitos
### Configure scopes
[Ver código fuente relevante](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/auth/utils/get-microsoft-apis-oauth-scopes.ts#L2-L9)
[See relevant source code](https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/engine/core-modules/auth/utils/get-microsoft-apis-oauth-scopes.ts#L2-L9)
* 'openid'
* 'correo Electrónico'
* 'perfil'
* 'email'
* 'profile'
* 'offline_access'
* 'Mail.ReadWrite'
* 'Mail.Send'
* 'Calendars.Read'
### Si su aplicación está en modo de prueba
### If your app is in test mode
Si su aplicación está en modo de prueba, deberá agregar usuarios de prueba a su proyecto.
If your app is in test mode, you will need to add test users to your project.
Agregue sus usuarios de prueba a la sección "Usuarios y grupos".
Add your test users to the "Users and groups" section.
## Trabajos en segundo plano para Calendarios y Mensajes
## Background Jobs for Calendar & Messaging
Después de configurar las integraciones de Gmail, Google Calendar, o Microsoft 365, necesita iniciar los trabajos en segundo plano que sincronizan los datos.
After configuring Gmail, Google Calendar, or Microsoft 365 integrations, you need to start the background jobs that sync data.
Registre los siguientes trabajos recurrentes en su contenedor de trabajo:
Register the following recurring jobs in your worker container:
```bash
# desde su contenedor de trabajo
# from your worker container
yarn command:prod cron:messaging:messages-import
yarn command:prod cron:messaging:message-list-fetch
yarn command:prod cron:calendar:calendar-event-list-fetch
@@ -249,15 +249,15 @@ yarn command:prod cron:calendar:ongoing-stale
yarn command:prod cron:workflow:automated-cron-trigger
```
## Configuración de Correo Electrónico
## Email Configuration
1. Vaya a **Configuración → Panel de Administración → Variables de Configuración**
2. Encuentre la sección **Correo Electrónico**
3. Configure su configuración SMTP:
1. Go to **Settings → Admin Panel → Configuration Variables**
2. Find the **Email** section
3. Configure your SMTP settings:
<ArticleTabs label1="Gmail" label2="Office365" label3="Smtp4dev">
<ArticleTab>
Necesitará proporcionar una [Contraseña de Aplicación](https://support.google.com/accounts/answer/185833).
You will need to provision an [App Password](https://support.google.com/accounts/answer/185833).
* EMAIL_DRIVER=smtp
* EMAIL_SMTP_HOST=smtp.gmail.com
@@ -267,7 +267,7 @@ yarn command:prod cron:workflow:automated-cron-trigger
</ArticleTab>
<ArticleTab>
Tenga en cuenta que si tiene la autenticación de dos factores habilitada, necesitará proporcionar una [Contraseña de Aplicación](https://support.microsoft.com/en-us/account-billing/manage-app-passwords-for-two-step-verification-d6dc8c6d-4bf7-4851-ad95-6d07799387e9).
Keep in mind that if you have 2FA enabled, you will need to provision an [App Password](https://support.microsoft.com/en-us/account-billing/manage-app-passwords-for-two-step-verification-d6dc8c6d-4bf7-4851-ad95-6d07799387e9).
* EMAIL_DRIVER=smtp
* EMAIL_SMTP_HOST=smtp.office365.com
@@ -277,11 +277,11 @@ yarn command:prod cron:workflow:automated-cron-trigger
</ArticleTab>
<ArticleTab>
**smtp4dev** es un servidor de correo SMTP falso para desarrollo y pruebas.
**smtp4dev** is a fake SMTP email server for development and testing.
* Ejecute la imagen de smtp4dev: `docker run --rm -it -p 8090:80 -p 2525:25 rnwood/smtp4dev`
* Acceda a la interfaz de smtp4dev aquí: [http://localhost:8090](http://localhost:8090)
* Establezca las siguientes variables:
* Run the smtp4dev image: `docker run --rm -it -p 8090:80 -p 2525:25 rnwood/smtp4dev`
* Access the smtp4dev ui here: [http://localhost:8090](http://localhost:8090)
* Set the following variables:
* EMAIL_DRIVER=smtp
* EMAIL_SMTP_HOST=localhost
* EMAIL_SMTP_PORT=2525
@@ -289,5 +289,5 @@ yarn command:prod cron:workflow:automated-cron-trigger
</ArticleTabs>
<Warning>
**Modo solo de entorno:** Si establece `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`, agregue estas variables a su archivo `.env` en su lugar.
**Environment-only mode:** If you set `IS_CONFIG_VARIABLES_IN_DB_ENABLED=false`, add these variables to your `.env` file instead.
</Warning>
@@ -1,33 +1,34 @@
---
title: Solución de problemas
title: Troubleshooting
---
## Solución de Problemas
## Troubleshooting
Si encuentra algún problema al configurar el entorno para el desarrollo, al actualizar su instancia o al autoalojar, aquí hay algunas soluciones para problemas comunes.
If you encounter any problem while setting up environment for development, upgrading your instance or self-hosting,
here are some solutions for common problems.
### Self-hosting
#### La primera instalación resulta en `fallo de autenticación de contraseña para el usuario "postgres"`
#### First install results in `password authentication failed for user "postgres"`
🚨 **IMPORTANTE: Esta solución es SOLO para instalaciones nuevas** 🚨
Si tiene una instancia de Twenty existente con datos de producción, **NO** siga estos pasos ya que borrarán permanentemente su base de datos.
🚨 **IMPORTANT: This solution is ONLY for fresh installations** 🚨
If you have an existing Twenty instance with production data, **DO NOT** follow these steps as they will permanently delete your database!
Al instalar Twenty por primera vez, es posible que desee cambiar la contraseña predeterminada de la base de datos.
La contraseña que establezca durante la primera instalación se almacena permanentemente en el volumen de base de datos. Si más tarde intenta cambiar esta contraseña en su configuración sin eliminar el volumen anterior, obtendrá errores de autenticación porque la base de datos todavía está usando la contraseña original.
While installing Twenty for the first time, you might want to change the default database password.
The password you set during the first installation becomes permanently stored in the database volume. If you later try to change this password in your configuration without removing the old volume, you'll get authentication errors because the database is still using the original password.
⚠️ ADVERTENCIA: ¡Seguir los pasos borrará PERMANENTEMENTE todos los datos de la base de datos! ⚠️
Prosiga solo si se trata de una instalación nueva sin datos importantes.
⚠️ WARNING: Following steps will PERMANENTLY DELETE all database data! ⚠️
Only proceed if this is a fresh installation with no important data.
Para actualizar el `PG_DATABASE_PASSWORD` necesita:
In order to update the `PG_DATABASE_PASSWORD` you need to:
```sh
# Actualizar el PG_DATABASE_PASSWORD en .env
# Update the PG_DATABASE_PASSWORD in .env
docker compose down --volumes
docker compose up -d
```
#### Rupturas de línea de CR encontradas [Windows]
#### CR line breaks found [Windows]
This is due to the line break characters of Windows and the git configuration. Try running:
@@ -35,25 +36,25 @@ This is due to the line break characters of Windows and the git configuration. T
git config --global core.autocrlf false
```
Luego elimine el repositorio y clónelo de nuevo.
Then delete the repository and clone it again.
#### Esquema de metadatos faltante
#### Missing metadata schema
Durante la instalación de Twenty, debe aprovisionar su base de datos postgres con los esquemas, extensiones y usuarios correctos.
Si ha ejecutado con éxito este aprovisionamiento, debería tener esquemas `default` y `metadata` en su base de datos.
Si no los tiene, asegúrese de no tener más de una instancia de postgres ejecutándose en su computadora.
During Twenty installation, you need to provision your postgres database with the right schemas, extensions, and users.
If you're successful in running this provisioning, you should have `default` and `metadata` schemas in your database.
If you don't, make sure you don't have more than one postgres instance running on your computer.
#### No se puede encontrar el módulo 'twenty-emails' o sus declaraciones de tipo correspondientes.
#### Cannot find module 'twenty-emails' or its corresponding type declarations.
Tienes que construir el paquete `twenty-emails` antes de ejecutar la inicialización de la base de datos con `npx nx run twenty-emails:build`
You have to build the package `twenty-emails` before running the initialization of the database with `npx nx run twenty-emails:build`
#### Missing twenty-x package
Asegúrese de ejecutar yarn en el directorio raíz y luego ejecute `npx nx server:dev twenty-server`. Si esto aún no funciona, intente construir el paquete faltante manualmente.
Make sure to run yarn in the root directory and then run `npx nx server:dev twenty-server`. If this still doesn't work try building the missing package manually.
#### Lint on Save no funciona
#### Lint on Save not working
This should work out of the box with the eslint extension installed. Si esto no funciona, intente agregar esto a su configuración de vscode (en el ámbito del contenedor de desarrollo):
This should work out of the box with the eslint extension installed. If this doesn't work try adding this to your vscode setting (on the dev container scope):
```
"editor.codeActionsOnSave": {
@@ -65,83 +66,83 @@ This should work out of the box with the eslint extension installed. Si esto no
#### While running `npx nx start` or `npx nx start twenty-front`, Out of memory error is thrown
En `packages/twenty-front/.env` descomente `VITE_DISABLE_TYPESCRIPT_CHECKER=true` y `VITE_DISABLE_ESLINT_CHECKER=true` para deshabilitar las comprobaciones en segundo plano y así reducir la cantidad de RAM necesaria.
In `packages/twenty-front/.env` uncomment `VITE_DISABLE_TYPESCRIPT_CHECKER=true` to disable background checks thus reducing amount of needed RAM.
**If it does not work:**
Run only the services you need, instead of `npx nx start`. Por ejemplo, si trabaja en el servidor, ejecute solo `npx nx worker twenty-server`
Run only the services you need, instead of `npx nx start`. For instance, if you work on the server, run only `npx nx worker twenty-server`
**If it does not work:**
If you tried to run only `npx nx run twenty-server:start` on WSL and it's failing with the below memory error:
`ERROR FATAL: Las marcas compactas ineficaces cercanas al límite del montón Falló la asignación - JavaScript heap out of memory`
`FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory`
La solución es ejecutar el siguiente comando en el terminal o agregarlo en el perfil .bashrc para configurarlo automáticamente:
Workaround is to execute below command in terminal or add it in .bashrc profile to get setup automatically:
`export NODE_OPTIONS="--max-old-space-size=8192"`
La bandera --max-old-space-size=8192 establece un límite superior de 8GB para el montón de Node.js; su uso escala con la demanda de la aplicación.
Referencia: https://stackoverflow.com/questions/56982005/where-do-i-set-node-options-max-old-space-size-2048
The --max-old-space-size=8192 flag sets an upper limit of 8GB for the Node.js heap; usage scales with application demand.
Reference: https://stackoverflow.com/questions/56982005/where-do-i-set-node-options-max-old-space-size-2048
**If it does not work:**
Investigate which processes are taking you most of your machine RAM. En Twenty, notamos que algunas extensiones de VScode estaban ocupando mucha RAM, por lo que las desactivamos temporalmente.
Investigate which processes are taking you most of your machine RAM. At Twenty, we noticed that some VScode extensions were taking a lot of RAM so we temporarily disable them.
**If it does not work:**
Restart your machine helps to clean up ghost processes.
#### Mientras ejecuta `npx nx start` hay [0] y [1] extraños en los registros
#### While running `npx nx start` there are weird [0] and [1] in logs
Es esperado, ya que el comando `npx nx start` está ejecutando más comandos detrás de escena.
That's expected as command `npx nx start` is running more commands under the hood
#### No se envían correos electrónicos
#### No emails are sent
La mayoría de las veces, se debe a que el `worker` no se está ejecutando en segundo plano. Intente ejecutar
Most of the time, it's because the `worker` is not running in the background. Try to run
```
npx nx worker twenty-server
```
#### No se puede conectar mi cuenta de Microsoft 365
#### Cannot connect my Microsoft 365 account
La mayoría de las veces, se debe a que su administrador no ha habilitado la licencia de Microsoft 365 para su cuenta. Verifique [https://admin.microsoft.com/](https://admin.microsoft.com/Adminportal/Home).
Most of the time, it's because your admin has not enabled the Microsoft 365 Licence for your account. Check [https://admin.microsoft.com/](https://admin.microsoft.com/Adminportal/Home).
Si tiene un código de error `AADSTS50020`, probablemente significa que está usando una cuenta de Microsoft personal. Esto aún no es compatible. Más información [aquí](https://learn.microsoft.com/fr-fr/troubleshoot/entra/entra-id/app-integration/error-code-aadsts50020-user-account-identity-provider-does-not-exist)
If you have an error code `AADSTS50020`, it probably means that you are using a personal Microsoft account. This is not supported yet. More info [here](https://learn.microsoft.com/fr-fr/troubleshoot/entra/entra-id/app-integration/error-code-aadsts50020-user-account-identity-provider-does-not-exist)
#### Mientras ejecuta `yarn` aparecen advertencias en la consola
#### While running `yarn` warnings appear in console
Las advertencias informan sobre la carga de dependencias adicionales que no están explicitadas en `package.json`, así que mientras no aparezca un error crítico, todo debería funcionar como se espera.
Warnings are informing about pulling additional dependencies which aren't explicitly stated in `package.json`, so as long as no breaking error appears, everything should work as expected.
#### Cuando el usuario accede a la página de inicio de sesión, aparece un error sobre un usuario no autorizado que intenta acceder al espacio de trabajo en los registros
#### When user accesses login page, error about unauthorized user trying to access workspace appears in logs
Es esperado ya que el usuario no está autorizado cuando cierra sesión porque su identidad no está verificada.
That's expected as user is unauthorized when logged out since its identity is not verified.
#### ¿Cómo comprobar si su worker está funcionando?
#### How to check if your worker is running?
* Vaya a [webhook-test.com](https://webhook-test.com/) y copie **Su URL de Webhook Única**.
* Go to [webhook-test.com](https://webhook-test.com/) and copy **Your Unique Webhook URL**.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/developers/self-hosting/webhook-test.jpg" alt="Prueba de webhook" />
<img src="/images/docs/developers/self-hosting/webhook-test.jpg" alt="Webhook test" />
</div>
* Abra la aplicación Twenty, navegue a `/settings` y active el interruptor **Avanzado** en la parte inferior izquierda de la pantalla.
* Cree un nuevo webhook.
* Pegue **Su URL de Webhook Única** en el campo **Url de EndPoint** en Twenty. Establezca los **Filtros** en `Companies` y `Created`.
* Open your Twenty app, navigate to `/settings`, and enable the **Advanced** toggle at the bottom left of the screen.
* Create a new webhook.
* Paste **Your Unique Webhook URL** in the **Endpoint Url** field in Twenty. Set the **Filters** to `Companies` and `Created`.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/developers/self-hosting/webhook-settings.jpg" alt="Configuraciones del webhook" />
<img src="/images/docs/developers/self-hosting/webhook-settings.jpg" alt="Webhook settings" />
</div>
* Vaya a `/objects/companies` y cree un nuevo registro de empresa.
* Regrese a [webhook-test.com](https://webhook-test.com/) y verifique si se ha recibido una nueva **solicitud POST**.
* Go to `/objects/companies` and create a new company record.
* Return to [webhook-test.com](https://webhook-test.com/) and check if a new **POST request** has been received.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/developers/self-hosting/webhook-test-result.jpg" alt="Resultado de la prueba del webhook" />
<img src="/images/docs/developers/self-hosting/webhook-test-result.jpg" alt="Webhook test result" />
</div>
* Si se recibe una **solicitud POST**, su worker está funcionando con éxito. De lo contrario, debe solucionar problemas de su worker.
* If a **POST request** is received, your worker is running successfully. Otherwise, you need to troubleshoot your worker.
#### El front-end no comienza y devuelve el error TS5042: La opción 'project' no se puede mezclar con archivos fuente en una línea de comando
#### Front-end fails to start and returns error TS5042: Option 'project' cannot be mixed with source files on a command line
Comente el plugin checker en `packages/twenty-ui/vite-config.ts` como en el ejemplo a continuación
Comment out checker plugin in `packages/twenty-ui/vite-config.ts` like in example below
```
plugins: [
@@ -165,62 +166,62 @@ plugins: [
],
```
#### Panel de administración no accesible
#### Admin panel not accessible
Ejecute `UPDATE core."user" SET "canAccessFullAdminPanel" = TRUE WHERE email = 'you@yourdomain.com';` en el contenedor de la base de datos para obtener acceso al panel de administración.
Run `UPDATE core."user" SET "canAccessFullAdminPanel" = TRUE WHERE email = 'you@yourdomain.com';` in database container to get access to admin panel.
### 1-click Docker compose
#### No se puede iniciar sesión
#### Unable to Log In
Si no puedes iniciar sesión después de la configuración:
If you can't log in after setup:
1. Ejecución de los siguientes comandos:
1. Run the following commands:
```bash
docker exec -it twenty-server-1 yarn
docker exec -it twenty-server-1 npx nx database:reset --configuration=no-seed
```
2. Reinicie los contenedores de Docker:
2. Restart the Docker containers:
```bash
docker compose down
docker compose up -d
```
Tenga en cuenta que el comando database:reset borrará toda su base de datos y la recreará desde cero.
Note the database:reset command will completely erase your database and recreate it from scratch.
#### Problemas de conexión detrás de un Proxy Reverso
#### Connection Issues Behind a Reverse Proxy
Si está ejecutando Twenty detrás de un proxy inverso y experimenta problemas de conexión:
If you're running Twenty behind a reverse proxy and experiencing connection issues:
1. **Verifique SERVER_URL:**
1. **Verify SERVER_URL:**
Asegúrese de que `SERVER_URL` en su archivo `.env` coincida con su URL de acceso externa, incluyendo `https` si SSL está habilitado.
Ensure `SERVER_URL` in your `.env` file matches your external access URL, including `https` if SSL is enabled.
2. **Verifique la configuración del Proxy Reverso:**
2. **Check Reverse Proxy Settings:**
* Confirme que su proxy reverso está reenviando correctamente las solicitudes al servidor de Twenty.
* Asegúrese de que los encabezados como `X-Forwarded-For` y `X-Forwarded-Proto` estén configurados correctamente.
* Confirm that your reverse proxy is correctly forwarding requests to the Twenty server.
* Ensure headers like `X-Forwarded-For` and `X-Forwarded-Proto` are properly set.
3. **Reinicie los Servicios:**
3. **Restart Services:**
Después de hacer cambios, reinicie tanto el proxy inverso como los contenedores de Twenty.
After making changes, restart both the reverse proxy and Twenty containers.
#### Error al cargar una imagen - permiso denegado
#### Error when uploading an image - permission denied
Cambiar la propiedad de la carpeta de datos en el host de raíz a otro usuario y grupo resuelve este problema.
Switching the data folder ownership on the host from root to another user and group resolves this problem.
## Obtención de Ayuda
## Getting Help
Si enfrenta problemas no cubiertos en esta guía:
If you encounter issues not covered in this guide:
* Verifique los Registros:
* Check Logs:
Vea los registros del contenedor por mensajes de error:
View container logs for error messages:
```bash
docker compose logs
```
* Soporte Comunitario:
* Community Support:
Póngase en contacto con la [comunidad de Twenty](https://github.com/twentyhq/twenty/issues) o [los canales de soporte](https://discord.gg/cx5n4Jzs57) para obtener asistencia.
Reach out to the [Twenty community](https://github.com/twentyhq/twenty/issues) or [support channels](https://discord.gg/cx5n4Jzs57) for assistance.
@@ -1,40 +1,40 @@
---
title: Guía de actualización
title: Upgrade guide
---
## Guías generales
## General guidelines
**Always make sure to back up your database before starting the upgrade process** by running `docker exec -it {db_container_name_or_id} pg_dumpall -U {postgres_user} > databases_backup.sql`.
To restore backup, run `cat databases_backup.sql | docker exec -i {db_container_name_or_id} psql -U {postgres_user}`.
Si usó Docker Compose, siga estos pasos:
If you used Docker Compose, follow these steps:
1. En una terminal, en el host donde Twenty está funcionando, apague Twenty: `docker compose down`
1. In a terminal, on the host where Twenty is running, turn off Twenty: `docker compose down`
2. Actualice la versión cambiando el valor de `TAG` en el archivo .env cerca de su docker-compose. ( Recomendamos consumir la versión `major.minor` como `v0.53` )
2. Upgrade the version by changing the `TAG` value in the .env file near your docker-compose. ( We recommend consuming `major.minor` version such as `v0.53` )
3. Vuelva a conectar Twenty con `docker compose up -d`
3. Bring Twenty back online with `docker compose up -d`
Si desea actualizar su instancia por algunas versiones, por ejemplo de v0.33.0 a v0.35.0, debe actualizar su instancia secuencialmente, en este ejemplo de v0.33.0 a v0.34.0, luego de v0.34.0 a v0.35.0.
If you want to upgrade your instance by few versions, e.g. from v0.33.0 to v0.35.0, you have to upgrade your instance sequentially, in this example from v0.33.0 to v0.34.0, then from v0.34.0 to v0.35.0.
**Asegúrese de que después de cada versión actualizada tenga una copia de respaldo no corrupta.**
**Make sure that after each upgraded version you have non-corrupted backup.**
## Pasos de actualización específicos por versión
## Version-specific upgrade steps
## v1.0
¡Hola Twenty v1.0! 🎉
Hello Twenty v1.0! 🎉
## v0.60
### Mejoras de rendimiento
### Performance Enhancements
Todas las interacciones con la API de metadatos han sido optimizadas para un mejor rendimiento, particularmente para la manipulación de metadatos de objetos y operaciones de creación de espacios de trabajo.
All interactions with the metadata API have been optimized for better performance, particularly for object metadata manipulation and workspace creation operations.
Hemos reestructurado nuestra estrategia de almacenamiento en caché para priorizar los aciertos de caché sobre las consultas de base de datos cuando sea posible, mejorando significativamente el rendimiento de las operaciones de la API de metadatos.
We've refactored our caching strategy to prioritize cache hits over database queries when possible, significantly improving the performance of metadata API operations.
Si encuentra problemas de ejecución después de actualizar, es posible que deba vaciar su caché para asegurar que esté sincronizado con los cambios más recientes. Ejecute este comando en su contenedor del servidor de twenty:
If you encounter any runtime issues after upgrading, you may need to flush your cache to ensure it's synchronized with the latest changes. Run this command in your twenty-server container:
```bash
yarn command:prod cache:flush
@@ -42,113 +42,113 @@ yarn command:prod cache:flush
### v0.55
Actualice su instancia de Twenty para usar la imagen v0.55
Upgrade your Twenty instance to use v0.55 image
Ya no necesita ejecutar ningún comando, la nueva imagen se encargará automáticamente de ejecutar todas las migraciones necesarias.
You don't need to run any command anymore, the new image will automatically care about running all required migrations.
### Error: `El usuario no tiene permiso`
### `User does not have permission` error
Si encuentra errores de autorización en la mayoría de solicitudes después de actualizar, es posible que deba vaciar su caché para recalcular los permisos más recientes.
If you encounter authorization errors on most requests after upgrading, you may need to flush your cache to recompute the latest permissions.
En su contenedor `twenty-server`, ejecute:
In your `twenty-server` container, run:
```bash
yarn command:prod cache:flush
```
Este problema es específico de esta versión de Twenty y no debería ser necesario para futuras actualizaciones.
This issue is specific to this Twenty version and should not be required for future upgrades.
### v0.54
Desde la versión `0.53`, no se necesitan acciones manuales.
Since version `0.53`, no manual actions needed.
#### Desaparición del esquema de metadatos
#### Metadata schema deprecation
Hemos fusionado el esquema `metadata` en el esquema `core` para simplificar la recuperación de datos desde `TypeORM`.
Hemos fusionado el paso del comando `migrate` dentro del comando `upgrade`. No recomendamos ejecutar `migrate` manualmente dentro de ninguno de sus contenedores de servidor/trabajador.
We've merged the `metadata` schema into the `core` one to simplify data retrieval from `TypeORM`.
We have merged the `migrate` command step within the `upgrade` command. We do not recommend running `migrate` manually within any of your server/worker containers.
### Desde v0.53
### Since v0.53
A partir de `0.53`, la actualización se realiza de forma programática dentro del `DockerFile`, esto significa que de ahora en adelante, no debería necesitar ejecutar ningún comando manualmente.
Starting from `0.53`, upgrade is programmatically done within the `DockerFile`, this means from now on, you shouldn't have to run any command manually anymore.
Asegúrese de seguir actualizando su instancia secuencialmente, sin omitir ninguna versión principal (por ejemplo, de `0.43.3` a `0.44.0` está permitido, pero de `0.43.1` a `0.45.0` no lo está), de lo contrario, podría provocar un desincronización de la versión del espacio de trabajo que podría resultar en errores de ejecución y funciones faltantes.
Make sure to keep upgrading your instance sequentially, without skipping any major version (e.g. `0.43.3` to `0.44.0` is allowed, but `0.43.1` to `0.45.0` isn't), else could lead to workspace version desynchronization that could result in runtime error and missing functionality.
Para verificar si un espacio de trabajo se ha migrado correctamente, puede revisar su versión en la base de datos en la tabla `core.workspace`.
To check if a workspace has been correctly migrated you can review its version in database in `core.workspace` table.
Siempre debería estar dentro del rango de la versión `major.minor` actual de su instancia de Twenty; puede ver la versión de su instancia en el panel de administración (en `/settings/admin-panel`, accesible si su usuario tiene la propiedad `canAccessFullAdminPanel` establecida en verdadero en la base de datos) o ejecutando `echo $APP_VERSION` en su contenedor `twenty-server`.
It should always be in the range of your current Twenty's instance `major.minor` version, you can view your instance version in the admin panel (at `/settings/admin-panel`, accessible if your user has `canAccessFullAdminPanel` property set to true in the database) or by running `echo $APP_VERSION` in your `twenty-server` container.
Para corregir una versión de espacio de trabajo desincronizada, tendrá que actualizar desde la correspondiente versión de twenty siguiendo la guía de actualización relacionada secuencialmente, y así sucesivamente hasta alcanzar la versión deseada.
To fix a desynchronized workspace version, you will have to upgrade from the corresponding twenty's version following related upgrade guide sequentially and so on until it reaches desired version.
#### Eliminación de `auditLog`
#### `auditLog` removal
Hemos eliminado el objeto estándar auditLog, lo que significa que el tamaño de su copia de seguridad podría reducirse significativamente después de esta migración.
We've removed the auditLog standard object, which means your backup size might be significantly reduced after this migration.
### v0.51 a v0.52
### v0.51 to v0.52
Actualice su instancia de Twenty para usar la imagen v0.52
Upgrade your Twenty instance to use v0.52 image
```
yarn database:migrate:prod
yarn command:prod upgrade
```
#### Tengo un espacio de trabajo bloqueado en la versión entre `0.52.0` y `0.52.6`
#### I have a workspace blocked in version between `0.52.0` and `0.52.6`
Desafortunadamente, `0.52.0` y `0.52.6` se han eliminado completamente de dockerHub.
Tendrá que actualizar manualmente la versión de su espacio de trabajo a `0.51.0` en la base de datos y actualizar usando la versión twenty `0.52.11` siguiendo su guía de actualización justo arriba.
Unfortunately `0.52.0` and `0.52.6` have been completely removed from dockerHub.
You will have to manually update your workspace version to `0.51.0` in database and upgrade using twenty version `0.52.11` following its just above upgrade guide.
### v0.50 a v0.51
### v0.50 to v0.51
Actualice su instancia de Twenty para usar la imagen v0.51
Upgrade your Twenty instance to use v0.51 image
```
yarn database:migrate:prod
yarn command:prod upgrade
```
### v0.44.0 a v0.50.0
### v0.44.0 to v0.50.0
Actualice su instancia de Twenty para usar la imagen v0.50.0
Upgrade your Twenty instance to use v0.50.0 image
```
yarn database:migrate:prod
yarn command:prod upgrade
```
#### Mutación del docker-compose.yml
#### Docker-compose.yml mutation
Esta versión incluye una mutación del `docker-compose.yml` para dar acceso al servicio `worker` al volumen `server-local-data`.
Actualice su `docker-compose.yml` local con el [docker-compose.yml de v0.50.0](https://github.com/twentyhq/twenty/blob/v0.50.0/packages/twenty-docker/docker-compose.yml)
This version includes a `docker-compose.yml` mutation to give `worker` service access to the `server-local-data` volume.
Please update your local `docker-compose.yml` with [v0.50.0 docker-compose.yml](https://github.com/twentyhq/twenty/blob/v0.50.0/packages/twenty-docker/docker-compose.yml)
### v0.43.0 a v0.44.0
### v0.43.0 to v0.44.0
Actualice su instancia de Twenty para usar la imagen v0.44.0
Upgrade your Twenty instance to use v0.44.0 image
```
yarn database:migrate:prod
yarn command:prod upgrade
```
### v0.42.0 a v0.43.0
### v0.42.0 to v0.43.0
Actualice su instancia de Twenty para usar la imagen v0.43.0
Upgrade your Twenty instance to use v0.43.0 image
```
yarn database:migrate:prod
yarn command:prod upgrade
```
En esta versión, también hemos cambiado a la imagen de postgres:16 en docker-compose.yml.
In this version, we have also switched to postgres:16 image in docker-compose.yml.
#### (Opción 1) Migración de base de datos
#### (Option 1) Database migration
Mantener la imagen postgres-spilo existente está bien, pero tendrá que congelar la versión en su docker-compose.yml a 0.43.0.
Keeping the existing postgres-spilo image is fine, but you will have to freeze the version in your docker-compose.yml to be 0.43.0.
#### (Opción 2) Migración de base de datos
#### (Option 2) Database migration
Si desea migrar su base de datos a la nueva imagen de postgres:16, siga estos pasos:
If you want to migrate your database to the new postgres:16 image, please follow these steps:
1. Descargue su base de datos del contenedor antiguo de postgres-spilo
1. Dump your database from the old postgres-spilo container
```
docker exec -it twenty-db-1 sh
@@ -157,11 +157,11 @@ exit
docker cp twenty-db-1:/home/postgres/databases_backup.sql .
```
Asegúrese de que su archivo de respaldo no esté vacío.
Make sure your dump file is not empty.
2. Actualice su docker-compose.yml para usar la imagen de postgres:16 como en el archivo [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml).
2. Upgrade your docker-compose.yml to use postgres:16 image as in the [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml) file.
3. Restaure la base de datos al nuevo contenedor postgres:16
3. Restore the database to the new postgres:16 container
```
docker cp databases_backup.sql twenty-db-1:/databases_backup.sql
@@ -170,86 +170,86 @@ psql -U {YOUR_POSTGRES_USER} -d {YOUR_POSTGRES_DB} -f databases_backup.sql
exit
```
### v0.41.0 a v0.42.0
### v0.41.0 to v0.42.0
Actualice su instancia de Twenty para usar la imagen v0.42.0
Upgrade your Twenty instance to use v0.42.0 image
```
yarn database:migrate:prod
yarn command:prod upgrade-0.42
```
**Variables del entorno**
**Environment Variables**
* Removidos: `FRONT_PORT`, `FRONT_PROTOCOL`, `FRONT_DOMAIN`, `PORT`
* Agregados: `FRONTEND_URL`, `NODE_PORT`, `MAX_NUMBER_OF_WORKSPACES_DELETED_PER_EXECUTION`, `MESSAGING_PROVIDER_MICROSOFT_ENABLED`, `CALENDAR_PROVIDER_MICROSOFT_ENABLED`, `IS_MICROSOFT_SYNC_ENABLED`
* Removed: `FRONT_PORT`, `FRONT_PROTOCOL`, `FRONT_DOMAIN`, `PORT`
* Added: `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 a v0.41.0
### v0.40.0 to v0.41.0
Actualice su instancia de Twenty para usar la imagen v0.41.0
Upgrade your Twenty instance to use v0.41.0 image
```
yarn database:migrate:prod
yarn command:prod upgrade-0.41
```
**Variables del entorno**
**Environment Variables**
* Removido: `AUTH_MICROSOFT_TENANT_ID`
* Removed: `AUTH_MICROSOFT_TENANT_ID`
### v0.35.0 a v0.40.0
### v0.35.0 to v0.40.0
Actualice su instancia de Twenty para usar la imagen v0.40.0
Upgrade your Twenty instance to use v0.40.0 image
```
yarn database:migrate:prod
yarn command:prod upgrade-0.40
```
**Variables del entorno**
**Environment Variables**
* Agregados: `IS_EMAIL_VERIFICATION_REQUIRED`, `EMAIL_VERIFICATION_TOKEN_EXPIRES_IN`, `WORKFLOW_EXEC_THROTTLE_LIMIT`, `WORKFLOW_EXEC_THROTTLE_TTL`
* Added: `IS_EMAIL_VERIFICATION_REQUIRED`, `EMAIL_VERIFICATION_TOKEN_EXPIRES_IN`, `WORKFLOW_EXEC_THROTTLE_LIMIT`, `WORKFLOW_EXEC_THROTTLE_TTL`
### v0.34.0 a v0.35.0
### v0.34.0 to v0.35.0
Actualice su instancia de Twenty para usar la imagen v0.35.0
Upgrade your Twenty instance to use v0.35.0 image
```
yarn database:migrate:prod
yarn command:prod upgrade-0.35
```
El comando `yarn database:migrate:prod` aplicará las migraciones a la estructura de la base de datos (esquemas core y metadata)
El `yarn command:prod upgrade-0.35` se encarga de la migración de datos de todos los espacios de trabajo.
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
The `yarn command:prod upgrade-0.35` takes care of the data migration of all workspaces.
**Variables del entorno**
**Environment Variables**
* Reemplazamos `ENABLE_DB_MIGRATIONS` por `DISABLE_DB_MIGRATIONS` (valor predeterminado ahora es `false`, probablemente no tenga que establecer nada)
* We replaced `ENABLE_DB_MIGRATIONS` with `DISABLE_DB_MIGRATIONS` (default value is now `false`, you probably don't have to set anything)
### v0.33.0 a v0.34.0
### v0.33.0 to v0.34.0
Actualice su instancia de Twenty para usar la imagen v0.34.0
Upgrade your Twenty instance to use v0.34.0 image
```
yarn database:migrate:prod
yarn command:prod upgrade-0.34
```
El comando `yarn database:migrate:prod` aplicará las migraciones a la estructura de la base de datos (esquemas core y metadata)
El `yarn command:prod upgrade-0.34` se encarga de la migración de datos de todos los espacios de trabajo.
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
The `yarn command:prod upgrade-0.34` takes care of the data migration of all workspaces.
**Variables del entorno**
**Environment Variables**
* Removido: `FRONT_BASE_URL`
* Agregados: `FRONT_DOMAIN`, `FRONT_PROTOCOL`, `FRONT_PORT`
* Removed: `FRONT_BASE_URL`
* Added: `FRONT_DOMAIN`, `FRONT_PROTOCOL`, `FRONT_PORT`
Hemos actualizado la forma en que manejamos la URL del frontend.
Ahora puede configurar la URL del frontend usando las variables `FRONT_DOMAIN`, `FRONT_PROTOCOL` y `FRONT_PORT`.
Si FRONT_DOMAIN no está configurado, la URL del frontend volverá a `SERVER_URL`.
We have updated the way we handle the frontend URL.
You can now set the frontend URL using the `FRONT_DOMAIN`, `FRONT_PROTOCOL` and `FRONT_PORT` variables.
If FRONT_DOMAIN is not set, the frontend URL will fall back to `SERVER_URL`.
### v0.32.0 a v0.33.0
### v0.32.0 to v0.33.0
Actualice su instancia de Twenty para usar la imagen v0.33.0
Upgrade your Twenty instance to use v0.33.0 image
```
yarn command:prod cache:flush
@@ -257,68 +257,68 @@ yarn database:migrate:prod
yarn command:prod upgrade-0.33
```
El comando `yarn command:prod cache:flush` eliminará la caché de Redis.
El comando `yarn database:migrate:prod` aplicará las migraciones a la estructura de la base de datos (esquemas core y metadata)
El `yarn command:prod upgrade-0.33` se encarga de la migración de datos de todos los espacios de trabajo.
The `yarn command:prod cache:flush` command will flush the Redis cache.
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
The `yarn command:prod upgrade-0.33` takes care of the data migration of all workspaces.
A partir de esta versión, la imagen twenty-postgres para DB quedó obsoleta y ahora se usa twenty-postgres-spilo.
Si desea seguir usando la imagen twenty-postgres, simplemente reemplace `twentycrm/twenty-postgres:${TAG}` con `twentycrm/twenty-postgres` en docker-compose.yml.
Starting from this version, twenty-postgres image for DB became deprecated and twenty-postgres-spilo is used instead.
If you want to keep using twenty-postgres image, simply replace `twentycrm/twenty-postgres:${TAG}` with `twentycrm/twenty-postgres` in docker-compose.yml.
### v0.31.0 a v0.32.0
### v0.31.0 to v0.32.0
Actualice su instancia de Twenty para usar la imagen v0.32.0
Upgrade your Twenty instance to use v0.32.0 image
**Migración de esquemas y datos**
**Schema and data migration**
```
yarn database:migrate:prod
yarn command:prod upgrade-0.32
```
El comando `yarn database:migrate:prod` aplicará las migraciones a la estructura de la base de datos (esquemas core y metadata)
El `yarn command:prod upgrade-0.32` se encarga de la migración de datos de todos los espacios de trabajo.
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
The `yarn command:prod upgrade-0.32` takes care of the data migration of all workspaces.
**Variables del entorno**
**Environment Variables**
Hemos actualizado la forma en que manejamos la conexión Redis.
We have updated the way we handle the Redis connection.
* Removidos: `REDIS_HOST`, `REDIS_PORT`, `REDIS_USERNAME`, `REDIS_PASSWORD`
* Agregado: `REDIS_URL`
* Removed: `REDIS_HOST`, `REDIS_PORT`, `REDIS_USERNAME`, `REDIS_PASSWORD`
* Added: `REDIS_URL`
Actualice su archivo `.env` para usar la nueva variable `REDIS_URL` en lugar de los parámetros de conexión individuales de Redis.
Update your `.env` file to use the new `REDIS_URL` variable instead of the individual Redis connection parameters.
También hemos simplificado la forma en que manejamos los tokens JWT.
We have also simplified the way we handle the JWT tokens.
* Removidos: `ACCESS_TOKEN_SECRET`, `LOGIN_TOKEN_SECRET`, `REFRESH_TOKEN_SECRET`, `FILE_TOKEN_SECRET`
* Agregado: `APP_SECRET`
* Removed: `ACCESS_TOKEN_SECRET`, `LOGIN_TOKEN_SECRET`, `REFRESH_TOKEN_SECRET`, `FILE_TOKEN_SECRET`
* Added: `APP_SECRET`
Actualice su archivo `.env` para usar la nueva variable `APP_SECRET` en lugar de los secretos de tokens individuales (puede usar el mismo secreto que antes o generar una nueva cadena aleatoria)
Update your `.env` file to use the new `APP_SECRET` variable instead of the individual tokens secrets (you can use the same secret as before or generate a new random string)
**Cuenta conectada**
**Connected Account**
Si está utilizando cuentas conectadas para sincronizar sus correos electrónicos y calendarios de Google, deberá activar la [API de People](https://developers.google.com/people) en su consola de administración de Google.
If you are using connected account to synchronize your Google emails and calendars, you will need to activate the [People API](https://developers.google.com/people) on your Google Admin console.
### v0.30.0 a v0.31.0
### v0.30.0 to v0.31.0
Actualice su instancia de Twenty para usar la imagen v0.31.0
Upgrade your Twenty instance to use v0.31.0 image
**Migración de esquemas y datos:**
**Schema and data migration**:
```
yarn database:migrate:prod
yarn command:prod upgrade-0.31
```
El comando `yarn database:migrate:prod` aplicará las migraciones a la estructura de la base de datos (esquemas core y metadata)
El `yarn command:prod upgrade-0.31` se encarga de la migración de datos de todos los espacios de trabajo.
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
The `yarn command:prod upgrade-0.31` takes care of the data migration of all workspaces.
### v0.24.0 a v0.30.0
### v0.24.0 to v0.30.0
Actualice su instancia de Twenty para usar la imagen v0.30.0
Upgrade your Twenty instance to use v0.30.0 image
**Breaking change**:
To enhance performances, Twenty now requires redis cache to be configured. Hemos actualizado nuestro [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml) para reflejar esto.
Asegúrese de actualizar su configuración y sus variables de entorno en consecuencia:
To enhance performances, Twenty now requires redis cache to be configured. We have updated our [docker-compose.yml](https://raw.githubusercontent.com/twentyhq/twenty/main/packages/twenty-docker/docker-compose.yml) to reflect this.
Make sure to update your configuration and to update your environment variables accordingly:
```
REDIS_HOST={your-redis-host}
@@ -326,49 +326,49 @@ REDIS_PORT={your-redis-port}
CACHE_STORAGE_TYPE=redis
```
**Migración de esquemas y datos:**
**Schema and data migration**:
```
yarn database:migrate:prod
yarn command:prod upgrade-0.30
```
El comando `yarn database:migrate:prod` aplicará las migraciones a la estructura de la base de datos (esquemas core y metadata)
El `yarn command:prod upgrade-0.30` se encarga de la migración de datos de todos los espacios de trabajo.
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
The `yarn command:prod upgrade-0.30` takes care of the data migration of all workspaces.
### v0.23.0 a v0.24.0
### v0.23.0 to v0.24.0
Actualice su instancia de Twenty para usar la imagen v0.24.0
Upgrade your Twenty instance to use v0.24.0 image
Ejecución de los siguientes comandos:
Run the following commands:
```
yarn database:migrate:prod
yarn command:prod upgrade-0.24
```
El comando `yarn database:migrate:prod` aplicará las migraciones a la estructura de la base de datos (esquemas core y metadata)
El `yarn command:prod upgrade-0.24` se encarga de la migración de datos de todos los espacios de trabajo.
The `yarn database:migrate:prod` command will apply the migrations to the database structure (core and metadata schemas)
The `yarn command:prod upgrade-0.24` takes care of the data migration of all workspaces.
### v0.22.0 a v0.23.0
### v0.22.0 to v0.23.0
Actualice su instancia de Twenty para usar la imagen v0.23.0
Upgrade your Twenty instance to use v0.23.0 image
Ejecución de los siguientes comandos:
Run the following commands:
```
yarn database:migrate:prod
yarn command:prod upgrade-0.23
```
El comando `yarn database:migrate:prod` aplicará las migraciones a la base de datos.
El `yarn command:prod upgrade-0.23` se encarga de la migración de datos, incluyendo la transferencia de actividades a tareas/notas.
The `yarn database:migrate:prod` command will apply the migrations to the Database.
The `yarn command:prod upgrade-0.23` takes care of the data migration, including transferring activities to tasks/notes.
### v0.21.0 a v0.22.0
### v0.21.0 to v0.22.0
Actualice su instancia de Twenty para usar la imagen v0.22.0
Upgrade your Twenty instance to use v0.22.0 image
Ejecución de los siguientes comandos:
Run the following commands:
```
yarn database:migrate:prod
@@ -376,6 +376,6 @@ yarn command:prod workspace:sync-metadata -f
yarn command:prod upgrade-0.22
```
El comando `yarn database:migrate:prod` aplicará las migraciones a la base de datos.
El comando `yarn command:prod workspace:sync-metadata -f` sincronizará la definición de objetos estándar a las tablas de metadatos y aplicará las migraciones requeridas a los espacios de trabajo existentes.
El comando `yarn command:prod upgrade-0.22` aplicará transformaciones de datos específicas para adaptarse a las nuevas opciones predeterminadas de instrumentación de solicitud de objetos.
The `yarn database:migrate:prod` command will apply the migrations to the Database.
The `yarn command:prod workspace:sync-metadata -f` command will sync the definition of standard objects to the metadata tables and apply to required migrations to existing workspaces.
The `yarn command:prod upgrade-0.22` command will apply specific data transformations to adapt to the new object defaultRequestInstrumentationOptions.
@@ -4,10 +4,10 @@ description: Deploy and manage Twenty on your own infrastructure.
---
<Frame>
<img src="/images/user-guide/what-is-twenty/20.png" alt="IA" />
<img src="/images/user-guide/what-is-twenty/20.png" alt="AI" />
</Frame>
## Resumen
## Overview
Twenty can be self-hosted on your own infrastructure, giving you full control over your data and deployment.
+14 -14
View File
@@ -15,7 +15,7 @@
}
},
"dataModel": {
"label": "Modelo de datos",
"label": "Data Model",
"groups": {
"dataModelCapabilities": {
"label": "Capabilities"
@@ -48,7 +48,7 @@
}
},
"workflows": {
"label": "Flujos de trabajo",
"label": "Workflows",
"groups": {
"workflowsCapabilities": {
"label": "Capabilities"
@@ -73,7 +73,7 @@
}
},
"ai": {
"label": "IA",
"label": "AI",
"groups": {
"aiCapabilities": {
"label": "Capabilities"
@@ -95,7 +95,7 @@
}
},
"dashboards": {
"label": "Tableros",
"label": "Dashboards",
"groups": {
"dashboardsCapabilities": {
"label": "Capabilities"
@@ -117,7 +117,7 @@
}
},
"billing": {
"label": "Facturación",
"label": "Billing",
"groups": {
"billingCapabilities": {
"label": "Capabilities"
@@ -128,7 +128,7 @@
}
},
"settings": {
"label": "Configuración",
"label": "Settings",
"groups": {
"settingsCapabilities": {
"label": "Capabilities"
@@ -141,10 +141,10 @@
}
},
"developers": {
"label": "Desarrolladores",
"label": "Developers",
"groups": {
"developersGroup": {
"label": "Desarrolladores"
"label": "Developers"
},
"extend": {
"label": "Extend",
@@ -169,29 +169,29 @@
"label": "Capabilities",
"groups": {
"frontendDevelopment": {
"label": "Desarrollo Frontend",
"label": "Frontend Development",
"groups": {
"twentyUi": {
"label": "Twenty UI",
"groups": {
"display": {
"label": "Mostrar"
"label": "Display"
},
"feedback": {
"label": "Retroalimentación"
"label": "Feedback"
},
"input": {
"label": "Entrada"
"label": "Input"
},
"navigation": {
"label": "Navegación"
"label": "Navigation"
}
}
}
}
},
"backendDevelopment": {
"label": "Desarrollo Backend"
"label": "Backend Development"
}
}
}
@@ -1,16 +1,16 @@
---
title: Consejo de la aplicación
title: App Tooltip
image: /images/user-guide/tips/light-bulb.png
---
<Frame>
<img src="/images/user-guide/tips/light-bulb.png" alt="Encabezado" />
<img src="/images/user-guide/tips/light-bulb.png" alt="Header" />
</Frame>
Un breve mensaje que muestra información adicional cuando un usuario interactúa con un elemento.
A brief message that displays additional information when a user interacts with an element.
<Tabs>
<Tab title="Uso">
<Tab title="Usage">
```jsx
import { AppTooltip } from "@/ui/display/tooltip/AppTooltip";
@@ -38,26 +38,26 @@ Un breve mensaje que muestra información adicional cuando un usuario interactú
</Tab>
<Tab title="Props">
| Props | Tipo | Descripción |
| ------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| nombreDeClase | cadena | Clase CSS opcional para estilo adicional |
| anchorSelect | Selector CSS | Selector para el ancla del consejo (el elemento que activa el consejo) |
| contenido | cadena | El contenido que desea mostrar dentro del consejo |
| delayHide | número | The delay in seconds before hiding the tooltip after the cursor leaves the anchor |
| desplazamiento | número | El desplazamiento en píxeles para posicionar el consejo |
| sinFlecha | booleano | Si es `true`, oculta la flecha en el consejo |
| estáAbierto | booleano | Si es `true`, el consejo está abierto por defecto |
| lugar | Cadena `PlacesType` de `react-tooltip` | Especifica la colocación del consejo. Los valores incluyen `inferior`, `izquierda`, `derecha`, `superior`, `superior-inicio`, `superior-fin`, `derecha-inicio`, `derecha-fin`, `inferior-inicio`, `inferior-fin`, `izquierda-inicio` y `izquierda-fin` |
| estrategiaPosicion | Cadena `PositionStrategy` de `react-tooltip` | Estrategia de posición para el consejo. Tiene dos valores: `absoluto` y `fijo` |
| Props | Type | Description |
| ---------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| className | string | Optional CSS class for additional styling |
| anchorSelect | CSS selector | Selector for the tooltip anchor (the element that triggers the tooltip) |
| content | string | The content you want to display within the tooltip |
| delayHide | number | The delay in seconds before hiding the tooltip after the cursor leaves the anchor |
| offset | number | The offset in pixels for positioning the tooltip |
| noArrow | boolean | If `true`, hides the arrow on the tooltip |
| isOpen | boolean | If `true`, the tooltip is open by default |
| place | `PlacesType` string from `react-tooltip` | Specifies the placement of the tooltip. Values include `bottom`, `left`, `right`, `top`, `top-start`, `top-end`, `right-start`, `right-end`, `bottom-start`, `bottom-end`, `left-start`, and `left-end` |
| positionStrategy | `PositionStrategy` string from `react-tooltip` | Position strategy for the tooltip. Has two values: `absolute` and `fixed` |
</Tab>
</Tabs>
## Texto Desbordante con Consejo
## Overflowing Text with Tooltip
Maneja texto desbordante y muestra un consejo cuando el texto se desborda.
Handles overflowing text and displays a tooltip when the text overflows.
<Tabs>
<Tab title="Uso">
<Tab title="Usage">
```jsx
import { OverflowingTextWithTooltip } from 'twenty-ui/display';
@@ -71,8 +71,8 @@ Maneja texto desbordante y muestra un consejo cuando el texto se desborda.
</Tab>
<Tab title="Props">
| Props | Tipo | Descripción |
| ----- | ------ | -------------------------------------------------------------- |
| texto | cadena | El contenido que desea mostrar en el área de texto desbordante |
| Props | Type | Description |
| ----- | ------ | ------------------------------------------------------------ |
| text | string | The content you want to display in the overflowing text area |
</Tab>
</Tabs>
@@ -1,16 +1,16 @@
---
title: Marca de verificación
title: Checkmark
image: /images/user-guide/tasks/tasks_header.png
---
<Frame>
<img src="/images/user-guide/tasks/tasks_header.png" alt="Encabezado" />
<img src="/images/user-guide/tasks/tasks_header.png" alt="Header" />
</Frame>
Representa una acción exitosa o completada.
Represents a successful or completed action.
<Tabs>
<Tab title="Uso">
<Tab title="Usage">
```jsx
import { Checkmark } from 'twenty-ui/display';
@@ -21,16 +21,16 @@ Representa una acción exitosa o completada.
</Tab>
<Tab title="Props">
Extiende `React.ComponentPropsWithoutRef<'div'>` y acepta todas las propiedades de un elemento `div` regular.
Extends `React.ComponentPropsWithoutRef<'div'>` and accepts all the props of a regular `div` element.
</Tab>
</Tabs>
## Marca de verificación animada
## Animated Checkmark
Representa un ícono de marca de verificación con la característica adicional de animación.
Represents a checkmark icon with the added feature of animation.
<Tabs>
<Tab title="Uso">
<Tab title="Usage">
```jsx
import { AnimatedCheckmark } from 'twenty-ui/display';
@@ -48,11 +48,11 @@ Representa un ícono de marca de verificación con la característica adicional
</Tab>
<Tab title="Props">
| Props | Tipo | Descripción | Predeterminado |
| ----------- | -------- | -------------------------------------------------- | -------------- |
| isAnimating | booleano | Controla si la marca de verificación está animando | falso |
| color | cadena | Color de la marca de verificación | |
| duración | número | La duración de la animación en segundos | 0.5 segundos |
| tamaño | número | El tamaño de la marca de verificación | 28 píxeles |
| Props | Type | Description | Default |
| ----------- | ------- | ------------------------------------------- | ----------- |
| isAnimating | boolean | Controls whether the checkmark is animating | false |
| color | string | Color of the checkmark | |
| duration | number | The duration of the animation in seconds | 0.5 seconds |
| size | number | The size of the checkmark | 28 pixels |
</Tab>
</Tabs>
@@ -4,13 +4,13 @@ image: /images/user-guide/github/github-header.png
---
<Frame>
<img src="/images/user-guide/github/github-header.png" alt="Encabezado" />
<img src="/images/user-guide/github/github-header.png" alt="Header" />
</Frame>
A visual element that you can use as a clickable or non-clickable container with a label, optional left and right components, and various styling options to display labels and tags.
<Tabs>
<Tab title="Uso">
<Tab title="Usage">
```jsx
import { Chip } from 'twenty-ui/components';
@@ -34,21 +34,21 @@ A visual element that you can use as a clickable or non-clickable container with
</Tab>
<Tab title="Props">
| Props | Tipo | Descripción |
| ------------ | ------------------------ | ------------------------------------------------------------------------------------------------ |
| linkToEntity | cadena | El enlace a la entidad |
| entityId | cadena | El identificador único de la entidad |
| nombre | cadena | El nombre de la entidad |
| pictureUrl | cadena | s picture", |
| avatarType | Tipo de Avatar | El tipo de avatar que quieres mostrar. Tiene dos opciones: `redondeado` y `cuadrado` |
| variante | `EntityChipVariant` enum | Variante del chip de entidad que quieres mostrar. Tiene dos opciones: `regular` y `transparente` |
| LeftIcon | IconComponent | Un componente de React que representa un ícono. Mostrado en el lado izquierdo del chip |
| Props | Type | Description |
| ------------ | ------------------------ | -------------------------------------------------------------------------------------------- |
| linkToEntity | string | The link to the entity |
| entityId | string | The unique identifier for the entity |
| name | string | The name of the entity |
| pictureUrl | string | s picture", |
| avatarType | Avatar Type | The type of avatar you want to display. Has two options: `rounded` and `squared` |
| variant | `EntityChipVariant` enum | Variant of the entity chip you want to display. Has two options: `regular` and `transparent` |
| LeftIcon | IconComponent | A React component representing an icon. Displayed on the left side of the chip |
</Tab>
</Tabs>
## Ejemplos
## Examples
### Chip Transparente Deshabilitado
### Transparent Disabled Chip
```jsx
import { Chip } from 'twenty-ui/components';
@@ -73,7 +73,7 @@ export const MyComponent = () => {
<br />
### Chip Deshabilitado con Tooltip
### Disabled Chip with Tooltip
```jsx
import { Chip } from "twenty-ui/components";
@@ -95,12 +95,12 @@ export const MyComponent = () => {
};
```
## Chip de Entidad
## Entity Chip
Un elemento tipo Chip para mostrar información sobre una entidad.
A Chip-like element to display information about an entity.
<Tabs>
<Tab title="Uso">
<Tab title="Usage">
```jsx
import { BrowserRouter as Router } from 'react-router-dom';
import { IconTwentyStar } from 'twenty-ui/display';
@@ -125,14 +125,14 @@ Un elemento tipo Chip para mostrar información sobre una entidad.
</Tab>
<Tab title="Props">
| Props | Tipo | Descripción |
| ------------ | ------------------------ | ------------------------------------------------------------------------------------------------ |
| linkToEntity | cadena | El enlace a la entidad |
| entityId | cadena | El identificador único de la entidad |
| nombre | cadena | El nombre de la entidad |
| pictureUrl | cadena | s picture", |
| avatarType | Tipo de Avatar | El tipo de avatar que quieres mostrar. Tiene dos opciones: `redondeado` y `cuadrado` |
| variante | `EntityChipVariant` enum | Variante del chip de entidad que quieres mostrar. Tiene dos opciones: `regular` y `transparente` |
| LeftIcon | IconComponent | Un componente de React que representa un ícono. Mostrado en el lado izquierdo del chip |
| Props | Type | Description |
| ------------ | ------------------------ | -------------------------------------------------------------------------------------------- |
| linkToEntity | string | The link to the entity |
| entityId | string | The unique identifier for the entity |
| name | string | The name of the entity |
| pictureUrl | string | s picture", |
| avatarType | Avatar Type | The type of avatar you want to display. Has two options: `rounded` and `squared` |
| variant | `EntityChipVariant` enum | Variant of the entity chip you want to display. Has two options: `regular` and `transparent` |
| LeftIcon | IconComponent | A React component representing an icon. Displayed on the left side of the chip |
</Tab>
</Tabs>
@@ -1,20 +1,20 @@
---
title: Iconos
title: Icons
image: /images/user-guide/objects/objects.png
---
<Frame>
<img src="/images/user-guide/objects/objects.png" alt="Encabezado" />
<img src="/images/user-guide/objects/objects.png" alt="Header" />
</Frame>
Una lista de iconos utilizados en toda nuestra aplicación.
A list of icons used throughout our app.
## Iconos Tabler
## Tabler Icons
Usamos iconos Tabler para React en toda la aplicación.
We use Tabler icons for React throughout the app.
<Tabs>
<Tab title="Instalación">
<Tab title="Installation">
<br />
```
@@ -22,8 +22,8 @@ Usamos iconos Tabler para React en toda la aplicación.
```
</Tab>
<Tab title="Propiedades">
Puede importar cada icono como un componente. Aquí hay un ejemplo:
<Tab title="Props">
You can import each icon as a component. Here's an example:
<br />
@@ -36,25 +36,25 @@ Usamos iconos Tabler para React en toda la aplicación.
```
</Tab>
<Tab title="Propiedades">
| Propiedades | Tipo | Descripción | Predeterminado |
| ----------- | ------ | ----------------------------------------- | -------------- |
| tamaño | número | La altura y el ancho del icono en píxeles | 24 |
| color | cadena | El color de los iconos | currentColor |
| trazo | número | El ancho del trazo del icono en píxeles | 2 |
<Tab title="Props">
| Props | Type | Description | Default |
| ------ | ------ | ------------------------------------------ | ------------ |
| size | number | The height and width of the icon in pixels | 24 |
| color | string | The color of the icons | currentColor |
| stroke | number | The stroke width of the icon in pixels | 2 |
</Tab>
</Tabs>
## Iconos Personalizados
## Custom Icons
Además de los iconos Tabler, la aplicación también utiliza algunos iconos personalizados.
In addition to Tabler icons, the app also uses some custom icons.
### Icono de Libreta de Direcciones
### Icon Address Book
Muestra un icono de libreta de direcciones.
Displays an address book icon.
<Tabs>
<Tab title="&#x22;Uso&#x22;">
<Tab title="Usage">
```jsx
import { IconAddressBook } from 'twenty-ui/display';
@@ -64,10 +64,10 @@ Muestra un icono de libreta de direcciones.
```
</Tab>
<Tab title="&#x22;Props&#x22;">
| "Props" | Tipo | Descripción | Predeterminado |
| ------- | ------ | ----------------------------------------- | -------------- |
| tamaño | número | La altura y el ancho del icono en píxeles | 24 |
| trazo | número | El ancho del trazo del icono en píxeles | 2 |
<Tab title="Props">
| Props | Type | Description | Default |
| ------ | ------ | ------------------------------------------ | ------- |
| size | number | The height and width of the icon in pixels | 24 |
| stroke | number | The stroke width of the icon in pixels | 2 |
</Tab>
</Tabs>
@@ -4,7 +4,7 @@ image: /images/user-guide/kanban-views/kanban.png
---
<Frame>
<img src="/images/user-guide/kanban-views/kanban.png" alt="Encabezado" />
<img src="/images/user-guide/kanban-views/kanban.png" alt="Header" />
</Frame>
A small badge or "pill" to indicate something is coming soon.
@@ -1,16 +1,16 @@
---
title: Etiqueta
title: Tag
image: /images/user-guide/table-views/table.png
---
<Frame>
<img src="/images/user-guide/table-views/table.png" alt="Encabezado" />
<img src="/images/user-guide/table-views/table.png" alt="Header" />
</Frame>
Componente para categorizar o etiquetar contenido visualmente.
Component to visually categorize or label content.
<Tabs>
<Tab title="Uso">
<Tab title="Usage">
```jsx
import { Tag } from "@/ui/display/tag/components/Tag";
@@ -28,11 +28,11 @@ Componente para categorizar o etiquetar contenido visualmente.
</Tab>
<Tab title="Props">
| Props | Tipo | Descripción |
| ------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| nombreDeClase | cadena | Nombre opcional para estilo adicional |
| color | cadena | Color de la etiqueta. Las opciones incluyen: `verde`, `turquesa`, `cielo`, `azul`, `púrpura`, `rosa`, `rojo`, `naranja`, `amarillo`, `gris` |
| texto | cadena | El contenido de la etiqueta |
| enClic | funcn | Función opcional llamada cuando un usuario hace clic en la etiqueta |
| Props | Type | Description |
| --------- | -------- | --------------------------------------------------------------------------------------------------------------------------- |
| className | string | Optional name for additional styling |
| color | string | Color of the tag. Options include: `green`, `turquoise`, `sky`, `blue`, `purple`, `pink`, `red`, `orange`, `yellow`, `gray` |
| text | string | The content of the tag |
| onClick | function | Optional function called when a user clicks on the tag |
</Tab>
</Tabs>

Some files were not shown because too many files have changed in this diff Show More