Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e772554be | |||
| af84ac2164 | |||
| cad7430e5e | |||
| a6e13d1998 | |||
| f0383a830e | |||
| 10f63359ea | |||
| 12e958600d | |||
| 667dd627c8 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "twenty-emails",
|
||||
"version": "0.40.0-canary",
|
||||
"version": "0.34.6",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "twenty-front",
|
||||
"version": "0.40.0-canary",
|
||||
"version": "0.34.6",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
+15
-10
@@ -4,6 +4,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
|
||||
import { useAddNewCard } from '@/object-record/record-board/record-board-column/hooks/useAddNewCard';
|
||||
import { recordBoardNewRecordByColumnIdSelector } from '@/object-record/record-board/states/selectors/recordBoardNewRecordByColumnIdSelector';
|
||||
import { SingleRecordSelect } from '@/object-record/relation-picker/components/SingleRecordSelect';
|
||||
import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
const StyledCompanyPickerContainer = styled.div`
|
||||
@@ -37,16 +38,20 @@ export const RecordBoardColumnNewOpportunity = ({
|
||||
<>
|
||||
{newRecord.isCreating && newRecord.position === position && (
|
||||
<StyledCompanyPickerContainer>
|
||||
<SingleRecordSelect
|
||||
disableBackgroundBlur
|
||||
onCancel={() => handleCreateSuccess(position, columnId, false)}
|
||||
onRecordSelected={(company) =>
|
||||
company ? handleEntitySelect(position, company) : null
|
||||
}
|
||||
objectNameSingular={CoreObjectNameSingular.Company}
|
||||
recordPickerInstanceId="relation-picker"
|
||||
selectedRecordIds={[]}
|
||||
/>
|
||||
<RecordPickerComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'relation-picker' }}
|
||||
>
|
||||
<SingleRecordSelect
|
||||
disableBackgroundBlur
|
||||
onCancel={() => handleCreateSuccess(position, columnId, false)}
|
||||
onRecordSelected={(company) =>
|
||||
company ? handleEntitySelect(position, company) : null
|
||||
}
|
||||
objectNameSingular={CoreObjectNameSingular.Company}
|
||||
recordPickerInstanceId="relation-picker"
|
||||
selectedRecordIds={[]}
|
||||
/>
|
||||
</RecordPickerComponentInstanceContext.Provider>
|
||||
</StyledCompanyPickerContainer>
|
||||
)}
|
||||
</>
|
||||
|
||||
-2
@@ -22,7 +22,6 @@ export const SingleRecordSelect = ({
|
||||
onCreate,
|
||||
onRecordSelected,
|
||||
objectNameSingular,
|
||||
recordPickerInstanceId,
|
||||
selectedRecordIds,
|
||||
width = 200,
|
||||
}: SingleRecordSelectProps) => {
|
||||
@@ -60,7 +59,6 @@ export const SingleRecordSelect = ({
|
||||
onCreate,
|
||||
onRecordSelected,
|
||||
objectNameSingular,
|
||||
recordPickerInstanceId,
|
||||
selectedRecordIds,
|
||||
}}
|
||||
/>
|
||||
|
||||
+7
-4
@@ -4,10 +4,12 @@ import {
|
||||
} from '@/object-record/relation-picker/components/SingleRecordSelectMenuItems';
|
||||
import { useRecordPickerRecordsOptions } from '@/object-record/relation-picker/hooks/useRecordPickerRecordsOptions';
|
||||
import { useRecordSelectSearch } from '@/object-record/relation-picker/hooks/useRecordSelectSearch';
|
||||
import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext';
|
||||
import { CreateNewButton } from '@/ui/input/relation-picker/components/CreateNewButton';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { Placement } from '@floating-ui/react';
|
||||
import { IconPlus } from 'twenty-ui';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@@ -37,13 +39,14 @@ export const SingleRecordSelectMenuItemsWithSearch = ({
|
||||
onCreate,
|
||||
onRecordSelected,
|
||||
objectNameSingular,
|
||||
recordPickerInstanceId = 'record-picker',
|
||||
selectedRecordIds,
|
||||
dropdownPlacement,
|
||||
}: SingleRecordSelectMenuItemsWithSearchProps) => {
|
||||
const { handleSearchFilterChange } = useRecordSelectSearch({
|
||||
recordPickerInstanceId,
|
||||
});
|
||||
const { handleSearchFilterChange } = useRecordSelectSearch();
|
||||
|
||||
const recordPickerInstanceId = useAvailableComponentInstanceIdOrThrow(
|
||||
RecordPickerComponentInstanceContext,
|
||||
);
|
||||
|
||||
const { records, recordPickerSearchFilter } = useRecordPickerRecordsOptions({
|
||||
objectNameSingular,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "twenty-server",
|
||||
"version": "0.40.0-canary",
|
||||
"version": "0.34.6",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ConfirmationQuestion } from 'src/database/commands/questions/confirmati
|
||||
import { UpgradeTo0_32CommandModule } from 'src/database/commands/upgrade-version/0-32/0-32-upgrade-version.module';
|
||||
import { UpgradeTo0_33CommandModule } from 'src/database/commands/upgrade-version/0-33/0-33-upgrade-version.module';
|
||||
import { UpgradeTo0_34CommandModule } from 'src/database/commands/upgrade-version/0-34/0-34-upgrade-version.module';
|
||||
import { UpgradeTo0_35CommandModule } from 'src/database/commands/upgrade-version/0-35/0-35-upgrade-version.module';
|
||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
|
||||
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
@@ -51,6 +52,7 @@ import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/worksp
|
||||
UpgradeTo0_32CommandModule,
|
||||
UpgradeTo0_33CommandModule,
|
||||
UpgradeTo0_34CommandModule,
|
||||
UpgradeTo0_35CommandModule,
|
||||
FeatureFlagModule,
|
||||
],
|
||||
providers: [
|
||||
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import { Command } from 'nest-commander';
|
||||
import { Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import {
|
||||
ActiveWorkspacesCommandOptions,
|
||||
ActiveWorkspacesCommandRunner,
|
||||
} from 'src/database/commands/active-workspaces.command';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import {
|
||||
FieldMetadataEntity,
|
||||
FieldMetadataType,
|
||||
} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
import {
|
||||
WorkspaceMigrationColumnActionType,
|
||||
WorkspaceMigrationTableAction,
|
||||
WorkspaceMigrationTableActionType,
|
||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceMigrationFactory } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.factory';
|
||||
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
|
||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
|
||||
import { isDefined } from 'src/utils/is-defined';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade-0.35:phone-calling-code-create-column',
|
||||
description: 'Create the callingCode column',
|
||||
})
|
||||
export class PhoneCallingCodeCreateColumnCommand extends ActiveWorkspacesCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
@InjectRepository(FieldMetadataEntity, 'metadata')
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
||||
private readonly workspaceMigrationFactory: WorkspaceMigrationFactory,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {
|
||||
super(workspaceRepository);
|
||||
}
|
||||
|
||||
async executeActiveWorkspacesCommand(
|
||||
_passedParam: string[],
|
||||
options: ActiveWorkspacesCommandOptions,
|
||||
workspaceIds: string[],
|
||||
): Promise<void> {
|
||||
this.logger.log(
|
||||
'Running command to add calling code and change country code with default one',
|
||||
);
|
||||
|
||||
this.logger.verbose(`Part 1 - Workspace`);
|
||||
let workspaceIterator = 1;
|
||||
|
||||
for (const workspaceId of workspaceIds) {
|
||||
this.logger.verbose(
|
||||
`Running command for workspace ${workspaceId} ${workspaceIterator}/${workspaceIds.length}`,
|
||||
);
|
||||
|
||||
this.logger.verbose(
|
||||
`P1 Step 1 - let's find all the fieldsMetadata that have the PHONES type, and extract the objectMetadataId`,
|
||||
);
|
||||
|
||||
try {
|
||||
const phonesFieldMetadata = await this.fieldMetadataRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
type: FieldMetadataType.PHONES,
|
||||
},
|
||||
relations: ['object'],
|
||||
});
|
||||
|
||||
for (const phoneFieldMetadata of phonesFieldMetadata) {
|
||||
if (
|
||||
isDefined(phoneFieldMetadata?.name) &&
|
||||
isDefined(phoneFieldMetadata.object)
|
||||
) {
|
||||
this.logger.verbose(
|
||||
`P1 Step 1 - Let's find the "nameSingular" of this objectMetadata: ${phoneFieldMetadata.object.nameSingular || 'not found'}`,
|
||||
);
|
||||
|
||||
if (!phoneFieldMetadata.object?.nameSingular) continue;
|
||||
|
||||
this.logger.verbose(
|
||||
`P1 Step 1 - Create migration for field ${phoneFieldMetadata.name}`,
|
||||
);
|
||||
|
||||
if (options.dryRun) {
|
||||
continue;
|
||||
}
|
||||
await this.workspaceMigrationService.createCustomMigration(
|
||||
generateMigrationName(
|
||||
`create-${phoneFieldMetadata.object.nameSingular}PrimaryPhoneCallingCode-for-field-${phoneFieldMetadata.name}`,
|
||||
),
|
||||
workspaceId,
|
||||
[
|
||||
{
|
||||
name: computeObjectTargetTable(phoneFieldMetadata.object),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: this.workspaceMigrationFactory.createColumnActions(
|
||||
WorkspaceMigrationColumnActionType.CREATE,
|
||||
{
|
||||
id: v4(),
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: `${phoneFieldMetadata.name}PrimaryPhoneCallingCode`,
|
||||
label: `${phoneFieldMetadata.name}PrimaryPhoneCallingCode`,
|
||||
objectMetadataId: phoneFieldMetadata.object.id,
|
||||
workspaceId: workspaceId,
|
||||
isNullable: true,
|
||||
defaultValue: "''",
|
||||
} satisfies Partial<FieldMetadataEntity>,
|
||||
),
|
||||
} satisfies WorkspaceMigrationTableAction,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.verbose(
|
||||
`P1 Step 1 - RUN migration to create callingCodes for ${workspaceId.slice(0, 5)}`,
|
||||
);
|
||||
await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.log(`Error in workspace ${workspaceId} : ${error}`);
|
||||
}
|
||||
workspaceIterator++;
|
||||
}
|
||||
|
||||
this.logger.log(chalk.green(`Command completed!`));
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { ActiveWorkspacesCommandRunner } from 'src/database/commands/active-workspaces.command';
|
||||
import { PhoneCallingCodeCreateColumnCommand } from 'src/database/commands/upgrade-version/0-35/0-35-phone-calling-code-create-column.command';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
|
||||
interface UpdateTo0_35CommandOptions {
|
||||
workspaceId?: string;
|
||||
}
|
||||
|
||||
@Command({
|
||||
name: 'upgrade-0.35',
|
||||
description: 'Upgrade to 0.35',
|
||||
})
|
||||
export class UpgradeTo0_35Command extends ActiveWorkspacesCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
protected readonly workspaceRepository: Repository<Workspace>,
|
||||
private readonly phoneCallingCodeCreateColumnCommand: PhoneCallingCodeCreateColumnCommand,
|
||||
) {
|
||||
super(workspaceRepository);
|
||||
}
|
||||
|
||||
async executeActiveWorkspacesCommand(
|
||||
passedParam: string[],
|
||||
options: UpdateTo0_35CommandOptions,
|
||||
workspaceIds: string[],
|
||||
): Promise<void> {
|
||||
await this.phoneCallingCodeCreateColumnCommand.executeActiveWorkspacesCommand(
|
||||
passedParam,
|
||||
options,
|
||||
workspaceIds,
|
||||
);
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { PhoneCallingCodeCreateColumnCommand } from 'src/database/commands/upgrade-version/0-35/0-35-phone-calling-code-create-column.command';
|
||||
import { UpgradeTo0_35Command } from 'src/database/commands/upgrade-version/0-35/0-35-upgrade-version.command';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace], 'core'),
|
||||
TypeOrmModule.forFeature([FieldMetadataEntity], 'metadata'),
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
WorkspaceMigrationModule,
|
||||
],
|
||||
providers: [UpgradeTo0_35Command, PhoneCallingCodeCreateColumnCommand],
|
||||
})
|
||||
export class UpgradeTo0_35CommandModule {}
|
||||
+30
-27
@@ -50,40 +50,43 @@ export class SyncWorkspaceMetadataCommand extends ActiveWorkspacesCommandRunner
|
||||
`Running workspace sync for workspace: ${workspaceId} (${count} out of ${workspaceIds.length})`,
|
||||
);
|
||||
count++;
|
||||
try {
|
||||
const issues =
|
||||
await this.workspaceHealthService.healthCheck(workspaceId);
|
||||
|
||||
// Security: abort if there are issues.
|
||||
if (issues.length > 0) {
|
||||
if (!options.force) {
|
||||
try {
|
||||
const issues =
|
||||
await this.workspaceHealthService.healthCheck(workspaceId);
|
||||
|
||||
// Security: abort if there are issues.
|
||||
if (issues.length > 0) {
|
||||
if (!options.force) {
|
||||
this.logger.error(
|
||||
`Workspace contains ${issues.length} issues, aborting.`,
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
'If you want to force the migration, use --force flag',
|
||||
);
|
||||
this.logger.log(
|
||||
'Please use `workspace:health` command to check issues and fix them before running this command.',
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
this.logger.warn(
|
||||
`Workspace contains ${issues.length} issues, sync has been forced.`,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!options.force) {
|
||||
this.logger.error(
|
||||
`Workspace contains ${issues.length} issues, aborting.`,
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
'If you want to force the migration, use --force flag',
|
||||
);
|
||||
this.logger.log(
|
||||
'Please use `workspace:health` command to check issues and fix them before running this command.',
|
||||
);
|
||||
|
||||
continue;
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.logger.warn(
|
||||
`Workspace contains ${issues.length} issues, sync has been forced.`,
|
||||
`Workspace health check failed with error, but sync has been forced.`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!options.force) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.logger.warn(
|
||||
`Workspace health check failed with error, but sync has been forced.`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
-5
@@ -1,6 +1,5 @@
|
||||
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import {
|
||||
RelationMetadataType,
|
||||
@@ -9,7 +8,6 @@ import {
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
|
||||
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
|
||||
import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.decorator';
|
||||
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
|
||||
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
|
||||
import { FAVORITE_FOLDER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
@@ -25,9 +23,6 @@ import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/f
|
||||
icon: 'IconFolder',
|
||||
})
|
||||
@WorkspaceIsSystem()
|
||||
@WorkspaceGate({
|
||||
featureFlag: FeatureFlagKey.IsFavoriteFolderEntityEnabled,
|
||||
})
|
||||
export class FavoriteFolderWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
@WorkspaceField({
|
||||
standardId: FAVORITE_FOLDER_STANDARD_FIELD_IDS.position,
|
||||
|
||||
-6
@@ -105,16 +105,10 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
inverseSideTarget: () => FavoriteFolderWorkspaceEntity,
|
||||
inverseSideFieldKey: 'favorites',
|
||||
})
|
||||
@WorkspaceGate({
|
||||
featureFlag: FeatureFlagKey.IsFavoriteFolderEntityEnabled,
|
||||
})
|
||||
@WorkspaceIsNullable()
|
||||
favoriteFolder: Relation<FavoriteFolderWorkspaceEntity> | null;
|
||||
|
||||
@WorkspaceJoinColumn('favoriteFolder')
|
||||
@WorkspaceGate({
|
||||
featureFlag: FeatureFlagKey.IsFavoriteFolderEntityEnabled,
|
||||
})
|
||||
favoriteFolderId: string;
|
||||
|
||||
@WorkspaceRelation({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "twenty-ui",
|
||||
"version": "0.40.0-canary",
|
||||
"version": "0.34.6",
|
||||
"type": "module",
|
||||
"main": "./src/index.ts",
|
||||
"exports": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "twenty-website",
|
||||
"version": "0.40.0-canary",
|
||||
"version": "0.34.6",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"nx": "NX_DEFAULT_PROJECT=twenty-website node ../../node_modules/nx/bin/nx.js",
|
||||
|
||||
Reference in New Issue
Block a user