Merge branch 'main' into feat/email-attachments-and-open-in-app

This commit is contained in:
Félix Malfait
2026-04-09 12:47:20 +02:00
committed by GitHub
105 changed files with 1667 additions and 254 deletions
@@ -0,0 +1,59 @@
import { CoreApiClient } from 'twenty-client-sdk/core';
import { definePostInstallLogicFunction } from 'twenty-sdk';
const POST_CARDS_TO_SEED = [
{
name: 'Greetings from Paris',
content:
'Wish you were here! The Eiffel Tower looks even better in person. - Alex',
},
{
name: 'Hello from Tokyo',
content:
'The cherry blossoms are amazing this time of year. See you soon! - Sam',
},
];
const handler = async (): Promise<{
message: string;
createdIds: string[];
}> => {
console.log('Seeding 2 post cards...');
const client = new CoreApiClient();
const createdIds: string[] = [];
for (const postCard of POST_CARDS_TO_SEED) {
const { createPostCard } = await client.mutation({
createPostCard: {
__args: {
data: {
name: postCard.name,
content: postCard.content,
},
},
id: true,
},
});
if (!createPostCard?.id) {
throw new Error(`Failed to create post card "${postCard.name}"`);
}
createdIds.push(createPostCard.id);
}
console.log('Seeding complete!');
return {
message: `Seeded ${createdIds.length} post cards`,
createdIds,
};
};
export default definePostInstallLogicFunction({
universalIdentifier: '9f3d8c21-b471-4a82-8e5c-6f3a7b8c9d01',
name: 'seed-post-cards',
description: 'Seeds the workspace with 2 sample post card records.',
timeoutSeconds: 10,
handler,
});
@@ -33,7 +33,7 @@ export default defineRole({
objectUniversalIdentifier: POST_CARD_UNIVERSAL_IDENTIFIER,
fieldUniversalIdentifier: CONTENT_FIELD_UNIVERSAL_IDENTIFIER,
canReadFieldValue: false,
canUpdateFieldValue: false,
canUpdateFieldValue: true,
},
],
permissionFlags: [PermissionFlag.APPLICATIONS],
@@ -66,12 +66,18 @@ The share link uses the server's base URL (without any workspace subdomain) so i
### Version management
When updating an already deployed tarball app, the server requires the `version` in `package.json` to be **strictly higher** (per [semver](https://semver.org) ordering) than the currently deployed version. Re-deploying the same version, or pushing a lower one, is rejected before the tarball is stored — you'll see a `VERSION_ALREADY_EXISTS` error from the CLI.
To release an update:
1. Bump the `version` field in your `package.json`
1. Bump the `version` field in your `package.json` (e.g. `1.2.3` → `1.2.4`, `1.3.0`, or `2.0.0`)
2. Run `yarn twenty deploy` (or `yarn twenty deploy --remote production`)
3. Workspaces that have the app installed will see the upgrade available in their settings
<Note>
Pre-release tags work as expected: bumping `1.0.0-rc.1` → `1.0.0-rc.2` is allowed, and a final release like `1.0.0` is correctly recognized as higher than `1.0.0-rc.5`. The version in `package.json` must itself be a valid semver string.
</Note>
{/* TODO: add screenshot of the Upgrade button */}
## Publishing to npm
@@ -189,3 +195,12 @@ You can also install apps from the command line:
```bash filename="Terminal"
yarn twenty install
```
<Note>
The server enforces semver versioning on install, mirroring the rules on deploy:
- Installing the same version that is already installed in your workspace is rejected with an `APP_ALREADY_INSTALLED` error.
- Installing a lower version than the one currently installed is rejected with a `CANNOT_DOWNGRADE_APPLICATION` error.
To install a newer version, deploy or publish it first, then re-run `yarn twenty install`.
</Note>
@@ -66,12 +66,18 @@ yarn twenty deploy
### إدارة الإصدارات
عند تحديث تطبيق tarball منشور مسبقًا، يشترط الخادم أن تكون قيمة `version` في `package.json` **أعلى قطعًا** (وفق ترتيب [الإصدار الدلالي](https://semver.org)) من الإصدار المنشور حاليًا. Re-deploying the same version, or pushing a lower one, is rejected before the tarball is stored — you'll see a `VERSION_ALREADY_EXISTS` error from the CLI.
لطرح تحديث:
1. ارفع قيمة الحقل `version` في ملف `package.json`
1. Bump the `version` field in your `package.json` (e.g. `1.2.3` → `1.2.4`, `1.3.0`, or `2.0.0`)
2. شغّل `yarn twenty deploy` (أو `yarn twenty deploy --remote production`)
3. سترى مساحات العمل التي ثبّتت التطبيق الترقية متاحة في إعداداتها
<Note>
Pre-release tags work as expected: bumping `1.0.0-rc.1` → `1.0.0-rc.2` is allowed, and a final release like `1.0.0` is correctly recognized as higher than `1.0.0-rc.5`. The version in `package.json` must itself be a valid semver string.
</Note>
{/* TODO: add screenshot of the Upgrade button */}
## النشر على npm
@@ -189,3 +195,12 @@ jobs:
```bash filename="Terminal"
yarn twenty install
```
<Note>
The server enforces semver versioning on install, mirroring the rules on deploy:
* Installing the same version that is already installed in your workspace is rejected with an `APP_ALREADY_INSTALLED` error.
* Installing a lower version than the one currently installed is rejected with a `CANNOT_DOWNGRADE_APPLICATION` error.
To install a newer version, deploy or publish it first, then re-run `yarn twenty install`.
</Note>
@@ -66,12 +66,18 @@ Odkaz ke sdílení používá základní adresu URL serveru (bez jakékoli subdo
### Správa verzí
When updating an already deployed tarball app, the server requires the `version` in `package.json` to be **strictly higher** (per [semver](https://semver.org) ordering) than the currently deployed version. Re-deploying the same version, or pushing a lower one, is rejected before the tarball is stored — you'll see a `VERSION_ALREADY_EXISTS` error from the CLI.
Chcete-li vydat aktualizaci:
1. Zvyšte hodnotu pole `version` v souboru `package.json`
1. Bump the `version` field in your `package.json` (e.g. `1.2.3` → `1.2.4`, `1.3.0`, or `2.0.0`)
2. Spusťte `yarn twenty deploy` (nebo `yarn twenty deploy --remote production`)
3. Pracovní prostory, které mají aplikaci nainstalovanou, uvidí dostupnou aktualizaci ve svém nastavení
<Note>
Pre-release tags work as expected: bumping `1.0.0-rc.1` → `1.0.0-rc.2` is allowed, and a final release like `1.0.0` is correctly recognized as higher than `1.0.0-rc.5`. The version in `package.json` must itself be a valid semver string.
</Note>
{/* TODO: add screenshot of the Upgrade button */}
## Publikování na npm
@@ -189,3 +195,12 @@ Aplikace můžete nainstalovat také z příkazového řádku:
```bash filename="Terminal"
yarn twenty install
```
<Note>
The server enforces semver versioning on install, mirroring the rules on deploy:
* Installing the same version that is already installed in your workspace is rejected with an `APP_ALREADY_INSTALLED` error.
* Installing a lower version than the one currently installed is rejected with a `CANNOT_DOWNGRADE_APPLICATION` error.
To install a newer version, deploy or publish it first, then re-run `yarn twenty install`.
</Note>
@@ -66,12 +66,18 @@ Der Freigabelink verwendet die Basis-URL des Servers (ohne Workspace-Subdomain),
### Versionsverwaltung
When updating an already deployed tarball app, the server requires the `version` in `package.json` to be **strictly higher** (per [semver](https://semver.org) ordering) than the currently deployed version. Re-deploying the same version, or pushing a lower one, is rejected before the tarball is stored — you'll see a `VERSION_ALREADY_EXISTS` error from the CLI.
So veröffentlichen Sie ein Update:
1. Erhöhen Sie das Feld `version` in Ihrer `package.json`
1. Bump the `version` field in your `package.json` (e.g. `1.2.3` → `1.2.4`, `1.3.0`, or `2.0.0`)
2. Führen Sie `yarn twenty deploy` aus (oder `yarn twenty deploy --remote production`)
3. Arbeitsbereiche, die die App installiert haben, sehen in ihren Einstellungen, dass ein Upgrade verfügbar ist.
<Note>
Pre-release tags work as expected: bumping `1.0.0-rc.1` → `1.0.0-rc.2` is allowed, and a final release like `1.0.0` is correctly recognized as higher than `1.0.0-rc.5`. The version in `package.json` must itself be a valid semver string.
</Note>
{/* TODO: add screenshot of the Upgrade button */}
## Auf npm veröffentlichen
@@ -189,3 +195,12 @@ Sie können Apps auch über die Befehlszeile installieren:
```bash filename="Terminal"
yarn twenty install
```
<Note>
The server enforces semver versioning on install, mirroring the rules on deploy:
* Installing the same version that is already installed in your workspace is rejected with an `APP_ALREADY_INSTALLED` error.
* Installing a lower version than the one currently installed is rejected with a `CANNOT_DOWNGRADE_APPLICATION` error.
To install a newer version, deploy or publish it first, then re-run `yarn twenty install`.
</Note>
@@ -66,12 +66,18 @@ Il link di condivisione utilizza l'URL di base del server (senza alcun sottodomi
### Gestione delle versioni
When updating an already deployed tarball app, the server requires the `version` in `package.json` to be **strictly higher** (per [semver](https://semver.org) ordering) than the currently deployed version. Re-deploying the same version, or pushing a lower one, is rejected before the tarball is stored — you'll see a `VERSION_ALREADY_EXISTS` error from the CLI.
Per rilasciare un aggiornamento:
1. Incrementa il campo `version` nel tuo `package.json`
1. Bump the `version` field in your `package.json` (e.g. `1.2.3` → `1.2.4`, `1.3.0`, or `2.0.0`)
2. Esegui `yarn twenty deploy` (oppure `yarn twenty deploy --remote production`)
3. Gli spazi di lavoro che hanno l'app installata vedranno l'aggiornamento disponibile nelle proprie impostazioni
<Note>
Pre-release tags work as expected: bumping `1.0.0-rc.1` → `1.0.0-rc.2` is allowed, and a final release like `1.0.0` is correctly recognized as higher than `1.0.0-rc.5`. The version in `package.json` must itself be a valid semver string.
</Note>
{/* TODO: add screenshot of the Upgrade button */}
## Pubblicazione su npm
@@ -189,3 +195,12 @@ Puoi anche installare le app dalla riga di comando:
```bash filename="Terminal"
yarn twenty install
```
<Note>
The server enforces semver versioning on install, mirroring the rules on deploy:
* Installing the same version that is already installed in your workspace is rejected with an `APP_ALREADY_INSTALLED` error.
* Installing a lower version than the one currently installed is rejected with a `CANNOT_DOWNGRADE_APPLICATION` error.
To install a newer version, deploy or publish it first, then re-run `yarn twenty install`.
</Note>
@@ -66,12 +66,18 @@ O link de compartilhamento usa a URL base do servidor (sem qualquer subdomínio
### Gerenciamento de versões
When updating an already deployed tarball app, the server requires the `version` in `package.json` to be **strictly higher** (per [semver](https://semver.org) ordering) than the currently deployed version. Re-deploying the same version, or pushing a lower one, is rejected before the tarball is stored — you'll see a `VERSION_ALREADY_EXISTS` error from the CLI.
Para lançar uma atualização:
1. Atualize o campo `version` no seu `package.json`
1. Bump the `version` field in your `package.json` (e.g. `1.2.3` → `1.2.4`, `1.3.0`, or `2.0.0`)
2. Execute `yarn twenty deploy` (ou `yarn twenty deploy --remote production`)
3. Os espaços de trabalho que têm o aplicativo instalado verão a atualização disponível em suas configurações
<Note>
Pre-release tags work as expected: bumping `1.0.0-rc.1` → `1.0.0-rc.2` is allowed, and a final release like `1.0.0` is correctly recognized as higher than `1.0.0-rc.5`. The version in `package.json` must itself be a valid semver string.
</Note>
{/* TODO: add screenshot of the Upgrade button */}
## Publicação no npm
@@ -189,3 +195,12 @@ Você também pode instalar apps pela linha de comando:
```bash filename="Terminal"
yarn twenty install
```
<Note>
The server enforces semver versioning on install, mirroring the rules on deploy:
* Installing the same version that is already installed in your workspace is rejected with an `APP_ALREADY_INSTALLED` error.
* Installing a lower version than the one currently installed is rejected with a `CANNOT_DOWNGRADE_APPLICATION` error.
To install a newer version, deploy or publish it first, then re-run `yarn twenty install`.
</Note>
@@ -66,12 +66,18 @@ yarn twenty deploy
### Управление версиями
When updating an already deployed tarball app, the server requires the `version` in `package.json` to be **strictly higher** (per [semver](https://semver.org) ordering) than the currently deployed version. Re-deploying the same version, or pushing a lower one, is rejected before the tarball is stored — you'll see a `VERSION_ALREADY_EXISTS` error from the CLI.
Чтобы выпустить обновление:
1. Обновите значение поля `version` в файле `package.json`
1. Bump the `version` field in your `package.json` (e.g. `1.2.3` → `1.2.4`, `1.3.0`, or `2.0.0`)
2. Выполните `yarn twenty deploy` (или `yarn twenty deploy --remote production`)
3. Рабочие пространства, в которых установлено приложение, увидят доступное обновление в своих настройках
<Note>
Pre-release tags work as expected: bumping `1.0.0-rc.1` → `1.0.0-rc.2` is allowed, and a final release like `1.0.0` is correctly recognized as higher than `1.0.0-rc.5`. The version in `package.json` must itself be a valid semver string.
</Note>
{/* TODO: add screenshot of the Upgrade button */}
## Публикация в npm
@@ -189,3 +195,12 @@ jobs:
```bash filename="Terminal"
yarn twenty install
```
<Note>
The server enforces semver versioning on install, mirroring the rules on deploy:
* Installing the same version that is already installed in your workspace is rejected with an `APP_ALREADY_INSTALLED` error.
* Installing a lower version than the one currently installed is rejected with a `CANNOT_DOWNGRADE_APPLICATION` error.
To install a newer version, deploy or publish it first, then re-run `yarn twenty install`.
</Note>
@@ -66,12 +66,18 @@ Paylaşım bağlantısı, sunucunun temel URLsini (herhangi bir çalışma al
### Sürüm yönetimi
When updating an already deployed tarball app, the server requires the `version` in `package.json` to be **strictly higher** (per [semver](https://semver.org) ordering) than the currently deployed version. Re-deploying the same version, or pushing a lower one, is rejected before the tarball is stored — you'll see a `VERSION_ALREADY_EXISTS` error from the CLI.
Bir güncelleme yayımlamak için:
1. `package.json` içindeki `version` alanını artırın
1. Bump the `version` field in your `package.json` (e.g. `1.2.3` → `1.2.4`, `1.3.0`, or `2.0.0`)
2. `yarn twenty deploy` (veya `yarn twenty deploy --remote production`) komutunu çalıştırın
3. Uygulamayı kurmuş olan çalışma alanları, ayarlarında mevcut güncellemeyi görecektir
<Note>
Pre-release tags work as expected: bumping `1.0.0-rc.1` → `1.0.0-rc.2` is allowed, and a final release like `1.0.0` is correctly recognized as higher than `1.0.0-rc.5`. The version in `package.json` must itself be a valid semver string.
</Note>
{/* TODO: add screenshot of the Upgrade button */}
## npmye yayımlama
@@ -189,3 +195,12 @@ Uygulamaları komut satırından da yükleyebilirsiniz:
```bash filename="Terminal"
yarn twenty install
```
<Note>
The server enforces semver versioning on install, mirroring the rules on deploy:
* Installing the same version that is already installed in your workspace is rejected with an `APP_ALREADY_INSTALLED` error.
* Installing a lower version than the one currently installed is rejected with a `CANNOT_DOWNGRADE_APPLICATION` error.
To install a newer version, deploy or publish it first, then re-run `yarn twenty install`.
</Note>
@@ -6,8 +6,8 @@ import { IsMinimalMetadataReadyEffect } from '@/metadata-store/effect-components
import { GotoHotkeysEffectsProvider } from '@/app/effect-components/GotoHotkeysEffectsProvider';
import { PageChangeEffect } from '@/app/effect-components/PageChangeEffect';
import { SignOutOnOtherTabSignOutEffect } from '@/auth/effect-components/SignOutOnOtherTabSignOutEffect';
import { AuthProvider } from '@/auth/components/AuthProvider';
import { SignOutOnOtherTabSignOutEffect } from '@/auth/effect-components/SignOutOnOtherTabSignOutEffect';
import { CaptchaProvider } from '@/captcha/components/CaptchaProvider';
import { ClientConfigProvider } from '@/client-config/components/ClientConfigProvider';
import { ClientConfigProviderEffect } from '@/client-config/components/ClientConfigProviderEffect';
@@ -1,5 +1,6 @@
import {
CreateOneObjectMetadataItemDocument,
FindManyCommandMenuItemsDocument,
FindManyNavigationMenuItemsDocument,
FindManyViewsDocument,
} from '~/generated-metadata/graphql';
@@ -11,6 +12,8 @@ export const findManyViewsQuery = FindManyViewsDocument;
export const findManyNavigationMenuItemsQuery =
FindManyNavigationMenuItemsDocument;
export const findManyCommandMenuItemsQuery = FindManyCommandMenuItemsDocument;
export const variables = {
input: {
object: {
@@ -4,6 +4,7 @@ import { useCreateOneObjectMetadataItem } from '@/object-metadata/hooks/useCreat
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
import {
findManyCommandMenuItemsQuery,
findManyNavigationMenuItemsQuery,
findManyViewsQuery,
query,
@@ -12,7 +13,7 @@ import {
} from '@/object-metadata/hooks/__mocks__/useCreateOneObjectMetadataItem';
import { jestExpectSuccessfulMetadataRequestResult } from '@/object-metadata/hooks/__tests__/utils/jest-expect-metadata-request-status.util';
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
import { GetCurrentUserDocument } from '~/generated-metadata/graphql';
import { mockedUserData } from '~/testing/mock-data/users';
import {
query as findManyObjectMetadataItemsQuery,
@@ -33,7 +34,7 @@ const mocks = [
},
{
request: {
query: GET_CURRENT_USER,
query: GetCurrentUserDocument,
variables: {},
},
result: jest.fn(() => ({
@@ -75,6 +76,17 @@ const mocks = [
},
})),
},
{
request: {
query: findManyCommandMenuItemsQuery,
variables: {},
},
result: jest.fn(() => ({
data: {
commandMenuItems: [],
},
})),
},
];
const Wrapper = getJestMetadataAndApolloMocksWrapper({
@@ -11,6 +11,7 @@ import {
import { jestExpectSuccessfulMetadataRequestResult } from '@/object-metadata/hooks/__tests__/utils/jest-expect-metadata-request-status.util';
import { GET_CURRENT_USER } from '@/users/graphql/queries/getCurrentUser';
import { FIND_ALL_VIEWS } from '@/views/graphql/queries/findAllViews';
import { FindManyCommandMenuItemsDocument } from '~/generated-metadata/graphql';
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
import { mockedUserData } from '~/testing/mock-data/users';
import { mockedViews } from '~/testing/mock-data/generated/metadata/views/mock-views-data';
@@ -62,6 +63,17 @@ const mocks = [
data: findManyObjectMetadataItemsResponseData,
})),
},
{
request: {
query: FindManyCommandMenuItemsDocument,
variables: {},
},
result: jest.fn(() => ({
data: {
commandMenuItems: [],
},
})),
},
];
const Wrapper = getJestMetadataAndApolloMocksWrapper({
@@ -2,6 +2,7 @@ import { useApolloClient, useMutation } from '@apollo/client/react';
import {
type CreateObjectInput,
CreateOneObjectMetadataItemDocument,
FindManyCommandMenuItemsDocument,
FindManyNavigationMenuItemsDocument,
FindManyViewsDocument,
} from '~/generated-metadata/graphql';
@@ -13,6 +14,7 @@ import { type FlatObjectMetadataItem } from '@/metadata-store/types/FlatObjectMe
import { splitViewWithRelated } from '@/metadata-store/utils/splitViewWithRelated';
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { useLoadCurrentUser } from '@/users/hooks/useLoadCurrentUser';
import { CombinedGraphQLErrors } from '@apollo/client/errors';
import { t } from '@lingui/core/macro';
import { CrudOperationType } from 'twenty-shared/types';
@@ -28,6 +30,7 @@ export const useCreateOneObjectMetadataItem = () => {
const { enqueueErrorSnackBar } = useSnackBar();
const { addToDraft, replaceDraft, applyChanges } =
useUpdateMetadataStoreDraft();
const { loadCurrentUser } = useLoadCurrentUser();
const createOneObjectMetadataItem = async (
input: CreateObjectInput,
@@ -70,17 +73,22 @@ export const useCreateOneObjectMetadataItem = () => {
applyChanges();
const [viewsResult, navItemsResult] = await Promise.all([
client.query({
query: FindManyViewsDocument,
variables: { objectMetadataId: createdObject.id },
fetchPolicy: 'network-only',
}),
client.query({
query: FindManyNavigationMenuItemsDocument,
fetchPolicy: 'network-only',
}),
]);
const [viewsResult, navItemsResult, commandMenuItemsResult] =
await Promise.all([
client.query({
query: FindManyViewsDocument,
variables: { objectMetadataId: createdObject.id },
fetchPolicy: 'network-only',
}),
client.query({
query: FindManyNavigationMenuItemsDocument,
fetchPolicy: 'network-only',
}),
client.query({
query: FindManyCommandMenuItemsDocument,
fetchPolicy: 'network-only',
}),
]);
const fetchedViews = viewsResult.data?.getViews ?? [];
@@ -107,7 +115,14 @@ export const useCreateOneObjectMetadataItem = () => {
navItemsResult.data?.navigationMenuItems ?? [],
);
replaceDraft(
'commandMenuItems',
commandMenuItemsResult.data?.commandMenuItems ?? [],
);
applyChanges();
await loadCurrentUser();
}
return {
@@ -1,5 +1,8 @@
import { useMutation } from '@apollo/client/react';
import { DeleteOneObjectMetadataItemDocument } from '~/generated-metadata/graphql';
import { useApolloClient, useMutation } from '@apollo/client/react';
import {
DeleteOneObjectMetadataItemDocument,
FindManyCommandMenuItemsDocument,
} from '~/generated-metadata/graphql';
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
import { useUpdateMetadataStoreDraft } from '@/metadata-store/hooks/useUpdateMetadataStoreDraft';
@@ -14,9 +17,11 @@ export const useDeleteOneObjectMetadataItem = () => {
DeleteOneObjectMetadataItemDocument,
);
const client = useApolloClient();
const { handleMetadataError } = useMetadataErrorHandler();
const { enqueueErrorSnackBar } = useSnackBar();
const { removeFromDraft, applyChanges } = useUpdateMetadataStoreDraft();
const { removeFromDraft, replaceDraft, applyChanges } =
useUpdateMetadataStoreDraft();
const deleteOneObjectMetadataItem = async (
idToDelete: string,
@@ -35,6 +40,17 @@ export const useDeleteOneObjectMetadataItem = () => {
removeFromDraft({ key: 'objectMetadataItems', itemIds: [idToDelete] });
applyChanges();
const commandMenuItemsResult = await client.query({
query: FindManyCommandMenuItemsDocument,
fetchPolicy: 'network-only',
});
replaceDraft(
'commandMenuItems',
commandMenuItemsResult.data?.commandMenuItems ?? [],
);
applyChanges();
return {
status: 'successful',
response,
@@ -1,6 +1,7 @@
import { useMutation } from '@apollo/client/react';
import { useApolloClient, useMutation } from '@apollo/client/react';
import {
type UpdateOneObjectInput,
FindManyCommandMenuItemsDocument,
UpdateOneObjectMetadataItemDocument,
} from '~/generated-metadata/graphql';
@@ -20,9 +21,11 @@ export const useUpdateOneObjectMetadataItem = () => {
UpdateOneObjectMetadataItemDocument,
);
const client = useApolloClient();
const { handleMetadataError } = useMetadataErrorHandler();
const { enqueueErrorSnackBar } = useSnackBar();
const { updateInDraft, applyChanges } = useUpdateMetadataStoreDraft();
const { updateInDraft, replaceDraft, applyChanges } =
useUpdateMetadataStoreDraft();
const updateOneObjectMetadataItem = async ({
idToUpdate,
@@ -52,6 +55,17 @@ export const useUpdateOneObjectMetadataItem = () => {
objectData as FlatObjectMetadataItem,
]);
applyChanges();
const commandMenuItemsResult = await client.query({
query: FindManyCommandMenuItemsDocument,
fetchPolicy: 'network-only',
});
replaceDraft(
'commandMenuItems',
commandMenuItemsResult.data?.commandMenuItems ?? [],
);
applyChanges();
}
return {
@@ -1,5 +1,6 @@
import { useCallback, useState } from 'react';
import { dispatchObjectRecordOperationBrowserEvent } from '@/browser-event/utils/dispatchObjectRecordOperationBrowserEvent';
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useGenerateDepthRecordGqlFieldsFromObject } from '@/object-record/graphql/record-gql-fields/hooks/useGenerateDepthRecordGqlFieldsFromObject';
@@ -8,10 +9,9 @@ import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQue
import { useMergeManyRecordsMutation } from '@/object-record/hooks/useMergeManyRecordsMutation';
import { useRefetchAggregateQueries } from '@/object-record/hooks/useRefetchAggregateQueries';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { dispatchObjectRecordOperationBrowserEvent } from '@/browser-event/utils/dispatchObjectRecordOperationBrowserEvent';
import { getMergeManyRecordsMutationResponseField } from '@/object-record/utils/getMergeManyRecordsMutationResponseField';
import { getOperationName } from '~/utils/getOperationName';
import { type RecordGqlOperationGqlRecordFields } from 'twenty-shared/types';
import { getOperationName } from '~/utils/getOperationName';
export type MergeManySettings = {
conflictPriorityIndex: number;
@@ -88,7 +88,6 @@ export const useMergeManyRecords = <
// Prevent cache updates during dry run to avoid overwriting original record data
...(preview && {
fetchPolicy: 'no-cache',
errorPolicy: 'ignore',
}),
refetchQueries: [
getOperationName(findOneRecordQuery) ?? '',
@@ -1,12 +1,14 @@
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
import { useMergeManyRecords } from '@/object-record/hooks/useMergeManyRecords';
import { useMergeRecordsSelectedRecords } from '@/object-record/record-merge/hooks/useMergeRecordsSelectedRecords';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { useEffect, useState } from 'react';
import { isMergeInProgressState } from '@/object-record/record-merge/states/mergeInProgressState';
import { mergeSettingsState } from '@/object-record/record-merge/states/mergeSettingsState';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { type ErrorLike } from '@apollo/client';
import { useEffect, useState } from 'react';
type UseMergePreviewProps = {
objectNameSingular: string;
@@ -30,6 +32,7 @@ export const usePerformMergePreview = ({
const { selectedRecords } = useMergeRecordsSelectedRecords();
const { upsertRecordsInStore } = useUpsertRecordsInStore();
const { enqueueErrorSnackBar } = useSnackBar();
useEffect(() => {
const fetchPreview = async () => {
@@ -60,8 +63,11 @@ export const usePerformMergePreview = ({
setMergePreviewRecord(transformPreviewRecord);
upsertRecordsInStore({ partialRecords: [transformPreviewRecord] });
} catch {
} catch (error) {
setMergePreviewRecord(null);
enqueueErrorSnackBar({
apolloError: error as ErrorLike,
});
} finally {
setIsGeneratingPreview(false);
setIsInitialized(true);
@@ -79,6 +85,7 @@ export const usePerformMergePreview = ({
mergeManyRecords,
upsertRecordsInStore,
isInitialized,
enqueueErrorSnackBar,
]);
return {
@@ -153,12 +153,14 @@ const buildSyntheticRole = (
canReadFieldValue: permission.canReadFieldValue,
canUpdateFieldValue: permission.canUpdateFieldValue,
})),
permissionFlags: (defaultRole.permissionFlags ?? []).map((flag) => ({
__typename: 'PermissionFlag' as const,
id: uuidv4(),
roleId: defaultRole.universalIdentifier,
flag: flag as PermissionFlagType,
})),
permissionFlags: (defaultRole.permissionFlags ?? []).map(
(permissionFlag) => ({
__typename: 'PermissionFlag' as const,
id: uuidv4(),
roleId: defaultRole.universalIdentifier,
flag: permissionFlag.flag,
}),
),
});
const buildFieldMetadataItemFromMarketplaceField = (
@@ -363,6 +363,9 @@ export const EXPECTED_MANIFEST: Manifest = {
canBeAssignedToAgents: false,
canBeAssignedToUsers: true,
canBeAssignedToApiKeys: false,
fieldPermissions: [],
objectPermissions: [],
permissionFlags: [],
},
],
};
@@ -1499,6 +1499,9 @@ export const EXPECTED_MANIFEST: Manifest = {
description: 'A simple root-level role',
label: 'Root role',
universalIdentifier: 'c0c1c2c3-c4c5-4000-8000-000000000001',
fieldPermissions: [],
objectPermissions: [],
permissionFlags: [],
},
{
canBeAssignedToAgents: false,
@@ -1512,6 +1515,7 @@ export const EXPECTED_MANIFEST: Manifest = {
description: 'Default role for function Twenty client',
fieldPermissions: [
{
universalIdentifier: 'dbc86ced-bd2c-5874-93f1-1f72c5111991',
canReadFieldValue: false,
canUpdateFieldValue: false,
fieldUniversalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
@@ -1521,6 +1525,7 @@ export const EXPECTED_MANIFEST: Manifest = {
label: 'Default function role',
objectPermissions: [
{
universalIdentifier: '99c7c326-04ca-5c8b-ad11-da6c5b819813',
canDestroyObjectRecords: false,
canReadObjectRecords: true,
canSoftDeleteObjectRecords: false,
@@ -1528,7 +1533,12 @@ export const EXPECTED_MANIFEST: Manifest = {
objectUniversalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
},
],
permissionFlags: [PermissionFlagType.APPLICATIONS],
permissionFlags: [
{
universalIdentifier: '01d7865a-7700-5d49-b2aa-62623c2cbac7',
flag: PermissionFlagType.APPLICATIONS,
},
],
universalIdentifier: 'b648f87b-1d26-4961-b974-0908fd991061',
},
],
@@ -38,6 +38,8 @@ import {
import { getInputSchemaFromSourceCode } from 'twenty-shared/logic-function';
import { assertUnreachable } from 'twenty-shared/utils';
import { addMissingFieldOptionIds } from '@/cli/utilities/build/manifest/utils/add-missing-field-option-ids';
import { fromRoleConfigToRoleManifest } from '@/cli/utilities/build/manifest/utils/from-role-config-to-role-manifest';
import { type RoleConfig } from '@/sdk/roles/role-config';
const loadSources = async (appPath: string): Promise<string[]> => {
return await glob(['**/*.ts', '**/*.tsx'], {
@@ -170,11 +172,12 @@ export const buildManifest = async (
break;
}
case ManifestEntityKey.Roles: {
const extract = await extractManifestFromFile<RoleManifest>({
const extract = await extractManifestFromFile<RoleConfig>({
appPath,
filePath,
});
roles.push(extract.config);
const roleConfig = fromRoleConfigToRoleManifest(extract.config);
roles.push(roleConfig);
errors.push(...extract.errors);
rolesFilePaths.push(relativePath);
break;
@@ -0,0 +1,41 @@
import { type RoleConfig } from '@/sdk/roles/role-config';
import { type RoleManifest } from 'twenty-shared/application';
import { v5 as uuidv5 } from 'uuid';
const ROLE_UNIVERSAL_IDENTIFIER_NAMESPACE =
'b403ec59-4d80-4f22-85e6-717a192dc9cb';
export const fromRoleConfigToRoleManifest = (
roleConfig: RoleConfig,
): RoleManifest => {
return {
...roleConfig,
objectPermissions: (roleConfig.objectPermissions ?? []).map(
(objectPermission) => ({
...objectPermission,
universalIdentifier: uuidv5(
`${roleConfig.universalIdentifier}:${objectPermission.objectUniversalIdentifier}`,
ROLE_UNIVERSAL_IDENTIFIER_NAMESPACE,
),
}),
),
fieldPermissions: (roleConfig.fieldPermissions ?? []).map(
(fieldPermission) => ({
...fieldPermission,
universalIdentifier: uuidv5(
`${roleConfig.universalIdentifier}:${fieldPermission.objectUniversalIdentifier}:${fieldPermission.fieldUniversalIdentifier}`,
ROLE_UNIVERSAL_IDENTIFIER_NAMESPACE,
),
}),
),
permissionFlags: (roleConfig.permissionFlags ?? []).map(
(permissionFlag) => ({
universalIdentifier: uuidv5(
`${roleConfig.universalIdentifier}:${permissionFlag}`,
ROLE_UNIVERSAL_IDENTIFIER_NAMESPACE,
),
flag: permissionFlag,
}),
),
};
};
@@ -4,10 +4,10 @@ import { type LogicFunctionConfig } from '@/sdk/logic-functions/logic-function-c
import { type ObjectConfig } from '@/sdk/objects/object-config';
import { type PageLayoutConfig } from '@/sdk/page-layouts/page-layout-config';
import { type ViewConfig } from '@/sdk/views/view-config';
import { type RoleConfig } from '@/sdk/roles/role-config';
import {
type FieldManifest,
type NavigationMenuItemManifest,
type RoleManifest,
type SkillManifest,
} from 'twenty-shared/application';
@@ -23,7 +23,7 @@ export type DefinableEntity =
| FieldManifest
| FrontComponentConfig
| LogicFunctionConfig
| RoleManifest
| RoleConfig
| SkillManifest
| ViewConfig
| NavigationMenuItemManifest
@@ -1,8 +1,8 @@
import { createValidationResult } from '@/sdk/common/utils/create-validation-result';
import { type RoleManifest } from 'twenty-shared/application';
import { type DefineEntity } from '@/sdk/common/types/define-entity.type';
import { type RoleConfig } from '@/sdk/roles/role-config';
export const defineRole: DefineEntity<RoleManifest> = (config) => {
export const defineRole: DefineEntity<RoleConfig> = (config) => {
const errors = [];
if (!config.universalIdentifier) {
@@ -0,0 +1,15 @@
import type {
FieldPermissionManifest,
ObjectPermissionManifest,
RoleManifest,
} from 'twenty-shared/application';
import { type PermissionFlagType } from 'twenty-shared/constants';
export type RoleConfig = Omit<
RoleManifest,
'objectPermissions' | 'fieldPermissions' | 'permissionFlags'
> & {
objectPermissions?: Omit<ObjectPermissionManifest, 'universalIdentifier'>[];
fieldPermissions?: Omit<FieldPermissionManifest, 'universalIdentifier'>[];
permissionFlags?: PermissionFlagType[];
};
@@ -29,6 +29,8 @@ export class ApplicationExceptionFilter implements ExceptionFilter {
throw new ForbiddenError(exception);
case ApplicationExceptionCode.INVALID_INPUT:
case ApplicationExceptionCode.SOURCE_CHANNEL_MISMATCH:
case ApplicationExceptionCode.APP_ALREADY_INSTALLED:
case ApplicationExceptionCode.CANNOT_DOWNGRADE_APPLICATION:
throw new UserInputError(exception);
case ApplicationExceptionCode.PACKAGE_RESOLUTION_FAILED:
case ApplicationExceptionCode.TARBALL_EXTRACTION_FAILED:
@@ -4,6 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { promises as fs } from 'fs';
import { resolve } from 'path';
import semver from 'semver';
import { Manifest } from 'twenty-shared/application';
import { FileFolder } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
@@ -117,6 +118,37 @@ export class ApplicationInstallService {
sourceType: appRegistration.sourceType,
});
const incomingVersion = resolvedPackage.packageJson.version;
if (
!wasCreated &&
isDefined(application.version) &&
isDefined(incomingVersion)
) {
if (!isDefined(semver.valid(incomingVersion))) {
throw new ApplicationException(
`Invalid version "${incomingVersion}" in package.json. Must be a valid semver version.`,
ApplicationExceptionCode.INVALID_INPUT,
);
}
if (isDefined(semver.valid(application.version))) {
if (semver.eq(incomingVersion, application.version)) {
throw new ApplicationException(
`${universalIdentifier}@${incomingVersion} is already installed in this workspace.`,
ApplicationExceptionCode.APP_ALREADY_INSTALLED,
);
}
if (semver.lt(incomingVersion, application.version)) {
throw new ApplicationException(
`Cannot install ${universalIdentifier}@${incomingVersion}: version ${application.version} is already installed and downgrading is not allowed.`,
ApplicationExceptionCode.CANNOT_DOWNGRADE_APPLICATION,
);
}
}
}
await this.writeFilesToStorage(
resolvedPackage.extractedDir,
resolvedPackage.manifest,
@@ -1,6 +1,6 @@
import { Injectable, Logger } from '@nestjs/common';
import { type Manifest, type RoleManifest } from 'twenty-shared/application';
import { type Manifest } from 'twenty-shared/application';
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
import { isDefined } from 'twenty-shared/utils';
@@ -15,9 +15,6 @@ import { computeApplicationManifestAllUniversalFlatEntityMaps } from 'src/engine
import { getApplicationSubAllFlatEntityMaps } from 'src/engine/core-modules/application/application-manifest/utils/get-application-sub-all-flat-entity-maps.util';
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
import { FieldPermissionService } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.service';
import { ObjectPermissionService } from 'src/engine/metadata-modules/object-permission/object-permission.service';
import { PermissionFlagService } from 'src/engine/metadata-modules/permission-flag/permission-flag.service';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
@@ -34,9 +31,6 @@ export class ApplicationManifestMigrationService {
private readonly workspaceCacheService: WorkspaceCacheService,
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly applicationService: ApplicationService,
private readonly objectPermissionService: ObjectPermissionService,
private readonly fieldPermissionService: FieldPermissionService,
private readonly permissionFlagService: PermissionFlagService,
) {}
async syncMetadataFromManifest({
@@ -119,7 +113,7 @@ export class ApplicationManifestMigrationService {
`Metadata migration completed for application ${ownerFlatApplication.universalIdentifier}`,
);
await this.syncRolePermissionsAndDefaultRole({
await this.syncDefaultRoleAndSettingsCustomTab({
manifest,
workspaceId,
ownerFlatApplication,
@@ -131,13 +125,7 @@ export class ApplicationManifestMigrationService {
};
}
/**
* @deprecated should be remove once below issues are resolved:
* - [objectPermission](https://github.com/twentyhq/core-team-issues/issues/2223)
* - [fieldPermission](https://github.com/twentyhq/core-team-issues/issues/2224)
* - [permissionFlag](https://github.com/twentyhq/core-team-issues/issues/2225)
*/
private async syncRolePermissionsAndDefaultRole({
private async syncDefaultRoleAndSettingsCustomTab({
manifest,
workspaceId,
ownerFlatApplication,
@@ -148,13 +136,9 @@ export class ApplicationManifestMigrationService {
}) {
const {
flatRoleMaps: refreshedFlatRoleMaps,
flatObjectMetadataMaps: refreshedFlatObjectMetadataMaps,
flatFieldMetadataMaps: refreshedFlatFieldMetadataMaps,
flatFrontComponentMaps: refreshedFlatFrontComponentMaps,
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
'flatRoleMaps',
'flatObjectMetadataMaps',
'flatFieldMetadataMaps',
'flatFrontComponentMaps',
]);
@@ -173,14 +157,6 @@ export class ApplicationManifestMigrationService {
);
}
await this.syncApplicationRolePermissions({
role,
workspaceId,
roleId: flatRole.id,
refreshedFlatObjectMetadataMaps,
refreshedFlatFieldMetadataMaps,
});
if (
role.universalIdentifier ===
manifest.application.defaultRoleUniversalIdentifier
@@ -216,126 +192,4 @@ export class ApplicationManifestMigrationService {
...(isDefined(defaultRoleId) ? { defaultRoleId } : {}),
});
}
private async syncApplicationRolePermissions({
role,
workspaceId,
roleId,
refreshedFlatObjectMetadataMaps,
refreshedFlatFieldMetadataMaps,
}: {
role: RoleManifest;
workspaceId: string;
roleId: string;
refreshedFlatObjectMetadataMaps: Awaited<
ReturnType<WorkspaceCacheService['getOrRecompute']>
>['flatObjectMetadataMaps'];
refreshedFlatFieldMetadataMaps: Awaited<
ReturnType<WorkspaceCacheService['getOrRecompute']>
>['flatFieldMetadataMaps'];
}) {
if (
(role.objectPermissions ?? []).length > 0 ||
(role.fieldPermissions ?? []).length > 0
) {
const formattedObjectPermissions = role.objectPermissions
?.map((permission) => {
const flatObjectMetadata = findFlatEntityByUniversalIdentifier({
flatEntityMaps: refreshedFlatObjectMetadataMaps,
universalIdentifier: permission.objectUniversalIdentifier,
});
if (!isDefined(flatObjectMetadata)) {
throw new ApplicationException(
`Failed to find object with universalIdentifier ${permission.objectUniversalIdentifier}`,
ApplicationExceptionCode.OBJECT_NOT_FOUND,
);
}
return {
...permission,
objectMetadataId: flatObjectMetadata.id,
};
})
.filter(
(
permission,
): permission is typeof permission & { objectMetadataId: string } =>
isDefined(permission.objectMetadataId),
);
if (isDefined(formattedObjectPermissions)) {
await this.objectPermissionService.upsertObjectPermissions({
workspaceId,
input: {
roleId,
objectPermissions: formattedObjectPermissions,
},
});
}
const formattedFieldPermissions = role.fieldPermissions
?.map((permission) => {
const flatObjectMetadata = findFlatEntityByUniversalIdentifier({
flatEntityMaps: refreshedFlatObjectMetadataMaps,
universalIdentifier: permission.objectUniversalIdentifier,
});
if (!isDefined(flatObjectMetadata)) {
throw new ApplicationException(
`Failed to find object with universalIdentifier ${permission.objectUniversalIdentifier}`,
ApplicationExceptionCode.OBJECT_NOT_FOUND,
);
}
const flatFieldMetadata = findFlatEntityByUniversalIdentifier({
flatEntityMaps: refreshedFlatFieldMetadataMaps,
universalIdentifier: permission.fieldUniversalIdentifier,
});
if (!isDefined(flatFieldMetadata)) {
throw new ApplicationException(
`Failed to find field with universalIdentifier ${permission.fieldUniversalIdentifier}`,
ApplicationExceptionCode.FIELD_NOT_FOUND,
);
}
return {
...permission,
objectMetadataId: flatObjectMetadata.id,
fieldMetadataId: flatFieldMetadata.id,
};
})
.filter(
(
permission,
): permission is typeof permission & {
objectMetadataId: string;
fieldMetadataId: string;
} =>
isDefined(permission.objectMetadataId) &&
isDefined(permission.fieldMetadataId),
);
if (isDefined(formattedFieldPermissions)) {
await this.fieldPermissionService.upsertFieldPermissions({
workspaceId,
input: {
roleId,
fieldPermissions: formattedFieldPermissions,
},
});
}
}
if (isDefined(role.permissionFlags) && role.permissionFlags.length > 0) {
await this.permissionFlagService.upsertPermissionFlags({
workspaceId,
input: {
roleId,
permissionFlagKeys: role.permissionFlags,
},
});
}
}
}
@@ -7,8 +7,6 @@ import { ApplicationSyncService } from 'src/engine/core-modules/application/appl
import { ApplicationVariableEntityModule } from 'src/engine/core-modules/application/application-variable/application-variable.module';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { FileStorageModule } from 'src/engine/core-modules/file-storage/file-storage.module';
import { ObjectPermissionModule } from 'src/engine/metadata-modules/object-permission/object-permission.module';
import { PermissionFlagModule } from 'src/engine/metadata-modules/permission-flag/permission-flag.module';
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor';
@@ -21,8 +19,6 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
ApplicationVariableEntityModule,
FeatureFlagModule,
FileStorageModule,
ObjectPermissionModule,
PermissionFlagModule,
PermissionsModule,
WorkspaceCacheModule,
WorkspaceMigrationModule,
@@ -0,0 +1,28 @@
import { type FieldPermissionManifest } from 'twenty-shared/application';
import { type UniversalFlatFieldPermission } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-field-permission.type';
export const fromFieldPermissionManifestToUniversalFlatFieldPermission = ({
fieldPermissionManifest,
roleUniversalIdentifier,
applicationUniversalIdentifier,
now,
}: {
fieldPermissionManifest: FieldPermissionManifest;
roleUniversalIdentifier: string;
applicationUniversalIdentifier: string;
now: string;
}): UniversalFlatFieldPermission => {
return {
universalIdentifier: fieldPermissionManifest.universalIdentifier,
applicationUniversalIdentifier,
roleUniversalIdentifier,
objectMetadataUniversalIdentifier:
fieldPermissionManifest.objectUniversalIdentifier,
fieldMetadataUniversalIdentifier:
fieldPermissionManifest.fieldUniversalIdentifier,
canReadFieldValue: fieldPermissionManifest.canReadFieldValue ?? null,
canUpdateFieldValue: fieldPermissionManifest.canUpdateFieldValue ?? null,
createdAt: now,
updatedAt: now,
};
};
@@ -0,0 +1,29 @@
import { type ObjectPermissionManifest } from 'twenty-shared/application';
import { type UniversalFlatObjectPermission } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-object-permission.type';
export const fromObjectPermissionManifestToUniversalFlatObjectPermission = ({
objectPermissionManifest,
roleUniversalIdentifier,
applicationUniversalIdentifier,
now,
}: {
objectPermissionManifest: ObjectPermissionManifest;
roleUniversalIdentifier: string;
applicationUniversalIdentifier: string;
now: string;
}): UniversalFlatObjectPermission => {
return {
universalIdentifier: objectPermissionManifest.universalIdentifier,
applicationUniversalIdentifier,
roleUniversalIdentifier,
objectMetadataUniversalIdentifier:
objectPermissionManifest.objectUniversalIdentifier,
canReadObjectRecords: objectPermissionManifest.canReadObjectRecords,
canUpdateObjectRecords: objectPermissionManifest.canUpdateObjectRecords,
canSoftDeleteObjectRecords:
objectPermissionManifest.canSoftDeleteObjectRecords,
canDestroyObjectRecords: objectPermissionManifest.canDestroyObjectRecords,
createdAt: now,
updatedAt: now,
};
};
@@ -0,0 +1,23 @@
import { type UniversalFlatPermissionFlag } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-permission-flag.type';
import { PermissionFlagManifest } from 'twenty-shared/application';
export const fromPermissionFlagToUniversalFlatPermissionFlag = ({
permissionFlag,
roleUniversalIdentifier,
applicationUniversalIdentifier,
now,
}: {
permissionFlag: PermissionFlagManifest;
roleUniversalIdentifier: string;
applicationUniversalIdentifier: string;
now: string;
}): UniversalFlatPermissionFlag => {
return {
universalIdentifier: permissionFlag.universalIdentifier,
applicationUniversalIdentifier,
roleUniversalIdentifier,
flag: permissionFlag.flag,
createdAt: now,
updatedAt: now,
};
};
@@ -4,13 +4,16 @@ import { isDefined } from 'twenty-shared/utils';
import { fromCommandMenuItemManifestToUniversalFlatCommandMenuItem } from 'src/engine/core-modules/application/application-manifest/converters/from-command-menu-item-manifest-to-universal-flat-command-menu-item.util';
import { fromFieldManifestToUniversalFlatFieldMetadata } from 'src/engine/core-modules/application/application-manifest/converters/from-field-manifest-to-universal-flat-field-metadata.util';
import { fromFieldPermissionManifestToUniversalFlatFieldPermission } from 'src/engine/core-modules/application/application-manifest/converters/from-field-permission-manifest-to-universal-flat-field-permission.util';
import { fromFrontComponentManifestToUniversalFlatFrontComponent } from 'src/engine/core-modules/application/application-manifest/converters/from-front-component-manifest-to-universal-flat-front-component.util';
import { fromLogicFunctionManifestToUniversalFlatLogicFunction } from 'src/engine/core-modules/application/application-manifest/converters/from-logic-function-manifest-to-universal-flat-logic-function.util';
import { fromNavigationMenuItemManifestToUniversalFlatNavigationMenuItem } from 'src/engine/core-modules/application/application-manifest/converters/from-navigation-menu-item-manifest-to-universal-flat-navigation-menu-item.util';
import { fromObjectManifestToUniversalFlatObjectMetadata } from 'src/engine/core-modules/application/application-manifest/converters/from-object-manifest-to-universal-flat-object-metadata.util';
import { fromObjectPermissionManifestToUniversalFlatObjectPermission } from 'src/engine/core-modules/application/application-manifest/converters/from-object-permission-manifest-to-universal-flat-object-permission.util';
import { fromPageLayoutManifestToUniversalFlatPageLayout } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-manifest-to-universal-flat-page-layout.util';
import { fromPageLayoutTabManifestToUniversalFlatPageLayoutTab } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util';
import { fromPageLayoutWidgetManifestToUniversalFlatPageLayoutWidget } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util';
import { fromPermissionFlagToUniversalFlatPermissionFlag } from 'src/engine/core-modules/application/application-manifest/converters/from-permission-flag-to-universal-flat-permission-flag.util';
import { fromRoleManifestToUniversalFlatRole } from 'src/engine/core-modules/application/application-manifest/converters/from-role-manifest-to-universal-flat-role.util';
import { fromSkillManifestToUniversalFlatSkill } from 'src/engine/core-modules/application/application-manifest/converters/from-skill-manifest-to-universal-flat-skill.util';
import { computeSearchVectorUniversalSettingsFromObjectManifest } from 'src/engine/core-modules/application/application-manifest/utils/compute-search-vector-universal-settings-from-object-manifest.util';
@@ -144,6 +147,47 @@ export const computeApplicationManifestAllUniversalFlatEntityMaps = ({
}),
universalFlatEntityMapsToMutate: allUniversalFlatEntityMaps.flatRoleMaps,
});
for (const objectPermissionManifest of roleManifest.objectPermissions ??
[]) {
addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow({
universalFlatEntity:
fromObjectPermissionManifestToUniversalFlatObjectPermission({
objectPermissionManifest,
roleUniversalIdentifier: roleManifest.universalIdentifier,
applicationUniversalIdentifier,
now,
}),
universalFlatEntityMapsToMutate:
allUniversalFlatEntityMaps.flatObjectPermissionMaps,
});
}
for (const fieldPermissionManifest of roleManifest.fieldPermissions ?? []) {
addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow({
universalFlatEntity:
fromFieldPermissionManifestToUniversalFlatFieldPermission({
fieldPermissionManifest,
roleUniversalIdentifier: roleManifest.universalIdentifier,
applicationUniversalIdentifier,
now,
}),
universalFlatEntityMapsToMutate:
allUniversalFlatEntityMaps.flatFieldPermissionMaps,
});
}
for (const permissionFlag of roleManifest.permissionFlags ?? []) {
addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow({
universalFlatEntity: fromPermissionFlagToUniversalFlatPermissionFlag({
permissionFlag,
roleUniversalIdentifier: roleManifest.universalIdentifier,
applicationUniversalIdentifier,
now,
}),
universalFlatEntityMapsToMutate:
allUniversalFlatEntityMaps.flatPermissionFlagMaps,
});
}
}
for (const skillManifest of manifest.skills ?? []) {
@@ -12,6 +12,7 @@ export enum ApplicationRegistrationExceptionCode {
INVALID_INPUT = 'INVALID_INPUT',
SOURCE_CHANNEL_MISMATCH = 'SOURCE_CHANNEL_MISMATCH',
VARIABLE_NOT_FOUND = 'VARIABLE_NOT_FOUND',
VERSION_ALREADY_EXISTS = 'VERSION_ALREADY_EXISTS',
}
const getExceptionUserFriendlyMessage = (
@@ -32,6 +33,8 @@ const getExceptionUserFriendlyMessage = (
return msg`The app source channel does not match the expected type.`;
case ApplicationRegistrationExceptionCode.VARIABLE_NOT_FOUND:
return msg`Application registration variable not found.`;
case ApplicationRegistrationExceptionCode.VERSION_ALREADY_EXISTS:
return msg`This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again.`;
default:
assertUnreachable(code);
}
@@ -5,6 +5,7 @@ import { promises as fs } from 'fs';
import { tmpdir } from 'os';
import { join } from 'path';
import semver from 'semver';
import { FileFolder } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { Repository } from 'typeorm';
@@ -103,6 +104,33 @@ export class ApplicationTarballService {
ApplicationRegistrationExceptionCode.SOURCE_CHANNEL_MISMATCH,
);
}
if (
appRegistration.sourceType ===
ApplicationRegistrationSourceType.TARBALL &&
isDefined(appRegistration.latestAvailableVersion) &&
isDefined(packageJson?.version)
) {
const incomingVersion = packageJson.version;
const currentVersion = appRegistration.latestAvailableVersion;
if (!isDefined(semver.valid(incomingVersion))) {
throw new ApplicationRegistrationException(
`Invalid version "${incomingVersion}" in package.json. Must be a valid semver version.`,
ApplicationRegistrationExceptionCode.INVALID_INPUT,
);
}
if (
isDefined(semver.valid(currentVersion)) &&
semver.lte(incomingVersion, currentVersion)
) {
throw new ApplicationRegistrationException(
`Cannot deploy ${universalIdentifier}@${incomingVersion}: version must be higher than the currently deployed version ${currentVersion}. Please bump the version in package.json.`,
ApplicationRegistrationExceptionCode.VERSION_ALREADY_EXISTS,
);
}
}
} else {
appRegistration = this.appRegistrationRepository.create({
universalIdentifier,
@@ -18,6 +18,8 @@ export enum ApplicationExceptionCode {
PACKAGE_RESOLUTION_FAILED = 'PACKAGE_RESOLUTION_FAILED',
TARBALL_EXTRACTION_FAILED = 'TARBALL_EXTRACTION_FAILED',
UPGRADE_FAILED = 'UPGRADE_FAILED',
APP_ALREADY_INSTALLED = 'APP_ALREADY_INSTALLED',
CANNOT_DOWNGRADE_APPLICATION = 'CANNOT_DOWNGRADE_APPLICATION',
}
const getApplicationExceptionUserFriendlyMessage = (
@@ -50,6 +52,10 @@ const getApplicationExceptionUserFriendlyMessage = (
return msg`Failed to extract tarball.`;
case ApplicationExceptionCode.UPGRADE_FAILED:
return msg`Application upgrade failed.`;
case ApplicationExceptionCode.APP_ALREADY_INSTALLED:
return msg`This version of the application is already installed in this workspace.`;
case ApplicationExceptionCode.CANNOT_DOWNGRADE_APPLICATION:
return msg`A higher version of this application is already installed. Downgrading is not allowed.`;
default:
assertUnreachable(code);
}
@@ -104,6 +104,11 @@ msgstr "'n Frontkomponent met hierdie naam bestaan reeds."
msgid "A function with this name already exists."
msgstr "'n Funksie met hierdie naam bestaan reeds."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Hierdie gebruiker is reeds 'n lid van die werksruimte."
msgid "This variable can only be set via environment."
msgstr "Hierdie veranderlike kan slegs via die omgewing gestel word."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "يوجد مكوّن أمامي بهذا الاسم بالفعل."
msgid "A function with this name already exists."
msgstr "توجد دالة بهذا الاسم بالفعل."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "هذا المستخدم عضو بالفعل في مساحة العمل."
msgid "This variable can only be set via environment."
msgstr "يمكن تعيين هذا المتغير فقط عبر البيئة."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Ja existeix un component frontal amb aquest nom."
msgid "A function with this name already exists."
msgstr "Ja existeix una funció amb aquest nom."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Aquest usuari ja forma part de l'espai de treball."
msgid "This variable can only be set via environment."
msgstr "Aquesta variable només es pot establir mitjançant l'entorn."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Frontendová komponenta s tímto názvem již existuje."
msgid "A function with this name already exists."
msgstr "Funkce s tímto názvem již existuje."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Tento uživatel je již členem pracovního prostoru."
msgid "This variable can only be set via environment."
msgstr "Tuto proměnnou lze nastavit pouze pomocí proměnných prostředí."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "En frontkomponent med dette navn findes allerede."
msgid "A function with this name already exists."
msgstr "En funktion med dette navn findes allerede."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Denne bruger er allerede medlem af arbejdsområdet."
msgid "This variable can only be set via environment."
msgstr "Denne variabel kan kun sættes via miljøet."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Eine Front-Komponente mit diesem Namen existiert bereits."
msgid "A function with this name already exists."
msgstr "Eine Funktion mit diesem Namen existiert bereits."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Dieser Benutzer ist bereits Mitglied des Arbeitsbereichs."
msgid "This variable can only be set via environment."
msgstr "Diese Variable kann nur über die Umgebung gesetzt werden."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Υπάρχει ήδη front component με αυτό το όνομα."
msgid "A function with this name already exists."
msgstr "Υπάρχει ήδη συνάρτηση με αυτό το όνομα."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Αυτός ο χρήστης είναι ήδη μέλος του χώρ
msgid "This variable can only be set via environment."
msgstr "Αυτή η μεταβλητή μπορεί να οριστεί μόνο μέσω περιβάλλοντος."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -99,6 +99,11 @@ msgstr "A front component with this name already exists."
msgid "A function with this name already exists."
msgstr "A function with this name already exists."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr "A higher version of this application is already installed. Downgrading is not allowed."
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7230,6 +7235,16 @@ msgstr "This user is already a member of the workspace."
msgid "This variable can only be set via environment."
msgstr "This variable can only be set via environment."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr "This version of the application is already installed in this workspace."
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Ya existe un componente de interfaz con este nombre."
msgid "A function with this name already exists."
msgstr "Ya existe una función con este nombre."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Este usuario ya es miembro del espacio de trabajo."
msgid "This variable can only be set via environment."
msgstr "Esta variable solo se puede establecer mediante el entorno."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Tämän niminen front-komponentti on jo olemassa."
msgid "A function with this name already exists."
msgstr "Tämän niminen funktio on jo olemassa."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Tämä käyttäjä on jo työtilan jäsen."
msgid "This variable can only be set via environment."
msgstr "Tämä muuttuja voidaan asettaa vain ympäristön kautta."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Un composant frontal portant ce nom existe déjà."
msgid "A function with this name already exists."
msgstr "Une fonction portant ce nom existe déjà."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Cet utilisateur est déjà membre de l'espace de travail."
msgid "This variable can only be set via environment."
msgstr "Cette variable ne peut être définie que via l'environnement."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
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
@@ -104,6 +104,11 @@ msgstr "רכיב פרונט בשם זה כבר קיים."
msgid "A function with this name already exists."
msgstr "פונקציה בשם זה כבר קיימת."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "משתמש זה כבר חבר בסביבת העבודה."
msgid "This variable can only be set via environment."
msgstr "ניתן להגדיר משתנה זה רק באמצעות הסביבה."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Már létezik ilyen nevű front komponens."
msgid "A function with this name already exists."
msgstr "Már létezik ilyen nevű függvény."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Ez a felhasználó már tagja a munkaterületnek."
msgid "This variable can only be set via environment."
msgstr "Ezt a változót csak környezeten keresztül lehet beállítani."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Esiste già un componente front-end con questo nome."
msgid "A function with this name already exists."
msgstr "Esiste già una funzione con questo nome."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Questo utente è già membro dello spazio di lavoro."
msgid "This variable can only be set via environment."
msgstr "Questa variabile può essere impostata solo tramite l'ambiente."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "この名前のフロントコンポーネントはすでに存在しま
msgid "A function with this name already exists."
msgstr "この名前の関数はすでに存在します。"
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "このユーザーはすでにワークスペースのメンバーです
msgid "This variable can only be set via environment."
msgstr "この変数は環境変数でのみ設定できます。"
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "이 이름의 프런트 컴포넌트가 이미 존재합니다."
msgid "A function with this name already exists."
msgstr "이 이름의 함수가 이미 존재합니다."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "이 사용자는 이미 워크스페이스의 멤버입니다."
msgid "This variable can only be set via environment."
msgstr "이 변수는 환경을 통해서만 설정할 수 있습니다."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Er bestaat al een frontcomponent met deze naam."
msgid "A function with this name already exists."
msgstr "Er bestaat al een functie met deze naam."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Deze gebruiker is al lid van de werkruimte."
msgid "This variable can only be set via environment."
msgstr "Deze variabele kan alleen via de omgeving worden ingesteld."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "En frontkomponent med dette navnet finnes allerede."
msgid "A function with this name already exists."
msgstr "En funksjon med dette navnet finnes allerede."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Denne brukeren er allerede medlem av arbeidsområdet."
msgid "This variable can only be set via environment."
msgstr "Denne variabelen kan bare settes via miljøet."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Komponent frontowy o tej nazwie już istnieje."
msgid "A function with this name already exists."
msgstr "Funkcja o tej nazwie już istnieje."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Ten użytkownik jest już członkiem przestrzeni roboczej."
msgid "This variable can only be set via environment."
msgstr "Tę zmienną można ustawić tylko za pośrednictwem środowiska."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -99,6 +99,11 @@ msgstr ""
msgid "A function with this name already exists."
msgstr ""
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7230,6 +7235,16 @@ msgstr ""
msgid "This variable can only be set via environment."
msgstr ""
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Já existe um componente de front-end com este nome."
msgid "A function with this name already exists."
msgstr "Uma função com este nome já existe."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Este usuário já é membro do espaço de trabalho."
msgid "This variable can only be set via environment."
msgstr "Esta variável só pode ser definida via ambiente."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Um componente de front-end com este nome já existe."
msgid "A function with this name already exists."
msgstr "Uma função com este nome já existe."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Este usuário já é membro do espaço de trabalho."
msgid "This variable can only be set via environment."
msgstr "Esta variável só pode ser definida via ambiente."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "O componentă de interfață cu acest nume există deja."
msgid "A function with this name already exists."
msgstr "O funcție cu acest nume există deja."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Acest utilizator este deja membru al spațiului de lucru."
msgid "This variable can only be set via environment."
msgstr "Această variabilă poate fi setată doar prin variabilele de mediu."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Компонент фронтенда с таким именем уже
msgid "A function with this name already exists."
msgstr "Функция с таким именем уже существует."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Этот пользователь уже является участни
msgid "This variable can only be set via environment."
msgstr "Эту переменную можно установить только через окружение."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Фронтенд компонента са овим именом већ
msgid "A function with this name already exists."
msgstr "Функција са овим именом већ постоји."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Овај корисник је већ члан радног просто
msgid "This variable can only be set via environment."
msgstr "Ова променљива се може поставити само преко окружења."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "En frontkomponent med detta namn finns redan."
msgid "A function with this name already exists."
msgstr "En funktion med detta namn finns redan."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7241,6 +7246,16 @@ msgstr "Denna användare är redan medlem i arbetsytan."
msgid "This variable can only be set via environment."
msgstr "Denna variabel kan endast ställas in via miljön."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Bu isimde bir ön bileşen zaten mevcut."
msgid "A function with this name already exists."
msgstr "Bu isimde bir işlev zaten mevcut."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Bu kullanıcı zaten çalışma alanının bir üyesi."
msgid "This variable can only be set via environment."
msgstr "Bu değişken yalnızca ortam üzerinden ayarlanabilir."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Фронтенд-компонент з такою назвою вже і
msgid "A function with this name already exists."
msgstr "Функція з такою назвою вже існує."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Цей користувач уже є учасником робочог
msgid "This variable can only be set via environment."
msgstr "Цю змінну можна встановити лише через середовище."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "Một thành phần giao diện có tên này đã tồn tại."
msgid "A function with this name already exists."
msgstr "Một hàm có tên này đã tồn tại."
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "Người dùng này đã là thành viên của không gian làm việc.
msgid "This variable can only be set via environment."
msgstr "Biến này chỉ có thể được đặt thông qua môi trường."
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "已存在同名前端组件。"
msgid "A function with this name already exists."
msgstr "已存在同名函数。"
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "该用户已是此工作区成员。"
msgid "This variable can only be set via environment."
msgstr "此变量只能通过环境进行设置。"
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"
@@ -104,6 +104,11 @@ msgstr "具有此名稱的前端元件已存在。"
msgid "A function with this name already exists."
msgstr "具有此名稱的函式已存在。"
#. js-lingui-id: 6yZjO1
#: src/engine/core-modules/application/application.exception.ts
msgid "A higher version of this application is already installed. Downgrading is not allowed."
msgstr ""
#. js-lingui-id: Nh/ZZe
#: src/engine/metadata-modules/object-metadata/object-metadata.exception.ts
msgid "A name conflict occurred."
@@ -7235,6 +7240,16 @@ msgstr "此使用者已是該工作區成員。"
msgid "This variable can only be set via environment."
msgstr "此變數只能透過環境變數設定。"
#. js-lingui-id: Y5Fzhi
#: src/engine/core-modules/application/application-registration/application-registration.exception.ts
msgid "This version is not higher than the currently deployed version. Please bump the version in package.json before deploying again."
msgstr ""
#. js-lingui-id: ZXnasf
#: src/engine/core-modules/application/application.exception.ts
msgid "This version of the application is already installed in this workspace."
msgstr ""
#. js-lingui-id: Zl0BJl
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-channel-message-association-standard-flat-field-metadata.util.ts
msgid "Thread External Id"

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