Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee2f8e0226 | ||
|
|
cb44b22e15 | ||
|
|
9498a60f74 | ||
|
|
191a277ddf | ||
|
|
7f1814805d | ||
|
|
34b81adce8 | ||
|
|
cd2e08b912 | ||
|
|
fb21f3ccf5 | ||
|
|
281bb6d783 |
@@ -36,6 +36,9 @@ jobs:
|
||||
services:
|
||||
postgres:
|
||||
image: twentycrm/twenty-postgres-spilo
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
env:
|
||||
PGUSER_SUPERUSER: postgres
|
||||
PGPASSWORD_SUPERUSER: postgres
|
||||
@@ -50,10 +53,16 @@ jobs:
|
||||
--health-retries 5
|
||||
redis:
|
||||
image: redis
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
ports:
|
||||
- 6379:6379
|
||||
clickhouse:
|
||||
image: clickhouse/clickhouse-server:25.8.8
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
env:
|
||||
CLICKHOUSE_PASSWORD: clickhousePassword
|
||||
CLICKHOUSE_URL: "http://default:clickhousePassword@localhost:8123/twenty"
|
||||
@@ -143,7 +152,6 @@ jobs:
|
||||
set_env_var "CLICKHOUSE_PASSWORD" "clickhousePassword"
|
||||
|
||||
npx nx run twenty-server:database:init:prod
|
||||
npx nx run twenty-server:database:migrate:prod
|
||||
|
||||
- name: Seed current branch database with test data
|
||||
run: |
|
||||
@@ -296,7 +304,6 @@ jobs:
|
||||
set_env_var "CLICKHOUSE_PASSWORD" "clickhousePassword"
|
||||
|
||||
npx nx run twenty-server:database:init:prod
|
||||
npx nx run twenty-server:database:migrate:prod
|
||||
|
||||
- name: Seed main branch database with test data
|
||||
run: |
|
||||
@@ -395,6 +402,12 @@ jobs:
|
||||
# Clean up temp directory
|
||||
rm -rf /tmp/current-branch-files
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Install OpenAPI Diff Tool
|
||||
run: |
|
||||
# Using the Java-based OpenAPITools/openapi-diff via Docker
|
||||
|
||||
@@ -37,6 +37,9 @@ jobs:
|
||||
services:
|
||||
postgres:
|
||||
image: twentycrm/twenty-postgres-spilo
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
env:
|
||||
PGUSER_SUPERUSER: postgres
|
||||
PGPASSWORD_SUPERUSER: postgres
|
||||
@@ -51,6 +54,9 @@ jobs:
|
||||
--health-retries 5
|
||||
redis:
|
||||
image: redis
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
ports:
|
||||
- 6379:6379
|
||||
env:
|
||||
|
||||
@@ -26,6 +26,9 @@ jobs:
|
||||
services:
|
||||
postgres:
|
||||
image: twentycrm/twenty-postgres-spilo
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
env:
|
||||
PGUSER_SUPERUSER: postgres
|
||||
PGPASSWORD_SUPERUSER: postgres
|
||||
@@ -40,6 +43,9 @@ jobs:
|
||||
--health-retries 5
|
||||
redis:
|
||||
image: redis
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
ports:
|
||||
- 6379:6379
|
||||
steps:
|
||||
|
||||
@@ -57,6 +57,9 @@ jobs:
|
||||
services:
|
||||
postgres:
|
||||
image: twentycrm/twenty-postgres-spilo
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
env:
|
||||
PGUSER_SUPERUSER: postgres
|
||||
PGPASSWORD_SUPERUSER: postgres
|
||||
@@ -71,6 +74,9 @@ jobs:
|
||||
--health-retries 5
|
||||
redis:
|
||||
image: redis
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
ports:
|
||||
- 6379:6379
|
||||
env:
|
||||
|
||||
@@ -84,6 +84,9 @@ jobs:
|
||||
services:
|
||||
postgres:
|
||||
image: twentycrm/twenty-postgres-spilo
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
env:
|
||||
PGUSER_SUPERUSER: postgres
|
||||
PGPASSWORD_SUPERUSER: postgres
|
||||
@@ -98,6 +101,9 @@ jobs:
|
||||
--health-retries 5
|
||||
redis:
|
||||
image: redis
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
ports:
|
||||
- 6379:6379
|
||||
steps:
|
||||
@@ -122,7 +128,6 @@ jobs:
|
||||
PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "default";'
|
||||
PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres -d postgres -c 'CREATE DATABASE "test";'
|
||||
npx nx run twenty-server:database:init:prod
|
||||
npx nx run twenty-server:database:migrate:prod
|
||||
- name: Worker / Run
|
||||
run: |
|
||||
timeout 30s npx nx run twenty-server:worker || exit_code=$?
|
||||
@@ -227,6 +232,9 @@ jobs:
|
||||
services:
|
||||
postgres:
|
||||
image: twentycrm/twenty-postgres-spilo
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
env:
|
||||
PGUSER_SUPERUSER: postgres
|
||||
PGPASSWORD_SUPERUSER: postgres
|
||||
@@ -241,10 +249,16 @@ jobs:
|
||||
--health-retries 5
|
||||
redis:
|
||||
image: redis
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
ports:
|
||||
- 6379:6379
|
||||
clickhouse:
|
||||
image: clickhouse/clickhouse-server:25.8.8
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
env:
|
||||
CLICKHOUSE_PASSWORD: clickhousePassword
|
||||
CLICKHOUSE_URL: "http://default:clickhousePassword@localhost:8123/twenty"
|
||||
|
||||
@@ -27,6 +27,11 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
- name: Run compose
|
||||
run: |
|
||||
echo "Patching docker-compose.yml..."
|
||||
@@ -97,6 +102,11 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
- name: Create frontend placeholder
|
||||
run: |
|
||||
mkdir -p packages/twenty-front/build
|
||||
|
||||
@@ -27,6 +27,9 @@ jobs:
|
||||
services:
|
||||
postgres:
|
||||
image: twentycrm/twenty-postgres-spilo
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
env:
|
||||
PGUSER_SUPERUSER: postgres
|
||||
PGPASSWORD_SUPERUSER: postgres
|
||||
|
||||
@@ -30,6 +30,9 @@ jobs:
|
||||
services:
|
||||
postgres:
|
||||
image: twentycrm/twenty-postgres-spilo
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
env:
|
||||
PGUSER_SUPERUSER: postgres
|
||||
PGPASSWORD_SUPERUSER: postgres
|
||||
@@ -44,6 +47,9 @@ jobs:
|
||||
--health-retries 5
|
||||
redis:
|
||||
image: redis
|
||||
credentials:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
ports:
|
||||
- 6379:6379
|
||||
steps:
|
||||
|
||||
@@ -17,6 +17,12 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.event.client_payload.pr_head_sha }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||
|
||||
- name: Run compose setup
|
||||
run: |
|
||||
echo "Patching docker-compose.yml..."
|
||||
|
||||
@@ -32,11 +32,11 @@ has_schema=$(PGPASSWORD=twenty psql -h localhost -U twenty -d default -tAc \
|
||||
|
||||
if [ "$has_schema" = "f" ]; then
|
||||
echo "Database appears to be empty, running initial setup..."
|
||||
NODE_OPTIONS="--max-old-space-size=1500" node ./dist/scripts/setup-db.js
|
||||
NODE_OPTIONS="--max-old-space-size=1500" node ./dist/database/scripts/setup-db.js
|
||||
fi
|
||||
|
||||
# Always run migrations (idempotent — skips already-applied ones)
|
||||
yarn database:migrate:prod
|
||||
yarn database:migrate:prod --force
|
||||
|
||||
yarn command:prod cache:flush
|
||||
yarn command:prod upgrade
|
||||
|
||||
@@ -38,12 +38,6 @@ RUN npx nx run twenty-server:lingui:extract && \
|
||||
|
||||
RUN npx nx run twenty-server:build
|
||||
|
||||
# Bundle setup-db script into a standalone JS file so the final image
|
||||
# doesn't need tsx or the TypeScript source tree at runtime.
|
||||
RUN npx esbuild packages/twenty-server/scripts/setup-db.ts \
|
||||
--bundle --platform=node --outfile=packages/twenty-server/dist/scripts/setup-db.js \
|
||||
--external:typeorm --external:dotenv --external:pg
|
||||
|
||||
# Clean server build output (type declarations and compiled tests are not needed at runtime;
|
||||
# source maps are kept because twenty-infra extracts them from the image for Sentry uploads)
|
||||
RUN find /app/packages/twenty-server/dist -name '*.d.ts' -delete \
|
||||
|
||||
@@ -13,8 +13,7 @@ setup_and_migrate_db() {
|
||||
has_schema=$(psql -tAc "SELECT EXISTS (SELECT 1 FROM information_schema.schemata WHERE schema_name = 'core')" ${PG_DATABASE_URL})
|
||||
if [ "$has_schema" = "f" ]; then
|
||||
echo "Database appears to be empty, running migrations."
|
||||
NODE_OPTIONS="--max-old-space-size=1500" node ./dist/scripts/setup-db.js
|
||||
yarn database:migrate:prod
|
||||
yarn database:init:prod
|
||||
fi
|
||||
|
||||
yarn command:prod cache:flush
|
||||
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { type View } from '@/views/types/View';
|
||||
import {
|
||||
NavigationMenuItemType,
|
||||
ViewKey,
|
||||
type NavigationMenuItem,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
import { getNavigationMenuItemLabel } from '@/navigation-menu-item/display/utils/getNavigationMenuItemLabel';
|
||||
|
||||
type ObjectMetadata = Pick<
|
||||
EnrichedObjectMetadataItem,
|
||||
'id' | 'labelPlural' | 'nameSingular'
|
||||
>;
|
||||
type ViewMetadata = Pick<View, 'id' | 'name' | 'objectMetadataId' | 'key'>;
|
||||
|
||||
const objectMetadataItems: ObjectMetadata[] = [
|
||||
{ id: 'obj-1', labelPlural: 'Notes', nameSingular: 'note' },
|
||||
{ id: 'obj-2', labelPlural: 'Companies', nameSingular: 'company' },
|
||||
];
|
||||
|
||||
const views: ViewMetadata[] = [
|
||||
{
|
||||
id: 'view-index',
|
||||
name: 'All Notes',
|
||||
objectMetadataId: 'obj-1',
|
||||
key: ViewKey.INDEX,
|
||||
},
|
||||
{
|
||||
id: 'view-custom',
|
||||
name: 'My Custom View',
|
||||
objectMetadataId: 'obj-1',
|
||||
key: null,
|
||||
},
|
||||
];
|
||||
|
||||
const baseItem: NavigationMenuItem = {
|
||||
id: 'nav-1',
|
||||
type: NavigationMenuItemType.OBJECT,
|
||||
position: 0,
|
||||
createdAt: '',
|
||||
updatedAt: '',
|
||||
};
|
||||
|
||||
describe('getNavigationMenuItemLabel', () => {
|
||||
describe('when type is OBJECT', () => {
|
||||
it('should return labelPlural for a matching object', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.OBJECT,
|
||||
targetObjectMetadataId: 'obj-1',
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'Notes',
|
||||
);
|
||||
});
|
||||
|
||||
it('should return empty string when object is not found', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.OBJECT,
|
||||
targetObjectMetadataId: 'nonexistent',
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when type is VIEW', () => {
|
||||
it('should return the resolved view name for an INDEX view', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.VIEW,
|
||||
viewId: 'view-index',
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'All Notes',
|
||||
);
|
||||
});
|
||||
|
||||
it('should return the view name for a non-INDEX view', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.VIEW,
|
||||
viewId: 'view-custom',
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'My Custom View',
|
||||
);
|
||||
});
|
||||
|
||||
it('should return empty string when view is not found', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.VIEW,
|
||||
viewId: 'nonexistent',
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when type is LINK', () => {
|
||||
it('should return the item name when present', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.LINK,
|
||||
name: 'Documentation',
|
||||
link: 'https://docs.example.com',
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'Documentation',
|
||||
);
|
||||
});
|
||||
|
||||
it('should return the link URL when name is null', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.LINK,
|
||||
name: null,
|
||||
link: 'https://docs.example.com',
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'https://docs.example.com',
|
||||
);
|
||||
});
|
||||
|
||||
it('should return "Link" when both name and link are empty', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.LINK,
|
||||
name: null,
|
||||
link: ' ',
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'Link',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when type is RECORD', () => {
|
||||
it('should return labelIdentifier from targetRecordIdentifier', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.RECORD,
|
||||
targetRecordIdentifier: {
|
||||
id: 'rec-1',
|
||||
labelIdentifier: 'Acme Corp',
|
||||
},
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'Acme Corp',
|
||||
);
|
||||
});
|
||||
|
||||
it('should return empty string when targetRecordIdentifier is missing', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.RECORD,
|
||||
targetRecordIdentifier: null,
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when type is FOLDER', () => {
|
||||
it('should return the item name when present', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.FOLDER,
|
||||
name: 'Sales',
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'Sales',
|
||||
);
|
||||
});
|
||||
|
||||
it('should return "Folder" when name is null', () => {
|
||||
const item = {
|
||||
...baseItem,
|
||||
type: NavigationMenuItemType.FOLDER,
|
||||
name: null,
|
||||
};
|
||||
|
||||
expect(getNavigationMenuItemLabel(item, objectMetadataItems, views)).toBe(
|
||||
'Folder',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
+19
-60
@@ -1,9 +1,10 @@
|
||||
import { getLinkNavigationMenuItemComputedLink } from '@/navigation-menu-item/display/link/utils/getLinkNavigationMenuItemComputedLink';
|
||||
import { getObjectNavigationMenuItemComputedLink } from '@/navigation-menu-item/display/object/utils/getObjectNavigationMenuItemComputedLink';
|
||||
import { getRecordNavigationMenuItemComputedLink } from '@/navigation-menu-item/display/record/utils/getRecordNavigationMenuItemComputedLink';
|
||||
import { getViewNavigationMenuItemComputedLink } from '@/navigation-menu-item/display/view/utils/getViewNavigationMenuItemComputedLink';
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { recordIdentifierToObjectRecordIdentifier } from '@/navigation-menu-item/common/utils/recordIdentifierToObjectRecordIdentifier';
|
||||
import { type View } from '@/views/types/View';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { AppPath, NavigationMenuItemType } from 'twenty-shared/types';
|
||||
import { getAppPath, isDefined } from 'twenty-shared/utils';
|
||||
import { NavigationMenuItemType } from 'twenty-shared/types';
|
||||
import { type NavigationMenuItem } from '~/generated-metadata/graphql';
|
||||
|
||||
export const getNavigationMenuItemComputedLink = (
|
||||
@@ -12,64 +13,22 @@ export const getNavigationMenuItemComputedLink = (
|
||||
views: Pick<View, 'id' | 'objectMetadataId' | 'key'>[],
|
||||
): string => {
|
||||
switch (item.type) {
|
||||
case NavigationMenuItemType.OBJECT: {
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(meta) => meta.id === item.targetObjectMetadataId,
|
||||
case NavigationMenuItemType.OBJECT:
|
||||
return getObjectNavigationMenuItemComputedLink(
|
||||
item,
|
||||
objectMetadataItems,
|
||||
views,
|
||||
);
|
||||
if (!isDefined(objectMetadataItem)) {
|
||||
return '';
|
||||
}
|
||||
const indexView = views.find(
|
||||
(view) =>
|
||||
view.objectMetadataId === objectMetadataItem.id &&
|
||||
view.key === ViewKey.INDEX,
|
||||
case NavigationMenuItemType.VIEW:
|
||||
return getViewNavigationMenuItemComputedLink(
|
||||
item,
|
||||
objectMetadataItems,
|
||||
views,
|
||||
);
|
||||
return getAppPath(
|
||||
AppPath.RecordIndexPage,
|
||||
{ objectNamePlural: objectMetadataItem.namePlural },
|
||||
indexView ? { viewId: indexView.id } : {},
|
||||
);
|
||||
}
|
||||
case NavigationMenuItemType.VIEW: {
|
||||
const view = views.find((view) => view.id === item.viewId);
|
||||
if (!isDefined(view)) {
|
||||
return '';
|
||||
}
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(meta) => meta.id === view.objectMetadataId,
|
||||
);
|
||||
if (!isDefined(objectMetadataItem)) {
|
||||
return '';
|
||||
}
|
||||
return getAppPath(
|
||||
AppPath.RecordIndexPage,
|
||||
{ objectNamePlural: objectMetadataItem.namePlural },
|
||||
{ viewId: item.viewId! },
|
||||
);
|
||||
}
|
||||
case NavigationMenuItemType.LINK: {
|
||||
const linkUrl = (item.link ?? '').trim();
|
||||
if (linkUrl.startsWith('http://') || linkUrl.startsWith('https://')) {
|
||||
return linkUrl;
|
||||
}
|
||||
return linkUrl ? `https://${linkUrl}` : '';
|
||||
}
|
||||
case NavigationMenuItemType.RECORD: {
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(meta) => meta.id === item.targetObjectMetadataId,
|
||||
);
|
||||
if (
|
||||
!isDefined(objectMetadataItem) ||
|
||||
!isDefined(item.targetRecordIdentifier)
|
||||
) {
|
||||
return '';
|
||||
}
|
||||
const objectRecordIdentifier = recordIdentifierToObjectRecordIdentifier({
|
||||
recordIdentifier: item.targetRecordIdentifier,
|
||||
objectMetadataItem,
|
||||
});
|
||||
return objectRecordIdentifier.linkToShowPage ?? '';
|
||||
}
|
||||
case NavigationMenuItemType.LINK:
|
||||
return getLinkNavigationMenuItemComputedLink(item);
|
||||
case NavigationMenuItemType.RECORD:
|
||||
return getRecordNavigationMenuItemComputedLink(item, objectMetadataItems);
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
+15
-31
@@ -1,8 +1,11 @@
|
||||
import { getFolderNavigationMenuItemLabel } from '@/navigation-menu-item/display/folder/utils/getFolderNavigationMenuItemLabel';
|
||||
import { getLinkNavigationMenuItemLabel } from '@/navigation-menu-item/display/link/utils/getLinkNavigationMenuItemLabel';
|
||||
import { getObjectNavigationMenuItemLabel } from '@/navigation-menu-item/display/object/utils/getObjectNavigationMenuItemLabel';
|
||||
import { getRecordNavigationMenuItemLabel } from '@/navigation-menu-item/display/record/utils/getRecordNavigationMenuItemLabel';
|
||||
import { getViewNavigationMenuItemLabel } from '@/navigation-menu-item/display/view/utils/getViewNavigationMenuItemLabel';
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { type View } from '@/views/types/View';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { NavigationMenuItemType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type NavigationMenuItem } from '~/generated-metadata/graphql';
|
||||
|
||||
export const getNavigationMenuItemLabel = (
|
||||
@@ -14,35 +17,16 @@ export const getNavigationMenuItemLabel = (
|
||||
views: Pick<View, 'id' | 'name' | 'objectMetadataId' | 'key'>[],
|
||||
): string => {
|
||||
switch (item.type) {
|
||||
case NavigationMenuItemType.OBJECT: {
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(meta) => meta.id === item.targetObjectMetadataId,
|
||||
);
|
||||
return objectMetadataItem?.labelPlural ?? '';
|
||||
}
|
||||
case NavigationMenuItemType.VIEW: {
|
||||
const view = views.find((view) => view.id === item.viewId);
|
||||
if (!isDefined(view)) {
|
||||
return '';
|
||||
}
|
||||
if (view.key === ViewKey.INDEX) {
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(meta) => meta.id === view.objectMetadataId,
|
||||
);
|
||||
return objectMetadataItem?.labelPlural ?? view.name;
|
||||
}
|
||||
return view.name;
|
||||
}
|
||||
case NavigationMenuItemType.LINK: {
|
||||
const linkUrl = (item.link ?? '').trim();
|
||||
return (item.name ?? linkUrl) || 'Link';
|
||||
}
|
||||
case NavigationMenuItemType.RECORD: {
|
||||
return item.targetRecordIdentifier?.labelIdentifier ?? '';
|
||||
}
|
||||
case NavigationMenuItemType.FOLDER: {
|
||||
return item.name ?? 'Folder';
|
||||
}
|
||||
case NavigationMenuItemType.OBJECT:
|
||||
return getObjectNavigationMenuItemLabel(item, objectMetadataItems);
|
||||
case NavigationMenuItemType.VIEW:
|
||||
return getViewNavigationMenuItemLabel(item, views);
|
||||
case NavigationMenuItemType.LINK:
|
||||
return getLinkNavigationMenuItemLabel(item);
|
||||
case NavigationMenuItemType.RECORD:
|
||||
return getRecordNavigationMenuItemLabel(item);
|
||||
case NavigationMenuItemType.FOLDER:
|
||||
return getFolderNavigationMenuItemLabel(item);
|
||||
default:
|
||||
return item.name ?? '';
|
||||
}
|
||||
|
||||
-9
@@ -1,23 +1,14 @@
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { type View } from '@/views/types/View';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type NavigationMenuItem } from '~/generated-metadata/graphql';
|
||||
|
||||
export const getViewNavigationMenuItemLabel = (
|
||||
item: Pick<NavigationMenuItem, 'viewId'>,
|
||||
views: Pick<View, 'id' | 'name' | 'objectMetadataId' | 'key'>[],
|
||||
objectMetadataItems: Pick<EnrichedObjectMetadataItem, 'id' | 'labelPlural'>[],
|
||||
): string => {
|
||||
const view = views.find((view) => view.id === item.viewId);
|
||||
if (!isDefined(view)) {
|
||||
return '';
|
||||
}
|
||||
if (view.key === ViewKey.INDEX) {
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(meta) => meta.id === view.objectMetadataId,
|
||||
);
|
||||
return objectMetadataItem?.labelPlural ?? view.name;
|
||||
}
|
||||
return view.name;
|
||||
};
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
"start:prod": "node dist/main",
|
||||
"command:prod": "node dist/command/command",
|
||||
"worker:prod": "node dist/queue-worker/queue-worker",
|
||||
"database:init:prod": "npx ts-node ./scripts/setup-db.ts && yarn database:migrate:prod",
|
||||
"database:migrate:prod": "npx -y typeorm migration:run -d dist/database/typeorm/core/core.datasource",
|
||||
"database:init:prod": "node dist/database/scripts/setup-db.js && yarn database:migrate:prod --force",
|
||||
"database:migrate:prod": "node dist/command/command run-typeorm-migration",
|
||||
"clickhouse:migrate:prod": "node dist/database/clickHouse/migrations/run-migrations.js",
|
||||
"typeorm": "../../node_modules/typeorm/.bin/typeorm"
|
||||
},
|
||||
|
||||
@@ -246,8 +246,8 @@
|
||||
"no-seed": {
|
||||
"cwd": "packages/twenty-server",
|
||||
"commands": [
|
||||
"nx ts-node-no-deps-transpile-only -- ./scripts/truncate-db.ts",
|
||||
"nx ts-node-no-deps-transpile-only -- ./scripts/setup-db.ts",
|
||||
"node dist/database/scripts/truncate-db.js",
|
||||
"node dist/database/scripts/setup-db.js",
|
||||
"nx database:migrate",
|
||||
"nx command-no-deps -- cache:flush"
|
||||
],
|
||||
@@ -256,8 +256,8 @@
|
||||
"seed": {
|
||||
"cwd": "packages/twenty-server",
|
||||
"commands": [
|
||||
"nx ts-node-no-deps-transpile-only -- ./scripts/truncate-db.ts",
|
||||
"nx ts-node-no-deps-transpile-only -- ./scripts/setup-db.ts",
|
||||
"node dist/database/scripts/truncate-db.js",
|
||||
"node dist/database/scripts/setup-db.js",
|
||||
"nx database:migrate",
|
||||
"nx command-no-deps -- cache:flush",
|
||||
"nx command-no-deps -- workspace:seed:dev"
|
||||
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`UpgradeCommandRunner Workspace upgrade should fail when APP_VERSION is not defined 1`] = `[Error: Cannot run upgrade command when APP_VERSION is not defined, please double check your env variables]`;
|
||||
|
||||
exports[`UpgradeCommandRunner Workspace upgrade should fail when all commands contains invalid semver keys 1`] = `[Error: No previous version found for version 2.0.0. Please review the "allCommands" record. Available versions are: invalid, 2.0.0]`;
|
||||
|
||||
exports[`UpgradeCommandRunner Workspace upgrade should fail when current version commands are not found 1`] = `[Error: No command found for version 42.0.0. Please check the commands record.]`;
|
||||
|
||||
exports[`UpgradeCommandRunner Workspace upgrade should fail when previous version is not found 1`] = `[Error: No previous version found for version 1.0.0. Please review the "allCommands" record. Available versions are: 1.0.0, 2.0.0]`;
|
||||
|
||||
exports[`UpgradeCommandRunner Workspace upgrade should fail when workspace version is not defined 1`] = `
|
||||
[Error: Unable to run the upgrade command. Aborting the upgrade process.
|
||||
Please ensure that all workspaces are on at least the previous minor version (1.0.0).
|
||||
If any workspaces are not on the previous minor version, roll back to that version and run the upgrade command again.]
|
||||
`;
|
||||
|
||||
exports[`UpgradeCommandRunner Workspace upgrade should fail when workspace version is not equal to fromVersion 1`] = `
|
||||
[Error: Unable to run the upgrade command. Aborting the upgrade process.
|
||||
Please ensure that all workspaces are on at least the previous minor version (1.0.0).
|
||||
If any workspaces are not on the previous minor version, roll back to that version and run the upgrade command again.]
|
||||
`;
|
||||
+62
-43
@@ -7,35 +7,41 @@ import {
|
||||
} from 'twenty-shared/testing';
|
||||
import { type Repository } from 'typeorm';
|
||||
|
||||
import { UpgradeCommandRunner } from 'src/database/commands/command-runners/upgrade.command-runner';
|
||||
import {
|
||||
UpgradeCommandRunner,
|
||||
type AllCommands,
|
||||
} from 'src/database/commands/command-runners/upgrade.command-runner';
|
||||
import { CoreMigrationRunnerService } from 'src/database/commands/core-migration-runner/services/core-migration-runner.service';
|
||||
import { UPGRADE_COMMAND_SUPPORTED_VERSIONS } from 'src/engine/constants/upgrade-command-supported-versions.constant';
|
||||
import { CoreEngineVersionService } from 'src/engine/core-engine-version/services/core-engine-version.service';
|
||||
import { type ConfigVariables } from 'src/engine/core-modules/twenty-config/config-variables';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceVersionService } from 'src/engine/workspace-manager/workspace-version/services/workspace-version.service';
|
||||
|
||||
const CURRENT_VERSION =
|
||||
UPGRADE_COMMAND_SUPPORTED_VERSIONS[
|
||||
UPGRADE_COMMAND_SUPPORTED_VERSIONS.length - 1
|
||||
];
|
||||
const PREVIOUS_VERSION =
|
||||
UPGRADE_COMMAND_SUPPORTED_VERSIONS[
|
||||
UPGRADE_COMMAND_SUPPORTED_VERSIONS.length - 2
|
||||
];
|
||||
|
||||
class BasicUpgradeCommandRunner extends UpgradeCommandRunner {
|
||||
allCommands = {
|
||||
'1.0.0': [],
|
||||
'2.0.0': [],
|
||||
};
|
||||
allCommands = Object.fromEntries(
|
||||
UPGRADE_COMMAND_SUPPORTED_VERSIONS.map((version) => [version, []]),
|
||||
) as unknown as AllCommands;
|
||||
}
|
||||
|
||||
class InvalidUpgradeCommandRunner extends UpgradeCommandRunner {
|
||||
allCommands = {
|
||||
invalid: [],
|
||||
'2.0.0': [],
|
||||
};
|
||||
}
|
||||
|
||||
type CommandRunnerValues =
|
||||
| typeof BasicUpgradeCommandRunner
|
||||
| typeof InvalidUpgradeCommandRunner;
|
||||
type CommandRunnerValues = typeof BasicUpgradeCommandRunner;
|
||||
|
||||
const generateMockWorkspace = (overrides?: Partial<WorkspaceEntity>) =>
|
||||
({
|
||||
id: 'workspace-id',
|
||||
version: '1.0.0',
|
||||
version: PREVIOUS_VERSION,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
allowImpersonation: false,
|
||||
@@ -73,12 +79,18 @@ const buildUpgradeCommandModule = async ({
|
||||
twentyConfigService: TwentyConfigService,
|
||||
globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
dataSourceService: DataSourceService,
|
||||
coreEngineVersionService: CoreEngineVersionService,
|
||||
workspaceVersionService: WorkspaceVersionService,
|
||||
coreMigrationRunnerService: CoreMigrationRunnerService,
|
||||
) => {
|
||||
return new commandRunner(
|
||||
workspaceRepository,
|
||||
twentyConfigService,
|
||||
globalWorkspaceOrmManager,
|
||||
dataSourceService,
|
||||
coreEngineVersionService,
|
||||
workspaceVersionService,
|
||||
coreMigrationRunnerService,
|
||||
);
|
||||
},
|
||||
inject: [
|
||||
@@ -86,6 +98,9 @@ const buildUpgradeCommandModule = async ({
|
||||
TwentyConfigService,
|
||||
GlobalWorkspaceOrmManager,
|
||||
DataSourceService,
|
||||
CoreEngineVersionService,
|
||||
WorkspaceVersionService,
|
||||
CoreMigrationRunnerService,
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -98,6 +113,7 @@ const buildUpgradeCommandModule = async ({
|
||||
),
|
||||
update: jest.fn(),
|
||||
find: jest.fn().mockResolvedValue(workspaces),
|
||||
exists: jest.fn().mockResolvedValue(workspaces.length > 0),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -130,6 +146,12 @@ const buildUpgradeCommandModule = async ({
|
||||
provide: DataSourceService,
|
||||
useValue: mockDataSourceService,
|
||||
},
|
||||
CoreEngineVersionService,
|
||||
WorkspaceVersionService,
|
||||
{
|
||||
provide: CoreMigrationRunnerService,
|
||||
useValue: { run: jest.fn().mockResolvedValue(undefined) },
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
@@ -139,7 +161,7 @@ const buildUpgradeCommandModule = async ({
|
||||
describe('UpgradeCommandRunner', () => {
|
||||
let upgradeCommandRunner: BasicUpgradeCommandRunner;
|
||||
let workspaceRepository: Repository<WorkspaceEntity>;
|
||||
let runCoreMigrationsSpy: jest.SpyInstance;
|
||||
let coreMigrationRunnerService: CoreMigrationRunnerService;
|
||||
|
||||
type BuildModuleAndSetupSpiesArgs = {
|
||||
numberOfWorkspace?: number;
|
||||
@@ -153,7 +175,7 @@ describe('UpgradeCommandRunner', () => {
|
||||
workspaceOverride,
|
||||
workspaces,
|
||||
commandRunner = BasicUpgradeCommandRunner,
|
||||
appVersion = '2.0.0',
|
||||
appVersion = CURRENT_VERSION,
|
||||
}: BuildModuleAndSetupSpiesArgs) => {
|
||||
const generatedWorkspaces = Array.from(
|
||||
{ length: numberOfWorkspace },
|
||||
@@ -176,9 +198,8 @@ describe('UpgradeCommandRunner', () => {
|
||||
jest.spyOn(upgradeCommandRunner['logger'], 'warn').mockImplementation();
|
||||
|
||||
jest.spyOn(upgradeCommandRunner, 'runOnWorkspace');
|
||||
runCoreMigrationsSpy = jest
|
||||
.spyOn(upgradeCommandRunner, 'runCoreMigrations')
|
||||
.mockImplementation(() => Promise.resolve());
|
||||
|
||||
coreMigrationRunnerService = module.get(CoreMigrationRunnerService);
|
||||
|
||||
workspaceRepository = module.get<Repository<WorkspaceEntity>>(
|
||||
getRepositoryToken(WorkspaceEntity),
|
||||
@@ -190,12 +211,10 @@ describe('UpgradeCommandRunner', () => {
|
||||
id: 'higher_version_workspace',
|
||||
version: '42.42.42',
|
||||
});
|
||||
const appVersion = '2.0.0';
|
||||
|
||||
await buildModuleAndSetupSpies({
|
||||
numberOfWorkspace: 0,
|
||||
workspaces: [higherVersionWorkspace],
|
||||
appVersion,
|
||||
});
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
const passedParams = [];
|
||||
@@ -221,11 +240,9 @@ describe('UpgradeCommandRunner', () => {
|
||||
|
||||
it('should run upgrade over several workspaces', async () => {
|
||||
const numberOfWorkspace = 42;
|
||||
const appVersion = '2.0.0';
|
||||
|
||||
await buildModuleAndSetupSpies({
|
||||
numberOfWorkspace,
|
||||
appVersion,
|
||||
});
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
const passedParams = [];
|
||||
@@ -240,7 +257,7 @@ describe('UpgradeCommandRunner', () => {
|
||||
expect(workspaceRepository.update).toHaveBeenNthCalledWith(
|
||||
numberOfWorkspace,
|
||||
{ id: expect.any(String) },
|
||||
{ version: appVersion },
|
||||
{ version: CURRENT_VERSION },
|
||||
);
|
||||
expect(upgradeCommandRunner.migrationReport.success.length).toBe(42);
|
||||
expect(upgradeCommandRunner.migrationReport.fail.length).toBe(0);
|
||||
@@ -254,9 +271,9 @@ describe('UpgradeCommandRunner', () => {
|
||||
title: 'even if workspace version and app version differ in patch',
|
||||
context: {
|
||||
input: {
|
||||
appVersion: 'v2.0.0',
|
||||
appVersion: `v${CURRENT_VERSION}`,
|
||||
workspaceOverride: {
|
||||
version: 'v1.0.12',
|
||||
version: `v${PREVIOUS_VERSION.replace('.0', '.12')}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -266,9 +283,9 @@ describe('UpgradeCommandRunner', () => {
|
||||
'even if workspace version and app version differ in patch and semantic',
|
||||
context: {
|
||||
input: {
|
||||
appVersion: 'v2.0.0',
|
||||
appVersion: `v${CURRENT_VERSION}`,
|
||||
workspaceOverride: {
|
||||
version: '1.0.12',
|
||||
version: PREVIOUS_VERSION.replace('.0', '.12'),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -277,9 +294,9 @@ describe('UpgradeCommandRunner', () => {
|
||||
title: 'even if app version contains a patch value',
|
||||
context: {
|
||||
input: {
|
||||
appVersion: '2.0.24',
|
||||
appVersion: CURRENT_VERSION.replace('.0', '.24'),
|
||||
workspaceOverride: {
|
||||
version: '1.0.12',
|
||||
version: PREVIOUS_VERSION.replace('.0', '.12'),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -303,7 +320,7 @@ describe('UpgradeCommandRunner', () => {
|
||||
|
||||
expect(failReport.length).toBe(0);
|
||||
expect(successReport.length).toBe(1);
|
||||
expect(runCoreMigrationsSpy).toHaveBeenCalledTimes(1);
|
||||
expect(coreMigrationRunnerService.run).toHaveBeenCalledTimes(1);
|
||||
const { workspaceId } = successReport[0];
|
||||
|
||||
expect(workspaceId).toBe('workspace_0');
|
||||
@@ -316,19 +333,20 @@ describe('UpgradeCommandRunner', () => {
|
||||
input: Omit<BuildModuleAndSetupSpiesArgs, 'numberOfWorkspace'>;
|
||||
output?: {
|
||||
failReportWorkspaceId: string;
|
||||
expectedErrorMessage: string;
|
||||
};
|
||||
}>[] = [
|
||||
{
|
||||
title: 'when workspace version is not equal to fromVersion',
|
||||
context: {
|
||||
input: {
|
||||
appVersion: '2.0.0',
|
||||
workspaceOverride: {
|
||||
version: '0.1.0',
|
||||
},
|
||||
},
|
||||
output: {
|
||||
failReportWorkspaceId: 'workspace_0',
|
||||
expectedErrorMessage: `Unable to run the upgrade command. Aborting the upgrade process.\nPlease ensure that all workspaces are on at least the previous minor version (${PREVIOUS_VERSION}).\nIf any workspaces are not on the previous minor version, roll back to that version and run the upgrade command again.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -342,6 +360,7 @@ describe('UpgradeCommandRunner', () => {
|
||||
},
|
||||
output: {
|
||||
failReportWorkspaceId: 'workspace_0',
|
||||
expectedErrorMessage: `Unable to run the upgrade command. Aborting the upgrade process.\nPlease ensure that all workspaces are on at least the previous minor version (${PREVIOUS_VERSION}).\nIf any workspaces are not on the previous minor version, roll back to that version and run the upgrade command again.`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -353,6 +372,8 @@ describe('UpgradeCommandRunner', () => {
|
||||
},
|
||||
output: {
|
||||
failReportWorkspaceId: 'global',
|
||||
expectedErrorMessage:
|
||||
'APP_VERSION is not defined, please double check your env variables',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -364,6 +385,8 @@ describe('UpgradeCommandRunner', () => {
|
||||
},
|
||||
output: {
|
||||
failReportWorkspaceId: 'global',
|
||||
expectedErrorMessage:
|
||||
'No command found for version 42.0.0. Please check the commands record.',
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -371,15 +394,11 @@ describe('UpgradeCommandRunner', () => {
|
||||
title: 'when previous version is not found',
|
||||
context: {
|
||||
input: {
|
||||
appVersion: '1.0.0',
|
||||
appVersion: UPGRADE_COMMAND_SUPPORTED_VERSIONS[0],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'when all commands contains invalid semver keys',
|
||||
context: {
|
||||
input: {
|
||||
commandRunner: InvalidUpgradeCommandRunner,
|
||||
output: {
|
||||
failReportWorkspaceId: 'global',
|
||||
expectedErrorMessage: `No previous version found for version ${UPGRADE_COMMAND_SUPPORTED_VERSIONS[0]}. Available versions: ${UPGRADE_COMMAND_SUPPORTED_VERSIONS.join(', ')}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -403,7 +422,7 @@ describe('UpgradeCommandRunner', () => {
|
||||
const { workspaceId, error } = failReport[0];
|
||||
|
||||
expect(workspaceId).toBe(output?.failReportWorkspaceId ?? 'global');
|
||||
expect(error).toMatchSnapshot();
|
||||
expect(error).toEqual(new Error(output?.expectedErrorMessage ?? ''));
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
+21
-129
@@ -1,13 +1,9 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { exec } from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { SemVer } from 'semver';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandOptions,
|
||||
@@ -17,22 +13,24 @@ import {
|
||||
RunOnWorkspaceArgs,
|
||||
WorkspacesMigrationCommandRunner,
|
||||
} from 'src/database/commands/command-runners/workspaces-migration.command-runner';
|
||||
import { CoreMigrationRunnerService } from 'src/database/commands/core-migration-runner/services/core-migration-runner.service';
|
||||
import { type UpgradeCommandVersion } from 'src/engine/constants/upgrade-command-supported-versions.constant';
|
||||
import { CoreEngineVersionService } from 'src/engine/core-engine-version/services/core-engine-version.service';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { type DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceVersionService } from 'src/engine/workspace-manager/workspace-version/services/workspace-version.service';
|
||||
import {
|
||||
type CompareVersionMajorAndMinorReturnType,
|
||||
compareVersionMajorAndMinor,
|
||||
} from 'src/utils/version/compare-version-minor-and-major';
|
||||
import { getPreviousVersion } from 'src/utils/version/get-previous-version';
|
||||
|
||||
export type VersionCommands = (
|
||||
| WorkspacesMigrationCommandRunner
|
||||
| ActiveOrSuspendedWorkspacesMigrationCommandRunner
|
||||
)[];
|
||||
export type AllCommands = Record<string, VersionCommands>;
|
||||
const execPromise = promisify(exec);
|
||||
export type AllCommands = Record<UpgradeCommandVersion, VersionCommands>;
|
||||
|
||||
export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
private fromWorkspaceVersion: SemVer;
|
||||
@@ -47,95 +45,13 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi
|
||||
protected readonly twentyConfigService: TwentyConfigService,
|
||||
protected readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
protected readonly coreEngineVersionService: CoreEngineVersionService,
|
||||
protected readonly workspaceVersionService: WorkspaceVersionService,
|
||||
protected readonly coreMigrationRunnerService: CoreMigrationRunnerService,
|
||||
) {
|
||||
super(workspaceRepository, globalWorkspaceOrmManager, dataSourceService);
|
||||
}
|
||||
|
||||
private async loadActiveOrSuspendedWorkspace() {
|
||||
return await this.workspaceRepository.find({
|
||||
select: ['id', 'version', 'displayName'],
|
||||
where: {
|
||||
activationStatus: In([
|
||||
WorkspaceActivationStatus.ACTIVE,
|
||||
WorkspaceActivationStatus.SUSPENDED,
|
||||
]),
|
||||
},
|
||||
order: {
|
||||
id: 'ASC',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private async shouldSkipUpgradeIfFreshInstallation(): Promise<boolean> {
|
||||
const activeWorkspaceOrSuspendedWorkspaceCount =
|
||||
await this.loadActiveOrSuspendedWorkspace();
|
||||
|
||||
return activeWorkspaceOrSuspendedWorkspaceCount.length === 0;
|
||||
}
|
||||
|
||||
async runCoreMigrations(): Promise<void> {
|
||||
this.logger.log('Running global database migrations');
|
||||
|
||||
try {
|
||||
this.logger.log('Running core datasource migrations...');
|
||||
const coreResult = await execPromise(
|
||||
'npx -y typeorm migration:run -d dist/database/typeorm/core/core.datasource',
|
||||
);
|
||||
|
||||
this.logger.log(coreResult.stdout);
|
||||
|
||||
this.logger.log('Database migrations completed successfully');
|
||||
} catch (error) {
|
||||
this.logger.error('Error running database migrations:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async workspacesThatAreBelowFromWorkspaceVersion(
|
||||
fromWorkspaceVersion: SemVer,
|
||||
): Promise<Pick<WorkspaceEntity, 'id' | 'displayName' | 'version'>[]> {
|
||||
try {
|
||||
const allActiveOrSuspendedWorkspaces =
|
||||
await this.loadActiveOrSuspendedWorkspace();
|
||||
|
||||
if (allActiveOrSuspendedWorkspaces.length === 0) {
|
||||
this.logger.log(
|
||||
'No workspaces found. Running migrations for fresh installation.',
|
||||
);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
const workspacesThatAreBelowFromWorkspaceVersion =
|
||||
allActiveOrSuspendedWorkspaces.filter((workspace) => {
|
||||
if (!isDefined(workspace.version)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
const versionCompareResult = compareVersionMajorAndMinor(
|
||||
workspace.version,
|
||||
fromWorkspaceVersion.version,
|
||||
);
|
||||
|
||||
return versionCompareResult === 'lower';
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Error checking workspace ${workspace.id} version: ${error.message}`,
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return workspacesThatAreBelowFromWorkspaceVersion;
|
||||
} catch (error) {
|
||||
this.logger.error('Error checking workspaces below version:', error);
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private setUpgradeContextVersionsAndCommandsForCurrentAppVersion() {
|
||||
const upgradeContextIsAlreadyDefined = [
|
||||
this.currentAppVersion,
|
||||
@@ -147,8 +63,9 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi
|
||||
return;
|
||||
}
|
||||
|
||||
const currentAppVersion = this.retrieveCurrentAppVersion();
|
||||
const currentVersionMajorMinor = `${currentAppVersion.major}.${currentAppVersion.minor}.0`;
|
||||
const currentAppVersion = this.coreEngineVersionService.getCurrentVersion();
|
||||
const currentVersionMajorMinor =
|
||||
`${currentAppVersion.major}.${currentAppVersion.minor}.0` as UpgradeCommandVersion;
|
||||
const currentCommands = this.allCommands[currentVersionMajorMinor];
|
||||
|
||||
if (!isDefined(currentCommands)) {
|
||||
@@ -157,17 +74,8 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi
|
||||
);
|
||||
}
|
||||
|
||||
const allCommandsVersions = Object.keys(this.allCommands);
|
||||
const previousVersion = getPreviousVersion({
|
||||
currentVersion: currentVersionMajorMinor,
|
||||
versions: allCommandsVersions,
|
||||
});
|
||||
const previousVersion = this.coreEngineVersionService.getPreviousVersion();
|
||||
|
||||
if (!isDefined(previousVersion)) {
|
||||
throw new Error(
|
||||
`No previous version found for version ${currentAppVersion}. Please review the "allCommands" record. Available versions are: ${allCommandsVersions.join(', ')}`,
|
||||
);
|
||||
}
|
||||
this.commands = currentCommands;
|
||||
this.fromWorkspaceVersion = previousVersion;
|
||||
this.currentAppVersion = currentAppVersion;
|
||||
@@ -189,10 +97,12 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi
|
||||
try {
|
||||
this.setUpgradeContextVersionsAndCommandsForCurrentAppVersion();
|
||||
|
||||
const shouldSkipUpgradeIfFreshInstallation =
|
||||
await this.shouldSkipUpgradeIfFreshInstallation();
|
||||
// On fresh installs there are no workspaces yet, so skip the
|
||||
// per-workspace upgrade loop (core migrations already ran above).
|
||||
const hasWorkspaces =
|
||||
await this.workspaceVersionService.hasActiveOrSuspendedWorkspaces();
|
||||
|
||||
if (shouldSkipUpgradeIfFreshInstallation) {
|
||||
if (!hasWorkspaces) {
|
||||
this.logger.log(
|
||||
chalk.blue('Fresh installation detected, skipping migration'),
|
||||
);
|
||||
@@ -201,8 +111,8 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi
|
||||
}
|
||||
|
||||
const workspacesThatAreBelowFromWorkspaceVersion =
|
||||
await this.workspacesThatAreBelowFromWorkspaceVersion(
|
||||
this.fromWorkspaceVersion,
|
||||
await this.workspaceVersionService.getWorkspacesBelowVersion(
|
||||
this.fromWorkspaceVersion.version,
|
||||
);
|
||||
|
||||
if (workspacesThatAreBelowFromWorkspaceVersion.length > 0) {
|
||||
@@ -234,7 +144,7 @@ If any workspaces are not on the previous minor version, roll back to that versi
|
||||
return;
|
||||
}
|
||||
|
||||
await this.runCoreMigrations();
|
||||
await this.coreMigrationRunnerService.run();
|
||||
await super.runMigrationCommand(passedParams, options);
|
||||
}
|
||||
|
||||
@@ -295,24 +205,6 @@ If any workspaces are not on the previous minor version, roll back to that versi
|
||||
}
|
||||
}
|
||||
|
||||
private retrieveCurrentAppVersion() {
|
||||
const appVersion = this.twentyConfigService.get('APP_VERSION');
|
||||
|
||||
if (!isDefined(appVersion)) {
|
||||
throw new Error(
|
||||
'Cannot run upgrade command when APP_VERSION is not defined, please double check your env variables',
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
return new SemVer(appVersion);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Should never occur, APP_VERSION is invalid ${appVersion}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async retrieveWorkspaceVersionAndCompareToWorkspaceFromVersion(
|
||||
workspaceId: string,
|
||||
): Promise<CompareVersionMajorAndMinorReturnType> {
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { CoreMigrationRunnerService } from 'src/database/commands/core-migration-runner/services/core-migration-runner.service';
|
||||
|
||||
@Module({
|
||||
providers: [CoreMigrationRunnerService],
|
||||
exports: [CoreMigrationRunnerService],
|
||||
})
|
||||
export class CoreMigrationRunnerModule {}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectDataSource } from '@nestjs/typeorm';
|
||||
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
@Injectable()
|
||||
export class CoreMigrationRunnerService {
|
||||
private readonly logger = new Logger(CoreMigrationRunnerService.name);
|
||||
|
||||
constructor(
|
||||
@InjectDataSource()
|
||||
private readonly dataSource: DataSource,
|
||||
) {}
|
||||
|
||||
async run(): Promise<void> {
|
||||
this.logger.log('Running core datasource migrations...');
|
||||
|
||||
try {
|
||||
const migrations = await this.dataSource.runMigrations({
|
||||
transaction: 'each',
|
||||
});
|
||||
|
||||
if (migrations.length === 0) {
|
||||
this.logger.log('No pending migrations');
|
||||
} else {
|
||||
this.logger.log(
|
||||
`Executed ${migrations.length} migration(s): ${migrations.map((migration) => migration.name).join(', ')}`,
|
||||
);
|
||||
}
|
||||
|
||||
this.logger.log('Database migrations completed successfully');
|
||||
} catch (error) {
|
||||
this.logger.error('Error running database migrations:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,12 @@ import { CronRegisterAllCommand } from 'src/database/commands/cron-register-all.
|
||||
import { DataSeedWorkspaceCommand } from 'src/database/commands/data-seed-dev-workspace.command';
|
||||
import { ListOrphanedWorkspaceEntitiesCommand } from 'src/database/commands/list-and-delete-orphaned-workspace-entities.command';
|
||||
import { ConfirmationQuestion } from 'src/database/commands/questions/confirmation.question';
|
||||
import { WorkspaceExportModule } from 'src/database/commands/workspace-export/workspace-export.module';
|
||||
import { RunTypeormMigrationCommand } from 'src/database/commands/run-typeorm-migration.command';
|
||||
import { UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/upgrade-version-command.module';
|
||||
import { WorkspaceExportModule } from 'src/database/commands/workspace-export/workspace-export.module';
|
||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||
import { CoreEngineVersionModule } from 'src/engine/core-engine-version/core-engine-version.module';
|
||||
import { CoreMigrationRunnerModule } from 'src/database/commands/core-migration-runner/core-migration-runner.module';
|
||||
import { ApiKeyModule } from 'src/engine/core-modules/api-key/api-key.module';
|
||||
import { GenerateApiKeyCommand } from 'src/engine/core-modules/api-key/commands/generate-api-key.command';
|
||||
import { MarketplaceModule } from 'src/engine/core-modules/application/application-marketplace/marketplace.module';
|
||||
@@ -31,6 +34,7 @@ import { DevSeederModule } from 'src/engine/workspace-manager/dev-seeder/dev-see
|
||||
import { WorkspaceCleanerModule } from 'src/engine/workspace-manager/workspace-cleaner/workspace-cleaner.module';
|
||||
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
|
||||
import { WorkspaceVersionModule } from 'src/engine/workspace-manager/workspace-version/workspace-version.module';
|
||||
import { CalendarEventImportManagerModule } from 'src/modules/calendar/calendar-event-import-manager/calendar-event-import-manager.module';
|
||||
import { MessagingImportManagerModule } from 'src/modules/messaging/message-import-manager/messaging-import-manager.module';
|
||||
import { WorkflowRunQueueModule } from 'src/modules/workflow/workflow-runner/workflow-run-queue/workflow-run-queue.module';
|
||||
@@ -68,6 +72,9 @@ import { AutomatedTriggerModule } from 'src/modules/workflow/workflow-trigger/au
|
||||
MarketplaceModule,
|
||||
ApplicationUpgradeModule,
|
||||
StaleRegistrationCleanupModule,
|
||||
CoreEngineVersionModule,
|
||||
CoreMigrationRunnerModule,
|
||||
WorkspaceVersionModule,
|
||||
],
|
||||
providers: [
|
||||
DataSeedWorkspaceCommand,
|
||||
@@ -76,6 +83,7 @@ import { AutomatedTriggerModule } from 'src/modules/workflow/workflow-trigger/au
|
||||
ListOrphanedWorkspaceEntitiesCommand,
|
||||
EnterpriseKeyValidationCronCommand,
|
||||
GenerateApiKeyCommand,
|
||||
RunTypeormMigrationCommand,
|
||||
],
|
||||
})
|
||||
export class DatabaseCommandModule {}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { Command, CommandRunner, Option } from 'nest-commander';
|
||||
|
||||
import { CoreMigrationRunnerService } from 'src/database/commands/core-migration-runner/services/core-migration-runner.service';
|
||||
import { CoreEngineVersionService } from 'src/engine/core-engine-version/services/core-engine-version.service';
|
||||
import { WorkspaceVersionService } from 'src/engine/workspace-manager/workspace-version/services/workspace-version.service';
|
||||
|
||||
type RunTypeormMigrationCommandOptions = {
|
||||
force?: boolean;
|
||||
};
|
||||
|
||||
@Command({
|
||||
name: 'run-typeorm-migration',
|
||||
description:
|
||||
'Run TypeORM core migrations with workspace version safety check',
|
||||
})
|
||||
export class RunTypeormMigrationCommand extends CommandRunner {
|
||||
private readonly logger = new Logger(RunTypeormMigrationCommand.name);
|
||||
|
||||
constructor(
|
||||
private readonly coreEngineVersionService: CoreEngineVersionService,
|
||||
private readonly workspaceVersionService: WorkspaceVersionService,
|
||||
private readonly coreMigrationRunnerService: CoreMigrationRunnerService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
@Option({
|
||||
flags: '-f, --force',
|
||||
description: 'Skip workspace version safety check',
|
||||
required: false,
|
||||
})
|
||||
parseForce(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
async run(
|
||||
_passedParams: string[],
|
||||
options: RunTypeormMigrationCommandOptions,
|
||||
): Promise<void> {
|
||||
if (options.force) {
|
||||
this.logger.warn(
|
||||
chalk.yellow('Skipping workspace version check (--force flag used)'),
|
||||
);
|
||||
} else {
|
||||
const previousVersion =
|
||||
this.coreEngineVersionService.getPreviousVersion();
|
||||
|
||||
const workspacesBelow =
|
||||
await this.workspaceVersionService.getWorkspacesBelowVersion(
|
||||
previousVersion.version,
|
||||
);
|
||||
|
||||
if (workspacesBelow.length > 0) {
|
||||
for (const workspace of workspacesBelow) {
|
||||
this.logger.error(
|
||||
chalk.red(
|
||||
`Workspace ${workspace.id} (${workspace.displayName}) is at version ${workspace.version ?? 'undefined'}, which is below the minimum required version.`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
'Unable to run TypeORM migrations. Some workspace(s) are below the minimum required version.\n' +
|
||||
'Please ensure all workspaces are on at least the previous minor version before running migrations.\n' +
|
||||
'Use --force to bypass this check (not recommended).',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
await this.coreMigrationRunnerService.run();
|
||||
}
|
||||
}
|
||||
+14
-4
@@ -255,8 +255,11 @@ export class BackfillCommandMenuItemsCommand extends ActiveOrSuspendedWorkspaces
|
||||
|
||||
const trigger = workflowVersion.trigger as WorkflowManualTrigger;
|
||||
|
||||
const { availabilityType, availabilityObjectMetadataId } =
|
||||
await this.resolveManualTriggerAvailability(trigger, workspaceId);
|
||||
const {
|
||||
availabilityType,
|
||||
availabilityObjectMetadataId,
|
||||
availabilityObjectMetadataUniversalIdentifier,
|
||||
} = await this.resolveManualTriggerAvailability(trigger, workspaceId);
|
||||
|
||||
const id = uuidv4();
|
||||
const now = new Date().toISOString();
|
||||
@@ -276,7 +279,7 @@ export class BackfillCommandMenuItemsCommand extends ActiveOrSuspendedWorkspaces
|
||||
hotKeys: null,
|
||||
availabilityType,
|
||||
availabilityObjectMetadataId: availabilityObjectMetadataId ?? null,
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
availabilityObjectMetadataUniversalIdentifier,
|
||||
conditionalAvailabilityExpression: null,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
@@ -340,6 +343,7 @@ export class BackfillCommandMenuItemsCommand extends ActiveOrSuspendedWorkspaces
|
||||
): Promise<{
|
||||
availabilityType: CommandMenuItemAvailabilityType;
|
||||
availabilityObjectMetadataId: string | undefined;
|
||||
availabilityObjectMetadataUniversalIdentifier: string | null;
|
||||
}> {
|
||||
const availability = trigger.settings.availability;
|
||||
|
||||
@@ -347,10 +351,11 @@ export class BackfillCommandMenuItemsCommand extends ActiveOrSuspendedWorkspaces
|
||||
return {
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
availabilityObjectMetadataId: undefined,
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
};
|
||||
}
|
||||
|
||||
const { objectIdByNameSingular } =
|
||||
const { objectIdByNameSingular, flatObjectMetadataMaps } =
|
||||
await this.workflowCommonWorkspaceService.getFlatEntityMaps(workspaceId);
|
||||
|
||||
const objectId = objectIdByNameSingular[availability.objectNameSingular];
|
||||
@@ -363,12 +368,17 @@ export class BackfillCommandMenuItemsCommand extends ActiveOrSuspendedWorkspaces
|
||||
return {
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
availabilityObjectMetadataId: undefined,
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
};
|
||||
}
|
||||
|
||||
const objectUniversalIdentifier =
|
||||
flatObjectMetadataMaps.universalIdentifierById[objectId] ?? null;
|
||||
|
||||
return {
|
||||
availabilityType: CommandMenuItemAvailabilityType.RECORD_SELECTION,
|
||||
availabilityObjectMetadataId: objectId,
|
||||
availabilityObjectMetadataUniversalIdentifier: objectUniversalIdentifier,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -229,6 +229,7 @@ export class BackfillPageLayoutsAndFieldsWidgetViewFieldsCommand extends ActiveO
|
||||
);
|
||||
|
||||
const {
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
flatPageLayoutMaps: existingFlatPageLayoutMaps,
|
||||
flatPageLayoutTabMaps: existingFlatPageLayoutTabMaps,
|
||||
flatPageLayoutWidgetMaps: existingFlatPageLayoutWidgetMaps,
|
||||
@@ -236,6 +237,7 @@ export class BackfillPageLayoutsAndFieldsWidgetViewFieldsCommand extends ActiveO
|
||||
flatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
flatViewFieldGroupMaps: existingFlatViewFieldGroupMaps,
|
||||
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatFieldMetadataMaps',
|
||||
'flatPageLayoutMaps',
|
||||
'flatPageLayoutTabMaps',
|
||||
'flatPageLayoutWidgetMaps',
|
||||
@@ -320,6 +322,15 @@ export class BackfillPageLayoutsAndFieldsWidgetViewFieldsCommand extends ActiveO
|
||||
allStandardFieldsWidgetViewUniversalIds.has(
|
||||
viewField.viewUniversalIdentifier,
|
||||
),
|
||||
)
|
||||
// Skip viewFields whose referenced fieldMetadata doesn't exist in the workspace yet
|
||||
// (e.g. fields added to the standard definition but not yet synced to this workspace)
|
||||
.filter((viewField) =>
|
||||
isDefined(
|
||||
existingFlatFieldMetadataMaps.byUniversalIdentifier[
|
||||
viewField.fieldMetadataUniversalIdentifier
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
// Same delete-and-recreate approach for viewFieldGroups
|
||||
|
||||
+6
@@ -6,8 +6,11 @@ import { V1_18_UpgradeVersionCommandModule } from 'src/database/commands/upgrade
|
||||
import { V1_19_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-19/1-19-upgrade-version-command.module';
|
||||
import { V1_20_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-20/1-20-upgrade-version-command.module';
|
||||
import { UpgradeCommand } from 'src/database/commands/upgrade-version-command/upgrade.command';
|
||||
import { CoreEngineVersionModule } from 'src/engine/core-engine-version/core-engine-version.module';
|
||||
import { CoreMigrationRunnerModule } from 'src/database/commands/core-migration-runner/core-migration-runner.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { WorkspaceVersionModule } from 'src/engine/workspace-manager/workspace-version/workspace-version.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -17,6 +20,9 @@ import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-s
|
||||
V1_19_UpgradeVersionCommandModule,
|
||||
V1_20_UpgradeVersionCommandModule,
|
||||
DataSourceModule,
|
||||
CoreEngineVersionModule,
|
||||
CoreMigrationRunnerModule,
|
||||
WorkspaceVersionModule,
|
||||
],
|
||||
providers: [UpgradeCommand],
|
||||
})
|
||||
|
||||
+9
@@ -9,6 +9,7 @@ import {
|
||||
UpgradeCommandRunner,
|
||||
type VersionCommands,
|
||||
} from 'src/database/commands/command-runners/upgrade.command-runner';
|
||||
import { CoreMigrationRunnerService } from 'src/database/commands/core-migration-runner/services/core-migration-runner.service';
|
||||
import { BackfillApplicationPackageFilesCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-backfill-application-package-files.command';
|
||||
import { DeleteFileRecordsAndUpdateTableCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-delete-all-files-and-update-table.command';
|
||||
import { FixMorphRelationFieldNamesCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-fix-morph-relation-field-names.command';
|
||||
@@ -49,10 +50,12 @@ import { MigrateMessagingInfrastructureToMetadataCommand } from 'src/database/co
|
||||
import { MigrateRichTextToTextCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-migrate-rich-text-to-text.command';
|
||||
import { SeedCliApplicationRegistrationCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-seed-cli-application-registration.command';
|
||||
import { UpdateStandardIndexViewNamesCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-update-standard-index-view-names.command';
|
||||
import { CoreEngineVersionService } from 'src/engine/core-engine-version/services/core-engine-version.service';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceVersionService } from 'src/engine/workspace-manager/workspace-version/services/workspace-version.service';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade',
|
||||
@@ -67,6 +70,9 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
protected readonly twentyConfigService: TwentyConfigService,
|
||||
protected readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
protected readonly coreEngineVersionService: CoreEngineVersionService,
|
||||
protected readonly workspaceVersionService: WorkspaceVersionService,
|
||||
protected readonly coreMigrationRunnerService: CoreMigrationRunnerService,
|
||||
|
||||
// 1.17 Commands
|
||||
protected readonly backfillApplicationPackageFilesCommand: BackfillApplicationPackageFilesCommand,
|
||||
@@ -121,6 +127,9 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
twentyConfigService,
|
||||
globalWorkspaceOrmManager,
|
||||
dataSourceService,
|
||||
coreEngineVersionService,
|
||||
workspaceVersionService,
|
||||
coreMigrationRunnerService,
|
||||
);
|
||||
|
||||
// Note: Required empty commands array to allow retrieving previous version
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { rawDataSource } from 'src/database/typeorm/raw/raw.datasource';
|
||||
|
||||
import { camelToSnakeCase, performQuery } from './utils';
|
||||
import { camelToSnakeCase, performQuery } from './setup-db-utils';
|
||||
|
||||
rawDataSource
|
||||
.initialize()
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { rawDataSource } from 'src/database/typeorm/raw/raw.datasource';
|
||||
|
||||
import { performQuery } from './utils';
|
||||
import { performQuery } from './setup-db-utils';
|
||||
|
||||
async function dropSchemasSequentially() {
|
||||
try {
|
||||
+1
-1
@@ -23,8 +23,8 @@ import { useDirectExecution } from 'src/engine/api/graphql/direct-execution/hook
|
||||
import { WorkspaceSchemaFactory } from 'src/engine/api/graphql/workspace-schema.factory';
|
||||
import { CoreEngineModule } from 'src/engine/core-modules/core-engine.module';
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { useSentryTracing } from 'src/engine/core-modules/exception-handler/hooks/use-sentry-tracing';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { useDisableIntrospectionAndSuggestionsForUnauthenticatedUsers } from 'src/engine/core-modules/graphql/hooks/use-disable-introspection-and-suggestions-for-unauthenticated-users.hook';
|
||||
import { useGraphQLErrorHandlerHook } from 'src/engine/core-modules/graphql/hooks/use-graphql-error-handler.hook';
|
||||
import { useGraphQLQueryTiming } from 'src/engine/core-modules/graphql/hooks/use-graphql-query-timing.hook';
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
export const UPGRADE_COMMAND_SUPPORTED_VERSIONS = [
|
||||
'1.16.0',
|
||||
'1.17.0',
|
||||
'1.18.0',
|
||||
'1.19.0',
|
||||
'1.20.0',
|
||||
] as const;
|
||||
|
||||
export type UpgradeCommandVersion =
|
||||
(typeof UPGRADE_COMMAND_SUPPORTED_VERSIONS)[number];
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { CoreEngineVersionService } from 'src/engine/core-engine-version/services/core-engine-version.service';
|
||||
|
||||
@Module({
|
||||
providers: [CoreEngineVersionService],
|
||||
exports: [CoreEngineVersionService],
|
||||
})
|
||||
export class CoreEngineVersionModule {}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { SemVer } from 'semver';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { UPGRADE_COMMAND_SUPPORTED_VERSIONS } from 'src/engine/constants/upgrade-command-supported-versions.constant';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { getPreviousVersion } from 'src/utils/version/get-previous-version';
|
||||
|
||||
@Injectable()
|
||||
export class CoreEngineVersionService {
|
||||
constructor(private readonly twentyConfigService: TwentyConfigService) {}
|
||||
|
||||
getCurrentVersion(): SemVer {
|
||||
const appVersion = this.twentyConfigService.get('APP_VERSION');
|
||||
|
||||
if (!isDefined(appVersion)) {
|
||||
throw new Error(
|
||||
'APP_VERSION is not defined, please double check your env variables',
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
return new SemVer(appVersion);
|
||||
} catch {
|
||||
throw new Error(`APP_VERSION is not a valid semver: "${appVersion}"`);
|
||||
}
|
||||
}
|
||||
|
||||
getPreviousVersion(): SemVer {
|
||||
const currentAppVersion = this.getCurrentVersion();
|
||||
const currentVersionMajorMinor = `${currentAppVersion.major}.${currentAppVersion.minor}.0`;
|
||||
|
||||
const previousVersion = getPreviousVersion({
|
||||
currentVersion: currentVersionMajorMinor,
|
||||
versions: [...UPGRADE_COMMAND_SUPPORTED_VERSIONS],
|
||||
});
|
||||
|
||||
if (!isDefined(previousVersion)) {
|
||||
throw new Error(
|
||||
`No previous version found for version ${currentAppVersion}. Available versions: ${UPGRADE_COMMAND_SUPPORTED_VERSIONS.join(', ')}`,
|
||||
);
|
||||
}
|
||||
|
||||
return previousVersion;
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export const MAX_WORKSPACES_WITHOUT_ENTERPRISE_KEY = 5;
|
||||
+3
@@ -97,6 +97,9 @@ const createSignInUpServiceForTests = () => {
|
||||
{
|
||||
uploadWorkspaceLogoFromUrl: jest.fn(),
|
||||
} as any,
|
||||
{
|
||||
isValid: jest.fn().mockReturnValue(false),
|
||||
} as any,
|
||||
{
|
||||
createQueryRunner: jest.fn(() => queryRunnerMock),
|
||||
} as any,
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Repository, type DataSource, type QueryRunner } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { USER_SIGNUP_EVENT_NAME } from 'src/engine/api/graphql/workspace-query-runner/constants/user-signup-event-name.constants';
|
||||
import { MAX_WORKSPACES_WITHOUT_ENTERPRISE_KEY } from 'src/engine/core-modules/auth/constants/max-workspaces-without-enterprise-key.constants';
|
||||
import { type AppTokenEntity } from 'src/engine/core-modules/app-token/app-token.entity';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import {
|
||||
@@ -29,6 +30,7 @@ import {
|
||||
type SignInUpNewUserPayload,
|
||||
} from 'src/engine/core-modules/auth/types/signInUp.type';
|
||||
import { SubdomainManagerService } from 'src/engine/core-modules/domain/subdomain-manager/services/subdomain-manager.service';
|
||||
import { EnterprisePlanService } from 'src/engine/core-modules/enterprise/services/enterprise-plan.service';
|
||||
import { FileCorePictureService } from 'src/engine/core-modules/file/file-core-picture/services/file-core-picture.service';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type';
|
||||
@@ -65,6 +67,7 @@ export class SignInUpService {
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
private readonly fileCorePictureService: FileCorePictureService,
|
||||
private readonly enterprisePlanService: EnterprisePlanService,
|
||||
@InjectDataSource()
|
||||
private readonly dataSource: DataSource,
|
||||
) {}
|
||||
@@ -424,6 +427,8 @@ export class SignInUpService {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.assertWorkspaceCountWithinLimit(workspaceCount);
|
||||
|
||||
if (
|
||||
!this.twentyConfigService.get(
|
||||
'IS_WORKSPACE_CREATION_LIMITED_TO_SERVER_ADMINS',
|
||||
@@ -449,6 +454,26 @@ export class SignInUpService {
|
||||
);
|
||||
}
|
||||
|
||||
private async assertWorkspaceCountWithinLimit(
|
||||
workspaceCount: number,
|
||||
): Promise<void> {
|
||||
if (this.enterprisePlanService.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (workspaceCount < MAX_WORKSPACES_WITHOUT_ENTERPRISE_KEY) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new AuthException(
|
||||
`Cannot create more than ${MAX_WORKSPACES_WITHOUT_ENTERPRISE_KEY} workspaces without a valid enterprise key`,
|
||||
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
||||
{
|
||||
userFriendlyMessage: msg`Workspace limit reached. A valid enterprise key is required to create more workspaces.`,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async signUpOnNewWorkspace(
|
||||
userData: ExistingUserOrPartialUserWithPicture['userData'],
|
||||
) {
|
||||
|
||||
+68
@@ -42,6 +42,74 @@ describe('SubdomainManagerService', () => {
|
||||
twentyConfigService = module.get<TwentyConfigService>(TwentyConfigService);
|
||||
});
|
||||
|
||||
describe('getSubdomainAndDomainFromUrl', () => {
|
||||
it('should extract subdomain from a full URL with protocol', () => {
|
||||
jest
|
||||
.spyOn(twentyConfigService, 'get')
|
||||
.mockImplementation((key: string) => {
|
||||
const env = {
|
||||
FRONTEND_URL: 'https://twenty.com',
|
||||
DEFAULT_SUBDOMAIN: 'app',
|
||||
};
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
return env[key];
|
||||
});
|
||||
|
||||
const result =
|
||||
domainServerConfigService.getSubdomainAndDomainFromUrl(
|
||||
'https://myworkspace.twenty.com',
|
||||
);
|
||||
|
||||
expect(result.subdomain).toBe('myworkspace');
|
||||
expect(result.domain).toBeNull();
|
||||
});
|
||||
|
||||
it('should handle URL without protocol scheme', () => {
|
||||
jest
|
||||
.spyOn(twentyConfigService, 'get')
|
||||
.mockImplementation((key: string) => {
|
||||
const env = {
|
||||
FRONTEND_URL: 'https://twenty.com',
|
||||
DEFAULT_SUBDOMAIN: 'app',
|
||||
};
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
return env[key];
|
||||
});
|
||||
|
||||
const result =
|
||||
domainServerConfigService.getSubdomainAndDomainFromUrl(
|
||||
'myworkspace.twenty.com',
|
||||
);
|
||||
|
||||
expect(result.subdomain).toBe('myworkspace');
|
||||
expect(result.domain).toBeNull();
|
||||
});
|
||||
|
||||
it('should return custom domain for non-front domain URLs', () => {
|
||||
jest
|
||||
.spyOn(twentyConfigService, 'get')
|
||||
.mockImplementation((key: string) => {
|
||||
const env = {
|
||||
FRONTEND_URL: 'https://twenty.com',
|
||||
DEFAULT_SUBDOMAIN: 'app',
|
||||
};
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
return env[key];
|
||||
});
|
||||
|
||||
const result =
|
||||
domainServerConfigService.getSubdomainAndDomainFromUrl(
|
||||
'custom.example.com',
|
||||
);
|
||||
|
||||
expect(result.subdomain).toBeUndefined();
|
||||
expect(result.domain).toBe('custom.example.com');
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildBaseUrl', () => {
|
||||
it('should build the base URL from environment variables', () => {
|
||||
jest
|
||||
|
||||
+3
-1
@@ -46,7 +46,9 @@ export class DomainServerConfigService {
|
||||
}
|
||||
|
||||
getSubdomainAndDomainFromUrl = (url: string) => {
|
||||
const { hostname: originHostname } = new URL(url);
|
||||
const urlWithProtocol = url.includes('://') ? url : `https://${url}`;
|
||||
|
||||
const { hostname: originHostname } = new URL(urlWithProtocol);
|
||||
|
||||
const frontDomain = this.getFrontUrl().hostname;
|
||||
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Kontakauto skeppingsbeleid"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Inhoud kan nie leeg wees nie"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Konteks"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Werksruimte-ID en rol stem nie ooreen nie."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Werksruimte is nie gereed om nuwe lede te verwelkom nie"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "سياسة إنشاء جهة الاتصال التلقائية"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "لا يمكن أن يكون المحتوى فارغًا"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "السياق"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "عدم تطابق بين معرّف مساحة العمل والدور."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "مساحة العمل ليست جاهزة للترحيب بأعضاء جدد"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Política d'autocreació de contactes"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "El contingut no pot estar buit"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Context"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "No coincideixen l'ID de l'espai de treball i el rol."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "L'espai de treball no està preparat per donar la benvinguda a nous membres"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Politika automatického vytváření kontaktů"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Obsah nesmí být prázdný"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Kontext"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Nesoulad ID pracovního prostoru a role."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Pracovní prostor není připraven přivítat nové členy"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr ""
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Indhold kan ikke være tomt"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Kontekst"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Uoverensstemmelse mellem arbejdsområde-ID og rolle."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Arbejdsområdet er ikke klar til at byde nye medlemmer velkommen"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Richtlinie zur automatischen Kontakterstellung"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Inhalt darf nicht leer sein"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Kontext"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Arbeitsbereichs-ID und Rolle stimmen nicht überein."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Workspace ist nicht bereit, neue Mitglieder willkommen zu heißen"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Πολιτική Αυτόματης Δημιουργίας Επαφής"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Το περιεχόμενο δεν μπορεί να είναι κενό"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Περιβάλλον"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Ασυμφωνία αναγνωριστικού χώρου εργασί
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Ο χώρος εργασίας δεν είναι έτοιμος να υποδεχθεί νέα μέλη"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1497,16 +1497,6 @@ msgstr "Contact auto creation policy"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Content cannot be empty"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Context"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr "Context of the workflow run"
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5357,16 +5347,6 @@ msgstr "Other"
|
||||
msgid "Outgoing"
|
||||
msgstr "Outgoing"
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr "Output"
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr "Output of the workflow run"
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8365,6 +8345,11 @@ msgstr "Workspace ID and role mismatch."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Workspace is not ready to welcome new members"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Política de creación automática de contactos"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "El contenido no puede estar vacío"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Contexto"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "El ID del espacio de trabajo y el rol no coinciden."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "El espacio de trabajo no está listo para recibir nuevos miembros"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr ""
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Sisältö ei voi olla tyhjä"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Konteksti"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Työtilan tunnus ja rooli eivät vastaa toisiaan."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Työtila ei ole valmis vastaanottamaan uusia jäseniä"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Politique de création automatique de contacts"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Le contenu ne peut pas être vide"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Contexte"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Incompatibilité entre l'ID d'espace de travail et le rôle."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "L'espace de travail n'est pas prêt à accueillir de nouveaux membres"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
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
@@ -1502,16 +1502,6 @@ msgstr "מדיניות יצירת אנשי קשר אוטומטית"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "התוכן לא יכול להיות ריק"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "הקשר"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "אי התאמה בין מזהה סביבת עבודה לתפקיד."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "מקום העבודה אינו מוכן לקבל חברים חדשים."
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Kapcsolattartó automatikus létrehozásának politikája"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "A tartalom nem lehet üres"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Kontextus"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "A munkaterület-azonosító és a szerepkör nem egyezik."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "A munkaterület nem áll készen új tagok fogadására"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Politica di creazione automatica dei contatti"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Il contenuto non può essere vuoto"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Contesto"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "ID dello spazio di lavoro e ruolo non corrispondono."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Lo spazio di lavoro non è pronto ad accogliere nuovi membri"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "連絡先自動作成ポリシー"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "コンテンツは空にできません"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "コンテキスト"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "ワークスペースIDとロールが一致しません。"
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "ワークスペースは新しいメンバーを迎える準備ができていません"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "연락처 자동 생성 정책"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "내용은 비워 둘 수 없습니다"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "컨텍스트"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "워크스페이스 ID와 역할이 일치하지 않습니다."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "작업 공간은 새로운 멤버를 환영할 준비가 되어 있지 않습니다"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Beleid voor automatisch aanmaken van contacten"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Inhoud mag niet leeg zijn"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Context"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Werkruimte-ID en rol komen niet overeen."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Werkruimte is niet gereed om nieuwe leden te verwelkomen."
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Policy for automatisk oppretting av kontakter"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Innhold kan ikke være tomt"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Kontekst"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Arbeidsområde-ID og rolle samsvarer ikke."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Arbeidsområdet er ikke klart for å ta imot nye medlemmer"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Polityka automatycznego tworzenia kontaktu"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Zawartość nie może być pusta"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Kontekst"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Niezgodność identyfikatora przestrzeni roboczej i roli."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Workspace nie jest gotowy na przyjęcie nowych członków"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1497,16 +1497,6 @@ msgstr ""
|
||||
msgid "Content cannot be empty"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5357,16 +5347,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8365,6 +8345,11 @@ msgstr ""
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr ""
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "O conteúdo não pode estar vazio"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Incompatibilidade entre o ID do espaço de trabalho e a função."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "O espaço de trabalho não está pronto para receber novos membros"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Política de Criação Automática de Contactos"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "O conteúdo não pode estar vazio"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Contexto"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Incompatibilidade entre ID do espaço de trabalho e função."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Espaço de trabalho não está pronto para receber novos membros"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Politica de creare automată a contactelor"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Conținutul nu poate fi gol"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Context"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Nepotrivire între ID-ul spațiului de lucru și rol."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Spațiul de lucru nu este pregătit să primească noi membri"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Политика Автосоздания Контактов"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Содержимое не может быть пустым"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Контекст"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Несоответствие идентификатора рабочег
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Рабочее пространство не готово принять новых участников"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Правила за аутоматско креирање контака
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Садржај не може бити празан"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Контекст"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Неподударање ID-ја радног простора и уло
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Радни простор није спреман за пријем нових чланова"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr "Policy för automatisk kontakt skapande"
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Innehåll får inte vara tomt"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Sammanhang"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5364,16 +5354,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8376,6 +8356,11 @@ msgstr "Arbetsyte-ID och roll stämmer inte överens."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Arbetsutrymmet är inte redo att välkomna nya medlemmar"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr ""
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "İçerik boş olamaz"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr "Bağlam"
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Çalışma alanı kimliği ile rol uyuşmuyor."
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Çalışma alanı yeni üyeleri ağırlamaya hazır değil"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
@@ -1502,16 +1502,6 @@ msgstr ""
|
||||
msgid "Content cannot be empty"
|
||||
msgstr "Вміст не може бути порожнім"
|
||||
|
||||
#. js-lingui-id: M73whl
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: YPzDDR
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Context of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: cmBz2p
|
||||
#: src/engine/metadata-modules/object-permission/field-permission/field-permission.service.ts
|
||||
msgid "Contradicting field permissions have been detected on a relation field."
|
||||
@@ -5362,16 +5352,6 @@ msgstr ""
|
||||
msgid "Outgoing"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: gh06VD
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 5vO0WN
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workflow-run-standard-flat-field-metadata.util.ts
|
||||
msgid "Output of the workflow run"
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: 6ua+9g
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-workspace-member-standard-flat-field-metadata.util.ts
|
||||
msgid "Owned opportunities"
|
||||
@@ -8370,6 +8350,11 @@ msgstr "Невідповідність між ідентифікатором р
|
||||
msgid "Workspace is not ready to welcome new members"
|
||||
msgstr "Робочий простір не готовий приймати нових учасників"
|
||||
|
||||
#. js-lingui-id: iN7doz
|
||||
#: src/engine/core-modules/auth/services/sign-in-up.service.ts
|
||||
msgid "Workspace limit reached. A valid enterprise key is required to create more workspaces."
|
||||
msgstr ""
|
||||
|
||||
#. js-lingui-id: CbGxon
|
||||
#: src/engine/workspace-manager/twenty-standard-application/utils/field-metadata/compute-message-participant-standard-flat-field-metadata.util.ts
|
||||
msgid "Workspace member"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user