Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code 870c4ebf34 fix(server): normalize manifest author field to string in marketplace catalog sync
https://sonarly.com/issue/29282?type=bug

The `FindManyMarketplaceApps` GraphQL query crashes when a community app's CDN-hosted `manifest.json` contains an `author` field as an object (e.g. `{ url: "...", name: "akacores" }`) instead of a plain string, because the manifest is stored in the database without runtime validation.

Fix: The CDN-fetched manifest.json for community npm packages (e.g. akacores) can contain the `author` field as an npm-style object `{ name: "akacores", url: "https://github.com/akacores" }` instead of the expected plain string. The `fetchManifestFromRegistryCdn()` method uses an unsafe `as Manifest` type assertion with no runtime validation, so the object flows through JSONB storage unchanged. When `toMarketplaceAppDTO()` maps this to the GraphQL `MarketplaceAppDTO.author: String!` field, the GraphQL String scalar serializer throws: "String cannot represent value: { url: ..., name: ... }".

      Two-layer fix:
      1. **Read path (defensive)**: Added `resolveAuthorString()` in `MarketplaceQueryService` to safely extract the string name from either format before returning it to the GraphQL layer. This handles already-stored bad data.
      2. **Write path (preventive)**: Added `normalizeAuthorField()` in `MarketplaceCatalogSyncService` to normalize the author field to a plain string at sync time, preventing future bad data from entering the database.

Changed `author: app?.author ?? 'Unknown'` to `author: this.resolveAuthorString(app?.author)` in toMarketplaceAppDTO(). Added private resolveAuthorString() method that safely extracts a string from either plain string or npm-style {name, url} object format, falling back to 'Unknown'.

Added private normalizeAuthorField() method. Modified syncRegistryApps() to normalize the author field before storing the manifest, so object-format authors are converted to plain strings at write time.

Existing integration test (marketplace-catalog-sync.integration-spec.ts) passes — its test manifests have no author field, so the fallback paths are unaffected. Unit tests should be added for resolveAuthorString() and normalizeAuthorField() covering: string input, object {name, url} input, null/undefined input, and object with missing name.

-5: Linter and typecheck could not run (node_modules not installed in worktree or main repo).
      -5: No unit test added for the new helper methods (existing integration test verified unbroken).
      -3: Ideally fetchManifestFromRegistryCdn() should add Zod validation to match fetchAppsFromRegistry(), but that is a broader change outside the bug scope.
      -5: Could not verify against actual akacores CDN manifest payload.
      +82 base: Root cause clearly identified from Sentry payload, code path traced end-to-end, fix follows existing team patterns (same type guard style as used elsewhere), both read and write paths covered, brace balancing verified, file contents verified by re-reading.
2026-04-21 06:14:55 +00:00
3ee1b528a1 Website last fixes (#19895)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 05:43:06 +00:00
Charles BochetandGitHub 6ef15713b1 Release v2.0.0 for twenty-sdk, twenty-client-sdk, and create-twenty-app (#19910)
## Summary
- Bump `twenty-sdk` from `1.23.0` to `2.0.0`
- Bump `twenty-client-sdk` from `1.23.0` to `2.0.0`
- Bump `create-twenty-app` from `1.23.0` to `2.0.0`
2026-04-21 07:40:44 +02:00
dc50dbdb20 i18n - docs translations (#19909)
Created by Github action

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-21 03:01:02 +02:00
Charles BochetandGitHub 0adaf8aa7b docs: use twenty-sdk/define subpath in docs and website demo (#19908)
## Summary

Following the recent move of `defineXXX` exports (e.g.
`defineLogicFunction`, `defineObject`, `defineFrontComponent`, …) from
the `twenty-sdk` root entry to the `twenty-sdk/define` subpath, this PR
aligns the documentation and the marketing site so users see the correct
import paths.

- `packages/twenty-docs/developers/extend/apps/building.mdx`: every code
snippet now imports `defineXXX` and related types/enums (`FieldType`,
`RelationType`, `OnDeleteAction`,
`STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS`, `PermissionFlag`, `ViewKey`,
`NavigationMenuItemType`, `PageLayoutTabLayoutMode`,
`getPublicAssetUrl`, `DatabaseEventPayload`, `RoutePayload`,
`InstallPayload`, …) from `twenty-sdk/define`. Mixed imports were split
so that hooks and host-API helpers (`useRecordId`, `useUserId`,
`useFrontComponentId`, `enqueueSnackbar`, `closeSidePanel`, `pageType`,
`numberOfSelectedRecords`, `objectPermissions`, `everyEquals`,
`isDefined`) come from `twenty-sdk/front-component`.
-
`packages/twenty-website-new/.../DraggableTerminal/TerminalEditor/editorData.ts`:
the 29 demo source strings shown in the homepage's draggable terminal
now import from `twenty-sdk/define`.

Example apps under `packages/twenty-apps/{examples,internal,fixtures}`
were already using the right subpaths, so no code changes were needed
there.

Translations under `packages/twenty-docs/l/` are intentionally left
untouched — they will be refreshed via Crowdin from the English source.

## Test plan

- [ ] Skim the rendered `building.mdx` on Mintlify preview to confirm
code snippets look right.
- [ ] Visual check on the website's draggable terminal demo.


Made with [Cursor](https://cursor.com)
2026-04-21 02:08:02 +02:00
Charles BochetandGitHub 41ee6eac7a chore(server): bump current version to 2.0.0 and add 2.1.0 as next (#19907)
## Summary

We are releasing Twenty v2.0. This PR sets up the
upgrade-version-command machinery for the new release line:

- Move `1.23.0` into `TWENTY_PREVIOUS_VERSIONS` (it just shipped)
- Set `TWENTY_CURRENT_VERSION` to `2.0.0` (no specific upgrade commands
— this is just the major version cut)
- Set `TWENTY_NEXT_VERSIONS` to `['2.1.0']` so future PRs that
previously would have targeted `1.24.0` now target `2.1.0`
- Add empty `V2_0_UpgradeVersionCommandModule` and
`V2_1_UpgradeVersionCommandModule` and wire them into
`WorkspaceCommandProviderModule`
- Refresh the `InstanceCommandGenerationService` snapshots to reflect
the new current version (`2.0.0` / `2-0-` slug)

The `2-0/` directory is intentionally empty — there are no specific
upgrade commands for the v2.0 cut. New upgrade commands authored after
this merges should land in `2-1/` (or be generated against `--version
2.1.0`).

## Test plan

- [x] `npx jest` on the impacted upgrade test files
(`upgrade-sequence-reader`, `upgrade-command-registry`,
`instance-command-generation`) passes (41 tests, 8 snapshots)
- [x] `prettier --check` and `oxlint` clean on touched files
- [ ] Manual: open `nx run twenty-server:command -- upgrade --dry-run`
against a local stack with workspaces still on `1.23.0` and confirm the
sequence is computed without errors

Made with [Cursor](https://cursor.com)
2026-04-21 02:05:27 +02:00
Charles BochetandGitHub b4f996e0c4 Release v1.23.0 for twenty-sdk, twenty-client-sdk, and create-twenty-app (#19906)
## Summary
- Bump `twenty-sdk` from `1.23.0-canary.9` to `1.23.0`
- Bump `twenty-client-sdk` from `1.23.0-canary.9` to `1.23.0`
- Bump `create-twenty-app` from `1.23.0-canary.9` to `1.23.0`

Made with [Cursor](https://cursor.com)
2026-04-21 01:34:10 +02:00
5c58254eb4 Fix activity relation picker (#19898)
## Context
ActivityTargetsInlineCell passed editModeContent via
RecordInlineCellContext, but that context key was no longer read.
Fix aligns the code with the rest of the codebase.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-04-21 01:30:23 +02:00
Charles BochetandGitHub 192a842f57 fix(website-new): pre-resolve wyw-in-js babel presets to absolute paths (#19905)
## Problem

Building `twenty-website-new` in any environment that does **not** also
include `twenty-website` (e.g. the Docker image used by the deployment
workflow) fails with:

```
Error: Turbopack build failed with 99 errors:
Error evaluating Node.js code
Error: Cannot find module 'next/babel'
Require stack:
- /app/node_modules/@babel/core/lib/config/files/plugins.js
- ...
- /app/node_modules/babel-merge/src/index.js
- /app/packages/twenty-website-new/node_modules/@wyw-in-js/transform/lib/plugins/babel-transform.js
- /app/packages/twenty-website-new/node_modules/next-with-linaria/lib/loaders/turbopack-transform-loader.js
```

## Root cause

`packages/twenty-website-new/wyw-in-js.config.cjs` references presets by
bare name:

```js
presets: ['next/babel', '@wyw-in-js'],
```

These options flow through
[`babel-merge`](https://github.com/cellog/babel-merge/blob/master/src/index.js#L11),
which calls `@babel/core`'s `resolvePreset(name)` **without** a
`dirname` argument. With no `dirname`, `@babel/core` falls back to
`require.resolve(id)` from its own file location — so resolution starts
at `node_modules/@babel/core/...` and only walks parent `node_modules`
directories from there, never down into individual workspace packages.

In a normal local install both presets happen to be hoisted to the
workspace root (because `twenty-website` pins `next@^14` and wins the
hoist), so resolution succeeds by accident. In the single-workspace
Docker build only `twenty-website-new` is present, so `next` (16.1.7)
and `@wyw-in-js/babel-preset` are nested in
`packages/twenty-website-new/node_modules` and Babel cannot reach them —
hence the failure.

## Fix

Pre-resolve both presets with `require.resolve(...)` in the wyw-in-js
config so Babel receives absolute paths and resolution becomes
independent of hoisting layout.

## Verification

- `yarn nx build twenty-website-new` — passes locally with the full
workspace
- Reproduced the original failure with a simulated single-workspace
install (only `twenty-website-new` and `twenty-oxlint-rules` present),
confirmed it fails on `main` and passes with this patch
- This unblocks the `twenty-infra` `Deploy Website New` workflow
([related infra PR](https://github.com/twentyhq/twenty-infra/pull/586))


Made with [Cursor](https://cursor.com)
2026-04-21 01:03:26 +02:00
Charles BochetandGitHub 1b469168c8 chore(workflow): temporarily lift credit-cap gate on workflow steps (#19904)
## Summary

- Removes the per-step `canBillMeteredProduct(WORKFLOW_NODE_EXECUTION)`
gate in `WorkflowExecutorWorkspaceService.executeStep` so workflows keep
running when a workspace reaches `hasReachedCurrentPeriodCap`.
Previously every step failed with
`BILLING_WORKFLOW_EXECUTION_ERROR_MESSAGE` (\"No remaining credits to
execute workflow…\").
- Drops the now-unused `BillingService` injection, related imports, and
the helper `canBillWorkflowNodeExecution`. Updates the spec to drop the
corresponding billing-validation case and mock.
- Leaves the constant file and `BillingService` itself in place, plus a
TODO at the previous gate site, so the behavior can be re-enabled with a
small, reviewable revert.

## Notes

- Usage events are still emitted (`USAGE_RECORDED` /
`UsageResourceType.WORKFLOW`), and `EnforceUsageCapJob` keeps computing
the cap and flipping `hasReachedCurrentPeriodCap` — only the executor
stops consulting that flag.
- The runner-level `canFeatureBeUsed` check in
`WorkflowRunnerWorkspaceService.run` was already log-only (subscription
presence, not credits), so no change there.
- AI chat (`agent-chat.resolver.ts`) keeps its own
`BILLING_CREDITS_EXHAUSTED` gate; this PR does not touch it.

## Test plan

- [x] `npx jest workflow-executor.workspace-service.spec.ts` (17/17
pass)
- [ ] Manual: with billing enabled and the metered subscription item
flagged `hasReachedCurrentPeriodCap = true`, trigger a workflow run and
verify steps execute end-to-end instead of failing with the billing
error.

Made with [Cursor](https://cursor.com)
2026-04-21 01:00:28 +02:00
57de05ea74 i18n - translations (#19903)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-21 00:50:40 +02:00
Charles BochetandGitHub a174aff5c8 fix(infra): copy nx.json and tsconfig.base.json into website-new image (#19902)
## Summary

Fix the website-new Docker build which currently fails with:

\`\`\`
NX   \"production\" is an invalid fileset.
All filesets have to start with either {workspaceRoot} or {projectRoot}.
\`\`\`

\`packages/twenty-website-new/project.json\` declares \`\"inputs\":
[\"production\", \"^production\"]\` — a named input defined in the root
\`nx.json\`. Without copying \`nx.json\` into the image, nx can't
resolve it and the build fails.

Mirrors what the main twenty Dockerfile already does (line 9 of
\`packages/twenty-docker/twenty/Dockerfile\` copies both
\`tsconfig.base.json\` and \`nx.json\`).

## Test plan

- [ ] Re-run twenty-infra's \`Deploy Website New\` workflow (dev) —
build step should now pass

Made with [Cursor](https://cursor.com)
2026-04-21 00:45:17 +02:00
Charles BochetandGitHub 96fc98e710 Fix Apps UI: replace 'Managed' label with actual app name and unify app icons (#19897)
## Summary

- The Data Model table was labeling core Twenty objects (e.g. Person,
Company) as **Managed** even though they are part of the standard
application. This PR teaches the frontend to resolve an `applicationId`
back to its real application name (`Standard`, `Custom`, or any
installed app), and removes the misleading **Managed** label entirely.
- Introduces a single, consistent way to render an "app badge" across
the settings UI:
- new `Avatar` variant `type="app"` (rounded 4px corners + 1px
deterministic border derived from `placeholderColorSeed`)
- new `AppChip` component (icon + name) backed by a new
`useApplicationChipData` hook
- new `useApplicationsByIdMap` hook + `CurrentApplicationContext` so the
chip can render **This app** when shown inside the matching app's detail
page
- Reuses these primitives on:
- the application detail page header (`SettingsApplicationDetailTitle`)
  - the Installed / My apps tables (`SettingsApplicationTableRow`)
  - the NPM packages list (`SettingsApplicationsDeveloperTab`)
- Backend: exposes a minimal `installedApplications { id name
universalIdentifier }` field on `Workspace` (resolved from the workspace
cache, soft-deleted entries filtered out) so the frontend can resolve
`applicationId` -> name without N+1 fetches.
- Cleanup: deletes `getItemTagInfo` and inlines its tiny
responsibilities into the components that need them, matching the
`RecordChip` pattern.
2026-04-21 00:44:14 +02:00
Charles BochetandGitHub 9a963ddeca feat(infra): add Dockerfile for twenty-website-new (#19901)
## Summary

Adds the Docker build for the new marketing website at
`packages/twenty-website-new`, mirroring the existing
`packages/twenty-docker/twenty-website/Dockerfile`.

Differences from the existing `twenty-website` Dockerfile:

- Uses `nx build twenty-website-new` / `nx start twenty-website-new`
- Drops the `KEYSTATIC_*` build-time fake env (the new website doesn't
use Keystatic)
- Doesn't copy `twenty-ui` source (the new website has no workspace
dependency on it)

The image will be built by the new `deploy-website-new.yaml` workflow in
[`twentyhq/twenty-infra`](https://github.com/twentyhq/twenty-infra) and
pushed to ECR repos `dev-website-new` / `staging-website-new`.

Companion PRs:
- twentyhq/twenty-infra: Helm chart + ArgoCD app + deploy workflow
- twentyhq/twenty-infra-releases: bootstrap tags.yaml

## Test plan

- [ ] Local build: \`docker build -f
packages/twenty-docker/twenty-website-new/Dockerfile .\`
- [ ] First run of \`Deploy Website New\` workflow on dev succeeds
(build + push to ECR)
- [ ] ArgoCD \`website-new\` application becomes Healthy on dev
- [ ] https://website-new.twenty-main.com serves the new website

Made with [Cursor](https://cursor.com)
2026-04-21 00:27:11 +02:00
13afef5d1d fix(server): scope loadingMessage wrap/strip to AI-chat callers (#19896)
## Summary

MCP tool execution crashed with \`Cannot destructure property
'loadingMessage' of 'parameters' as it is undefined\` whenever
\`execute_tool\` was called without an inner \`arguments\` field. Root
cause: \`loadingMessage\` is an AI-chat UX affordance (lets the LLM
narrate progress so the chat UI can show "Sending email…") but it was
being wrapped into **every** tool schema — including those advertised to
external MCP clients — and \`dispatch\` unconditionally stripped it,
crashing on \`undefined\` args.

The fix scopes the wrap/strip pair to AI-chat callers only:

- Pair wrap and strip inside \`hydrateToolSet\` (they belong together).
- New \`includeLoadingMessage\` option on \`hydrateToolSet\` /
\`getToolsByName\` / \`getToolsByCategories\` (default \`true\` so
AI-chat behavior is unchanged).
- MCP opts out → external clients see clean inputSchemas without a
required \`loadingMessage\` field.
- \`dispatch\` no longer strips; args default to \`{}\` defensively.
- \`execute_tool\` defaults \`arguments\` to \`{}\` at the LLM boundary.

## Test plan

- [x] \`npx nx typecheck twenty-server\` passes
- [x] \`npx oxlint\` clean on changed files
- [x] \`npx jest mcp-protocol mcp-tool-executor\` — 23/23 tests pass
- [ ] Manually: call \`execute_tool\` via MCP with and without inner
\`arguments\` — verify no crash, endpoints execute
- [ ] Manually: inspect MCP \`tools/list\` response — verify
\`search_help_center\` schema no longer contains \`loadingMessage\`
- [ ] Regression: AI chat still streams loading messages as the LLM
calls tools

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 21:43:16 +02:00
Abdullah.andGitHub 83bc6d1a1b [Website] Self-host billing migration and some responsiveness fixes. (#19894)
Closes the following issues.

https://github.com/twentyhq/core-team-issues/issues/2371
https://github.com/twentyhq/core-team-issues/issues/2379
https://github.com/twentyhq/core-team-issues/issues/2383
2026-04-20 21:23:54 +02:00
755f1c92d1 i18n - translations (#19893)
Created by Github action

---------

Co-authored-by: github-actions <github-actions@twenty.com>
2026-04-20 19:45:24 +02:00
WeikoandGitHub 6d3ff4c9ce Translate standard page layouts (#19890)
## Context
Standard page layout tabs, page layout widgets, and view field group
titles were hardcoded English in the backend. This PR brings them under
the same translation pipeline as views.

Notes: Once a standard widget/tab/section title is overriden, the
backend returns its value without translation
2026-04-20 17:29:33 +00:00
305 changed files with 6917 additions and 2253 deletions
+121 -82
View File
@@ -1,126 +1,170 @@
<p align="center">
<a href="https://www.producthunt.com/products/twenty-crm?launch=twenty-2-0">
<img src="./packages/twenty-website/public/images/readme/product-hunt-banner.png" alt="We're live on Product Hunt — Support us" />
</a>
</p>
<p align="center">
<a href="https://www.twenty.com">
<img src="./packages/twenty-website/public/images/core/logo.svg" width="100px" alt="Twenty logo" />
</a>
</p>
<h2 align="center" >The #1 Open-Source CRM </h2>
<p align="center"><a href="https://twenty.com">🌐 Website</a> · <a href="https://docs.twenty.com">📚 Documentation</a> · <a href="https://github.com/orgs/twentyhq/projects/1"><img src="./packages/twenty-website/public/images/readme/planner-icon.svg" width="12" height="12"/> Roadmap </a> · <a href="https://discord.gg/cx5n4Jzs57"><img src="./packages/twenty-website/public/images/readme/discord-icon.svg" width="12" height="12"/> Discord</a> · <a href="https://www.figma.com/file/xt8O9mFeLl46C5InWwoMrN/Twenty"><img src="./packages/twenty-website/public/images/readme/figma-icon.png" width="12" height="12"/> Figma</a></p>
<br />
<h2 align="center" >The #1 Open-Source CRM</h2>
<p align="center"><a href="https://twenty.com"><img src="./packages/twenty-website/public/images/readme/globe-icon.svg" width="12" height="12"/> Website</a> · <a href="https://docs.twenty.com"><img src="./packages/twenty-website/public/images/readme/book-icon.svg" width="12" height="12"/> Documentation</a> · <a href="https://github.com/orgs/twentyhq/projects/1"><img src="./packages/twenty-website/public/images/readme/map-icon.svg" width="12" height="12"/> Roadmap </a> · <a href="https://discord.gg/cx5n4Jzs57"><img src="./packages/twenty-website/public/images/readme/discord-icon.svg" width="12" height="12"/> Discord</a> · <a href="https://www.figma.com/file/xt8O9mFeLl46C5InWwoMrN/Twenty"><img src="./packages/twenty-website/public/images/readme/figma-icon.png" width="12" height="12"/> Figma</a></p>
<p align="center">
<a href="https://www.twenty.com">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/github-cover-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/github-cover-light.png" />
<img src="./packages/twenty-website/public/images/readme/github-cover-light.png" alt="Cover" />
<source media="(prefers-color-scheme: dark)" srcset="./packages/twenty-website/public/images/readme/github-cover-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="./packages/twenty-website/public/images/readme/github-cover-light.png" />
<img src="./packages/twenty-website/public/images/readme/github-cover-light.png" alt="Twenty banner" />
</picture>
</a>
</p>
<br />
# Installation
See:
🚀 [Self-hosting](https://docs.twenty.com/developers/self-host/capabilities/docker-compose)
🖥️ [Local Setup](https://docs.twenty.com/developers/contribute/capabilities/local-setup)
# Why Twenty
We built Twenty for three reasons:
Twenty gives technical teams the building blocks for a custom CRM that meets complex business needs and quickly adapts as the business evolves. Twenty is the CRM you build, ship, and version like the rest of your stack.
**CRMs are too expensive, and users are trapped.** Companies use locked-in customer data to hike prices. It shouldn't be that way.
**A fresh start is required to build a better experience.** We can learn from past mistakes and craft a cohesive experience inspired by new UX patterns from tools like Notion, Airtable or Linear.
**We believe in open-source and community.** Hundreds of developers are already building Twenty together. Once we have plugin capabilities, a whole ecosystem will grow around it.
<a href="https://twenty.com/why-twenty"><img src="./packages/twenty-website/public/images/readme/star-icon.svg" width="14" height="14"/> Learn more about why we built Twenty</a>
<br />
# What You Can Do With Twenty
# Installation
Please feel free to flag any specific needs you have by creating an issue.
### <img src="./packages/twenty-website/public/images/readme/globe-icon.svg" width="14" height="14"/> Cloud
Below are a few features we have implemented to date:
The fastest way to get started. Sign up at [twenty.com](https://twenty.com) and spin up a workspace in under a minute, with no infrastructure to manage and always up to date.
+ [Personalize layouts with filters, sort, group by, kanban and table views](#personalize-layouts-with-filters-sort-group-by-kanban-and-table-views)
+ [Customize your objects and fields](#customize-your-objects-and-fields)
+ [Create and manage permissions with custom roles](#create-and-manage-permissions-with-custom-roles)
+ [Automate workflow with triggers and actions](#automate-workflow-with-triggers-and-actions)
+ [Emails, calendar events, files, and more](#emails-calendar-events-files-and-more)
### <img src="./packages/twenty-website/public/images/readme/book-icon.svg" width="14" height="14"/> Build an app
Scaffold a new app with the Twenty CLI:
## Personalize layouts with filters, sort, group by, kanban and table views
```bash
npx create-twenty-app my-app
```
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/views-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/views-light.png" />
<img src="./packages/twenty-website/public/images/readme/views-light.png" alt="Companies Kanban Views" />
</picture>
</p>
Define objects, fields, and views as code:
## Customize your objects and fields
```ts
import { defineObject, FieldType } from 'twenty-sdk/define';
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/data-model-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/data-model-light.png" />
<img src="./packages/twenty-website/public/images/readme/data-model-light.png" alt="Setting Custom Objects" />
</picture>
</p>
export default defineObject({
nameSingular: 'deal',
namePlural: 'deals',
labelSingular: 'Deal',
labelPlural: 'Deals',
fields: [
{ name: 'name', label: 'Name', type: FieldType.TEXT },
{ name: 'amount', label: 'Amount', type: FieldType.CURRENCY },
{ name: 'closeDate', label: 'Close Date', type: FieldType.DATE_TIME },
],
});
```
## Create and manage permissions with custom roles
Then ship it to your workspace:
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/permissions-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/permissions-light.png" />
<img src="./packages/twenty-website/public/images/readme/permissions-light.png" alt="Permissions" />
</picture>
</p>
```bash
npx twenty deploy
```
## Automate workflow with triggers and actions
See the [app development guide](https://docs.twenty.com/developers/extend/apps/getting-started) for objects, views, agents, and logic functions.
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/workflows-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/workflows-light.png" />
<img src="./packages/twenty-website/public/images/readme/workflows-light.png" alt="Workflows" />
</picture>
</p>
### <img src="./packages/twenty-website/public/images/readme/rocket-icon.svg" width="14" height="14"/> Self-hosting
## Emails, calendar events, files, and more
Run Twenty on your own infrastructure with [Docker Compose](https://docs.twenty.com/developers/self-host/capabilities/docker-compose), or contribute locally via the [local setup guide](https://docs.twenty.com/developers/contribute/capabilities/local-setup).
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/plus-other-features-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/twentyhq/twenty/refs/heads/main/packages/twenty-website/public/images/readme/plus-other-features-light.png" />
<img src="./packages/twenty-website/public/images/readme/plus-other-features-light.png" alt="Other Features" />
</picture>
</p>
<br />
<br />
# Everything you need
Twenty gives you the building blocks of a modern CRM (objects, views, workflows, and agents) and lets you extend them as code. Here's a tour of what's in the box.
Want to go deeper? Read the <a href="https://docs.twenty.com/user-guide/introduction"><img src="./packages/twenty-website/public/images/readme/planner-icon.svg" width="14" height="14"/> User Guide</a> for product walkthroughs, or the <a href="https://docs.twenty.com"><img src="./packages/twenty-website/public/images/readme/book-icon.svg" width="14" height="14"/> Documentation</a> for developer reference.
<table align="center">
<tr>
<td width="50%">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./packages/twenty-website/public/images/readme/v2-build-apps-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="./packages/twenty-website/public/images/readme/v2-build-apps-light.png" />
<img src="./packages/twenty-website/public/images/readme/v2-build-apps-light.png" alt="Create your apps" />
</picture>
<p align="center"><a href="https://docs.twenty.com/developers/extend/apps/getting-started"><img src="./packages/twenty-website/public/images/readme/code-icon.svg" width="16" height="16"/> Learn more about apps in doc</a></p>
</td>
<td width="50%">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./packages/twenty-website/public/images/readme/v2-version-control-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="./packages/twenty-website/public/images/readme/v2-version-control-light.png" />
<img src="./packages/twenty-website/public/images/readme/v2-version-control-light.png" alt="Stay on top with version control" />
</picture>
<p align="center"><a href="https://docs.twenty.com/developers/extend/apps/publishing"><img src="./packages/twenty-website/public/images/readme/monitor-icon.svg" width="16" height="16"/> Learn more about version control in doc</a></p>
</td>
</tr>
<tr>
<td width="50%">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./packages/twenty-website/public/images/readme/v2-all-tools-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="./packages/twenty-website/public/images/readme/v2-all-tools-light.png" />
<img src="./packages/twenty-website/public/images/readme/v2-all-tools-light.png" alt="All the tools you need to build anything" />
</picture>
<p align="center"><a href="https://docs.twenty.com/developers/extend/apps/building"><img src="./packages/twenty-website/public/images/readme/rocket-icon.svg" width="16" height="16"/> Learn more about primitives in doc</a></p>
</td>
<td width="50%">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./packages/twenty-website/public/images/readme/v2-tools-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="./packages/twenty-website/public/images/readme/v2-tools-light.png" />
<img src="./packages/twenty-website/public/images/readme/v2-tools-light.png" alt="Customize your layouts" />
</picture>
<p align="center"><a href="https://docs.twenty.com/user-guide/views-pipelines/overview"><img src="./packages/twenty-website/public/images/readme/planner-icon.svg" width="16" height="16"/> Learn more about layouts in doc</a></p>
</td>
</tr>
<tr>
<td width="50%">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./packages/twenty-website/public/images/readme/v2-ai-agents-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="./packages/twenty-website/public/images/readme/v2-ai-agents-light.png" />
<img src="./packages/twenty-website/public/images/readme/v2-ai-agents-light.png" alt="AI agents and chats" />
</picture>
<p align="center"><a href="https://docs.twenty.com/user-guide/ai/overview"><img src="./packages/twenty-website/public/images/readme/message-icon.svg" width="16" height="16"/> Learn more about AI in doc</a></p>
</td>
<td width="50%">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./packages/twenty-website/public/images/readme/v2-crm-tools-dark.png" />
<source media="(prefers-color-scheme: light)" srcset="./packages/twenty-website/public/images/readme/v2-crm-tools-light.png" />
<img src="./packages/twenty-website/public/images/readme/v2-crm-tools-light.png" alt="Plus all the tools of a good CRM" />
</picture>
<p align="center"><a href="https://docs.twenty.com/user-guide/introduction"><img src="./packages/twenty-website/public/images/readme/star-icon.svg" width="16" height="16"/> Learn more about CRM features in doc</a></p>
</td>
</tr>
</table>
<br />
# Stack
- [TypeScript](https://www.typescriptlang.org/)
- [Nx](https://nx.dev/)
- [NestJS](https://nestjs.com/), with [BullMQ](https://bullmq.io/), [PostgreSQL](https://www.postgresql.org/), [Redis](https://redis.io/)
- [React](https://reactjs.org/), with [Jotai](https://jotai.org/), [Linaria](https://linaria.dev/) and [Lingui](https://lingui.dev/)
- <a href="https://www.typescriptlang.org/"><img src="./packages/twenty-website/public/images/readme/stack-typescript.svg" width="14" height="14"/> TypeScript</a>
- <a href="https://nx.dev/"><img src="./packages/twenty-website/public/images/readme/stack-nx.svg" width="14" height="14"/> Nx</a>
- <a href="https://nestjs.com/"><img src="./packages/twenty-website/public/images/readme/stack-nestjs.svg" width="14" height="14"/> NestJS</a>, with <a href="https://bullmq.io/">BullMQ</a>, <a href="https://www.postgresql.org/"><img src="./packages/twenty-website/public/images/readme/stack-postgresql.svg" width="14" height="14"/> PostgreSQL</a>, <a href="https://redis.io/"><img src="./packages/twenty-website/public/images/readme/stack-redis.svg" width="14" height="14"/> Redis</a>
- <a href="https://reactjs.org/"><img src="./packages/twenty-website/public/images/readme/stack-react.svg" width="14" height="14"/> React</a>, with <a href="https://jotai.org/">Jotai</a>, <a href="https://linaria.dev/">Linaria</a> and <a href="https://lingui.dev/">Lingui</a>
# Thanks
<p align="center">
<a href="https://www.chromatic.com/"><img src="./packages/twenty-website/public/images/readme/chromatic.png" height="30" alt="Chromatic" /></a>
<a href="https://greptile.com"><img src="./packages/twenty-website/public/images/readme/greptile.png" height="30" alt="Greptile" /></a>
<a href="https://sentry.io/"><img src="./packages/twenty-website/public/images/readme/sentry.png" height="30" alt="Sentry" /></a>
<a href="https://crowdin.com/"><img src="./packages/twenty-website/public/images/readme/crowdin.png" height="30" alt="Crowdin" /></a>
<a href="https://e2b.dev/"><img src="./packages/twenty-website/public/images/readme/e2b.svg" height="30" alt="E2B" /></a>
<a href="https://www.chromatic.com/"><img src="./packages/twenty-website/public/images/readme/chromatic.png" height="28" alt="Chromatic" /></a>
&nbsp;&nbsp;&nbsp;&nbsp;
<a href="https://greptile.com"><img src="./packages/twenty-website/public/images/readme/greptile.png" height="28" alt="Greptile" /></a>
&nbsp;&nbsp;&nbsp;&nbsp;
<a href="https://sentry.io/"><img src="./packages/twenty-website/public/images/readme/sentry.png" height="28" alt="Sentry" /></a>
&nbsp;&nbsp;&nbsp;&nbsp;
<a href="https://crowdin.com/"><img src="./packages/twenty-website/public/images/readme/crowdin.png" height="28" alt="Crowdin" /></a>
</p>
Thanks to these amazing services that we use and recommend for UI testing (Chromatic), code review (Greptile), catching bugs (Sentry) and translating (Crowdin).
@@ -128,9 +172,4 @@ Below are a few features we have implemented to date:
# Join the Community
- Star the repo
- Subscribe to releases (watch -> custom -> releases)
- Follow us on [Twitter](https://twitter.com/twentycrm) or [LinkedIn](https://www.linkedin.com/company/twenty/)
- Join our [Discord](https://discord.gg/cx5n4Jzs57)
- Improve translations on [Crowdin](https://twenty.crowdin.com/twenty)
- [Contributions](https://github.com/twentyhq/twenty/contribute) are, of course, most welcome!
<p><a href="https://github.com/twentyhq/twenty"><img src="./packages/twenty-website/public/images/readme/star-icon.svg" width="12" height="12"/> Star the repo</a> · <a href="https://discord.gg/cx5n4Jzs57"><img src="./packages/twenty-website/public/images/readme/discord-icon.svg" width="12" height="12"/> Discord</a> · <a href="https://github.com/twentyhq/twenty/discussions"><img src="./packages/twenty-website/public/images/readme/message-icon.svg" width="12" height="12"/> Feature requests</a> · <a href="https://github.com/orgs/twentyhq/projects/1/views/35"><img src="./packages/twenty-website/public/images/readme/rocket-icon.svg" width="12" height="12"/> Releases</a> · <a href="https://twitter.com/twentycrm"><img src="./packages/twenty-website/public/images/readme/x-icon.svg" width="12" height="12"/> X</a> · <a href="https://www.linkedin.com/company/twenty/"><img src="./packages/twenty-website/public/images/readme/linkedin-icon.svg" width="12" height="12"/> LinkedIn</a> · <a href="https://twenty.crowdin.com/twenty"><img src="./packages/twenty-website/public/images/readme/language-icon.svg" width="12" height="12"/> Crowdin</a> · <a href="https://github.com/twentyhq/twenty/contribute"><img src="./packages/twenty-website/public/images/readme/code-icon.svg" width="12" height="12"/> Contribute</a></p>
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "create-twenty-app",
"version": "1.23.0-canary.9",
"version": "2.0.0",
"description": "Command-line interface to create Twenty application",
"main": "dist/cli.cjs",
"bin": "dist/cli.cjs",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "twenty-client-sdk",
"version": "1.23.0-canary.9",
"version": "2.0.0",
"sideEffects": false,
"license": "AGPL-3.0",
"scripts": {
@@ -830,6 +830,7 @@ type Workspace {
workspaceCustomApplication: Application
featureFlags: [FeatureFlag!]
billingSubscriptions: [BillingSubscription!]!
installedApplications: [Application!]!
currentBillingSubscription: BillingSubscription
billingEntitlements: [BillingEntitlement!]!
hasValidEnterpriseKey: Boolean!
@@ -619,6 +619,7 @@ export interface Workspace {
workspaceCustomApplication?: Application
featureFlags?: FeatureFlag[]
billingSubscriptions: BillingSubscription[]
installedApplications: Application[]
currentBillingSubscription?: BillingSubscription
billingEntitlements: BillingEntitlement[]
hasValidEnterpriseKey: Scalars['Boolean']
@@ -3504,6 +3505,7 @@ export interface WorkspaceGenqlSelection{
workspaceCustomApplication?: ApplicationGenqlSelection
featureFlags?: FeatureFlagGenqlSelection
billingSubscriptions?: BillingSubscriptionGenqlSelection
installedApplications?: ApplicationGenqlSelection
currentBillingSubscription?: BillingSubscriptionGenqlSelection
billingEntitlements?: BillingEntitlementGenqlSelection
hasValidEnterpriseKey?: boolean | number
@@ -1765,6 +1765,9 @@ export default {
"billingSubscriptions": [
138
],
"installedApplications": [
52
],
"currentBillingSubscription": [
138
],
@@ -0,0 +1,37 @@
FROM node:24-alpine AS twenty-website-new-build
WORKDIR /app
COPY ./package.json .
COPY ./yarn.lock .
COPY ./.yarnrc.yml .
COPY ./tsconfig.base.json .
COPY ./nx.json .
COPY ./.yarn/releases /app/.yarn/releases
COPY ./.yarn/patches /app/.yarn/patches
COPY ./packages/twenty-oxlint-rules /app/packages/twenty-oxlint-rules
COPY ./packages/twenty-website-new/package.json /app/packages/twenty-website-new/package.json
RUN yarn
COPY ./packages/twenty-website-new /app/packages/twenty-website-new
RUN npx nx build twenty-website-new
FROM node:24-alpine AS twenty-website-new
WORKDIR /app/packages/twenty-website-new
COPY --from=twenty-website-new-build /app /app
WORKDIR /app/packages/twenty-website-new
LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty
LABEL org.opencontainers.image.description="This image provides a consistent and reproducible environment for the new marketing website."
RUN chown -R 1000 /app
# Use non root user with uid 1000
USER 1000
CMD ["/bin/sh", "-c", "npx nx start twenty-website-new"]
@@ -28,7 +28,7 @@ import {
defineRole,
PermissionFlag,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
export default defineRole({
universalIdentifier: '2c80f640-2083-4803-bb49-003e38279de6',
@@ -77,7 +77,7 @@ Every app must have exactly one `defineApplication` call that describes:
- **(Optional) Pre-install / post-install functions**: logic functions that run before or after installation.
```ts src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { defineApplication } from 'twenty-sdk/define';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
@@ -132,7 +132,7 @@ The `defaultRoleUniversalIdentifier` in `application-config.ts` designates the d
When you scaffold a new app, the CLI creates a default role file:
```ts src/roles/default-role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';
import { defineRole, PermissionFlag } from 'twenty-sdk/define';
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
'b648f87b-1d26-4961-b974-0908fd991061';
@@ -172,7 +172,7 @@ Notes:
Custom objects describe both schema and behavior for records in your workspace. Use `defineObject()` to define objects with built-in validation:
```ts postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';
import { defineObject, FieldType } from 'twenty-sdk/define';
enum PostCardStatus {
DRAFT = 'DRAFT',
@@ -261,7 +261,7 @@ Key points:
Use `defineField()` to add fields to objects you don't own — such as standard Twenty objects (Person, Company, etc.) or objects from other apps. Unlike inline fields in `defineObject()`, standalone fields require an `objectUniversalIdentifier` to specify which object they extend:
```ts src/fields/company-loyalty-tier.field.ts
import { defineField, FieldType } from 'twenty-sdk';
import { defineField, FieldType } from 'twenty-sdk/define';
export default defineField({
universalIdentifier: 'f2a1b3c4-d5e6-7890-abcd-ef1234567890',
@@ -311,7 +311,7 @@ Suppose a `PostCard` can be sent to many `PostCardRecipient` records. Each recip
**Step 1: Define the ONE_TO_MANY side on PostCard** (the "one" side):
```ts src/fields/post-card-recipients-on-post-card.field.ts
import { defineField, FieldType, RelationType } from 'twenty-sdk';
import { defineField, FieldType, RelationType } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -338,7 +338,7 @@ export default defineField({
**Step 2: Define the MANY_TO_ONE side on PostCardRecipient** (the "many" side — holds the foreign key):
```ts src/fields/post-card-on-post-card-recipient.field.ts
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk';
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -379,7 +379,7 @@ import {
RelationType,
OnDeleteAction,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
import { SELF_HOSTING_USER_UNIVERSAL_IDENTIFIER } from '../objects/self-hosting-user.object';
export const PERSON_FIELD_ID = 'c3333333-3333-3333-3333-333333333333';
@@ -448,8 +448,8 @@ export default defineObject({
Each function file uses `defineLogicFunction()` to export a configuration with a handler and optional triggers.
```ts src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
import { CoreApiClient, type Person } from 'twenty-client-sdk/core';
const handler = async (params: RoutePayload) => {
@@ -519,7 +519,7 @@ When a route trigger invokes your logic function, it receives a `RoutePayload` o
Import the `RoutePayload` type from `twenty-sdk`:
```ts
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';
const handler = async (event: RoutePayload) => {
const { headers, queryStringParameters, pathParameters, body } = event;
@@ -584,7 +584,7 @@ Logic functions can be exposed as **tools** for AI agents and workflows. When ma
To mark a logic function as a tool, set `isTool: true`:
```ts src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import { CoreApiClient } from 'twenty-client-sdk/core';
const handler = async (params: { companyName: string; domain?: string }) => {
@@ -650,7 +650,7 @@ export default defineLogicFunction({
A post-install function is a logic function that runs automatically once your app has finished installing on a workspace. The server executes it **after** the app's metadata has been synchronized and the SDK client has been generated, so the workspace is fully ready to use and the new schema is in place. Typical use cases include seeding default data, creating initial records, configuring workspace settings, or provisioning resources on third-party services.
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Post install logic function executed successfully!', payload.previousVersion);
@@ -693,7 +693,7 @@ Key points:
A pre-install function is a logic function that runs automatically during installation, **before the workspace metadata migration is applied**. It shares the same payload shape as post-install (`InstallPayload`), but it is positioned earlier in the install flow so it can prepare state that the upcoming migration depends on — typical uses include backing up data, validating compatibility with the new schema, or archiving records that are about to be restructured or dropped.
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Pre install logic function executed successfully!', payload.previousVersion);
@@ -751,7 +751,7 @@ Pre-install is always **synchronous** (it blocks the install and can abort it).
Example — seed a default `PostCard` record after install:
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
@@ -783,7 +783,7 @@ export default definePostInstallLogicFunction({
Example — archive records before a destructive migration:
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
@@ -855,7 +855,7 @@ Front components can render in two locations within Twenty:
The quickest way to see a front component in action is to register it as a **command**. Adding a `command` field with `isPinned: true` makes it appear as a quick-action button in the top-right corner of the page — no page layout needed:
```tsx src/front-components/hello-world.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
const HelloWorld = () => {
return (
@@ -916,7 +916,8 @@ Front components come in two rendering modes controlled by the `isHeadless` opti
**Headless (`isHeadless: true`)** — The component mounts invisibly in the background. It does not open the side panel. Headless components are designed for actions that execute logic and then unmount themselves — for example, running an async task, navigating to a page, or showing a confirmation modal. They pair naturally with the SDK Command components described below.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId, enqueueSnackbar } from 'twenty-sdk/front-component';
import { useEffect } from 'react';
const SyncTracker = () => {
@@ -954,7 +955,7 @@ Import them from `twenty-sdk/command`:
Here is a full example of a headless front component using `Command` to run an action from the command menu:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
@@ -990,7 +991,7 @@ export default defineFrontComponent({
And an example using `CommandModal` to ask for confirmation before executing:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
@@ -1028,12 +1029,12 @@ export default defineFrontComponent({
Inside your component, use SDK hooks to access the current user, record, and component instance:
```tsx src/front-components/record-info.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
useUserId,
useRecordId,
useFrontComponentId,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
const RecordInfo = () => {
const userId = useUserId();
@@ -1082,8 +1083,9 @@ Front components can trigger navigation, modals, and notifications using functio
Here is an example that uses the host API to show a snackbar and close the side panel after an action completes:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId } from 'twenty-sdk/front-component';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
@@ -1143,14 +1145,14 @@ Adding a `command` field to `defineFrontComponent` registers the component in th
The `conditionalAvailabilityExpression` field lets you control when a command is visible based on the current page context. Import typed variables and operators from `twenty-sdk` to build expressions:
```tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
pageType,
numberOfSelectedRecords,
objectPermissions,
everyEquals,
isDefined,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
export default defineFrontComponent({
universalIdentifier: '...',
@@ -1210,7 +1212,7 @@ export default defineFrontComponent({
Front components can access files from the app's `public/` directory using `getPublicAssetUrl`:
```tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
const Logo = () => <img src={getPublicAssetUrl('logo.png')} alt="Logo" />;
@@ -1235,7 +1237,7 @@ Front components support multiple styling approaches. You can use:
- **Any CSS-in-JS library** compatible with React
```tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Button, Tag, Status } from 'twenty-sdk/ui';
const StyledWidget = () => {
@@ -1262,7 +1264,7 @@ export default defineFrontComponent({
Skills define reusable instructions and capabilities that AI agents can use within your workspace. Use `defineSkill()` to define skills with built-in validation:
```ts src/skills/example-skill.ts
import { defineSkill } from 'twenty-sdk';
import { defineSkill } from 'twenty-sdk/define';
export default defineSkill({
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
@@ -1291,7 +1293,7 @@ Key points:
Agents are AI assistants that live inside your workspace. Use `defineAgent()` to create agents with a custom system prompt:
```ts src/agents/example-agent.ts
import { defineAgent } from 'twenty-sdk';
import { defineAgent } from 'twenty-sdk/define';
export default defineAgent({
universalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
@@ -1317,7 +1319,7 @@ Key points:
Views are saved configurations for how records of an object are displayed — including which fields are visible, their order, and any filters or groups applied. Use `defineView()` to ship pre-configured views with your app:
```ts src/views/example-view.ts
import { defineView, ViewKey } from 'twenty-sdk';
import { defineView, ViewKey } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { NAME_FIELD_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
@@ -1353,7 +1355,7 @@ Key points:
Navigation menu items add custom entries to the workspace sidebar. Use `defineNavigationMenuItem()` to link to views, external URLs, or objects:
```ts src/navigation-menu-items/example-navigation-menu-item.ts
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk';
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk/define';
import { EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER } from '../views/example-view';
export default defineNavigationMenuItem({
@@ -1379,7 +1381,7 @@ Key points:
Page layouts let you customize how a record detail page looks — which tabs appear, what widgets are inside each tab, and how they are arranged. Use `definePageLayout()` to ship custom layouts with your app:
```ts src/page-layouts/example-record-page-layout.ts
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk';
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from '../front-components/hello-world';
@@ -1442,7 +1444,7 @@ Use the `getPublicAssetUrl` helper from `twenty-sdk` to get the full URL of a fi
**In a logic function:**
```ts src/logic-functions/send-invoice.ts
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk';
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk/define';
const handler = async (): Promise<any> => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1467,7 +1469,7 @@ export default defineLogicFunction({
**In a front component:**
```tsx src/front-components/company-card.tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
export default defineFrontComponent(() => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1491,7 +1493,7 @@ yarn add axios
Then import it in your code:
```ts src/logic-functions/fetch-data.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import axios from 'axios';
const handler = async (): Promise<any> => {
@@ -1512,7 +1514,7 @@ export default defineLogicFunction({
The same works for front components:
```tsx src/front-components/chart.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { format } from 'date-fns';
const DateWidget = () => {
@@ -28,7 +28,7 @@ import {
defineRole,
PermissionFlag,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
export default defineRole({
universalIdentifier: '2c80f640-2083-4803-bb49-003e38279de6',
@@ -77,7 +77,7 @@ export default defineRole({
* **(اختياري) دوال ما قبل التثبيت/ما بعد التثبيت**: دوال منطقية تعمل قبل التثبيت أو بعده.
```ts src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { defineApplication } from 'twenty-sdk/define';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
@@ -132,7 +132,7 @@ export default defineApplication({
عند توليد تطبيق جديد بالقالب، ينشئ CLI ملفّ دور افتراضي:
```ts src/roles/default-role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';
import { defineRole, PermissionFlag } from 'twenty-sdk/define';
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
'b648f87b-1d26-4961-b974-0908fd991061';
@@ -172,7 +172,7 @@ export default defineRole({
تصف الكائنات المخصصة كلًا من المخطط والسلوك للسجلات في مساحة عملك. استخدم `defineObject()` لتعريف كائنات مع تحقق مدمج:
```ts postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';
import { defineObject, FieldType } from 'twenty-sdk/define';
enum PostCardStatus {
DRAFT = 'DRAFT',
@@ -261,7 +261,7 @@ export default defineObject({
استخدم `defineField()` لإضافة حقول إلى كائنات لا تملكها — مثل كائنات Twenty القياسية (Person, Company, etc.) أو كائنات من تطبيقات أخرى. على خلاف الحقول المضمّنة في `defineObject()`، تتطلّب الحقول المستقلة `objectUniversalIdentifier` لتحديد الكائن الذي تقوم بتوسيعه:
```ts src/fields/company-loyalty-tier.field.ts
import { defineField, FieldType } from 'twenty-sdk';
import { defineField, FieldType } from 'twenty-sdk/define';
export default defineField({
universalIdentifier: 'f2a1b3c4-d5e6-7890-abcd-ef1234567890',
@@ -311,7 +311,7 @@ export default defineField({
**الخطوة 1: عرّف جانب ONE_TO_MANY على PostCard** (جانب "الواحد"):
```ts src/fields/post-card-recipients-on-post-card.field.ts
import { defineField, FieldType, RelationType } from 'twenty-sdk';
import { defineField, FieldType, RelationType } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -338,7 +338,7 @@ export default defineField({
**الخطوة 2: عرّف جانب MANY_TO_ONE على PostCardRecipient** (جانب "العديد" — يحمل المفتاح الخارجي):
```ts src/fields/post-card-on-post-card-recipient.field.ts
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk';
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -379,7 +379,7 @@ import {
RelationType,
OnDeleteAction,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
import { SELF_HOSTING_USER_UNIVERSAL_IDENTIFIER } from '../objects/self-hosting-user.object';
export const PERSON_FIELD_ID = 'c3333333-3333-3333-3333-333333333333';
@@ -448,8 +448,8 @@ export default defineObject({
كل ملف وظيفة يستخدم `defineLogicFunction()` لتصدير تكوين مع معالج ومشغّلات اختيارية.
```ts src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
import { CoreApiClient, type Person } from 'twenty-client-sdk/core';
const handler = async (params: RoutePayload) => {
@@ -518,7 +518,7 @@ yarn twenty logs
استورد نوع `RoutePayload` من `twenty-sdk`:
```ts
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';
const handler = async (event: RoutePayload) => {
const { headers, queryStringParameters, pathParameters, body } = event;
@@ -530,15 +530,15 @@ const handler = async (event: RoutePayload) => {
يحتوي نوع `RoutePayload` على البنية التالية:
| الخاصية | النوع | الوصف | مثال |
| ---------------------------- | ------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | رؤوس HTTP (فقط تلك المدرجة في `forwardedRequestHeaders`) | انظر القسم أدناه |
| `queryStringParameters` | `Record<string, string \| undefined>` | معلمات سلسلة الاستعلام (تُضمّ القيم المتعددة باستخدام فواصل) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record<string, string \| undefined>` | معلمات المسار المستخرجة من نمط المسار | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `المحتوى` | `object \| null` | جسم الطلب المُحلَّل (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `قيمة منطقية` | ما إذا كان جسم الطلب مُرمَّزًا بترميز base64 | |
| `requestContext.http.method` | `string` | طريقة HTTP (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | المسار الخام للطلب | |
| الخاصية | النوع | الوصف | مثال |
| ---------------------------- | ------------------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------- |
| `headers` | `Record\<string, string \| undefined>` | رؤوس HTTP (فقط تلك المدرجة في `forwardedRequestHeaders`) | انظر القسم أدناه |
| `queryStringParameters` | `Record\<string, string \| undefined>` | معلمات سلسلة الاستعلام (تُضمّ القيم المتعددة باستخدام فواصل) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record\<string, string \| undefined>` | معلمات المسار المستخرجة من نمط المسار | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `المحتوى` | `object \| null` | جسم الطلب المُحلَّل (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `قيمة منطقية` | ما إذا كان جسم الطلب مُرمَّزًا بترميز base64 | |
| `requestContext.http.method` | `string` | طريقة HTTP (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | المسار الخام للطلب | |
#### forwardedRequestHeaders
@@ -583,7 +583,7 @@ const handler = async (event: RoutePayload) => {
لتمييز دالة منطقية كأداة، عيِّن `isTool: true`:
```ts src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import { CoreApiClient } from 'twenty-client-sdk/core';
const handler = async (params: { companyName: string; domain?: string }) => {
@@ -649,7 +649,7 @@ export default defineLogicFunction({
دالة ما بعد التثبيت هي دالة منطقية تعمل تلقائيًا بعد تثبيت تطبيقك على مساحة عمل. ينفّذه الخادم **بعد** مزامنة البيانات الوصفية للتطبيق وإنشاء عميل SDK، بحيث تكون مساحة العمل جاهزة تمامًا للاستخدام ويكون المخطط الجديد مطبَّقًا. تشمل حالات الاستخدام النموذجية تهيئة البيانات الافتراضية، وإنشاء السجلات الأولية، وتكوين إعدادات مساحة العمل، أو توفير الموارد على خدمات جهات خارجية.
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Post install logic function executed successfully!', payload.previousVersion);
@@ -692,7 +692,7 @@ yarn twenty exec --postInstall
دالة ما قبل التثبيت هي دالة منطقية تعمل تلقائيًا أثناء التثبيت، **قبل تطبيق ترحيل البيانات الوصفية لمساحة العمل**. تتشارك نفس بنية الحمولة مع ما بعد التثبيت (`InstallPayload`)، لكنها موضوعة أبكر في تدفّق التثبيت كي تجهّز حالة يعتمد عليها الترحيل القادم — ومن الاستخدامات الشائعة: نسخ البيانات احتياطيًا، التحقق من التوافق مع المخطط الجديد، أو أرشفة السجلات التي ستُعاد هيكلتها أو ستُحذف.
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Pre install logic function executed successfully!', payload.previousVersion);
@@ -750,7 +750,7 @@ yarn twenty exec --preInstall
مثال — بَذر سجل `PostCard` افتراضي بعد التثبيت:
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
@@ -782,7 +782,7 @@ export default definePostInstallLogicFunction({
مثال — أرشف السجلات قبل ترحيل هدّام:
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
@@ -854,7 +854,7 @@ export default definePreInstallLogicFunction({
أسرع طريقة لرؤية مكوّن أمامي قيد العمل هي تسجيله كأمر. إضافة حقل `command` مع `isPinned: true` يجعلُه يظهر كزر إجراء سريع في الزاوية العلوية اليمنى من الصفحة — دون الحاجة إلى تخطيط صفحة:
```tsx src/front-components/hello-world.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
const HelloWorld = () => {
return (
@@ -915,7 +915,8 @@ export default defineFrontComponent({
**عديم الرأس (`isHeadless: true`)** — يتم تركيب المكوّن بشكل غير مرئي في الخلفية. لا يفتح اللوحة الجانبية. تم تصميم المكوّنات عديمة الرأس لإجراءات تنفّذ منطقًا ثم تُزيل تركيبها ذاتيًا — على سبيل المثال، تشغيل مهمة غير متزامنة، أو الانتقال إلى صفحة، أو إظهار نافذة تأكيد منبثقة. تتوافق بشكل طبيعي مع مكوّنات Command في SDK الموصوفة أدناه.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId, enqueueSnackbar } from 'twenty-sdk/front-component';
import { useEffect } from 'react';
const SyncTracker = () => {
@@ -953,7 +954,7 @@ export default defineFrontComponent({
فيما يلي مثال كامل لمكوّن واجهة أمامية عديم الرأس يستخدم `Command` لتشغيل إجراء من قائمة الأوامر:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
@@ -989,7 +990,7 @@ export default defineFrontComponent({
ومثال يستخدم `CommandModal` لطلب التأكيد قبل التنفيذ:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
@@ -1027,12 +1028,12 @@ export default defineFrontComponent({
داخل مكوّنك، استخدم خطافات SDK للوصول إلى المستخدم الحالي، والسجل، ومثيل المكوّن:
```tsx src/front-components/record-info.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
useUserId,
useRecordId,
useFrontComponentId,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
const RecordInfo = () => {
const userId = useUserId();
@@ -1081,8 +1082,9 @@ export default defineFrontComponent({
فيما يلي مثال يستخدم واجهة برمجة تطبيقات المضيف لعرض Snackbar وإغلاق اللوحة الجانبية بعد اكتمال الإجراء:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId } from 'twenty-sdk/front-component';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
@@ -1142,14 +1144,14 @@ export default defineFrontComponent({
يتيح لك الحقل `conditionalAvailabilityExpression` التحكّم في وقت ظهور الأمر بناءً على سياق الصفحة الحالي. استورد متغيّرات ومشغّلات مضبوطة الأنواع من `twenty-sdk` لبناء التعابير:
```tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
pageType,
numberOfSelectedRecords,
objectPermissions,
everyEquals,
isDefined,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
export default defineFrontComponent({
universalIdentifier: '...',
@@ -1209,7 +1211,7 @@ export default defineFrontComponent({
يمكن للمكوّنات الأمامية الوصول إلى ملفات من دليل `public/` للتطبيق باستخدام `getPublicAssetUrl`:
```tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
const Logo = () => <img src={getPublicAssetUrl('logo.png')} alt="Logo" />;
@@ -1234,7 +1236,7 @@ export default defineFrontComponent({
* **أي مكتبة CSS-in-JS** متوافقة مع React
```tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Button, Tag, Status } from 'twenty-sdk/ui';
const StyledWidget = () => {
@@ -1261,7 +1263,7 @@ export default defineFrontComponent({
تُحدِّد المهارات تعليمات وإمكانات قابلة لإعادة الاستخدام يمكن لوكلاء الذكاء الاصطناعي استخدامها داخل مساحة العمل لديك. استخدم `defineSkill()` لتعريف مهارات مع تحقّق مدمج:
```ts src/skills/example-skill.ts
import { defineSkill } from 'twenty-sdk';
import { defineSkill } from 'twenty-sdk/define';
export default defineSkill({
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
@@ -1290,7 +1292,7 @@ export default defineSkill({
الوكلاء هم مساعدون ذكاء اصطناعي يعيشون داخل مساحة العمل لديك. استخدم `defineAgent()` لإنشاء وكلاء بموجه نظام مخصّص:
```ts src/agents/example-agent.ts
import { defineAgent } from 'twenty-sdk';
import { defineAgent } from 'twenty-sdk/define';
export default defineAgent({
universalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
@@ -1316,7 +1318,7 @@ export default defineAgent({
العروض هي تكوينات محفوظة لكيفية عرض سجلات كائن ما — بما في ذلك الحقول المرئية وترتيبها وأي مرشّحات أو مجموعات مُطبَّقة. استخدم `defineView()` لتضمين عروض مُهيّأة مسبقًا مع تطبيقك:
```ts src/views/example-view.ts
import { defineView, ViewKey } from 'twenty-sdk';
import { defineView, ViewKey } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { NAME_FIELD_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
@@ -1352,7 +1354,7 @@ export default defineView({
تضيف عناصر قائمة التنقل إدخالات مخصّصة إلى الشريط الجانبي لمساحة العمل. استخدم `defineNavigationMenuItem()` للارتباط بالعروض أو عناوين URL خارجية أو الكائنات:
```ts src/navigation-menu-items/example-navigation-menu-item.ts
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk';
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk/define';
import { EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER } from '../views/example-view';
export default defineNavigationMenuItem({
@@ -1378,7 +1380,7 @@ export default defineNavigationMenuItem({
تتيح لك تخطيطات الصفحات تخصيص مظهر صفحة تفاصيل السجل — ما الألسنة التي تظهر، وما الويدجتات داخل كل لسان، وكيف يتم ترتيبها. استخدم `definePageLayout()` لتضمين تخطيطات مخصّصة مع تطبيقك:
```ts src/page-layouts/example-record-page-layout.ts
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk';
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from '../front-components/hello-world';
@@ -1441,7 +1443,7 @@ export default definePageLayout({
**في دالة منطقية:**
```ts src/logic-functions/send-invoice.ts
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk';
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk/define';
const handler = async (): Promise<any> => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1466,7 +1468,7 @@ export default defineLogicFunction({
**في مكوّن أمامي:**
```tsx src/front-components/company-card.tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
export default defineFrontComponent(() => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1490,7 +1492,7 @@ yarn add axios
ثم استوردها في شيفرتك:
```ts src/logic-functions/fetch-data.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import axios from 'axios';
const handler = async (): Promise<any> => {
@@ -1511,7 +1513,7 @@ export default defineLogicFunction({
وينطبق الأمر نفسه على المكوّنات الأمامية:
```tsx src/front-components/chart.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { format } from 'date-fns';
const DateWidget = () => {
@@ -1555,18 +1557,18 @@ yarn twenty add frontComponent
### أنواع الكيانات المتاحة
| نوع الكيان | أمر | الملف المُولَّد |
| ------------------ | ------------------------------------ | ------------------------------------- |
| كائن | `yarn twenty add object` | `src/objects/<name>.ts` |
| الحقل | `yarn twenty add field` | `src/fields/<name>.ts` |
| دالة منطقية | `yarn twenty add logicFunction` | `src/logic-functions/<name>.ts` |
| مكوّن أمامي | `yarn twenty add frontComponent` | `src/front-components/<name>.tsx` |
| دور | `yarn twenty add role` | `src/roles/<name>.ts` |
| مهارة | `yarn twenty add skill` | `src/skills/<name>.ts` |
| وكيل | `yarn twenty add agent` | `src/agents/<name>.ts` |
| عرض | `yarn twenty add view` | `src/views/<name>.ts` |
| عنصر قائمة التنقّل | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/<name>.ts` |
| تخطيط الصفحة | `yarn twenty add pageLayout` | `src/page-layouts/<name>.ts` |
| نوع الكيان | أمر | الملف المُولَّد |
| ------------------ | ------------------------------------ | ------------------------------------------------------- |
| كائن | `yarn twenty add object` | `src/objects/\<name>.ts` |
| الحقل | `yarn twenty add field` | `src/fields/\<name>.ts` |
| دالة منطقية | `yarn twenty add logicFunction` | `src/logic-functions/\<name>.ts` |
| مكوّن أمامي | `yarn twenty add frontComponent` | `src/front-components/\<name>.tsx` |
| دور | `yarn twenty add role` | `src/roles/\<name>.ts` |
| مهارة | `yarn twenty add skill` | `src/skills/\<name>.ts` |
| وكيل | `yarn twenty add agent` | `src/agents/\<name>.ts` |
| عرض | `yarn twenty add view` | `src/views/\<name>.ts` |
| عنصر قائمة التنقّل | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/\<name>.ts` |
| تخطيط الصفحة | `yarn twenty add pageLayout` | `src/page-layouts/\<name>.ts` |
### ما الذي تُنشئه أداة القوالب
@@ -28,7 +28,7 @@ import {
defineRole,
PermissionFlag,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
export default defineRole({
universalIdentifier: '2c80f640-2083-4803-bb49-003e38279de6',
@@ -77,7 +77,7 @@ Každá aplikace musí mít právě jedno volání `defineApplication`, které p
* **(Volitelné) předinstalační / postinstalační funkce**: logické funkce, které se spouštějí před nebo po instalaci.
```ts src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { defineApplication } from 'twenty-sdk/define';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
@@ -132,7 +132,7 @@ Pole `defaultRoleUniversalIdentifier` v `application-config.ts` určuje výchoz
Když vygenerujete novou aplikaci, CLI vytvoří výchozí soubor role:
```ts src/roles/default-role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';
import { defineRole, PermissionFlag } from 'twenty-sdk/define';
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
'b648f87b-1d26-4961-b974-0908fd991061';
@@ -172,7 +172,7 @@ Poznámky:
Vlastní objekty popisují jak schéma, tak chování záznamů ve vašem pracovním prostoru. K definování objektů s vestavěnou validací použijte `defineObject()`:
```ts postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';
import { defineObject, FieldType } from 'twenty-sdk/define';
enum PostCardStatus {
DRAFT = 'DRAFT',
@@ -261,7 +261,7 @@ ale to se nedoporučuje.
Pomocí `defineField()` přidejte pole k objektům, které nevlastníte — například ke standardním objektům Twenty (Person, Company atd.). nebo k objektům z jiných aplikací. Na rozdíl od inline polí v `defineObject()` vyžadují samostatná pole `objectUniversalIdentifier` k určení, který objekt rozšiřují:
```ts src/fields/company-loyalty-tier.field.ts
import { defineField, FieldType } from 'twenty-sdk';
import { defineField, FieldType } from 'twenty-sdk/define';
export default defineField({
universalIdentifier: 'f2a1b3c4-d5e6-7890-abcd-ef1234567890',
@@ -311,7 +311,7 @@ Předpokládejme, že `PostCard` lze odeslat mnoha záznamům `PostCardRecipient
**Krok 1: Definujte stranu ONE_TO_MANY na PostCard** (strana "one"):
```ts src/fields/post-card-recipients-on-post-card.field.ts
import { defineField, FieldType, RelationType } from 'twenty-sdk';
import { defineField, FieldType, RelationType } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -338,7 +338,7 @@ export default defineField({
**Krok 2: Definujte stranu MANY_TO_ONE na PostCardRecipient** (strana "many" — drží cizí klíč):
```ts src/fields/post-card-on-post-card-recipient.field.ts
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk';
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -379,7 +379,7 @@ import {
RelationType,
OnDeleteAction,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
import { SELF_HOSTING_USER_UNIVERSAL_IDENTIFIER } from '../objects/self-hosting-user.object';
export const PERSON_FIELD_ID = 'c3333333-3333-3333-3333-333333333333';
@@ -448,8 +448,8 @@ export default defineObject({
Každý soubor funkce používá `defineLogicFunction()` k exportu konfigurace s obslužnou funkcí (handlerem) a volitelnými spouštěči.
```ts src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
import { CoreApiClient, type Person } from 'twenty-client-sdk/core';
const handler = async (params: RoutePayload) => {
@@ -519,7 +519,7 @@ Když spouštěč typu route vyvolá vaši logickou funkci, ta obdrží objekt `
Importujte typ `RoutePayload` z `twenty-sdk`:
```ts
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';
const handler = async (event: RoutePayload) => {
const { headers, queryStringParameters, pathParameters, body } = event;
@@ -531,15 +531,15 @@ const handler = async (event: RoutePayload) => {
Typ `RoutePayload` má následující strukturu:
| Vlastnost | Typ | Popis | Příklad |
| ---------------------------- | ------------------------------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | Záhlaví HTTP (pouze ta uvedená v `forwardedRequestHeaders`) | viz sekce níže |
| `queryStringParameters` | `Record<string, string \| undefined>` | Parametry query stringu (více hodnot spojených čárkami) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record<string, string \| undefined>` | Parametry cesty extrahované ze vzoru trasy | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Parsované tělo požadavku (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `boolean` | Zda je tělo kódováno base64 | |
| `requestContext.http.method` | `string` | Metoda HTTP (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | Nezpracovaná cesta požadavku | |
| Vlastnost | Typ | Popis | Příklad |
| ---------------------------- | ------------------------------------------------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record\<string, string \| undefined>` | Záhlaví HTTP (pouze ta uvedená v `forwardedRequestHeaders`) | viz sekce níže |
| `queryStringParameters` | `Record\<string, string \| undefined>` | Parametry query stringu (více hodnot spojených čárkami) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record\<string, string \| undefined>` | Parametry cesty extrahované ze vzoru trasy | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Parsované tělo požadavku (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `boolean` | Zda je tělo kódováno base64 | |
| `requestContext.http.method` | `string` | Metoda HTTP (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | Nezpracovaná cesta požadavku | |
#### forwardedRequestHeaders
@@ -584,7 +584,7 @@ Logické funkce lze zpřístupnit jako **nástroje** pro agenty AI a pracovní p
Chcete-li označit logickou funkci jako nástroj, nastavte `isTool: true`:
```ts src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import { CoreApiClient } from 'twenty-client-sdk/core';
const handler = async (params: { companyName: string; domain?: string }) => {
@@ -650,7 +650,7 @@ export default defineLogicFunction({
Postinstalační funkce je logická funkce, která se spustí automaticky, jakmile je instalace vaší aplikace v pracovním prostoru dokončena. Server ji provede **poté**, co byla synchronizována metadata aplikace a vygenerován klient SDK, takže je pracovní prostor plně připraven k použití a nové schéma je zavedeno. Mezi typické případy použití patří naplnění výchozími daty, vytvoření počátečních záznamů, konfigurace nastavení pracovního prostoru nebo zřizování prostředků ve službách třetích stran.
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Post install logic function executed successfully!', payload.previousVersion);
@@ -693,7 +693,7 @@ Hlavní body:
Funkce pre-install je logická funkce, která se během instalace spouští automaticky, **před aplikováním migrace metadat pracovního prostoru**. Má stejný tvar payloadu jako post-install (`InstallPayload`), ale je zařazena dříve v instalačním toku, aby mohla připravit stav, na němž nadcházející migrace závisí — typické použití zahrnuje zálohování dat, ověření kompatibility s novým schématem nebo archivaci záznamů, které se chystají přeuspořádat nebo odstranit.
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Pre install logic function executed successfully!', payload.previousVersion);
@@ -751,7 +751,7 @@ Pre-install je vždy **synchronní** (blokuje instalaci a může ji přerušit).
Příklad — po instalaci naplňte výchozí záznam `PostCard`:
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
@@ -783,7 +783,7 @@ export default definePostInstallLogicFunction({
Příklad — archivujte záznamy před destruktivní migrací:
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
@@ -855,7 +855,7 @@ Front komponenty se mohou vykreslovat na dvou místech v rámci Twenty:
Nejrychlejší způsob, jak vidět frontendovou komponentu v akci, je zaregistrovat ji jako **příkaz**. Přidáním pole `command` s `isPinned: true` se zobrazí jako tlačítko rychlé akce v pravém horním rohu stránky — není potřeba žádné rozvržení stránky:
```tsx src/front-components/hello-world.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
const HelloWorld = () => {
return (
@@ -916,7 +916,8 @@ Front komponenty existují ve dvou režimech vykreslování řízených volbou `
**Headless (`isHeadless: true`)** — Komponenta se neviditelně inicializuje na pozadí. Neotevírá postranní panel. Headless komponenty jsou určené pro akce, které provedou logiku a poté se odpojí — například spuštění asynchronního úkolu, navigaci na stránku nebo zobrazení potvrzovacího modálního okna. Přirozeně se hodí ke komponentám SDK Command popsaným níže.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId, enqueueSnackbar } from 'twenty-sdk/front-component';
import { useEffect } from 'react';
const SyncTracker = () => {
@@ -954,7 +955,7 @@ Importujte je z `twenty-sdk/command`:
Zde je kompletní příklad headless front komponenty, která pomocí `Command` spouští akci z menu příkazů:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
@@ -990,7 +991,7 @@ export default defineFrontComponent({
A příklad s použitím `CommandModal` k vyžádání potvrzení před provedením:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
@@ -1028,12 +1029,12 @@ export default defineFrontComponent({
Uvnitř komponenty použijte hooky SDK pro přístup k aktuálnímu uživateli, záznamu a instanci komponenty:
```tsx src/front-components/record-info.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
useUserId,
useRecordId,
useFrontComponentId,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
const RecordInfo = () => {
const userId = useUserId();
@@ -1082,8 +1083,9 @@ Frontendové komponenty mohou pomocí funkcí z `twenty-sdk` vyvolávat navigaci
Zde je příklad, který používá hostitelské API k zobrazení snackbaru a zavření postranního panelu po dokončení akce:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId } from 'twenty-sdk/front-component';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
@@ -1143,14 +1145,14 @@ Přidání pole `command` do `defineFrontComponent` zaregistruje komponentu v p
Pole `conditionalAvailabilityExpression` vám umožní řídit viditelnost příkazu na základě aktuálního kontextu stránky. Pro sestavení výrazů importujte typované proměnné a operátory z `twenty-sdk`:
```tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
pageType,
numberOfSelectedRecords,
objectPermissions,
everyEquals,
isDefined,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
export default defineFrontComponent({
universalIdentifier: '...',
@@ -1210,7 +1212,7 @@ export default defineFrontComponent({
Frontendové komponenty mohou přistupovat k souborům ze složky aplikace `public/` pomocí `getPublicAssetUrl`:
```tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
const Logo = () => <img src={getPublicAssetUrl('logo.png')} alt="Logo" />;
@@ -1235,7 +1237,7 @@ Frontendové komponenty podporují více přístupů ke stylování. Můžete po
* **Jakákoli CSS-in-JS knihovna** kompatibilní s Reactem
```tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Button, Tag, Status } from 'twenty-sdk/ui';
const StyledWidget = () => {
@@ -1262,7 +1264,7 @@ export default defineFrontComponent({
Dovednosti definují znovupoužitelné pokyny a schopnosti, které mohou agenti AI používat ve vašem pracovním prostoru. K definování dovedností s vestavěnou validací použijte `defineSkill()`:
```ts src/skills/example-skill.ts
import { defineSkill } from 'twenty-sdk';
import { defineSkill } from 'twenty-sdk/define';
export default defineSkill({
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
@@ -1291,7 +1293,7 @@ Hlavní body:
Agenti jsou asistenti AI, kteří běží ve vašem pracovním prostoru. K vytvoření agentů s vlastním systémovým promptem použijte `defineAgent()`:
```ts src/agents/example-agent.ts
import { defineAgent } from 'twenty-sdk';
import { defineAgent } from 'twenty-sdk/define';
export default defineAgent({
universalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
@@ -1317,7 +1319,7 @@ Hlavní body:
Zobrazení jsou uložené konfigurace toho, jak se zobrazují záznamy objektu — včetně toho, která pole jsou viditelná, jejich pořadí a jaké filtry či seskupení jsou použity. Pomocí `defineView()` můžete k aplikaci přidat předkonfigurovaná zobrazení:
```ts src/views/example-view.ts
import { defineView, ViewKey } from 'twenty-sdk';
import { defineView, ViewKey } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { NAME_FIELD_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
@@ -1353,7 +1355,7 @@ Hlavní body:
Položky navigační nabídky přidávají vlastní položky do postranního panelu pracovního prostoru. Použijte `defineNavigationMenuItem()` k odkazování na zobrazení, externí URL nebo objekty:
```ts src/navigation-menu-items/example-navigation-menu-item.ts
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk';
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk/define';
import { EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER } from '../views/example-view';
export default defineNavigationMenuItem({
@@ -1379,7 +1381,7 @@ Hlavní body:
Rozvržení stránek vám umožní přizpůsobit vzhled stránky s detailem záznamu — které karty se zobrazí, jaké widgety jsou uvnitř každé karty a jak jsou uspořádány. Pomocí `definePageLayout()` můžete k aplikaci přidat vlastní rozvržení:
```ts src/page-layouts/example-record-page-layout.ts
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk';
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from '../front-components/hello-world';
@@ -1442,7 +1444,7 @@ K získání plné URL souboru ve vaší složce `public/` použijte pomocnou fu
**V logické funkci:**
```ts src/logic-functions/send-invoice.ts
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk';
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk/define';
const handler = async (): Promise<any> => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1467,7 +1469,7 @@ export default defineLogicFunction({
**Ve frontendové komponentě:**
```tsx src/front-components/company-card.tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
export default defineFrontComponent(() => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1491,7 +1493,7 @@ yarn add axios
Poté jej importujte ve svém kódu:
```ts src/logic-functions/fetch-data.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import axios from 'axios';
const handler = async (): Promise<any> => {
@@ -1512,7 +1514,7 @@ export default defineLogicFunction({
Stejně to funguje i pro frontendové komponenty:
```tsx src/front-components/chart.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { format } from 'date-fns';
const DateWidget = () => {
@@ -1556,18 +1558,18 @@ yarn twenty add frontComponent
### Dostupné typy entit
| Typ entity | Příkaz | Vygenerovaný soubor |
| ------------------------- | ------------------------------------ | ------------------------------------- |
| Objekt | `yarn twenty add object` | `src/objects/<name>.ts` |
| Pole | `yarn twenty add field` | `src/fields/<name>.ts` |
| Logická funkce | `yarn twenty add logicFunction` | `src/logic-functions/<name>.ts` |
| Frontendová komponenta | `yarn twenty add frontComponent` | `src/front-components/<name>.tsx` |
| Role | `yarn twenty add role` | `src/roles/<name>.ts` |
| Dovednost | `yarn twenty add skill` | `src/skills/<name>.ts` |
| Agent | `yarn twenty add agent` | `src/agents/<name>.ts` |
| Pohled | `yarn twenty add view` | `src/views/<name>.ts` |
| Položka navigační nabídky | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/<name>.ts` |
| Rozvržení stránky | `yarn twenty add pageLayout` | `src/page-layouts/<name>.ts` |
| Typ entity | Příkaz | Vygenerovaný soubor |
| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
| Objekt | `yarn twenty add object` | `src/objects/\<name>.ts` |
| Pole | `yarn twenty add field` | `src/fields/\<name>.ts` |
| Logická funkce | `yarn twenty add logicFunction` | `src/logic-functions/\<name>.ts` |
| Frontendová komponenta | `yarn twenty add frontComponent` | `src/front-components/\<name>.tsx` |
| Role | `yarn twenty add role` | `src/roles/\<name>.ts` |
| Dovednost | `yarn twenty add skill` | `src/skills/\<name>.ts` |
| Agent | `yarn twenty add agent` | `src/agents/\<name>.ts` |
| Pohled | `yarn twenty add view` | `src/views/\<name>.ts` |
| Položka navigační nabídky | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/\<name>.ts` |
| Rozvržení stránky | `yarn twenty add pageLayout` | `src/page-layouts/\<name>.ts` |
### Co generátor vytváří
@@ -28,7 +28,7 @@ import {
defineRole,
PermissionFlag,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
export default defineRole({
universalIdentifier: '2c80f640-2083-4803-bb49-003e38279de6',
@@ -77,7 +77,7 @@ Jede App muss genau einen Aufruf von `defineApplication` haben, der Folgendes be
* **(Optional) Pre-/Post-Installationsfunktionen**: Logikfunktionen, die vor oder nach der Installation ausgeführt werden.
```ts src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { defineApplication } from 'twenty-sdk/define';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
@@ -132,7 +132,7 @@ Das Feld `defaultRoleUniversalIdentifier` in `application-config.ts` legt die St
Wenn Sie eine neue App erzeugen, erstellt die CLI eine Standard-Rolldatei:
```ts src/roles/default-role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';
import { defineRole, PermissionFlag } from 'twenty-sdk/define';
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
'b648f87b-1d26-4961-b974-0908fd991061';
@@ -172,7 +172,7 @@ Notizen:
Benutzerdefinierte Objekte beschreiben sowohl Schema als auch Verhalten für Datensätze in Ihrem Workspace. Verwenden Sie `defineObject()`, um Objekte mit eingebauter Validierung zu definieren:
```ts postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';
import { defineObject, FieldType } from 'twenty-sdk/define';
enum PostCardStatus {
DRAFT = 'DRAFT',
@@ -261,7 +261,7 @@ dies wird jedoch nicht empfohlen.
Verwenden Sie `defineField()`, um Objekten, die Ihnen nicht gehören — etwa Standardobjekten von Twenty (Person, Company usw.) — Felder hinzuzufügen oder Objekten aus anderen Apps. Im Gegensatz zu Inline-Feldern in `defineObject()` benötigen eigenständige Felder einen `objectUniversalIdentifier`, um anzugeben, welches Objekt sie erweitern:
```ts src/fields/company-loyalty-tier.field.ts
import { defineField, FieldType } from 'twenty-sdk';
import { defineField, FieldType } from 'twenty-sdk/define';
export default defineField({
universalIdentifier: 'f2a1b3c4-d5e6-7890-abcd-ef1234567890',
@@ -311,7 +311,7 @@ Angenommen, eine `PostCard` kann an viele `PostCardRecipient`-Datensätze gesend
**Schritt 1: Definieren Sie die ONE_TO_MANY-Seite auf PostCard** (die "eine" Seite):
```ts src/fields/post-card-recipients-on-post-card.field.ts
import { defineField, FieldType, RelationType } from 'twenty-sdk';
import { defineField, FieldType, RelationType } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -338,7 +338,7 @@ export default defineField({
**Schritt 2: Definieren Sie die MANY_TO_ONE-Seite auf PostCardRecipient** (die "viele" Seite — hält den Fremdschlüssel):
```ts src/fields/post-card-on-post-card-recipient.field.ts
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk';
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -379,7 +379,7 @@ import {
RelationType,
OnDeleteAction,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
import { SELF_HOSTING_USER_UNIVERSAL_IDENTIFIER } from '../objects/self-hosting-user.object';
export const PERSON_FIELD_ID = 'c3333333-3333-3333-3333-333333333333';
@@ -448,8 +448,8 @@ export default defineObject({
Jede Funktionsdatei verwendet `defineLogicFunction()`, um eine Konfiguration mit einem Handler und optionalen Triggern zu exportieren.
```ts src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
import { CoreApiClient, type Person } from 'twenty-client-sdk/core';
const handler = async (params: RoutePayload) => {
@@ -518,7 +518,7 @@ Wenn ein Route-Trigger Ihre Logikfunktion aufruft, erhält sie ein `RoutePayload
Importieren Sie den Typ `RoutePayload` aus `twenty-sdk`:
```ts
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';
const handler = async (event: RoutePayload) => {
const { headers, queryStringParameters, pathParameters, body } = event;
@@ -530,15 +530,15 @@ const handler = async (event: RoutePayload) => {
Der Typ `RoutePayload` hat die folgende Struktur:
| Eigenschaft | Typ | Beschreibung | Beispiel |
| ---------------------------- | ------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | HTTP-Header (nur die in `forwardedRequestHeaders` aufgelisteten) | siehe Abschnitt unten |
| `queryStringParameters` | `Record<string, string \| undefined>` | Query-String-Parameter (mehrere Werte mit Kommas verbunden) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record<string, string \| undefined>` | Aus dem Routenmuster extrahierte Pfadparameter | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Geparster Request-Body (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `boolean` | Gibt an, ob der Body Base64-codiert ist | |
| `requestContext.http.method` | `string` | HTTP-Methode (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | Rohpfad der Anfrage | |
| Eigenschaft | Typ | Beschreibung | Beispiel |
| ---------------------------- | ------------------------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record\<string, string \| undefined>` | HTTP-Header (nur die in `forwardedRequestHeaders` aufgelisteten) | siehe Abschnitt unten |
| `queryStringParameters` | `Record\<string, string \| undefined>` | Query-String-Parameter (mehrere Werte mit Kommas verbunden) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record\<string, string \| undefined>` | Aus dem Routenmuster extrahierte Pfadparameter | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Geparster Request-Body (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `boolean` | Gibt an, ob der Body Base64-codiert ist | |
| `requestContext.http.method` | `string` | HTTP-Methode (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | Rohpfad der Anfrage | |
#### forwardedRequestHeaders
@@ -583,7 +583,7 @@ Logikfunktionen können als **Tools** für KI-Agenten und Workflows verfügbar g
Um eine Logikfunktion als Tool zu markieren, setzen Sie `isTool: true`:
```ts src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import { CoreApiClient } from 'twenty-client-sdk/core';
const handler = async (params: { companyName: string; domain?: string }) => {
@@ -649,7 +649,7 @@ export default defineLogicFunction({
Eine Post-Installationsfunktion ist eine Logikfunktion, die automatisch ausgeführt wird, nachdem Ihre App in einem Arbeitsbereich installiert wurde. Der Server führt sie **nach** der Synchronisierung der Metadaten der App und der Generierung des SDK-Clients aus, sodass der Arbeitsbereich vollständig einsatzbereit ist und das neue Schema bereitsteht. Typische Anwendungsfälle umfassen das Befüllen von Standarddaten, das Erstellen anfänglicher Datensätze, das Konfigurieren von Arbeitsbereichseinstellungen oder das Bereitstellen von Ressourcen bei Diensten von Drittanbietern.
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Post install logic function executed successfully!', payload.previousVersion);
@@ -692,7 +692,7 @@ Hauptpunkte:
Eine Pre-Install-Funktion ist eine Logikfunktion, die automatisch während der Installation ausgeführt wird, **bevor die Metadatenmigration des Workspaces angewendet wird**. Sie hat die gleiche Payload-Struktur wie Post-Install (`InstallPayload`), ist aber früher im Installationsablauf positioniert, sodass sie Zustände vorbereiten kann, von denen die bevorstehende Migration abhängt — typische Anwendungsfälle sind das Sichern von Daten, die Validierung der Kompatibilität mit dem neuen Schema oder das Archivieren von Datensätzen, die umstrukturiert oder entfernt werden sollen.
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Pre install logic function executed successfully!', payload.previousVersion);
@@ -750,7 +750,7 @@ Pre-Install ist immer **synchron** (blockiert die Installation und kann sie abbr
Beispiel — nach der Installation einen Standard-`PostCard`-Datensatz anlegen:
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
@@ -782,7 +782,7 @@ export default definePostInstallLogicFunction({
Beispiel — Datensätze vor einer destruktiven Migration archivieren:
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
@@ -854,7 +854,7 @@ Front-Komponenten können an zwei Stellen innerhalb von Twenty gerendert werden:
Der schnellste Weg, eine Frontend-Komponente in Aktion zu sehen, ist, sie als Befehl zu registrieren. Das Hinzufügen eines `command`-Felds mit `isPinned: true` lässt sie als Schnellaktionsschaltfläche oben rechts auf der Seite erscheinen — kein Seitenlayout erforderlich:
```tsx src/front-components/hello-world.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
const HelloWorld = () => {
return (
@@ -915,7 +915,8 @@ Front-Komponenten gibt es in zwei Rendering-Modi, die durch die Option `isHeadle
**Headless (`isHeadless: true`)** — Die Komponente wird unsichtbar im Hintergrund gemountet. Sie öffnet das Seitenpanel nicht. Headless-Komponenten sind für Aktionen konzipiert, die Logik ausführen und sich anschließend selbst unmounten — zum Beispiel das Ausführen einer asynchronen Aufgabe, das Navigieren zu einer Seite oder das Anzeigen eines Bestätigungsdialogs. Sie lassen sich gut mit den unten beschriebenen SDK-Command-Komponenten kombinieren.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId, enqueueSnackbar } from 'twenty-sdk/front-component';
import { useEffect } from 'react';
const SyncTracker = () => {
@@ -953,7 +954,7 @@ Importieren Sie sie aus `twenty-sdk/command`:
Hier ist ein vollständiges Beispiel einer Headless-Front-Komponente, die `Command` verwendet, um eine Aktion aus dem Befehlsmenü auszuführen:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
@@ -989,7 +990,7 @@ export default defineFrontComponent({
Und ein Beispiel, das `CommandModal` verwendet, um vor der Ausführung um Bestätigung zu bitten:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
@@ -1027,12 +1028,12 @@ export default defineFrontComponent({
Verwenden Sie innerhalb Ihrer Komponente SDK-Hooks, um auf den aktuellen Benutzer, den Datensatz und die Komponenteninstanz zuzugreifen:
```tsx src/front-components/record-info.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
useUserId,
useRecordId,
useFrontComponentId,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
const RecordInfo = () => {
const userId = useUserId();
@@ -1081,8 +1082,9 @@ Frontend-Komponenten können Navigation, Modals und Benachrichtigungen mittels F
Hier ist ein Beispiel, das die Host-API verwendet, um nach Abschluss einer Aktion eine Snackbar anzuzeigen und das Seitenpanel zu schließen:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId } from 'twenty-sdk/front-component';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
@@ -1142,14 +1144,14 @@ Das Hinzufügen eines `command`-Felds zu `defineFrontComponent` registriert die
Mit dem Feld `conditionalAvailabilityExpression` können Sie basierend auf dem aktuellen Seitenkontext steuern, wann ein Befehl sichtbar ist. Importieren Sie typisierte Variablen und Operatoren aus `twenty-sdk`, um Ausdrücke zu erstellen:
```tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
pageType,
numberOfSelectedRecords,
objectPermissions,
everyEquals,
isDefined,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
export default defineFrontComponent({
universalIdentifier: '...',
@@ -1209,7 +1211,7 @@ export default defineFrontComponent({
Frontend-Komponenten können mit `getPublicAssetUrl` auf Dateien aus dem `public/`-Verzeichnis der App zugreifen:
```tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
const Logo = () => <img src={getPublicAssetUrl('logo.png')} alt="Logo" />;
@@ -1234,7 +1236,7 @@ Frontend-Komponenten unterstützen mehrere Styling-Ansätze. Sie können verwend
* **Beliebige CSS-in-JS-Bibliothek**, die mit React kompatibel ist
```tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Button, Tag, Status } from 'twenty-sdk/ui';
const StyledWidget = () => {
@@ -1261,7 +1263,7 @@ export default defineFrontComponent({
Skills definieren wiederverwendbare Anweisungen und Fähigkeiten, die KI-Agenten in Ihrem Arbeitsbereich verwenden können. Verwenden Sie `defineSkill()`, um Skills mit eingebauter Validierung zu definieren:
```ts src/skills/example-skill.ts
import { defineSkill } from 'twenty-sdk';
import { defineSkill } from 'twenty-sdk/define';
export default defineSkill({
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
@@ -1290,7 +1292,7 @@ Hauptpunkte:
Agenten sind KI-Assistenten, die innerhalb Ihres Workspaces leben. Verwenden Sie `defineAgent()`, um Agenten mit einem benutzerdefinierten System-Prompt zu erstellen:
```ts src/agents/example-agent.ts
import { defineAgent } from 'twenty-sdk';
import { defineAgent } from 'twenty-sdk/define';
export default defineAgent({
universalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
@@ -1316,7 +1318,7 @@ Hauptpunkte:
Ansichten sind gespeicherte Konfigurationen dafür, wie Datensätze eines Objekts angezeigt werden — einschließlich sichtbarer Felder, deren Reihenfolge sowie angewendeter Filter oder Gruppen. Verwenden Sie `defineView()`, um vorkonfigurierte Ansichten mit Ihrer App auszuliefern:
```ts src/views/example-view.ts
import { defineView, ViewKey } from 'twenty-sdk';
import { defineView, ViewKey } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { NAME_FIELD_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
@@ -1352,7 +1354,7 @@ Hauptpunkte:
Navigationsmenüeinträge fügen der Workspace-Seitenleiste benutzerdefinierte Einträge hinzu. Verwenden Sie `defineNavigationMenuItem()`, um auf Ansichten, externe URLs oder Objekte zu verlinken:
```ts src/navigation-menu-items/example-navigation-menu-item.ts
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk';
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk/define';
import { EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER } from '../views/example-view';
export default defineNavigationMenuItem({
@@ -1378,7 +1380,7 @@ Hauptpunkte:
Seitenlayouts ermöglichen es Ihnen, das Aussehen einer Datensatzdetailseite anzupassen — welche Tabs erscheinen, welche Widgets sich in jedem Tab befinden und wie sie angeordnet sind. Verwenden Sie `definePageLayout()`, um benutzerdefinierte Layouts mit Ihrer App auszuliefern:
```ts src/page-layouts/example-record-page-layout.ts
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk';
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from '../front-components/hello-world';
@@ -1441,7 +1443,7 @@ Verwenden Sie den Helper `getPublicAssetUrl` aus `twenty-sdk`, um die vollständ
**In einer Logikfunktion:**
```ts src/logic-functions/send-invoice.ts
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk';
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk/define';
const handler = async (): Promise<any> => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1466,7 +1468,7 @@ export default defineLogicFunction({
**In einer Frontend-Komponente:**
```tsx src/front-components/company-card.tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
export default defineFrontComponent(() => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1490,7 +1492,7 @@ yarn add axios
Importieren Sie es anschließend in Ihrem Code:
```ts src/logic-functions/fetch-data.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import axios from 'axios';
const handler = async (): Promise<any> => {
@@ -1511,7 +1513,7 @@ export default defineLogicFunction({
Dasselbe funktioniert für Frontend-Komponenten:
```tsx src/front-components/chart.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { format } from 'date-fns';
const DateWidget = () => {
@@ -1555,18 +1557,18 @@ yarn twenty add frontComponent
### Verfügbare Entitätstypen
| Entitätstyp | Befehl | Generierte Datei |
| ---------------------- | ------------------------------------ | ------------------------------------- |
| Objekt | `yarn twenty add object` | `src/objects/<name>.ts` |
| Feld | `yarn twenty add field` | `src/fields/<name>.ts` |
| Logikfunktion | `yarn twenty add logicFunction` | `src/logic-functions/<name>.ts` |
| Frontend-Komponente | `yarn twenty add frontComponent` | `src/front-components/<name>.tsx` |
| Rolle | `yarn twenty add role` | `src/roles/<name>.ts` |
| Skill | `yarn twenty add skill` | `src/skills/<name>.ts` |
| Agent | `yarn twenty add agent` | `src/agents/<name>.ts` |
| Ansicht | `yarn twenty add view` | `src/views/<name>.ts` |
| Navigationsmenüeintrag | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/<name>.ts` |
| Seitenlayout | `yarn twenty add pageLayout` | `src/page-layouts/<name>.ts` |
| Entitätstyp | Befehl | Generierte Datei |
| ---------------------- | ------------------------------------ | ------------------------------------------------------- |
| Objekt | `yarn twenty add object` | `src/objects/\<name>.ts` |
| Feld | `yarn twenty add field` | `src/fields/\<name>.ts` |
| Logikfunktion | `yarn twenty add logicFunction` | `src/logic-functions/\<name>.ts` |
| Frontend-Komponente | `yarn twenty add frontComponent` | `src/front-components/\<name>.tsx` |
| Rolle | `yarn twenty add role` | `src/roles/\<name>.ts` |
| Skill | `yarn twenty add skill` | `src/skills/\<name>.ts` |
| Agent | `yarn twenty add agent` | `src/agents/\<name>.ts` |
| Ansicht | `yarn twenty add view` | `src/views/\<name>.ts` |
| Navigationsmenüeintrag | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/\<name>.ts` |
| Seitenlayout | `yarn twenty add pageLayout` | `src/page-layouts/\<name>.ts` |
### Was der Scaffolder generiert
@@ -28,7 +28,7 @@ import {
defineRole,
PermissionFlag,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
export default defineRole({
universalIdentifier: '2c80f640-2083-4803-bb49-003e38279de6',
@@ -77,7 +77,7 @@ Ogni app deve avere esattamente una chiamata a `defineApplication` che descrive:
* **(Opzionali) Funzioni di pre-installazione/post-installazione**: funzioni logiche che vengono eseguite prima o dopo l'installazione.
```ts src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { defineApplication } from 'twenty-sdk/define';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
@@ -132,7 +132,7 @@ Il `defaultRoleUniversalIdentifier` in `application-config.ts` indica il ruolo p
Quando esegui lo scaffolding di una nuova app, la CLI crea un file di ruolo predefinito:
```ts src/roles/default-role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';
import { defineRole, PermissionFlag } from 'twenty-sdk/define';
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
'b648f87b-1d26-4961-b974-0908fd991061';
@@ -172,7 +172,7 @@ Note:
Gli oggetti personalizzati descrivono sia lo schema sia il comportamento per i record nel tuo spazio di lavoro. Usa `defineObject()` per definire oggetti con convalida integrata:
```ts postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';
import { defineObject, FieldType } from 'twenty-sdk/define';
enum PostCardStatus {
DRAFT = 'DRAFT',
@@ -261,7 +261,7 @@ ma non è consigliato.
Usa `defineField()` per aggiungere campi a oggetti che non possiedi — come gli oggetti standard di Twenty (Person, Company, ecc.) o oggetti di altre app. A differenza dei campi inline in `defineObject()`, i campi autonomi richiedono un `objectUniversalIdentifier` per specificare quale oggetto estendono:
```ts src/fields/company-loyalty-tier.field.ts
import { defineField, FieldType } from 'twenty-sdk';
import { defineField, FieldType } from 'twenty-sdk/define';
export default defineField({
universalIdentifier: 'f2a1b3c4-d5e6-7890-abcd-ef1234567890',
@@ -311,7 +311,7 @@ Supponiamo che un `PostCard` possa essere inviato a molti record `PostCardRecipi
**Passaggio 1: definisci il lato ONE_TO_MANY su PostCard** (il lato "uno"):
```ts src/fields/post-card-recipients-on-post-card.field.ts
import { defineField, FieldType, RelationType } from 'twenty-sdk';
import { defineField, FieldType, RelationType } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -338,7 +338,7 @@ export default defineField({
**Passaggio 2: definisci il lato MANY_TO_ONE su PostCardRecipient** (il lato "molti" — contiene la chiave esterna):
```ts src/fields/post-card-on-post-card-recipient.field.ts
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk';
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -379,7 +379,7 @@ import {
RelationType,
OnDeleteAction,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
import { SELF_HOSTING_USER_UNIVERSAL_IDENTIFIER } from '../objects/self-hosting-user.object';
export const PERSON_FIELD_ID = 'c3333333-3333-3333-3333-333333333333';
@@ -448,8 +448,8 @@ export default defineObject({
Ogni file di funzione usa `defineLogicFunction()` per esportare una configurazione con un handler e trigger opzionali.
```ts src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
import { CoreApiClient, type Person } from 'twenty-client-sdk/core';
const handler = async (params: RoutePayload) => {
@@ -518,7 +518,7 @@ Quando un trigger di tipo route invoca la tua funzione logica, questa riceve un
Importa il tipo `RoutePayload` da `twenty-sdk`:
```ts
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';
const handler = async (event: RoutePayload) => {
const { headers, queryStringParameters, pathParameters, body } = event;
@@ -530,15 +530,15 @@ const handler = async (event: RoutePayload) => {
Il tipo `RoutePayload` ha la seguente struttura:
| Proprietà | Tipo | Descrizione | Esempio |
| ---------------------------- | ------------------------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | Intestazioni HTTP (solo quelle elencate in `forwardedRequestHeaders`) | vedi la sezione sotto |
| `queryStringParameters` | `Record<string, string \| undefined>` | Parametri della query string (valori multipli uniti da virgole) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record<string, string \| undefined>` | Parametri di percorso estratti dal pattern della route | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Corpo della richiesta analizzato (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `boolean` | Indica se il corpo è codificato in base64 | |
| `requestContext.http.method` | `string` | Metodo HTTP (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | Percorso della richiesta non elaborato | |
| Proprietà | Tipo | Descrizione | Esempio |
| ---------------------------- | ------------------------------------------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record\<string, string \| undefined>` | Intestazioni HTTP (solo quelle elencate in `forwardedRequestHeaders`) | vedi la sezione sotto |
| `queryStringParameters` | `Record\<string, string \| undefined>` | Parametri della query string (valori multipli uniti da virgole) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record\<string, string \| undefined>` | Parametri di percorso estratti dal pattern della route | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Corpo della richiesta analizzato (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `boolean` | Indica se il corpo è codificato in base64 | |
| `requestContext.http.method` | `string` | Metodo HTTP (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | Percorso della richiesta non elaborato | |
#### forwardedRequestHeaders
@@ -583,7 +583,7 @@ Le funzioni logiche possono essere esposte come **strumenti** per gli agenti di
Per contrassegnare una funzione logica come strumento, imposta `isTool: true`:
```ts src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import { CoreApiClient } from 'twenty-client-sdk/core';
const handler = async (params: { companyName: string; domain?: string }) => {
@@ -649,7 +649,7 @@ export default defineLogicFunction({
Una funzione post-installazione è una funzione logica che viene eseguita automaticamente dopo che la tua app è stata installata in uno spazio di lavoro. Il server la esegue **dopo** che i metadati dell'app sono stati sincronizzati e il client SDK è stato generato, così lo spazio di lavoro è completamente pronto per l'uso e il nuovo schema è attivo. I casi d'uso tipici includono il popolamento di dati predefiniti, la creazione di record iniziali, la configurazione delle impostazioni dello spazio di lavoro o il provisioning di risorse su servizi di terze parti.
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Post install logic function executed successfully!', payload.previousVersion);
@@ -692,7 +692,7 @@ Punti chiave:
Una funzione di pre-install è una funzione logica che viene eseguita automaticamente durante l'installazione, **prima che venga applicata la migrazione dei metadati del workspace**. Condivide la stessa struttura di payload del post-install (`InstallPayload`), ma è posizionata prima nel flusso di installazione così da poter preparare lo stato da cui dipenderà la migrazione imminente — usi tipici includono il backup dei dati, la validazione della compatibilità con il nuovo schema o l'archiviazione di record che stanno per essere ristrutturati o eliminati.
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Pre install logic function executed successfully!', payload.previousVersion);
@@ -750,7 +750,7 @@ Il pre-install è sempre **sincrono** (blocca l'installazione e può interromper
Esempio — eseguire il seeding di un record `PostCard` predefinito dopo l'installazione:
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
@@ -782,7 +782,7 @@ export default definePostInstallLogicFunction({
Esempio — archiviare i record prima di una migrazione distruttiva:
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
@@ -854,7 +854,7 @@ I componenti front possono essere renderizzati in due posizioni all'interno di T
Il modo più rapido per vedere in azione un componente front-end è registrarlo come **comando**. Aggiungere un campo `command` con `isPinned: true` lo fa apparire come pulsante di azione rapida nell'angolo in alto a destra della pagina — nessun layout di pagina necessario:
```tsx src/front-components/hello-world.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
const HelloWorld = () => {
return (
@@ -915,7 +915,8 @@ I componenti front prevedono due modalità di rendering controllate dall'opzione
**Headless (`isHeadless: true`)** — Il componente viene montato in modo invisibile in background. Non apre il pannello laterale. I componenti headless sono pensati per azioni che eseguono una logica e poi si smontano — ad esempio, eseguire un'attività asincrona, navigare a una pagina o mostrare una finestra modale di conferma. Si abbinano naturalmente ai componenti Command dell'SDK descritti di seguito.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId, enqueueSnackbar } from 'twenty-sdk/front-component';
import { useEffect } from 'react';
const SyncTracker = () => {
@@ -953,7 +954,7 @@ Importali da `twenty-sdk/command`:
Ecco un esempio completo di componente front headless che usa `Command` per eseguire un'azione dal menu comandi:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
@@ -989,7 +990,7 @@ export default defineFrontComponent({
E un esempio che usa `CommandModal` per chiedere conferma prima di eseguire:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
@@ -1027,12 +1028,12 @@ export default defineFrontComponent({
All'interno del tuo componente, usa gli hook dell'SDK per accedere all'utente corrente, al record e all'istanza del componente:
```tsx src/front-components/record-info.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
useUserId,
useRecordId,
useFrontComponentId,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
const RecordInfo = () => {
const userId = useUserId();
@@ -1081,8 +1082,9 @@ I componenti front-end possono attivare navigazione, modali e notifiche utilizza
Ecco un esempio che usa l'API host per mostrare una snackbar e chiudere il pannello laterale dopo il completamento di un'azione:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId } from 'twenty-sdk/front-component';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
@@ -1142,14 +1144,14 @@ Aggiungere un campo `command` a `defineFrontComponent` registra il componente ne
Il campo `conditionalAvailabilityExpression` consente di controllare quando un comando è visibile in base al contesto della pagina corrente. Importa variabili tipizzate e operatori da `twenty-sdk` per costruire espressioni:
```tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
pageType,
numberOfSelectedRecords,
objectPermissions,
everyEquals,
isDefined,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
export default defineFrontComponent({
universalIdentifier: '...',
@@ -1209,7 +1211,7 @@ export default defineFrontComponent({
I componenti front-end possono accedere ai file dalla directory `public/` dell'app utilizzando `getPublicAssetUrl`:
```tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
const Logo = () => <img src={getPublicAssetUrl('logo.png')} alt="Logo" />;
@@ -1234,7 +1236,7 @@ I componenti front-end supportano diversi approcci di styling. Puoi usare:
* **Qualsiasi libreria CSS-in-JS** compatibile con React
```tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Button, Tag, Status } from 'twenty-sdk/ui';
const StyledWidget = () => {
@@ -1261,7 +1263,7 @@ export default defineFrontComponent({
Le skill definiscono istruzioni e capacità riutilizzabili che gli agenti IA possono utilizzare all'interno del tuo spazio di lavoro. Usa `defineSkill()` per definire skill con convalida integrata:
```ts src/skills/example-skill.ts
import { defineSkill } from 'twenty-sdk';
import { defineSkill } from 'twenty-sdk/define';
export default defineSkill({
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
@@ -1290,7 +1292,7 @@ Punti chiave:
Gli agenti sono assistenti IA che vivono all'interno del tuo spazio di lavoro. Usa `defineAgent()` per creare agenti con un prompt di sistema personalizzato:
```ts src/agents/example-agent.ts
import { defineAgent } from 'twenty-sdk';
import { defineAgent } from 'twenty-sdk/define';
export default defineAgent({
universalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
@@ -1316,7 +1318,7 @@ Punti chiave:
Le viste sono configurazioni salvate di come vengono visualizzati i record di un oggetto — inclusi quali campi sono visibili, il loro ordine e gli eventuali filtri o raggruppamenti applicati. Usa `defineView()` per fornire viste preconfigurate con la tua app:
```ts src/views/example-view.ts
import { defineView, ViewKey } from 'twenty-sdk';
import { defineView, ViewKey } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { NAME_FIELD_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
@@ -1352,7 +1354,7 @@ Punti chiave:
Le voci del menu di navigazione aggiungono elementi personalizzati alla barra laterale dello spazio di lavoro. Usa `defineNavigationMenuItem()` per collegarti a viste, URL esterni o oggetti:
```ts src/navigation-menu-items/example-navigation-menu-item.ts
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk';
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk/define';
import { EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER } from '../views/example-view';
export default defineNavigationMenuItem({
@@ -1378,7 +1380,7 @@ Punti chiave:
I layout di pagina ti consentono di personalizzare l'aspetto di una pagina dei dettagli di un record — quali schede compaiono, quali widget sono all'interno di ciascuna scheda e come sono disposti. Usa `definePageLayout()` per fornire layout personalizzati con la tua app:
```ts src/page-layouts/example-record-page-layout.ts
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk';
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from '../front-components/hello-world';
@@ -1441,7 +1443,7 @@ Usa l'helper `getPublicAssetUrl` da `twenty-sdk` per ottenere l'URL completo di
**In una funzione logica:**
```ts src/logic-functions/send-invoice.ts
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk';
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk/define';
const handler = async (): Promise<any> => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1466,7 +1468,7 @@ export default defineLogicFunction({
**In un componente front-end:**
```tsx src/front-components/company-card.tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
export default defineFrontComponent(() => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1490,7 +1492,7 @@ yarn add axios
Quindi importalo nel tuo codice:
```ts src/logic-functions/fetch-data.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import axios from 'axios';
const handler = async (): Promise<any> => {
@@ -1511,7 +1513,7 @@ export default defineLogicFunction({
Lo stesso vale per i componenti front-end:
```tsx src/front-components/chart.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { format } from 'date-fns';
const DateWidget = () => {
@@ -1555,18 +1557,18 @@ yarn twenty add frontComponent
### Tipi di entità disponibili
| Tipo di entità | Comando | File generato |
| ---------------------------- | ------------------------------------ | ------------------------------------- |
| Oggetto | `yarn twenty add object` | `src/objects/<name>.ts` |
| Campo | `yarn twenty add field` | `src/fields/<name>.ts` |
| Funzione logica | `yarn twenty add logicFunction` | `src/logic-functions/<name>.ts` |
| Componente front-end | `yarn twenty add frontComponent` | `src/front-components/<name>.tsx` |
| Ruolo | `yarn twenty add role` | `src/roles/<name>.ts` |
| Abilità | `yarn twenty add skill` | `src/skills/<name>.ts` |
| Agente | `yarn twenty add agent` | `src/agents/<name>.ts` |
| Vista | `yarn twenty add view` | `src/views/<name>.ts` |
| Voce del menu di navigazione | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/<name>.ts` |
| Layout di pagina | `yarn twenty add pageLayout` | `src/page-layouts/<name>.ts` |
| Tipo di entità | Comando | File generato |
| ---------------------------- | ------------------------------------ | ------------------------------------------------------- |
| Oggetto | `yarn twenty add object` | `src/objects/\<name>.ts` |
| Campo | `yarn twenty add field` | `src/fields/\<name>.ts` |
| Funzione logica | `yarn twenty add logicFunction` | `src/logic-functions/\<name>.ts` |
| Componente front-end | `yarn twenty add frontComponent` | `src/front-components/\<name>.tsx` |
| Ruolo | `yarn twenty add role` | `src/roles/\<name>.ts` |
| Abilità | `yarn twenty add skill` | `src/skills/\<name>.ts` |
| Agente | `yarn twenty add agent` | `src/agents/\<name>.ts` |
| Vista | `yarn twenty add view` | `src/views/\<name>.ts` |
| Voce del menu di navigazione | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/\<name>.ts` |
| Layout di pagina | `yarn twenty add pageLayout` | `src/page-layouts/\<name>.ts` |
### Cosa genera lo scaffolder
@@ -28,7 +28,7 @@ import {
defineRole,
PermissionFlag,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
export default defineRole({
universalIdentifier: '2c80f640-2083-4803-bb49-003e38279de6',
@@ -77,7 +77,7 @@ Todo app deve ter exatamente uma chamada a `defineApplication` que descreve:
* **(Opcional) Funções de pré-instalação/pós-instalação**: funções de lógica que são executadas antes ou depois da instalação.
```ts src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { defineApplication } from 'twenty-sdk/define';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
@@ -132,7 +132,7 @@ O campo `defaultRoleUniversalIdentifier` em `application-config.ts` designa o pa
Ao criar um novo app com o scaffold, a CLI cria um arquivo de papel padrão:
```ts src/roles/default-role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';
import { defineRole, PermissionFlag } from 'twenty-sdk/define';
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
'b648f87b-1d26-4961-b974-0908fd991061';
@@ -172,7 +172,7 @@ Notas:
Objetos personalizados descrevem tanto o esquema quanto o comportamento de registros no seu espaço de trabalho. Use `defineObject()` para definir objetos com validação integrada:
```ts postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';
import { defineObject, FieldType } from 'twenty-sdk/define';
enum PostCardStatus {
DRAFT = 'DRAFT',
@@ -261,7 +261,7 @@ mas isso não é recomendado.
Use `defineField()` para adicionar campos a objetos que não são seus — como objetos padrão do Twenty (Person, Company, etc.). ou a objetos de outros apps. Ao contrário dos campos inline em `defineObject()`, os campos independentes exigem um `objectUniversalIdentifier` para especificar qual objeto eles estendem:
```ts src/fields/company-loyalty-tier.field.ts
import { defineField, FieldType } from 'twenty-sdk';
import { defineField, FieldType } from 'twenty-sdk/define';
export default defineField({
universalIdentifier: 'f2a1b3c4-d5e6-7890-abcd-ef1234567890',
@@ -311,7 +311,7 @@ Suponha que um `PostCard` possa ser enviado para muitos registros `PostCardRecip
**Etapa 1: Defina o lado ONE_TO_MANY em PostCard** (o lado "um"):
```ts src/fields/post-card-recipients-on-post-card.field.ts
import { defineField, FieldType, RelationType } from 'twenty-sdk';
import { defineField, FieldType, RelationType } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -338,7 +338,7 @@ export default defineField({
**Etapa 2: Defina o lado MANY_TO_ONE em PostCardRecipient** (o lado "muitos" — contém a chave estrangeira):
```ts src/fields/post-card-on-post-card-recipient.field.ts
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk';
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -379,7 +379,7 @@ import {
RelationType,
OnDeleteAction,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
import { SELF_HOSTING_USER_UNIVERSAL_IDENTIFIER } from '../objects/self-hosting-user.object';
export const PERSON_FIELD_ID = 'c3333333-3333-3333-3333-333333333333';
@@ -448,8 +448,8 @@ export default defineObject({
Cada arquivo de função usa `defineLogicFunction()` para exportar uma configuração com um handler e gatilhos opcionais.
```ts src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
import { CoreApiClient, type Person } from 'twenty-client-sdk/core';
const handler = async (params: RoutePayload) => {
@@ -518,7 +518,7 @@ Quando um gatilho de rota invoca sua função de lógica, ela recebe um objeto `
Importe o tipo `RoutePayload` de `twenty-sdk`:
```ts
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';
const handler = async (event: RoutePayload) => {
const { headers, queryStringParameters, pathParameters, body } = event;
@@ -530,15 +530,15 @@ const handler = async (event: RoutePayload) => {
O tipo `RoutePayload` tem a seguinte estrutura:
| Propriedade | Tipo | Descrição | Exemplo |
| ---------------------------- | ------------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | Cabeçalhos HTTP (apenas aqueles listados em `forwardedRequestHeaders`) | veja a seção abaixo |
| `queryStringParameters` | `Record<string, string \| undefined>` | Parâmetros de query string (valores múltiplos unidos por vírgulas) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record<string, string \| undefined>` | Parâmetros de caminho extraídos do padrão de rota | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Corpo da requisição analisado (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `boolean` | Se o corpo está codificado em base64 | |
| `requestContext.http.method` | `string` | Método HTTP (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | Caminho bruto da requisição | |
| Propriedade | Tipo | Descrição | Exemplo |
| ---------------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record\<string, string \| undefined>` | Cabeçalhos HTTP (apenas aqueles listados em `forwardedRequestHeaders`) | veja a seção abaixo |
| `queryStringParameters` | `Record\<string, string \| undefined>` | Parâmetros de query string (valores múltiplos unidos por vírgulas) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record\<string, string \| undefined>` | Parâmetros de caminho extraídos do padrão de rota | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Corpo da requisição analisado (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `boolean` | Se o corpo está codificado em base64 | |
| `requestContext.http.method` | `string` | Método HTTP (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | Caminho bruto da requisição | |
#### forwardedRequestHeaders
@@ -583,7 +583,7 @@ Funções lógicas podem ser expostas como **ferramentas** para agentes de IA e
Para marcar uma função de lógica como ferramenta, defina `isTool: true`:
```ts src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import { CoreApiClient } from 'twenty-client-sdk/core';
const handler = async (params: { companyName: string; domain?: string }) => {
@@ -649,7 +649,7 @@ export default defineLogicFunction({
Uma função de pós-instalação é uma função lógica que é executada automaticamente assim que seu aplicativo terminar de ser instalado em um espaço de trabalho. O servidor a executa **depois** que os metadados do aplicativo forem sincronizados e o cliente do SDK for gerado, para que o espaço de trabalho esteja totalmente pronto para uso e o novo esquema esteja disponível. Casos de uso típicos incluem popular dados padrão, criar registros iniciais, configurar as definições do espaço de trabalho ou provisionar recursos em serviços de terceiros.
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Post install logic function executed successfully!', payload.previousVersion);
@@ -692,7 +692,7 @@ Pontos-chave:
Uma função de pré-instalação é uma função de lógica que é executada automaticamente durante a instalação, **antes que a migração de metadados do workspace seja aplicada**. Ela compartilha o mesmo formato de payload que a pós-instalação (`InstallPayload`), mas está posicionada mais cedo no fluxo de instalação para poder preparar o estado do qual a próxima migração depende — usos típicos incluem fazer backup de dados, validar a compatibilidade com o novo esquema ou arquivar registros que estão prestes a ser reestruturados ou removidos.
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Pre install logic function executed successfully!', payload.previousVersion);
@@ -750,7 +750,7 @@ A pré-instalação é sempre **síncrona** (ela bloqueia a instalação e pode
Exemplo — popular um registro `PostCard` padrão após a instalação:
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
@@ -782,7 +782,7 @@ export default definePostInstallLogicFunction({
Exemplo — arquivar registros antes de uma migração destrutiva:
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
@@ -854,7 +854,7 @@ Os componentes de front-end podem ser renderizados em dois locais dentro do Twen
A maneira mais rápida de ver um componente de front-end em ação é registrá-lo como um **comando**. Adicionar um campo `command` com `isPinned: true` faz com que ele apareça como um botão de ação rápida no canto superior direito da página — não é necessário layout de página:
```tsx src/front-components/hello-world.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
const HelloWorld = () => {
return (
@@ -915,7 +915,8 @@ Os componentes de front-end têm dois modos de renderização controlados pela o
**Headless (`isHeadless: true`)** — The component mounts invisibly in the background. Ele não abre o painel lateral. Componentes headless são projetados para ações que executam lógica e, em seguida, se desmontam — por exemplo, executar uma tarefa assíncrona, navegar para uma página ou exibir um modal de confirmação. Eles se combinam naturalmente com os componentes Command do SDK descritos abaixo.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId, enqueueSnackbar } from 'twenty-sdk/front-component';
import { useEffect } from 'react';
const SyncTracker = () => {
@@ -953,7 +954,7 @@ Importe-os de `twenty-sdk/command`:
Aqui está um exemplo completo de um componente de front-end headless usando `Command` para executar uma ação a partir do menu de comandos:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
@@ -989,7 +990,7 @@ export default defineFrontComponent({
E um exemplo usando `CommandModal` para solicitar confirmação antes de executar:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
@@ -1027,12 +1028,12 @@ export default defineFrontComponent({
Dentro do seu componente, use hooks do SDK para acessar o usuário atual, o registro e a instância do componente:
```tsx src/front-components/record-info.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
useUserId,
useRecordId,
useFrontComponentId,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
const RecordInfo = () => {
const userId = useUserId();
@@ -1081,8 +1082,9 @@ Componentes de front-end podem acionar navegação, modais e notificações usan
Aqui está um exemplo que usa a API do host para exibir um snackbar e fechar o painel lateral após a conclusão de uma ação:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId } from 'twenty-sdk/front-component';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
@@ -1142,14 +1144,14 @@ Adicionar um campo `command` a `defineFrontComponent` registra o componente no m
O campo `conditionalAvailabilityExpression` permite controlar quando um comando é visível com base no contexto da página atual. Importe variáveis tipadas e operadores de `twenty-sdk` para construir expressões:
```tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
pageType,
numberOfSelectedRecords,
objectPermissions,
everyEquals,
isDefined,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
export default defineFrontComponent({
universalIdentifier: '...',
@@ -1209,7 +1211,7 @@ export default defineFrontComponent({
Componentes de front-end podem acessar arquivos do diretório `public/` do app usando `getPublicAssetUrl`:
```tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
const Logo = () => <img src={getPublicAssetUrl('logo.png')} alt="Logo" />;
@@ -1234,7 +1236,7 @@ Componentes de front-end suportam várias abordagens de estilização. Você pod
* **Qualquer biblioteca CSS-in-JS** compatível com React
```tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Button, Tag, Status } from 'twenty-sdk/ui';
const StyledWidget = () => {
@@ -1261,7 +1263,7 @@ export default defineFrontComponent({
As habilidades definem instruções e capacidades reutilizáveis que os agentes de IA podem usar no seu espaço de trabalho. Use `defineSkill()` para definir habilidades com validação integrada:
```ts src/skills/example-skill.ts
import { defineSkill } from 'twenty-sdk';
import { defineSkill } from 'twenty-sdk/define';
export default defineSkill({
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
@@ -1290,7 +1292,7 @@ Pontos-chave:
Agentes são assistentes de IA que vivem dentro do seu espaço de trabalho. Use `defineAgent()` para criar agentes com um prompt de sistema personalizado:
```ts src/agents/example-agent.ts
import { defineAgent } from 'twenty-sdk';
import { defineAgent } from 'twenty-sdk/define';
export default defineAgent({
universalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
@@ -1316,7 +1318,7 @@ Pontos-chave:
As visualizações são configurações salvas de como os registros de um objeto são exibidos — incluindo quais campos são visíveis, sua ordem e quaisquer filtros ou grupos aplicados. Use `defineView()` para enviar visualizações pré-configuradas com seu app:
```ts src/views/example-view.ts
import { defineView, ViewKey } from 'twenty-sdk';
import { defineView, ViewKey } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { NAME_FIELD_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
@@ -1352,7 +1354,7 @@ Pontos-chave:
Os itens do menu de navegação adicionam entradas personalizadas à barra lateral do espaço de trabalho. Use `defineNavigationMenuItem()` para vincular a visualizações, URLs externas ou objetos:
```ts src/navigation-menu-items/example-navigation-menu-item.ts
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk';
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk/define';
import { EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER } from '../views/example-view';
export default defineNavigationMenuItem({
@@ -1378,7 +1380,7 @@ Pontos-chave:
Layouts de página permitem personalizar como uma página de detalhes do registro se parece — quais abas aparecem, quais widgets estão dentro de cada aba e como eles são organizados. Use `definePageLayout()` para enviar layouts personalizados com seu app:
```ts src/page-layouts/example-record-page-layout.ts
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk';
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from '../front-components/hello-world';
@@ -1441,7 +1443,7 @@ Use o helper `getPublicAssetUrl` de `twenty-sdk` para obter a URL completa de um
**Em uma função lógica:**
```ts src/logic-functions/send-invoice.ts
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk';
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk/define';
const handler = async (): Promise<any> => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1466,7 +1468,7 @@ export default defineLogicFunction({
**Em um componente de front-end:**
```tsx src/front-components/company-card.tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
export default defineFrontComponent(() => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1490,7 +1492,7 @@ yarn add axios
Em seguida, importe-o no seu código:
```ts src/logic-functions/fetch-data.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import axios from 'axios';
const handler = async (): Promise<any> => {
@@ -1511,7 +1513,7 @@ export default defineLogicFunction({
O mesmo vale para componentes de front-end:
```tsx src/front-components/chart.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { format } from 'date-fns';
const DateWidget = () => {
@@ -1555,18 +1557,18 @@ yarn twenty add frontComponent
### Tipos de entidade disponíveis
| Tipo de entidade | Comando | Arquivo gerado |
| ------------------------- | ------------------------------------ | ------------------------------------- |
| Objeto | `yarn twenty add object` | `src/objects/<name>.ts` |
| Campo | `yarn twenty add field` | `src/fields/<name>.ts` |
| Função lógica | `yarn twenty add logicFunction` | `src/logic-functions/<name>.ts` |
| Componente de front-end | `yarn twenty add frontComponent` | `src/front-components/<name>.tsx` |
| Função | `yarn twenty add role` | `src/roles/<name>.ts` |
| Habilidade | `yarn twenty add skill` | `src/skills/<name>.ts` |
| Agente | `yarn twenty add agent` | `src/agents/<name>.ts` |
| Vista | `yarn twenty add view` | `src/views/<name>.ts` |
| Item do menu de navegação | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/<name>.ts` |
| Layout da página | `yarn twenty add pageLayout` | `src/page-layouts/<name>.ts` |
| Tipo de entidade | Comando | Arquivo gerado |
| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
| Objeto | `yarn twenty add object` | `src/objects/\<name>.ts` |
| Campo | `yarn twenty add field` | `src/fields/\<name>.ts` |
| Função lógica | `yarn twenty add logicFunction` | `src/logic-functions/\<name>.ts` |
| Componente de front-end | `yarn twenty add frontComponent` | `src/front-components/\<name>.tsx` |
| Função | `yarn twenty add role` | `src/roles/\<name>.ts` |
| Habilidade | `yarn twenty add skill` | `src/skills/\<name>.ts` |
| Agente | `yarn twenty add agent` | `src/agents/\<name>.ts` |
| Vista | `yarn twenty add view` | `src/views/\<name>.ts` |
| Item do menu de navegação | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/\<name>.ts` |
| Layout da página | `yarn twenty add pageLayout` | `src/page-layouts/\<name>.ts` |
### O que o scaffolder gera
@@ -28,7 +28,7 @@ import {
defineRole,
PermissionFlag,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
export default defineRole({
universalIdentifier: '2c80f640-2083-4803-bb49-003e38279de6',
@@ -77,7 +77,7 @@ export default defineRole({
* **(Необязательно) Предустановочные / постустановочные функции**: логические функции, которые запускаются до или после установки.
```ts src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { defineApplication } from 'twenty-sdk/define';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
@@ -132,7 +132,7 @@ export default defineApplication({
Когда вы генерируете новое приложение, CLI создаёт файл роли по умолчанию:
```ts src/roles/default-role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';
import { defineRole, PermissionFlag } from 'twenty-sdk/define';
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
'b648f87b-1d26-4961-b974-0908fd991061';
@@ -172,7 +172,7 @@ export default defineRole({
Пользовательские объекты описывают как схему, так и поведение записей в вашем рабочем пространстве. Используйте `defineObject()` для определения объектов со встроенной валидацией:
```ts postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';
import { defineObject, FieldType } from 'twenty-sdk/define';
enum PostCardStatus {
DRAFT = 'DRAFT',
@@ -261,7 +261,7 @@ export default defineObject({
Используйте `defineField()` для добавления полей к объектам, которые вам не принадлежат — например, к стандартным объектам Twenty (Person, Company и т. д.). или к объектам из других приложений. В отличие от встроенных полей в `defineObject()`, отдельные поля требуют `objectUniversalIdentifier`, чтобы указать, какой объект они расширяют:
```ts src/fields/company-loyalty-tier.field.ts
import { defineField, FieldType } from 'twenty-sdk';
import { defineField, FieldType } from 'twenty-sdk/define';
export default defineField({
universalIdentifier: 'f2a1b3c4-d5e6-7890-abcd-ef1234567890',
@@ -311,7 +311,7 @@ export default defineField({
**Шаг 1: Определите сторону ONE_TO_MANY на PostCard** (сторона "one"):
```ts src/fields/post-card-recipients-on-post-card.field.ts
import { defineField, FieldType, RelationType } from 'twenty-sdk';
import { defineField, FieldType, RelationType } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -338,7 +338,7 @@ export default defineField({
**Шаг 2: Определите сторону MANY_TO_ONE на PostCardRecipient** (сторона "many" — содержит внешний ключ):
```ts src/fields/post-card-on-post-card-recipient.field.ts
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk';
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -379,7 +379,7 @@ import {
RelationType,
OnDeleteAction,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
import { SELF_HOSTING_USER_UNIVERSAL_IDENTIFIER } from '../objects/self-hosting-user.object';
export const PERSON_FIELD_ID = 'c3333333-3333-3333-3333-333333333333';
@@ -448,8 +448,8 @@ export default defineObject({
Каждый файл функции использует `defineLogicFunction()` для экспорта конфигурации с обработчиком и необязательными триггерами.
```ts src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
import { CoreApiClient, type Person } from 'twenty-client-sdk/core';
const handler = async (params: RoutePayload) => {
@@ -518,7 +518,7 @@ yarn twenty logs
Импортируйте тип `RoutePayload` из `twenty-sdk`:
```ts
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';
const handler = async (event: RoutePayload) => {
const { headers, queryStringParameters, pathParameters, body } = event;
@@ -530,15 +530,15 @@ const handler = async (event: RoutePayload) => {
Тип `RoutePayload` имеет следующую структуру:
| Свойство | Тип | Описание | Пример |
| ---------------------------- | ------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | HTTP-заголовки (только перечисленные в `forwardedRequestHeaders`) | см. раздел ниже |
| `queryStringParameters` | `Record<string, string \| undefined>` | Параметры строки запроса (несколько значений объединяются запятыми) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record<string, string \| undefined>` | Параметры пути, извлечённые из шаблона маршрута | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Разобранное тело запроса (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `логический тип` | Является ли тело закодированным в base64 | |
| `requestContext.http.method` | `строка` | Метод HTTP (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `строка` | Необработанный путь запроса | |
| Свойство | Тип | Описание | Пример |
| ---------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record\<string, string \| undefined>` | HTTP-заголовки (только перечисленные в `forwardedRequestHeaders`) | см. раздел ниже |
| `queryStringParameters` | `Record\<string, string \| undefined>` | Параметры строки запроса (несколько значений объединяются запятыми) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record\<string, string \| undefined>` | Параметры пути, извлечённые из шаблона маршрута | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Разобранное тело запроса (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `логический тип` | Является ли тело закодированным в base64 | |
| `requestContext.http.method` | `строка` | Метод HTTP (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `строка` | Необработанный путь запроса | |
#### forwardedRequestHeaders
@@ -583,7 +583,7 @@ const handler = async (event: RoutePayload) => {
Чтобы пометить логическую функцию как инструмент, установите `isTool: true`:
```ts src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import { CoreApiClient } from 'twenty-client-sdk/core';
const handler = async (params: { companyName: string; domain?: string }) => {
@@ -649,7 +649,7 @@ export default defineLogicFunction({
Послеустановочная функция — это функция логики, которая автоматически выполняется после завершения установки вашего приложения в рабочем пространстве. Сервер выполняет её **после** того, как метаданные приложения синхронизированы и клиент SDK сгенерирован, так что рабочее пространство полностью готово к использованию, а новая схема уже применена. Типичные сценарии использования включают предзаполнение данных по умолчанию, создание начальных записей, настройку параметров рабочего пространства или выделение ресурсов в сторонних сервисах.
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Post install logic function executed successfully!', payload.previousVersion);
@@ -692,7 +692,7 @@ yarn twenty exec --postInstall
Функция pre-install — это логическая функция, которая автоматически выполняется во время установки, **до применения миграции метаданных рабочего пространства**. Она использует ту же структуру полезной нагрузки, что и post-install (`InstallPayload`), но находится раньше в процессе установки, чтобы подготовить состояние, от которого зависит предстоящая миграция, — типичные сценарии включают резервное копирование данных, проверку совместимости с новой схемой или архивирование записей, которые будут реструктурированы или удалены.
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Pre install logic function executed successfully!', payload.previousVersion);
@@ -750,7 +750,7 @@ Pre-install всегда **синхронный** (он блокирует ус
Пример — создать запись `PostCard` по умолчанию после установки:
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
@@ -782,7 +782,7 @@ export default definePostInstallLogicFunction({
Пример — архивировать записи перед разрушительной миграцией:
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
@@ -854,7 +854,7 @@ export default definePreInstallLogicFunction({
Самый быстрый способ увидеть фронтенд-компонент в действии — зарегистрировать его как **команду**. Добавление поля `command` с `isPinned: true` делает его кнопкой быстрого действия в правом верхнем углу страницы — макет страницы не требуется:
```tsx src/front-components/hello-world.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
const HelloWorld = () => {
return (
@@ -915,7 +915,8 @@ export default defineFrontComponent({
**Headless (`isHeadless: true`)** — компонент монтируется невидимо в фоновом режиме. Он не открывает боковую панель. Компоненты headless предназначены для действий, которые выполняют логику и затем размонтируются — например, запуск асинхронной задачи, переход на страницу или показ модального окна подтверждения. Они естественно сочетаются с компонентами SDK Command, описанными ниже.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId, enqueueSnackbar } from 'twenty-sdk/front-component';
import { useEffect } from 'react';
const SyncTracker = () => {
@@ -953,7 +954,7 @@ export default defineFrontComponent({
Полный пример headless фронт-компонента, использующего `Command` для запуска действия из меню команд:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
@@ -989,7 +990,7 @@ export default defineFrontComponent({
А также пример с использованием `CommandModal` для запроса подтверждения перед выполнением:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
@@ -1027,12 +1028,12 @@ export default defineFrontComponent({
Внутри вашего компонента используйте хуки SDK для доступа к текущему пользователю, записи и экземпляру компонента:
```tsx src/front-components/record-info.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
useUserId,
useRecordId,
useFrontComponentId,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
const RecordInfo = () => {
const userId = useUserId();
@@ -1081,8 +1082,9 @@ export default defineFrontComponent({
Пример, который использует API хоста для показа snackbar и закрытия боковой панели после завершения действия:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId } from 'twenty-sdk/front-component';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
@@ -1142,14 +1144,14 @@ export default defineFrontComponent({
Поле `conditionalAvailabilityExpression` позволяет управлять видимостью команды в зависимости от текущего контекста страницы. Импортируйте типизированные переменные и операторы из `twenty-sdk`, чтобы составлять выражения:
```tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
pageType,
numberOfSelectedRecords,
objectPermissions,
everyEquals,
isDefined,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
export default defineFrontComponent({
universalIdentifier: '...',
@@ -1209,7 +1211,7 @@ export default defineFrontComponent({
Компоненты фронтенда могут получать доступ к файлам из каталога приложения `public/` с помощью `getPublicAssetUrl`:
```tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
const Logo = () => <img src={getPublicAssetUrl('logo.png')} alt="Logo" />;
@@ -1234,7 +1236,7 @@ export default defineFrontComponent({
* **Любая библиотека CSS-in-JS**, совместимая с React
```tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Button, Tag, Status } from 'twenty-sdk/ui';
const StyledWidget = () => {
@@ -1261,7 +1263,7 @@ export default defineFrontComponent({
Навыки определяют многократно используемые инструкции и возможности, которые агенты ИИ могут использовать в вашем рабочем пространстве. Используйте `defineSkill()` для определения навыков со встроенной валидацией:
```ts src/skills/example-skill.ts
import { defineSkill } from 'twenty-sdk';
import { defineSkill } from 'twenty-sdk/define';
export default defineSkill({
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
@@ -1290,7 +1292,7 @@ export default defineSkill({
Агенты — это ИИ-помощники, работающие в вашем рабочем пространстве. Используйте `defineAgent()` для создания агентов с пользовательским системным промптом:
```ts src/agents/example-agent.ts
import { defineAgent } from 'twenty-sdk';
import { defineAgent } from 'twenty-sdk/define';
export default defineAgent({
universalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
@@ -1316,7 +1318,7 @@ export default defineAgent({
Представления — это сохранённые конфигурации отображения записей объекта: какие поля видны, их порядок, а также применённые фильтры и группы. Используйте `defineView()` для поставки преднастроенных представлений вместе с вашим приложением:
```ts src/views/example-view.ts
import { defineView, ViewKey } from 'twenty-sdk';
import { defineView, ViewKey } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { NAME_FIELD_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
@@ -1352,7 +1354,7 @@ export default defineView({
Пункты навигационного меню добавляют пользовательские элементы в боковую панель рабочего пространства. Используйте `defineNavigationMenuItem()` для ссылок на представления, внешние URL или объекты:
```ts src/navigation-menu-items/example-navigation-menu-item.ts
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk';
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk/define';
import { EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER } from '../views/example-view';
export default defineNavigationMenuItem({
@@ -1378,7 +1380,7 @@ export default defineNavigationMenuItem({
Макеты страниц позволяют настраивать вид страницы с деталями записи: какие вкладки отображаются, какие виджеты внутри каждой вкладки и как они расположены. Используйте `definePageLayout()` для поставки пользовательских макетов вместе с вашим приложением:
```ts src/page-layouts/example-record-page-layout.ts
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk';
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from '../front-components/hello-world';
@@ -1441,7 +1443,7 @@ export default definePageLayout({
**В логической функции:**
```ts src/logic-functions/send-invoice.ts
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk';
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk/define';
const handler = async (): Promise<any> => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1466,7 +1468,7 @@ export default defineLogicFunction({
**В компоненте фронтенда:**
```tsx src/front-components/company-card.tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
export default defineFrontComponent(() => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1490,7 +1492,7 @@ yarn add axios
Затем импортируйте его в своём коде:
```ts src/logic-functions/fetch-data.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import axios from 'axios';
const handler = async (): Promise<any> => {
@@ -1511,7 +1513,7 @@ export default defineLogicFunction({
То же самое работает для компонентов фронтенда:
```tsx src/front-components/chart.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { format } from 'date-fns';
const DateWidget = () => {
@@ -1555,18 +1557,18 @@ yarn twenty add frontComponent
### Доступные типы сущностей
| Тип сущности | Команда | Сгенерированный файл |
| -------------------- | ------------------------------------ | ------------------------------------- |
| Объект | `yarn twenty add object` | `src/objects/<name>.ts` |
| Поле | `yarn twenty add field` | `src/fields/<name>.ts` |
| Логическая функция | `yarn twenty add logicFunction` | `src/logic-functions/<name>.ts` |
| Компонент фронтенда | `yarn twenty add frontComponent` | `src/front-components/<name>.tsx` |
| Роль | `yarn twenty add role` | `src/roles/<name>.ts` |
| Навык | `yarn twenty add skill` | `src/skills/<name>.ts` |
| Агент | `yarn twenty add agent` | `src/agents/<name>.ts` |
| Представление | `yarn twenty add view` | `src/views/<name>.ts` |
| Пункт меню навигации | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/<name>.ts` |
| Макет страницы | `yarn twenty add pageLayout` | `src/page-layouts/<name>.ts` |
| Тип сущности | Команда | Сгенерированный файл |
| -------------------- | ------------------------------------ | ------------------------------------------------------- |
| Объект | `yarn twenty add object` | `src/objects/\<name>.ts` |
| Поле | `yarn twenty add field` | `src/fields/\<name>.ts` |
| Логическая функция | `yarn twenty add logicFunction` | `src/logic-functions/\<name>.ts` |
| Компонент фронтенда | `yarn twenty add frontComponent` | `src/front-components/\<name>.tsx` |
| Роль | `yarn twenty add role` | `src/roles/\<name>.ts` |
| Навык | `yarn twenty add skill` | `src/skills/\<name>.ts` |
| Агент | `yarn twenty add agent` | `src/agents/\<name>.ts` |
| Представление | `yarn twenty add view` | `src/views/\<name>.ts` |
| Пункт меню навигации | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/\<name>.ts` |
| Макет страницы | `yarn twenty add pageLayout` | `src/page-layouts/\<name>.ts` |
### Что генерирует скэффолдер
@@ -28,7 +28,7 @@ import {
defineRole,
PermissionFlag,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
export default defineRole({
universalIdentifier: '2c80f640-2083-4803-bb49-003e38279de6',
@@ -77,7 +77,7 @@ Her uygulamanın, şunları tanımlayan tam olarak bir adet `defineApplication`
* **(İsteğe bağlı) Kurulum öncesi / kurulum sonrası fonksiyonlar**: kurulumdan önce veya sonra çalışan mantık fonksiyonları.
```ts src/application-config.ts
import { defineApplication } from 'twenty-sdk';
import { defineApplication } from 'twenty-sdk/define';
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role';
export default defineApplication({
@@ -132,7 +132,7 @@ Eğer [uygulamanızı yayımlamayı](/l/tr/developers/extend/apps/publishing) pl
Yeni bir uygulama iskeleti oluşturduğunuzda, CLI varsayılan bir rol dosyası oluşturur:
```ts src/roles/default-role.ts
import { defineRole, PermissionFlag } from 'twenty-sdk';
import { defineRole, PermissionFlag } from 'twenty-sdk/define';
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
'b648f87b-1d26-4961-b974-0908fd991061';
@@ -172,7 +172,7 @@ Notlar:
Özel nesneler, çalışma alanınızdaki kayıtlar için hem şemayı hem de davranışı tanımlar. Yerleşik doğrulamayla nesneler tanımlamak için `defineObject()` kullanın:
```ts postCard.object.ts
import { defineObject, FieldType } from 'twenty-sdk';
import { defineObject, FieldType } from 'twenty-sdk/define';
enum PostCardStatus {
DRAFT = 'DRAFT',
@@ -261,7 +261,7 @@ ancak bu önerilmez.
Sahibi olmadığınız nesnelere alan eklemek için `defineField()` kullanın — standart Twenty nesneleri (Person, Company, vb.) gibi. veya diğer uygulamalardaki nesneler. `defineObject()` içindeki satır içi alanların aksine, bağımsız alanlar hangi nesneyi genişlettiklerini belirtmek için bir `objectUniversalIdentifier` gerektirir:
```ts src/fields/company-loyalty-tier.field.ts
import { defineField, FieldType } from 'twenty-sdk';
import { defineField, FieldType } from 'twenty-sdk/define';
export default defineField({
universalIdentifier: 'f2a1b3c4-d5e6-7890-abcd-ef1234567890',
@@ -311,7 +311,7 @@ Bir `PostCard`'ın birçok `PostCardRecipient` kaydına gönderilebildiğini var
**Adım 1: PostCard üzerinde ONE_TO_MANY tarafını tanımlayın** ("bir" taraf):
```ts src/fields/post-card-recipients-on-post-card.field.ts
import { defineField, FieldType, RelationType } from 'twenty-sdk';
import { defineField, FieldType, RelationType } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -338,7 +338,7 @@ export default defineField({
**Adım 2: PostCardRecipient üzerinde MANY_TO_ONE tarafını tanımlayın** ("çok" taraf — yabancı anahtarı tutar):
```ts src/fields/post-card-on-post-card-recipient.field.ts
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk';
import { defineField, FieldType, RelationType, OnDeleteAction } from 'twenty-sdk/define';
import { POST_CARD_UNIVERSAL_IDENTIFIER } from '../objects/post-card.object';
import { POST_CARD_RECIPIENT_UNIVERSAL_IDENTIFIER } from '../objects/post-card-recipient.object';
@@ -379,7 +379,7 @@ import {
RelationType,
OnDeleteAction,
STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS,
} from 'twenty-sdk';
} from 'twenty-sdk/define';
import { SELF_HOSTING_USER_UNIVERSAL_IDENTIFIER } from '../objects/self-hosting-user.object';
export const PERSON_FIELD_ID = 'c3333333-3333-3333-3333-333333333333';
@@ -448,8 +448,8 @@ export default defineObject({
Her fonksiyon dosyası, bir işleyici ve isteğe bağlı tetikleyiciler içeren bir yapılandırmayı dışa aktarmak için `defineLogicFunction()` kullanır.
```ts src/logic-functions/createPostCard.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
import { CoreApiClient, type Person } from 'twenty-client-sdk/core';
const handler = async (params: RoutePayload) => {
@@ -519,7 +519,7 @@ Bir rota tetikleyicisi mantık fonksiyonunuzu çağırdığında,
`RoutePayload` türünü `twenty-sdk` içinden içe aktarın:
```ts
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk';
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';
const handler = async (event: RoutePayload) => {
const { headers, queryStringParameters, pathParameters, body } = event;
@@ -531,15 +531,15 @@ const handler = async (event: RoutePayload) => {
`RoutePayload` türünün yapısı şu şekildedir:
| Özellik | Tür | Açıklama | Örnek |
| ---------------------------- | ------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record<string, string \| undefined>` | HTTP başlıkları (`forwardedRequestHeaders` içinde listelenenlerle sınırlı) | aşağıdaki bölüme bakın |
| `queryStringParameters` | `Record<string, string \| undefined>` | Sorgu dizesi parametreleri (birden çok değer virgülle birleştirilir) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record<string, string \| undefined>` | Rota deseninden çıkarılan yol parametreleri | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Ayrıştırılmış istek gövdesi (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `boolean` | Gövdenin base64 ile kodlanıp kodlanmadığı | |
| `requestContext.http.method` | `string` | HTTP yöntemi (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | Ham istek yolu | |
| Özellik | Tür | Açıklama | Örnek |
| ---------------------------- | ------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `headers` | `Record\<string, string \| undefined>` | HTTP başlıkları (`forwardedRequestHeaders` içinde listelenenlerle sınırlı) | aşağıdaki bölüme bakın |
| `queryStringParameters` | `Record\<string, string \| undefined>` | Sorgu dizesi parametreleri (birden çok değer virgülle birleştirilir) | `/users?ids=1&ids=2&ids=3&name=Alice` -> `{ ids: '1,2,3', name: 'Alice' }` |
| `pathParameters` | `Record\<string, string \| undefined>` | Rota deseninden çıkarılan yol parametreleri | `/users/:id`, `/users/123` -> `{ id: '123' }` |
| `body` | `object \| null` | Ayrıştırılmış istek gövdesi (JSON) | `{ id: 1 }` -> `{ id: 1 }` |
| `isBase64Encoded` | `boolean` | Gövdenin base64 ile kodlanıp kodlanmadığı | |
| `requestContext.http.method` | `string` | HTTP yöntemi (GET, POST, PUT, PATCH, DELETE) | |
| `requestContext.http.path` | `string` | Ham istek yolu | |
#### forwardedRequestHeaders
@@ -584,7 +584,7 @@ Mantık işlevleri, yapay zeka ajanları ve iş akışları için **araçlar** o
Bir mantık fonksiyonunu araç olarak işaretlemek için `isTool: true` olarak ayarlayın:
```ts src/logic-functions/enrich-company.logic-function.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import { CoreApiClient } from 'twenty-client-sdk/core';
const handler = async (params: { companyName: string; domain?: string }) => {
@@ -650,7 +650,7 @@ export default defineLogicFunction({
Kurulum sonrası işlev, uygulamanız bir çalışma alanına yüklendikten sonra otomatik olarak çalışan bir mantık işlevidir. Sunucu, uygulamanın meta verileri senkronize edildikten ve SDK istemcisi oluşturulduktan **sonra** bunu yürütür; böylece çalışma alanı tamamen kullanıma hazırdır ve yeni şema kullanıma alınmıştır. Tipik kullanım örnekleri arasında varsayılan verilerin tohumlanması, başlangıç kayıtlarının oluşturulması, çalışma alanı ayarlarının yapılandırılması veya üçüncü taraf hizmetlerde kaynak sağlanması yer alır.
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Post install logic function executed successfully!', payload.previousVersion);
@@ -693,7 +693,7 @@ yarn twenty exec --postInstall
Kurulum öncesi işlev, kurulum sırasında otomatik olarak çalışan ve **çalışma alanı üstveri (metadata) geçişi uygulanmadan önce** yürütülen bir mantık işlevidir. Kurulum sonrası ile (`InstallPayload`) aynı yük (payload) biçimini paylaşır, ancak kurulum akışında daha erken konumlandığından yaklaşan geçişin bağlı olduğu durumu hazırlayabilir — tipik kullanımlar arasında verileri yedeklemek, yeni şemayla uyumluluğu doğrulamak veya yeniden yapılandırılacak ya da kaldırılacak kayıtları arşivlemek yer alır.
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Pre install logic function executed successfully!', payload.previousVersion);
@@ -751,7 +751,7 @@ Kurulum öncesi her zaman **senkron**dur (kurulumu bloke eder ve iptal edebilir)
Örnek — kurulumdan sonra varsayılan bir `PostCard` kaydı tohumlama:
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
@@ -783,7 +783,7 @@ export default definePostInstallLogicFunction({
Örnek — yıkıcı bir geçişten önce kayıtları arşivleme:
```ts src/logic-functions/pre-install.ts
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk';
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
import { createClient } from './generated/client';
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
@@ -855,7 +855,7 @@ Emin değilseniz, varsayılan olarak **kurulum sonrası**nı tercih edin. Yalnı
Bir ön uç bileşenini çalışırken görmenin en hızlı yolu, onu bir komut olarak kaydetmektir. `isPinned: true` ile bir `command` alanı eklemek, sayfanın sağ üst köşesinde hızlı işlem düğmesi olarak görünmesini sağlar — herhangi bir sayfa düzenine gerek yoktur:
```tsx src/front-components/hello-world.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
const HelloWorld = () => {
return (
@@ -916,7 +916,8 @@ Komutların ötesinde, bir ön uç bileşenini bir **sayfa düzeninde** widget o
**Headless (`isHeadless: true`)** — Bileşen arka planda görünmez şekilde bağlanır. Yan paneli açmaz. Headless bileşenler, mantığı çalıştırıp ardından kendilerini kaldıran eylemler için tasarlanmıştır — örneğin, bir async görevi çalıştırma, bir sayfaya gitme veya bir onay modalı gösterme. Aşağıda açıklanan SDK Command bileşenleriyle doğal olarak eşleşirler.
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent, useRecordId, enqueueSnackbar } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId, enqueueSnackbar } from 'twenty-sdk/front-component';
import { useEffect } from 'react';
const SyncTracker = () => {
@@ -954,7 +955,7 @@ Bunları `twenty-sdk/command` içinden içe aktarın:
`Command` kullanarak komut menüsünden bir eylem çalıştıran headless bir ön bileşenin tam örneği:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
@@ -990,7 +991,7 @@ export default defineFrontComponent({
Ve yürütmeden önce onay istemek için `CommandModal` kullanan bir örnek:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { CommandModal } from 'twenty-sdk/command';
const DeleteDraft = () => {
@@ -1028,12 +1029,12 @@ export default defineFrontComponent({
Bileşeninizin içinde, geçerli kullanıcıya, kayda ve bileşen örneğine erişmek için SDK hook'larını kullanın:
```tsx src/front-components/record-info.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
useUserId,
useRecordId,
useFrontComponentId,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
const RecordInfo = () => {
const userId = useUserId();
@@ -1082,8 +1083,9 @@ Kullanılabilir hook'lar:
Bir eylem tamamlandıktan sonra bir snackbar göstermek ve yan paneli kapatmak için host API'sini kullanan bir örnek:
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent, useRecordId } from 'twenty-sdk';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId } from 'twenty-sdk/front-component';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-sdk/clients';
const ArchiveRecord = () => {
@@ -1143,14 +1145,14 @@ export default defineFrontComponent({
`conditionalAvailabilityExpression` alanı, geçerli sayfa bağlamına göre bir komutun ne zaman görünür olacağını kontrol etmenizi sağlar. İfadeler oluşturmak için `twenty-sdk`'den türlendirilmiş değişkenleri ve operatörleri içe aktarın:
```tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import {
defineFrontComponent,
pageType,
numberOfSelectedRecords,
objectPermissions,
everyEquals,
isDefined,
} from 'twenty-sdk';
} from 'twenty-sdk/front-component';
export default defineFrontComponent({
universalIdentifier: '...',
@@ -1210,7 +1212,7 @@ export default defineFrontComponent({
Ön uç bileşenleri, `getPublicAssetUrl` kullanarak uygulamanın `public/` dizinindeki dosyalara erişebilir:
```tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
const Logo = () => <img src={getPublicAssetUrl('logo.png')} alt="Logo" />;
@@ -1235,7 +1237,7 @@ Ayrıntılar için [genel varlıklar bölümüne](#accessing-public-assets-with-
* **React ile uyumlu herhangi bir CSS-in-JS kitaplığı**
```tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { Button, Tag, Status } from 'twenty-sdk/ui';
const StyledWidget = () => {
@@ -1262,7 +1264,7 @@ export default defineFrontComponent({
Yetenekler, yapay zekâ ajanlarının çalışma alanınızda kullanabileceği yeniden kullanılabilir yönergeleri ve kabiliyetleri tanımlar. Yerleşik doğrulamayla yetenekleri tanımlamak için `defineSkill()` kullanın:
```ts src/skills/example-skill.ts
import { defineSkill } from 'twenty-sdk';
import { defineSkill } from 'twenty-sdk/define';
export default defineSkill({
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
@@ -1291,7 +1293,7 @@ export default defineSkill({
Ajanlar, çalışma alanınız içinde bulunan yapay zekâ asistanlarıdır. Özel bir sistem istemiyle ajanlar oluşturmak için `defineAgent()` kullanın:
```ts src/agents/example-agent.ts
import { defineAgent } from 'twenty-sdk';
import { defineAgent } from 'twenty-sdk/define';
export default defineAgent({
universalIdentifier: 'b3c4d5e6-f7a8-9012-bcde-f34567890123',
@@ -1317,7 +1319,7 @@ export default defineAgent({
Görünümler, bir nesnenin kayıtlarının nasıl görüntüleneceğine ilişkin kaydedilmiş yapılandırmalardır — hangi alanların görünür olacağını, sıralarını ve uygulanan filtreleri veya grupları içerir. Uygulamanızla önceden yapılandırılmış görünümler sunmak için `defineView()` kullanın:
```ts src/views/example-view.ts
import { defineView, ViewKey } from 'twenty-sdk';
import { defineView, ViewKey } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { NAME_FIELD_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
@@ -1353,7 +1355,7 @@ export default defineView({
Gezinme menüsü öğeleri, çalışma alanı kenar çubuğuna özel girişler ekler. Görünümlere, harici URL'lere veya nesnelere bağlanmak için `defineNavigationMenuItem()` kullanın:
```ts src/navigation-menu-items/example-navigation-menu-item.ts
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk';
import { defineNavigationMenuItem, NavigationMenuItemType } from 'twenty-sdk/define';
import { EXAMPLE_VIEW_UNIVERSAL_IDENTIFIER } from '../views/example-view';
export default defineNavigationMenuItem({
@@ -1379,7 +1381,7 @@ export default defineNavigationMenuItem({
Sayfa düzenleri, bir kayıt ayrıntı sayfasının nasıl görüneceğini özelleştirmenizi sağlar — hangi sekmelerin görüneceği, her sekmenin içinde hangi widget'ların olacağı ve bunların nasıl düzenleneceği. Uygulamanızla özel düzenler sunmak için `definePageLayout()` kullanın:
```ts src/page-layouts/example-record-page-layout.ts
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk';
import { definePageLayout, PageLayoutTabLayoutMode } from 'twenty-sdk/define';
import { EXAMPLE_OBJECT_UNIVERSAL_IDENTIFIER } from '../objects/example-object';
import { HELLO_WORLD_FRONT_COMPONENT_UNIVERSAL_IDENTIFIER } from '../front-components/hello-world';
@@ -1442,7 +1444,7 @@ Uygulamanızın kökündeki `public/` klasörü, statik dosyaları barındırır
**Bir mantık işlevinde:**
```ts src/logic-functions/send-invoice.ts
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk';
import { defineLogicFunction, getPublicAssetUrl } from 'twenty-sdk/define';
const handler = async (): Promise<any> => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1467,7 +1469,7 @@ export default defineLogicFunction({
**Bir ön uç bileşeninde:**
```tsx src/front-components/company-card.tsx
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk';
import { defineFrontComponent, getPublicAssetUrl } from 'twenty-sdk/define';
export default defineFrontComponent(() => {
const logoUrl = getPublicAssetUrl('logo.png');
@@ -1491,7 +1493,7 @@ yarn add axios
Ardından kodunuza içe aktarın:
```ts src/logic-functions/fetch-data.ts
import { defineLogicFunction } from 'twenty-sdk';
import { defineLogicFunction } from 'twenty-sdk/define';
import axios from 'axios';
const handler = async (): Promise<any> => {
@@ -1512,7 +1514,7 @@ export default defineLogicFunction({
Aynısı ön uç bileşenleri için de geçerlidir:
```tsx src/front-components/chart.tsx
import { defineFrontComponent } from 'twenty-sdk';
import { defineFrontComponent } from 'twenty-sdk/define';
import { format } from 'date-fns';
const DateWidget = () => {
@@ -1556,18 +1558,18 @@ yarn twenty add frontComponent
### Kullanılabilir varlık türleri
| Varlık türü | Komut | Oluşturulan dosya |
| -------------------- | ------------------------------------ | ------------------------------------- |
| Nesne | `yarn twenty add object` | `src/objects/<name>.ts` |
| Alan | `yarn twenty add field` | `src/fields/<name>.ts` |
| Mantık işlevi | `yarn twenty add logicFunction` | `src/logic-functions/<name>.ts` |
| Ön uç bileşeni | `yarn twenty add frontComponent` | `src/front-components/<name>.tsx` |
| Rol | `yarn twenty add role` | `src/roles/<name>.ts` |
| Beceri | `yarn twenty add skill` | `src/skills/<name>.ts` |
| Temsilci | `yarn twenty add agent` | `src/agents/<name>.ts` |
| Görünüm | `yarn twenty add view` | `src/views/<name>.ts` |
| Gezinme menüsü öğesi | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/<name>.ts` |
| Sayfa düzeni | `yarn twenty add pageLayout` | `src/page-layouts/<name>.ts` |
| Varlık türü | Komut | Oluşturulan dosya |
| -------------------- | ------------------------------------ | ------------------------------------------------------- |
| Nesne | `yarn twenty add object` | `src/objects/\<name>.ts` |
| Alan | `yarn twenty add field` | `src/fields/\<name>.ts` |
| Mantık işlevi | `yarn twenty add logicFunction` | `src/logic-functions/\<name>.ts` |
| Ön uç bileşeni | `yarn twenty add frontComponent` | `src/front-components/\<name>.tsx` |
| Rol | `yarn twenty add role` | `src/roles/\<name>.ts` |
| Beceri | `yarn twenty add skill` | `src/skills/\<name>.ts` |
| Temsilci | `yarn twenty add agent` | `src/agents/\<name>.ts` |
| Görünüm | `yarn twenty add view` | `src/views/\<name>.ts` |
| Gezinme menüsü öğesi | `yarn twenty add navigationMenuItem` | `src/navigation-menu-items/\<name>.ts` |
| Sayfa düzeni | `yarn twenty add pageLayout` | `src/page-layouts/\<name>.ts` |
### İskelet oluşturucunun ürettikleri
File diff suppressed because one or more lines are too long
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Kalender"
@@ -5582,7 +5581,6 @@ msgstr "E-posdomeine"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "E-posse"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Lêeroplaai het misluk"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Lêers"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Los die betalingsprobleem op om jou ondernemingsfunksies aktief te hou."
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Vloei"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Tuis"
@@ -10379,16 +10370,6 @@ msgstr "Nie gedeel deur {notSharedByFullName} nie"
msgid "Not synced"
msgstr "Nie gesinkroniseer nie"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Nota"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notas"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Taaktitel"
msgid "Task Title"
msgstr "Taaktitel"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Take"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Hierdie aksie sal hierdie vouer en al {2} navigasiekieslysitems daarin u
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Hierdie aksie sal hierdie vouer en die navigasiekieslysitem daarin uitvee. Wil jy voortgaan?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Tydsone"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Tydlyn"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "تقويم"
@@ -5582,7 +5581,6 @@ msgstr "نطاقات البريد الإلكتروني"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "رسائل البريد الإلكتروني"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "فشل رفع الملف"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "ملفات"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "عالج مشكلة الدفع للإبقاء على ميزات Enterpri
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "تدفق"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "الرئيسية"
@@ -10379,16 +10370,6 @@ msgstr "لم تتم المشاركة من قِبَل {notSharedByFullName}"
msgid "Not synced"
msgstr "غير متزامن"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "ملاحظة"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "الملاحظات"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "عنوان المهمة"
msgid "Task Title"
msgstr "عنوان المهمة"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "المهام"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "سيؤدي هذا الإجراء إلى حذف هذا المجلد وج
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "سيؤدي هذا الإجراء إلى حذف هذا المجلد وعنصر قائمة التنقل الموجود بداخله. هل تريد المتابعة؟"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "المنطقة الزمنية"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "الجدول الزمني"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Calendari"
@@ -5582,7 +5581,6 @@ msgstr "Dominis de correu"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Correus electrònics"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "No s'ha pogut carregar el fitxer"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Arxius"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Solucioneu el problema de pagament per mantenir actives les funcionalita
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Flux"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Inici"
@@ -10379,16 +10370,6 @@ msgstr "No compartit per {notSharedByFullName}"
msgid "Not synced"
msgstr "No sincronitzat"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Nota"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notes"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Títol de la tasca"
msgid "Task Title"
msgstr "Títol de la tasca"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Tasques"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Aquesta acció suprimirà aquesta carpeta i tots els {2} elements del me
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Aquesta acció suprimirà aquesta carpeta i l'element del menú de navegació que conté. Vols continuar?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Zona horària"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Cronologia"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Kalendář"
@@ -5582,7 +5581,6 @@ msgstr "E-mailové domény"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "E-maily"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Nahrání souboru se nezdařilo"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Soubory"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Vyřešte problém s platbou, aby vaše funkce Enterprise zůstaly aktiv
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Tok"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Domů"
@@ -10379,16 +10370,6 @@ msgstr "Nesdíleno uživatelem {notSharedByFullName}"
msgid "Not synced"
msgstr "Nesynchronizováno"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Poznámka"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Poznámky"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Název úkolu"
msgid "Task Title"
msgstr "Název úkolu"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Úkoly"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Tato akce smaže tuto složku včetně všech {2} položek navigačního
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Tato akce smaže tuto složku a položku navigačního menu uvnitř. Chcete pokračovat?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Časové pásmo"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Časová osa"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Kalender"
@@ -5582,7 +5581,6 @@ msgstr "E-mail-domæner"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "E-mails"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Filupload mislykkedes"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Filer"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Løs betalingsproblemet for at holde dine Enterprise-funktioner aktive."
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Strøm"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Hjem"
@@ -10379,16 +10370,6 @@ msgstr "Ikke delt af {notSharedByFullName}"
msgid "Not synced"
msgstr "Ikke synkroniseret"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Notat"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Noter"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Opgavetitel"
msgid "Task Title"
msgstr "Opgavetitel"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Opgaver"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14340,6 +14316,11 @@ msgstr "Denne handling vil slette denne mappe og alle de {2} navigationsmenupunk
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Denne handling vil slette denne mappe og navigationsmenupunktet i den. Vil du fortsætte?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14529,7 +14510,6 @@ msgid "Time zone"
msgstr "Tidszone"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Tidslinje"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Kalender"
@@ -5582,7 +5581,6 @@ msgstr "E-Mail-Domänen"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "E-Mails"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Datei-Upload fehlgeschlagen"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Dateien"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Beheben Sie das Zahlungsproblem, um Ihre Enterprise-Funktionen aktiv zu
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Fluss"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Startseite"
@@ -10379,16 +10370,6 @@ msgstr "Nicht geteilt von {notSharedByFullName}"
msgid "Not synced"
msgstr "Nicht synchronisiert"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Notiz"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notizen"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Aufgabentitel"
msgid "Task Title"
msgstr "Aufgabentitel"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Aufgaben"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Diese Aktion löscht diesen Ordner und alle {2} enthaltenen Navigationsm
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Diese Aktion löscht diesen Ordner und das enthaltene Navigationsmenüelement. Möchten Sie fortfahren?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Zeitzone"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Zeitleiste"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Ημερολόγιο"
@@ -5582,7 +5581,6 @@ msgstr "Περιοχές Email"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Ηλεκτρονικά ταχυδρομεία"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Απέτυχε η μεταφόρτωση αρχείου"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Αρχεία"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Διορθώστε το πρόβλημα πληρωμής για να π
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Ροή"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Αρχική"
@@ -10379,16 +10370,6 @@ msgstr "Δεν κοινοποιήθηκε από τον/την {notSharedByFullN
msgid "Not synced"
msgstr "Δεν συγχρονίζεται"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Σημείωση"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Σημειώματα"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14040,11 +14021,6 @@ msgstr "Τίτλος Εργασίας"
msgid "Task Title"
msgstr "Τίτλος εργασίας"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Εργασίες"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14342,6 +14318,11 @@ msgstr "Αυτή η ενέργεια θα διαγράψει αυτόν τον
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Αυτή η ενέργεια θα διαγράψει αυτόν τον φάκελο και το στοιχείο μενού πλοήγησης μέσα. Θέλετε να συνεχίσετε;"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14531,7 +14512,6 @@ msgid "Time zone"
msgstr "Ζώνη ώρας"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Χρονολόγιο"
+5 -25
View File
@@ -2740,7 +2740,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Calendar"
@@ -5577,7 +5576,6 @@ msgstr "Emailing Domains"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Emails"
@@ -6899,11 +6897,6 @@ msgstr "File no longer exists - {0}"
msgid "File upload failed"
msgstr "File upload failed"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Files"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7022,7 +7015,6 @@ msgstr "Fix the payment issue to keep your enterprise features active."
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Flow"
@@ -7467,7 +7459,6 @@ msgid "Hide label"
msgstr "Hide label"
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Home"
@@ -10374,16 +10365,6 @@ msgstr "Not shared by {notSharedByFullName}"
msgid "Not synced"
msgstr "Not synced"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Note"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notes"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14033,11 +14014,6 @@ msgstr "Task title"
msgid "Task Title"
msgstr "Task Title"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Tasks"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14335,6 +14311,11 @@ msgstr "This action will delete this folder and all {2} navigation menu items in
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr "This app"
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14524,7 +14505,6 @@ msgid "Time zone"
msgstr "Time zone"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Timeline"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Calendario"
@@ -5582,7 +5581,6 @@ msgstr "Dominios de correo electrónico"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Correos electrónicos"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Error al subir el archivo"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Archivos"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Soluciona el problema de pago para mantener activas tus funciones Enterp
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Flujo"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Inicio"
@@ -10379,16 +10370,6 @@ msgstr "No compartido por {notSharedByFullName}"
msgid "Not synced"
msgstr "No sincronizado"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Nota"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notas"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Título de la tarea"
msgid "Task Title"
msgstr "Título de la tarea"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Tareas"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14340,6 +14316,11 @@ msgstr "Esta acción eliminará esta carpeta y todos los {2} elementos del menú
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Esta acción eliminará esta carpeta y el elemento del menú de navegación que contiene. ¿Deseas continuar?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14529,7 +14510,6 @@ msgid "Time zone"
msgstr "Zona horaria"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Cronología"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Kalenteri"
@@ -5582,7 +5581,6 @@ msgstr "Sähköpostitoimialueet"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Sähköpostit"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Tiedoston lähetys epäonnistui"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Tiedostot"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Korjaa maksuongelma pitääksesi Enterprise-ominaisuudet aktiivisina."
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Virtaus"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Koti"
@@ -10379,16 +10370,6 @@ msgstr "Ei jaettu käyttäjän {notSharedByFullName} toimesta"
msgid "Not synced"
msgstr "Ei synkronoitu"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Muistiinpano"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Muistiinpanot"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Tehtävän otsikko"
msgid "Task Title"
msgstr "Tehtävän otsikko"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Tehtävät"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Tämä toiminto poistaa tämän kansion ja kaikki {2} navigointivalikon
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Tämä toiminto poistaa tämän kansion ja sen sisällä olevan navigointivalikon valikkokohdan. Haluatko jatkaa?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Aikavyöhyke"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Aikajana"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Calendrier"
@@ -5582,7 +5581,6 @@ msgstr "Domaines d'envoi d'e-mail"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Courriels"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Échec du téléversement du fichier"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Fichiers"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Résolvez le problème de paiement pour garder vos fonctionnalités Ente
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Flux"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Accueil"
@@ -10379,16 +10370,6 @@ msgstr "Non partagé par {notSharedByFullName}"
msgid "Not synced"
msgstr "Non synchronisé"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Note"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notes"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Titre de la tâche"
msgid "Task Title"
msgstr "Titre de la tâche"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Tâches"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14340,6 +14316,11 @@ msgstr "Cette action supprimera ce dossier et les {2} éléments du menu de navi
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Cette action supprimera ce dossier ainsi que l'élément du menu de navigation qu'il contient. Voulez-vous continuer ?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14529,7 +14510,6 @@ msgid "Time zone"
msgstr "Fuseau horaire"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Chronologie"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "לוח שנה"
@@ -5582,7 +5581,6 @@ msgstr "<span dir=\"rtl\">דומיינים לשליחת מיילים</span>"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "דוא\"לים"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "העלאת הקובץ נכשלה"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "קבצים"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "תקן את בעיית התשלום כדי לשמור על תכונות
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "זרם"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "בית"
@@ -10379,16 +10370,6 @@ msgstr "לא שותף על ידי {notSharedByFullName}"
msgid "Not synced"
msgstr "לא מסונכרן"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "הערה"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "הערות"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "כותרת המשימה"
msgid "Task Title"
msgstr "כותרת המשימה"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "משימות"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "פעולה זו תמחק את התיקייה הזו ואת כל {2} הפ
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "פעולה זו תמחק את התיקייה הזו ואת הפריט בתפריט הניווט שבתוכה. האם להמשיך?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "אזור זמן"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "ציר זמן"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Naptár"
@@ -5582,7 +5581,6 @@ msgstr "Emailküldési Tartományok"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Emailek"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Fájl feltöltése nem sikerült"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Fájlok"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Oldja meg a fizetési problémát, hogy az Enterprise funkciók aktívak
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Folyamat"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Kezdőlap"
@@ -10379,16 +10370,6 @@ msgstr "Nem osztotta meg {notSharedByFullName}"
msgid "Not synced"
msgstr "Nincs szinkronizálva"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Megjegyzés"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Jegyzetek"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Feladat címe"
msgid "Task Title"
msgstr "Feladat címe"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Feladatok"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Ez a művelet törli ezt a mappát és a benne lévő összes {2} navig
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Ez a művelet törli ezt a mappát és a benne lévő navigációs menüelemet. Szeretné folytatni?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Időzóna"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Idővonal"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Calendario"
@@ -5582,7 +5581,6 @@ msgstr "Domini di email"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Email"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Caricamento del file non riuscito"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "File"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Risolvi il problema di pagamento per mantenere attive le funzionalità E
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Flusso"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Home"
@@ -10379,16 +10370,6 @@ msgstr "Non condiviso da {notSharedByFullName}"
msgid "Not synced"
msgstr "Non sincronizzato"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Nota"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Note"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Titolo dell'attività"
msgid "Task Title"
msgstr "Titolo dell'attività"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Attività"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14340,6 +14316,11 @@ msgstr "Questa azione eliminerà questa cartella e tutte le {2} voci del menu di
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Questa azione eliminerà questa cartella e la voce del menu di navigazione al suo interno. Vuoi continuare?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14529,7 +14510,6 @@ msgid "Time zone"
msgstr "Fuso orario"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Sequenza temporale"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "カレンダー"
@@ -5582,7 +5581,6 @@ msgstr "メール送信用ドメイン"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "メール"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "ファイルのアップロードに失敗しました"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "ファイル"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Enterprise 機能を有効のままに保つには、支払いの問題
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "フロー"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "ホーム"
@@ -10379,16 +10370,6 @@ msgstr "{notSharedByFullName}によって共有されていません"
msgid "Not synced"
msgstr "同期されていません"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "ノート"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "ノート"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "タスクのタイトル"
msgid "Task Title"
msgstr "タスクのタイトル"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "タスク"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "このフォルダーと中の {2} 件のナビゲーションメニュ
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "このフォルダーと中のナビゲーションメニュー項目が削除されます。続行しますか?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "タイムゾーン"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "タイムライン"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "캘린더"
@@ -5582,7 +5581,6 @@ msgstr "이메일 도메인"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "이메일"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "파일 업로드 실패"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "파일"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "엔터프라이즈 기능을 계속 사용하려면 결제 문제를 해
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "흐름"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "홈"
@@ -10379,16 +10370,6 @@ msgstr "{notSharedByFullName}에 의해 공유되지 않음"
msgid "Not synced"
msgstr "동기화되지 않음"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "노트"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "노트"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "작업 제목"
msgid "Task Title"
msgstr "작업 제목"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "작업"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "이 작업을 수행하면 이 폴더와 내부의 내비게이션 메
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "이 작업을 수행하면 이 폴더와 내부의 내비게이션 메뉴 항목이 삭제됩니다. 계속하시겠습니까?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "시간대"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "타임라인"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Kalender"
@@ -5582,7 +5581,6 @@ msgstr "E-maildomeinen"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "E-mails"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Niet gelukt om bestand te uploaden"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Bestanden"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Los het betalingsprobleem op om uw Enterprise-functies actief te houden.
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Stroom"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Home"
@@ -10379,16 +10370,6 @@ msgstr "Niet gedeeld door {notSharedByFullName}"
msgid "Not synced"
msgstr "Niet gesynchroniseerd"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Notitie"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notities"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Taaktitel"
msgid "Task Title"
msgstr "Taaktitel"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Taken"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14340,6 +14316,11 @@ msgstr "Deze actie verwijdert deze map en alle {2} navigatiemenu-items erin. Wil
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Deze actie verwijdert deze map en het navigatiemenu-item erin. Wil je doorgaan?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14529,7 +14510,6 @@ msgid "Time zone"
msgstr "Tijdzone"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Tijdlijn"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Kalender"
@@ -5582,7 +5581,6 @@ msgstr "E-postdomener"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "E-poster"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Filopplasting mislyktes"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Filer"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Løs betalingsproblemet for å holde Enterprise-funksjonene aktive."
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Flyt"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Hjem"
@@ -10379,16 +10370,6 @@ msgstr "Ikke delt av {notSharedByFullName}"
msgid "Not synced"
msgstr "Ikke synkronisert"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Notat"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notater"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Oppgavetittel"
msgid "Task Title"
msgstr "Oppgavetittel"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Oppgaver"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Denne handlingen vil slette denne mappen og alle {2} navigasjonsmenyelem
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Denne handlingen vil slette denne mappen og navigasjonsmenyelementet i den. Vil du fortsette?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Tidssone"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Tidslinje"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Kalendarz"
@@ -5582,7 +5581,6 @@ msgstr "Domeny wysyłkowe"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Emaile"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Nie udało się przesłać pliku"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Pliki"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Rozwiąż problem z płatnością, aby utrzymać aktywne funkcje Enterpr
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Przepływ"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Strona główna"
@@ -10379,16 +10370,6 @@ msgstr "Nie udostępnione przez {notSharedByFullName}"
msgid "Not synced"
msgstr "Niesynchronizowane"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Notatka"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "\"Notatki\""
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Tytuł zadania"
msgid "Task Title"
msgstr "Tytuł zadania"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Zadania"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Ta akcja usunie ten folder oraz {2, plural, one {# pozycję menu nawigac
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Ta akcja usunie ten folder oraz element menu nawigacji w środku. Czy chcesz kontynuować?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Strefa czasowa"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Oś czasu"
+5 -25
View File
@@ -2740,7 +2740,6 @@ msgstr ""
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr ""
@@ -5577,7 +5576,6 @@ msgstr ""
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr ""
@@ -6899,11 +6897,6 @@ msgstr ""
msgid "File upload failed"
msgstr ""
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr ""
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7022,7 +7015,6 @@ msgstr ""
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr ""
@@ -7467,7 +7459,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr ""
@@ -10374,16 +10365,6 @@ msgstr ""
msgid "Not synced"
msgstr ""
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr ""
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr ""
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14033,11 +14014,6 @@ msgstr ""
msgid "Task Title"
msgstr ""
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr ""
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14333,6 +14309,11 @@ msgstr ""
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr ""
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14522,7 +14503,6 @@ msgid "Time zone"
msgstr ""
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr ""
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Calendário"
@@ -5582,7 +5581,6 @@ msgstr "Domínios de E-mail"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "E-mails"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Falha ao carregar arquivo"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Arquivos"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Resolva o problema de pagamento para manter seus recursos Enterprise ati
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Fluxo"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Início"
@@ -10379,16 +10370,6 @@ msgstr "Não compartilhado por {notSharedByFullName}"
msgid "Not synced"
msgstr "Não sincronizado"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Nota"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notas"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Título da tarefa"
msgid "Task Title"
msgstr "Título da tarefa"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Tarefas"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Esta ação excluirá esta pasta e todos os {2} itens do menu de navega
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Esta ação excluirá esta pasta e o item do menu de navegação dentro dela. Deseja continuar?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Fuso horário"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Linha do Tempo"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Calendário"
@@ -5582,7 +5581,6 @@ msgstr "Domínios de Emails"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "E-mails"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Falha ao carregar o arquivo"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Arquivos"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Resolva o problema de pagamento para manter os seus recursos Enterprise
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Fluxo"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Início"
@@ -10379,16 +10370,6 @@ msgstr "Não compartilhado por {notSharedByFullName}"
msgid "Not synced"
msgstr "Não sincronizado"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Nota"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notas"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Título da Tarefa"
msgid "Task Title"
msgstr "Título da Tarefa"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Tarefas"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Esta ação eliminará esta pasta e todos os {2} itens do menu de navega
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr ""
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Fuso horário"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Linha do tempo"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Calendar"
@@ -5582,7 +5581,6 @@ msgstr "Domenii de email"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Emailuri"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Încărcarea fișierului a eșuat"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Fișiere"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Rezolvați problema de plată pentru a menține funcționalitățile Ent
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Flux"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Acasă"
@@ -10379,16 +10370,6 @@ msgstr "Nu este partajat de {notSharedByFullName}"
msgid "Not synced"
msgstr "Neacordat"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Notă"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notițe"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Titlul sarcinii"
msgid "Task Title"
msgstr "Titlul sarcinii"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Sarcini"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Această acțiune va șterge acest folder și toate cele {2} elemente di
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Această acțiune va șterge acest folder și elementul din meniul de navigare din interior. Doriți să continuați?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Fusul orar"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Cronologie"
Binary file not shown.
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Календар"
@@ -5582,7 +5581,6 @@ msgstr "Имејл домени"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Имејлови"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Отпремање датотеке није успело"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Датотеке"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Решите проблем са плаћањем да би ваше Ent
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Ток"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Почетна"
@@ -10379,16 +10370,6 @@ msgstr "Није дељено од стране {notSharedByFullName}"
msgid "Not synced"
msgstr "Није синхронизовано"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Белешка"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Белешке"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Наслов задатка"
msgid "Task Title"
msgstr "Наслов задатка"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Задаци"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Ова радња ће избрисати ову фасциклу и с
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Ова радња ће избрисати ову фасциклу и ставку навигационог менија унутар ње. Да ли желите да наставите?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Временска зона"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Трака времена"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Kalender"
@@ -5582,7 +5581,6 @@ msgstr "E-postdomäner"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "E-postmeddelanden"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Filuppladdningen misslyckades"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Filer"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Åtgärda betalningsproblemet för att dina Enterprise-funktioner ska fo
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Flöde"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Hem"
@@ -10381,16 +10372,6 @@ msgstr "Inte delad av {notSharedByFullName}"
msgid "Not synced"
msgstr "Inte synkroniserad"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Anteckning"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Anteckningar"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14044,11 +14025,6 @@ msgstr "Uppgiftstitel"
msgid "Task Title"
msgstr "Uppgiftstitel"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Uppgifter"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14346,6 +14322,11 @@ msgstr "Denna åtgärd kommer att ta bort denna mapp och alla {2} navigationsmen
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Denna åtgärd kommer att ta bort denna mapp och navigationsmenyalternativet i den. Vill du fortsätta?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14535,7 +14516,6 @@ msgid "Time zone"
msgstr "Tidszon"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Tidslinje"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Takvim"
@@ -5582,7 +5581,6 @@ msgstr "E-posta Alan Adları"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "E-postalar"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Dosya yükleme başarısız"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Dosyalar"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Kurumsal özelliklerinizin etkin kalması için ödeme sorununu giderin.
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Akış"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Ana sayfa"
@@ -10379,16 +10370,6 @@ msgstr "{notSharedByFullName} tarafından paylaşılmadı"
msgid "Not synced"
msgstr "Senkronize edilmedi"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Not"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Notlar"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Görev başlığı"
msgid "Task Title"
msgstr "Görev Başlığı"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Görevler"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Bu işlem bu klasörü ve içindeki tüm {2} gezinti menüsü öğesini
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Bu işlem bu klasörü ve içindeki gezinti menüsü öğesini silecek. Devam etmek istiyor musunuz?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Zaman dilimi"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Zaman Çizelgesi"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Календар"
@@ -5582,7 +5581,6 @@ msgstr "Домени відправки електронної пошти"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Електронні листи"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Не вдалося завантажити файл"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Файли"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Усуньте проблему з оплатою, щоб зберегт
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Потік"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Головна"
@@ -10379,16 +10370,6 @@ msgstr "Не поділився {notSharedByFullName}"
msgid "Not synced"
msgstr "Не синхронізовано"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Примітка"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Нотатки"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Назва завдання"
msgid "Task Title"
msgstr "Назва завдання"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Завдання"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14340,6 +14316,11 @@ msgstr "Ця дія видалить цю папку та всі {2} пункт
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Ця дія видалить цю папку та пункт навігаційного меню усередині. Продовжити?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14529,7 +14510,6 @@ msgid "Time zone"
msgstr "Часовий пояс"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Хронологія"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "Lịch"
@@ -5582,7 +5581,6 @@ msgstr "Tên miền Email"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "Thư điện tử"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "Tải tệp lên không thành công"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "Tập tin"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "Khắc phục sự cố thanh toán để giữ các tính năng Enterpr
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "Dòng chảy"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "Trang chủ"
@@ -10379,16 +10370,6 @@ msgstr "Không chia sẻ bởi {notSharedByFullName}"
msgid "Not synced"
msgstr "Chưa đồng bộ hóa"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "Ghi chú"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "Ghi chú"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "Tiêu đề nhiệm vụ"
msgid "Task Title"
msgstr "Tiêu đề nhiệm vụ"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "Nhiệm vụ"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "Hành động này sẽ xóa thư mục này và toàn bộ {2} mục me
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "Hành động này sẽ xóa thư mục này và mục menu điều hướng bên trong. Bạn có muốn tiếp tục không?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "Múi giờ"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "Dòng thời gian"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "日历"
@@ -5582,7 +5581,6 @@ msgstr "电子邮件发送域名"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "电子邮件"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "文件上传失败"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "文件"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "请解决付款问题以保持您的企业功能处于启用状态。"
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "流程"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "主页"
@@ -10379,16 +10370,6 @@ msgstr "未与 {notSharedByFullName} 共享"
msgid "Not synced"
msgstr "未同步"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "备注"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "备注"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "任务标题"
msgid "Task Title"
msgstr "任务标题"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "任务"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "此操作将删除此文件夹及其中的 {2} 个导航菜单项。是
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "此操作将删除此文件夹及其中的导航菜单项。是否继续?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "时区"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "时间轴"
+5 -25
View File
@@ -2745,7 +2745,6 @@ msgstr "caldav.example.com"
#. js-lingui-id: AjVXBS
#: src/modules/views/view-picker/constants/ViewPickerTypeSelectOptions.ts
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownLayoutContent.tsx
msgid "Calendar"
msgstr "日曆"
@@ -5582,7 +5581,6 @@ msgstr "電子郵件域名"
#: src/pages/settings/accounts/SettingsAccountsEmails.tsx
#: src/modules/settings/hooks/useSettingsNavigationItems.tsx
#: src/modules/settings/accounts/components/SettingsAccountsSettingsSection.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Emails"
msgstr "電子郵件"
@@ -6904,11 +6902,6 @@ msgstr ""
msgid "File upload failed"
msgstr "檔案上傳失敗"
#. js-lingui-id: sER+bs
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Files"
msgstr "檔案"
#. js-lingui-id: o7J4JM
#: src/modules/workflow/workflow-steps/workflow-actions/find-records-action/components/WorkflowEditActionFindRecords.tsx
#: src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx
@@ -7027,7 +7020,6 @@ msgstr "請修正付款問題以維持您的企業功能啟用。"
#. js-lingui-id: ylQd2j
#: src/modules/workflow/workflow-steps/workflow-actions/utils/getActionHeaderTypeOrThrow.ts
#: src/modules/side-panel/pages/workflow/action/components/SidePanelWorkflowSelectAction.tsx
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Flow"
msgstr "流程"
@@ -7472,7 +7464,6 @@ msgid "Hide label"
msgstr ""
#. js-lingui-id: i0qMbr
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/navigation/components/MainNavigationDrawerTabsRow.tsx
msgid "Home"
msgstr "首頁"
@@ -10379,16 +10370,6 @@ msgstr "未由 {notSharedByFullName} 分享"
msgid "Not synced"
msgstr "未同步"
#. js-lingui-id: KiJn9B
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Note"
msgstr "備註"
#. js-lingui-id: 1DBGsz
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Notes"
msgstr "備註"
#. js-lingui-id: DYCPYF
#: src/modules/page-layout/widgets/components/StandaloneWidgetPlaceholder.tsx
msgid "Nothing to see"
@@ -14038,11 +14019,6 @@ msgstr "任務標題"
msgid "Task Title"
msgstr "任務標題"
#. js-lingui-id: GtycJ/
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
msgid "Tasks"
msgstr "任務"
#. js-lingui-id: lKXcJz
#: src/pages/settings/emailing-domains/utils/getEmailingDomainStatusText.ts
msgid "Temporary Failure"
@@ -14338,6 +14314,11 @@ msgstr "此操作將刪除此資料夾及其中所有 {2} 個導覽選單項目
msgid "This action will delete this folder and the navigation menu item inside. Do you want to continue?"
msgstr "此操作將刪除此資料夾及其中的導覽選單項目。您要繼續嗎?"
#. js-lingui-id: 6jJt3O
#: src/modules/applications/hooks/useApplicationChipData.ts
msgid "This app"
msgstr ""
#. js-lingui-id: SLIRqz
#: src/modules/settings/admin-panel/config-variables/components/ConfigVariableHelpText.tsx
msgid "This database value overrides environment settings. "
@@ -14527,7 +14508,6 @@ msgid "Time zone"
msgstr "時區"
#. js-lingui-id: cklVjM
#: src/modules/page-layout/constants/StandardPageLayoutTabTitleTranslations.ts
#: src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownCalendarViewContent.tsx
msgid "Timeline"
msgstr "時間軸"
@@ -1,5 +1,5 @@
import { t } from '@lingui/core/macro';
import { useContext } from 'react';
import { useCallback, useContext, useState } from 'react';
import { ActivityTargetChips } from '@/activities/components/ActivityTargetChips';
import { useActivityTargetObjectRecords } from '@/activities/hooks/useActivityTargetObjectRecords';
@@ -13,8 +13,9 @@ import { FieldFocusContextProvider } from '@/object-record/record-field/ui/conte
import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/ui/states/contexts/RecordFieldComponentInstanceContext';
import { RecordInlineCellContainer } from '@/object-record/record-inline-cell/components/RecordInlineCellContainer';
import { RecordInlineCellContext } from '@/object-record/record-inline-cell/components/RecordInlineCellContext';
import { useInlineCell } from '@/object-record/record-inline-cell/hooks/useInlineCell';
import { RecordInlineCellEditMode } from '@/object-record/record-inline-cell/components/RecordInlineCellEditMode';
import { MultipleRecordPicker } from '@/object-record/record-picker/multiple-record-picker/components/MultipleRecordPicker';
import { useGoBackToPreviousDropdownFocusId } from '@/ui/layout/dropdown/hooks/useGoBackToPreviousDropdownFocusId';
import { IconArrowUpRight, IconPencil } from 'twenty-ui/display';
type ActivityTargetsInlineCellProps = {
@@ -37,8 +38,6 @@ export const ActivityTargetsInlineCell = ({
const { activityTargetObjectRecords } =
useActivityTargetObjectRecords(activityRecordId);
const { closeInlineCell } = useInlineCell(componentInstanceId);
const {
fieldDefinition,
isRecordFieldReadOnly: isReadOnly,
@@ -54,6 +53,28 @@ export const ActivityTargetsInlineCell = ({
activityId: activityRecordId,
});
const [isRelationPickerOpen, setIsRelationPickerOpen] = useState(false);
const { goBackToPreviousDropdownFocusId } =
useGoBackToPreviousDropdownFocusId();
const handleOpenRelationPicker = useCallback(() => {
openActivityTargetCellEditMode({
recordPickerInstanceId: componentInstanceId,
activityTargetObjectRecords,
});
setIsRelationPickerOpen(true);
}, [
activityTargetObjectRecords,
componentInstanceId,
openActivityTargetCellEditMode,
]);
const handleCloseRelationPicker = useCallback(() => {
setIsRelationPickerOpen(false);
goBackToPreviousDropdownFocusId();
}, [goBackToPreviousDropdownFocusId]);
return (
<RecordFieldsScopeContextProvider
value={{ scopeInstanceId: componentInstanceId }}
@@ -80,13 +101,24 @@ export const ActivityTargetsInlineCell = ({
showLabel: showLabel,
readonly: isReadOnly,
labelWidth: fieldDefinition?.labelWidth,
editModeContent: (
label: t`Relations`,
displayModeContent: (
<ActivityTargetChips
activityTargetObjectRecords={activityTargetObjectRecords}
maxWidth={maxWidth}
/>
),
onOpenEditMode: handleOpenRelationPicker,
onCloseEditMode: handleCloseRelationPicker,
}}
>
<RecordInlineCellContainer />
{isRelationPickerOpen && (
<RecordInlineCellEditMode>
<MultipleRecordPicker
focusId={componentInstanceId}
componentInstanceId={componentInstanceId}
onClickOutside={() => {
closeInlineCell();
}}
onClickOutside={handleCloseRelationPicker}
onChange={(morphItem) => {
updateActivityTargetFromCell({
recordPickerInstanceId: componentInstanceId,
@@ -95,27 +127,10 @@ export const ActivityTargetsInlineCell = ({
activityTargetObjectRecords,
});
}}
onSubmit={() => {
closeInlineCell();
}}
onSubmit={handleCloseRelationPicker}
/>
),
label: t`Relations`,
displayModeContent: (
<ActivityTargetChips
activityTargetObjectRecords={activityTargetObjectRecords}
maxWidth={maxWidth}
/>
),
onOpenEditMode: () => {
openActivityTargetCellEditMode({
recordPickerInstanceId: componentInstanceId,
activityTargetObjectRecords,
});
},
}}
>
<RecordInlineCellContainer />
</RecordInlineCellEditMode>
)}
</RecordInlineCellContext.Provider>
</FieldContextProvider>
</FieldFocusContextProvider>
@@ -87,6 +87,7 @@ const mockWorkspace = {
useRecommendedModels: true,
workspaceCustomApplication: CUSTOM_WORKSPACE_APPLICATION_MOCK,
workspaceCustomApplicationId: CUSTOM_WORKSPACE_APPLICATION_MOCK.id,
installedApplications: [],
};
const createMockOptions = (): Options => ({
@@ -0,0 +1,64 @@
import { useApplicationChipData } from '@/applications/hooks/useApplicationChipData';
import { Avatar } from 'twenty-ui/display';
import {
Chip,
ChipAccent,
type ChipSize,
ChipVariant,
LinkChip,
} from 'twenty-ui/components';
type AppChipProps = {
applicationId: string;
variant?: ChipVariant;
size?: ChipSize;
to?: string;
className?: string;
};
export const AppChip = ({
applicationId,
variant,
size,
to,
className,
}: AppChipProps) => {
const { applicationChipData } = useApplicationChipData({ applicationId });
const leftComponent = (
<Avatar
type="app"
size="md"
placeholder={applicationChipData.name}
placeholderColorSeed={applicationChipData.seed}
color={applicationChipData.colors?.color}
backgroundColor={applicationChipData.colors?.backgroundColor}
borderColor={applicationChipData.colors?.borderColor}
/>
);
if (to) {
return (
<LinkChip
className={className}
label={applicationChipData.name}
leftComponent={leftComponent}
size={size}
variant={variant ?? ChipVariant.Highlighted}
accent={ChipAccent.TextPrimary}
to={to}
/>
);
}
return (
<Chip
className={className}
label={applicationChipData.name}
leftComponent={leftComponent}
size={size}
variant={variant ?? ChipVariant.Transparent}
accent={ChipAccent.TextPrimary}
/>
);
};
@@ -0,0 +1,3 @@
import { createContext } from 'react';
export const CurrentApplicationContext = createContext<string | null>(null);
@@ -0,0 +1,59 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { useContext } from 'react';
import {
TWENTY_STANDARD_APPLICATION_NAME,
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER,
} from 'twenty-shared/application';
import { isDefined } from 'twenty-shared/utils';
import { ThemeContext } from 'twenty-ui/theme-constants';
export type ApplicationAvatarColors = {
color: string;
backgroundColor: string;
borderColor: string;
};
type UseApplicationAvatarColorsArgs = {
id?: string | null;
name?: string | null;
universalIdentifier?: string | null;
};
export const useApplicationAvatarColors = (
application: UseApplicationAvatarColorsArgs | null | undefined,
): ApplicationAvatarColors | undefined => {
const { theme } = useContext(ThemeContext);
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
if (!isDefined(application) || !isDefined(application.id)) {
return undefined;
}
const isStandard =
application.universalIdentifier ===
TWENTY_STANDARD_APPLICATION_UNIVERSAL_IDENTIFIER ||
application.name === TWENTY_STANDARD_APPLICATION_NAME;
const isCustom =
isDefined(currentWorkspace?.workspaceCustomApplication?.id) &&
currentWorkspace.workspaceCustomApplication.id === application.id;
if (isStandard) {
return {
backgroundColor: theme.color.blue5,
borderColor: theme.color.blue6,
color: theme.color.blue12,
};
}
if (isCustom) {
return {
backgroundColor: theme.color.orange5,
borderColor: theme.color.orange6,
color: theme.color.orange12,
};
}
return undefined;
};
@@ -0,0 +1,57 @@
import { CurrentApplicationContext } from '@/applications/contexts/CurrentApplicationContext';
import {
useApplicationAvatarColors,
type ApplicationAvatarColors,
} from '@/applications/hooks/useApplicationAvatarColors';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { t } from '@lingui/core/macro';
import { useContext } from 'react';
import { isDefined } from 'twenty-shared/utils';
type UseApplicationChipDataArgs = {
applicationId: string;
};
type ApplicationChipData = {
name: string;
seed: string;
colors?: ApplicationAvatarColors;
};
type UseApplicationChipDataReturnType = {
applicationChipData: ApplicationChipData;
};
export const useApplicationChipData = ({
applicationId,
}: UseApplicationChipDataArgs): UseApplicationChipDataReturnType => {
const currentApplicationId = useContext(CurrentApplicationContext);
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
const application = currentWorkspace?.installedApplications.find(
(installedApplication) => installedApplication.id === applicationId,
);
const colors = useApplicationAvatarColors(application);
if (!isDefined(application)) {
return {
applicationChipData: {
name: '',
seed: applicationId,
},
};
}
const isCurrent =
isDefined(currentApplicationId) && currentApplicationId === applicationId;
return {
applicationChipData: {
name: isCurrent ? t`This app` : application.name,
seed: application.universalIdentifier ?? application.name,
colors,
},
};
};
@@ -45,6 +45,10 @@ export type CurrentWorkspace = Pick<
> & {
defaultRole?: Omit<Role, 'workspaceMembers' | 'agents' | 'apiKeys'> | null;
workspaceCustomApplication: Pick<Application, 'id'> | null;
installedApplications: Pick<
Application,
'id' | 'name' | 'universalIdentifier'
>[];
};
export const currentWorkspaceState = createAtomState<CurrentWorkspace | null>({
@@ -19,6 +19,7 @@ export const CREATE_ONE_OBJECT_METADATA_ITEM = gql`
labelIdentifierFieldMetadataId
imageIdentifierFieldMetadataId
isLabelSyncedWithName
applicationId
fieldsList {
id
universalIdentifier
@@ -207,6 +208,7 @@ export const UPDATE_ONE_OBJECT_METADATA_ITEM = gql`
labelIdentifierFieldMetadataId
imageIdentifierFieldMetadataId
isLabelSyncedWithName
applicationId
}
}
`;
@@ -230,6 +232,7 @@ export const DELETE_ONE_OBJECT_METADATA_ITEM = gql`
labelIdentifierFieldMetadataId
imageIdentifierFieldMetadataId
isLabelSyncedWithName
applicationId
}
}
`;
@@ -19,6 +19,7 @@ export const query = gql`
labelIdentifierFieldMetadataId
imageIdentifierFieldMetadataId
isLabelSyncedWithName
applicationId
}
}
`;
@@ -41,4 +42,5 @@ export const responseData = {
updatedAt: '',
labelIdentifierFieldMetadataId: '20202020-72ba-4e11-a36d-e17b544541e1',
imageIdentifierFieldMetadataId: '',
applicationId: null,
};
@@ -29,6 +29,7 @@ describe('useColumnDefinitionsFromObjectMetadata', () => {
workspaceCustomApplication: {
id: CUSTOM_WORKSPACE_APPLICATION_MOCK.id,
},
installedApplications: [],
id: '1',
featureFlags: [],
allowImpersonation: false,
@@ -32,8 +32,6 @@ import { PAGE_LAYOUT_TAB_LIST_DROPPABLE_IDS } from '@/page-layout/components/Pag
import { PageLayoutTabListNewTabDropdownContent } from '@/page-layout/components/PageLayoutTabListNewTabDropdownContent';
import { PageLayoutTabListReorderableOverflowDropdown } from '@/page-layout/components/PageLayoutTabListReorderableOverflowDropdown';
import { PageLayoutTabListVisibleTabs } from '@/page-layout/components/PageLayoutTabListVisibleTabs';
import { STANDARD_PAGE_LAYOUT_TAB_TITLE_TRANSLATIONS } from '@/page-layout/constants/StandardPageLayoutTabTitleTranslations';
import { useIsCurrentObjectCustom } from '@/page-layout/hooks/useIsCurrentObjectCustom';
import { useIsPageLayoutInEditMode } from '@/page-layout/hooks/useIsPageLayoutInEditMode';
import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
import { pageLayoutTabListCurrentDragDroppableIdComponentState } from '@/page-layout/states/pageLayoutTabListCurrentDragDroppableIdComponentState';
@@ -113,9 +111,6 @@ export const PageLayoutTabList = ({
}: PageLayoutTabListProps) => {
const { getIcon } = useIcons();
const { t } = useLingui();
const { isCustom } = useIsCurrentObjectCustom();
const shouldTranslateTabTitles = !isCustom;
const isRecordPageGlobalEditionEnabled = useIsFeatureEnabled(
FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED,
@@ -123,12 +118,7 @@ export const PageLayoutTabList = ({
const tabsWithIcons: SingleTabProps[] = tabs.map((tab) => ({
id: tab.id,
// TODO: drop once the configuration of all record page layouts has been migrated to the backend.
title:
shouldTranslateTabTitles &&
isDefined(STANDARD_PAGE_LAYOUT_TAB_TITLE_TRANSLATIONS[tab.title])
? t(STANDARD_PAGE_LAYOUT_TAB_TITLE_TRANSLATIONS[tab.title])
: tab.title,
title: tab.title,
Icon: isDefined(tab.icon) ? getIcon(tab.icon) : undefined,
}));
@@ -1,6 +1,4 @@
import { STANDARD_PAGE_LAYOUT_TAB_TITLE_TRANSLATIONS } from '@/page-layout/constants/StandardPageLayoutTabTitleTranslations';
import { useCurrentPageLayoutOrThrow } from '@/page-layout/hooks/useCurrentPageLayoutOrThrow';
import { useIsCurrentObjectCustom } from '@/page-layout/hooks/useIsCurrentObjectCustom';
import { useUpdatePageLayoutTab } from '@/page-layout/hooks/useUpdatePageLayoutTab';
import { pageLayoutTabSettingsOpenTabIdComponentState } from '@/page-layout/states/pageLayoutTabSettingsOpenTabIdComponentState';
import { isReactivatableTab } from '@/page-layout/utils/isReactivatableTab';
@@ -33,9 +31,6 @@ export const PageLayoutTabListNewTabDropdownContent = ({
const { t } = useLingui();
const { getIcon } = useIcons();
const { closeDropdown } = useCloseDropdown();
const { isCustom } = useIsCurrentObjectCustom();
const shouldTranslateTabTitles = !isCustom;
const { currentPageLayout } = useCurrentPageLayoutOrThrow();
const { updatePageLayoutTab } = useUpdatePageLayoutTab();
@@ -77,16 +72,6 @@ export const PageLayoutTabListNewTabDropdownContent = ({
],
);
const getTabTitle = (title: string) => {
if (
shouldTranslateTabTitles &&
isDefined(STANDARD_PAGE_LAYOUT_TAB_TITLE_TRANSLATIONS[title])
) {
return t(STANDARD_PAGE_LAYOUT_TAB_TITLE_TRANSLATIONS[title]);
}
return title;
};
return (
<DropdownContent>
<DropdownMenuHeader>{t`New tab`}</DropdownMenuHeader>
@@ -106,7 +91,7 @@ export const PageLayoutTabListNewTabDropdownContent = ({
<MenuItem
key={tab.id}
LeftIcon={isDefined(tab.icon) ? getIcon(tab.icon) : undefined}
text={getTabTitle(tab.title)}
text={tab.title}
onClick={() => handleReactivateTab(tab.id)}
/>
))}
@@ -1,22 +0,0 @@
import { msg, type MacroMessageDescriptor } from '@lingui/core/macro';
// Translation map for standard page layout tab titles.
// When the backend hasn't translated the tab title (e.g. when using
// frontend fallback layouts), this map is used to translate known
// standard tab titles at the rendering point.
// Custom/user-created tab titles that are not in this map will be
// displayed as-is.
export const STANDARD_PAGE_LAYOUT_TAB_TITLE_TRANSLATIONS: Record<
string,
MacroMessageDescriptor
> = {
Home: msg`Home`,
Timeline: msg`Timeline`,
Tasks: msg`Tasks`,
Notes: msg`Notes`,
Files: msg`Files`,
Emails: msg`Emails`,
Calendar: msg`Calendar`,
Note: msg`Note`,
Flow: msg`Flow`,
};
@@ -1,11 +1,13 @@
import { isNonEmptyString } from '@sniptt/guards';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import { type ComponentType, type ReactNode } from 'react';
import { isNonEmptyString } from '@sniptt/guards';
import { type ReactNode } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { Tag } from 'twenty-ui/components';
import {
IconAlertTriangle,
IconBrandNpm,
type IconComponent,
IconLink,
IconMail,
IconWorld,
@@ -13,7 +15,7 @@ import {
import { themeCssVariables } from 'twenty-ui/theme-constants';
export type ContentEntry = {
icon: ComponentType<{ size?: number }>;
icon: IconComponent;
count: number;
one: string;
many: string;
@@ -62,17 +64,11 @@ const StyledSidebarValue = styled.div`
font-weight: ${themeCssVariables.font.weight.medium};
`;
const StyledContentItem = styled.div`
align-items: center;
color: ${themeCssVariables.font.color.primary};
const StyledContentList = styled.div`
align-items: flex-start;
display: flex;
font-size: ${themeCssVariables.font.size.sm};
flex-direction: column;
gap: ${themeCssVariables.spacing[2]};
margin-bottom: ${themeCssVariables.spacing[2]};
&:last-of-type {
margin-bottom: 0;
}
`;
const StyledLink = styled.a`
@@ -149,12 +145,18 @@ export const SettingsApplicationAboutSidebar = ({
{filteredContentEntries.length > 0 && (
<StyledSidebarSection>
<StyledSidebarLabel>{t`Content`}</StyledSidebarLabel>
{filteredContentEntries.map((entry) => (
<StyledContentItem key={entry.one}>
<entry.icon size={16} />
{entry.count} {entry.count === 1 ? entry.one : entry.many}
</StyledContentItem>
))}
<StyledContentList>
{filteredContentEntries.map((entry) => (
<Tag
key={entry.one}
color="gray"
Icon={entry.icon}
text={`${entry.count} ${
entry.count === 1 ? entry.one : entry.many
}`}
/>
))}
</StyledContentList>
</StyledSidebarSection>
)}
@@ -1,10 +1,7 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { getItemTagInfo } from '@/settings/data-model/utils/getItemTagInfo';
import { styled } from '@linaria/react';
import { AppChip } from '@/applications/components/AppChip';
import { Avatar } from 'twenty-ui/display';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { useContext } from 'react';
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
import { Chip, ChipAccent, ChipVariant } from 'twenty-ui/components';
import { isDefined } from 'twenty-shared/utils';
type SettingsItemTypeTagProps = {
item: {
@@ -15,38 +12,30 @@ type SettingsItemTypeTagProps = {
className?: string;
};
const StyledContainer = styled.div`
align-items: center;
color: ${themeCssVariables.font.color.secondary};
display: flex;
font-size: ${themeCssVariables.font.size.sm};
gap: ${themeCssVariables.spacing[1]};
`;
export const SettingsItemTypeTag = ({
className,
item: { isCustom, isRemote, applicationId },
item: { isRemote, applicationId },
}: SettingsItemTypeTagProps) => {
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
const itemTagInfo = getItemTagInfo({
item: { isCustom, isRemote, applicationId },
workspaceCustomApplicationId:
currentWorkspace?.workspaceCustomApplication?.id,
});
const { theme } = useContext(ThemeContext);
return (
<StyledContainer className={className}>
<Avatar
placeholder={itemTagInfo.labelText}
placeholderColorSeed={itemTagInfo.labelText}
type="squared"
size="xs"
color={theme.tag.text[itemTagInfo.labelColor]}
backgroundColor={theme.tag.background[itemTagInfo.labelColor]}
if (isDefined(applicationId)) {
return <AppChip applicationId={applicationId} className={className} />;
} else if (isRemote === true) {
return (
<Chip
className={className}
label="Remote"
variant={ChipVariant.Transparent}
accent={ChipAccent.TextPrimary}
leftComponent={
<Avatar
type="app"
size="md"
placeholder="Remote"
placeholderColorSeed="Remote"
/>
}
/>
{itemTagInfo.labelText}
</StyledContainer>
);
);
} else {
return null;
}
};
@@ -1,56 +0,0 @@
import { isDefined } from 'twenty-shared/utils';
export type ItemTagInfo =
| StandardItemTagInfo
| CustomItemTagInfo
| RemoteItemTagInfo
| ManagedItemTagInfo;
type StandardItemTagInfo = {
labelText: 'Standard';
labelColor: 'blue';
};
type CustomItemTagInfo = {
labelText: 'Custom';
labelColor: 'orange';
};
type RemoteItemTagInfo = {
labelText: 'Remote';
labelColor: 'green';
};
type ManagedItemTagInfo = {
labelText: 'Managed';
labelColor: 'sky';
};
export const getItemTagInfo = ({
item: { isCustom, isRemote, applicationId },
workspaceCustomApplicationId,
}: {
item: {
isCustom?: boolean;
isRemote?: boolean;
applicationId?: string | null;
};
workspaceCustomApplicationId?: string;
}): ItemTagInfo => {
if (
isDefined(applicationId) &&
applicationId !== workspaceCustomApplicationId
) {
return { labelText: 'Managed', labelColor: 'sky' };
}
if (isCustom!!) {
return { labelText: 'Custom', labelColor: 'orange' };
}
if (isRemote!!) {
return { labelText: 'Remote', labelColor: 'green' };
}
return { labelText: 'Standard', labelColor: 'blue' };
};
@@ -17,11 +17,13 @@ const StyledHeaderTitle = styled.div`
type SettingsLogicFunctionLabelContainerProps = {
value: string;
onChange: (value: string) => void;
readonly?: boolean;
};
export const SettingsLogicFunctionLabelContainer = ({
value,
onChange,
readonly = false,
}: SettingsLogicFunctionLabelContainerProps) => {
return (
<StyledHeaderTitle>
@@ -31,6 +33,7 @@ export const SettingsLogicFunctionLabelContainer = ({
value={value}
onChange={onChange}
placeholder={t`Function name`}
disabled={readonly}
/>
</StyledHeaderTitle>
);
@@ -18,7 +18,7 @@ const StyledIconContainer = styled.span`
`;
const StyledIconChevronRightContainer = styled(StyledIconContainer)`
color: ${themeCssVariables.font.color.tertiary};
color: ${themeCssVariables.font.color.light};
`;
export const SettingsLogicFunctionsFieldItemTableRow = ({
@@ -5,17 +5,20 @@ import { type LogicFunctionFormValues } from '@/logic-functions/hooks/useLogicFu
export const SettingsLogicFunctionSettingsTab = ({
formValues,
onChange,
readonly = false,
}: {
formValues: LogicFunctionFormValues;
onChange: <TKey extends keyof LogicFunctionFormValues>(
key: TKey,
) => (value: LogicFunctionFormValues[TKey]) => void;
readonly?: boolean;
}) => {
return (
<>
<SettingsLogicFunctionNewForm
formValues={formValues}
onChange={onChange}
readonly={readonly}
/>
<SettingsLogicFunctionTabEnvironmentVariablesSection />
</>
@@ -57,11 +57,13 @@ export const TableSection = ({
<IconChevronUp
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
color={theme.font.color.light}
/>
) : (
<IconChevronDown
size={theme.icon.size.md}
stroke={theme.icon.stroke.sm}
color={theme.font.color.light}
/>
)}
</StyledSectionHeader>
@@ -66,6 +66,11 @@ export const USER_QUERY_FRAGMENT = gql`
workspaceCustomApplication {
id
}
installedApplications {
id
name
universalIdentifier
}
isCustomDomainEnabled
workspaceUrls {
...WorkspaceUrlsFragment
@@ -1,3 +1,4 @@
import { CurrentApplicationContext } from '@/applications/contexts/CurrentApplicationContext';
import { useUpgradeApplication } from '@/marketplace/hooks/useUpgradeApplication';
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
@@ -287,30 +288,35 @@ export const SettingsApplicationDetails = () => {
};
return (
<SubMenuTopBarContainer
title={
<SettingsApplicationDetailTitle
displayName={displayName}
description={description}
logoUrl={logoUrl}
/>
}
links={[
{
children: t`Workspace`,
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: t`Applications`,
href: getSettingsPath(SettingsPath.Applications),
},
{ children: displayName },
]}
>
<SettingsPageContainer>
<TabList tabs={tabs} componentInstanceId={APPLICATION_DETAIL_ID} />
{renderActiveTabContent()}
</SettingsPageContainer>
</SubMenuTopBarContainer>
<CurrentApplicationContext.Provider value={application?.id ?? null}>
<SubMenuTopBarContainer
title={
<SettingsApplicationDetailTitle
displayName={displayName}
description={description}
logoUrl={logoUrl}
applicationId={application?.id}
applicationName={application?.name}
universalIdentifier={application?.universalIdentifier}
/>
}
links={[
{
children: t`Workspace`,
href: getSettingsPath(SettingsPath.Workspace),
},
{
children: t`Applications`,
href: getSettingsPath(SettingsPath.Applications),
},
{ children: displayName },
]}
>
<SettingsPageContainer>
<TabList tabs={tabs} componentInstanceId={APPLICATION_DETAIL_ID} />
{renderActiveTabContent()}
</SettingsPageContainer>
</SubMenuTopBarContainer>
</CurrentApplicationContext.Provider>
);
};

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