Fix various bugs before 0.2.2 (#3118)

* Fix various bugs before 0.2.2 release

* Additional fixes

* More fixes

* Fixes
This commit is contained in:
Charles Bochet
2023-12-21 23:48:52 +01:00
committed by GitHub
parent 69ffa0d229
commit 756b30815e
28 changed files with 183 additions and 245 deletions

View File

@ -28,7 +28,6 @@ export const ActivityBodyEditor = ({
const [body, setBody] = useState<string | null>(null); const [body, setBody] = useState<string | null>(null);
const { updateOneRecord } = useUpdateOneRecord({ const { updateOneRecord } = useUpdateOneRecord({
objectNameSingular: 'activity', objectNameSingular: 'activity',
refetchFindManyQuery: true,
}); });
useEffect(() => { useEffect(() => {

View File

@ -82,7 +82,6 @@ export const ActivityEditor = ({
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const { updateOneRecord: updateOneActivity } = useUpdateOneRecord<Activity>({ const { updateOneRecord: updateOneActivity } = useUpdateOneRecord<Activity>({
objectNameSingular: 'activity', objectNameSingular: 'activity',
refetchFindManyQuery: true,
}); });
const { FieldContextProvider: DueAtFieldContextProvider } = useFieldContext({ const { FieldContextProvider: DueAtFieldContextProvider } = useFieldContext({

View File

@ -24,7 +24,6 @@ export const useOpenCreateActivityDrawer = () => {
}); });
const { createOneRecord: createOneActivity } = useCreateOneRecord<Activity>({ const { createOneRecord: createOneActivity } = useCreateOneRecord<Activity>({
objectNameSingular: 'activity', objectNameSingular: 'activity',
refetchFindManyQuery: true,
}); });
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const setHotkeyScope = useSetHotkeyScope(); const setHotkeyScope = useSetHotkeyScope();

View File

@ -10,7 +10,6 @@ import {
IconCheckbox, IconCheckbox,
IconSearch, IconSearch,
IconSettings, IconSettings,
IconTargetArrow,
} from '@/ui/display/icon'; } from '@/ui/display/icon';
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
@ -70,12 +69,6 @@ export const MainNavigationDrawerItems = () => {
<NavigationDrawerSection> <NavigationDrawerSection>
<NavigationDrawerSectionTitle label="Workspace" /> <NavigationDrawerSectionTitle label="Workspace" />
<ObjectMetadataNavItems /> <ObjectMetadataNavItems />
<NavigationDrawerItem
label="Opportunities"
to="/objects/opportunities"
active={location.pathname === '/objects/opportunities'}
Icon={IconTargetArrow}
/>
</NavigationDrawerSection> </NavigationDrawerSection>
</> </>
); );

View File

@ -12,20 +12,45 @@ export const ObjectMetadataNavItems = () => {
return ( return (
<> <>
{activeObjectMetadataItems.map((objectMetadataItem) => {[
objectMetadataItem.nameSingular === 'opportunity' ? null : ( ...activeObjectMetadataItems
<NavigationDrawerItem .filter((item) =>
key={objectMetadataItem.id} ['person', 'company', 'opportunity'].includes(item.nameSingular),
label={objectMetadataItem.labelPlural} )
to={`/objects/${objectMetadataItem.namePlural}`} .sort((objectMetadataItemA, _) => {
active={currentPath == `/objects/${objectMetadataItem.namePlural}`} if (objectMetadataItemA.nameSingular === 'person') {
Icon={getIcon(objectMetadataItem.icon)} return -1;
onClick={() => { }
navigate(`/objects/${objectMetadataItem.namePlural}`);
}} if (objectMetadataItemA.nameSingular === 'opportunity') {
/> return 1;
), }
)}
return 0;
}),
...activeObjectMetadataItems
.filter(
(item) =>
!['person', 'company', 'opportunity'].includes(item.nameSingular),
)
.sort((objectMetadataItemA, objectMetadataItemB) => {
return new Date(objectMetadataItemA.createdAt) <
new Date(objectMetadataItemB.createdAt)
? 1
: -1;
}),
].map((objectMetadataItem) => (
<NavigationDrawerItem
key={objectMetadataItem.id}
label={objectMetadataItem.labelPlural}
to={`/objects/${objectMetadataItem.namePlural}`}
active={currentPath == `/objects/${objectMetadataItem.namePlural}`}
Icon={getIcon(objectMetadataItem.icon)}
onClick={() => {
navigate(`/objects/${objectMetadataItem.namePlural}`);
}}
/>
))}
</> </>
); );
}; };

View File

@ -38,7 +38,7 @@ const initializeValue = (
return { return {
amount: convertCurrencyMicrosToCurrency(fieldValue.amountMicros), amount: convertCurrencyMicrosToCurrency(fieldValue.amountMicros),
currencyCode: fieldValue.currencyCode, currencyCode: CurrencyCode.USD,
}; };
}; };

View File

@ -8,7 +8,6 @@ import { capitalize } from '~/utils/string/capitalize';
type useCreateOneRecordProps = { type useCreateOneRecordProps = {
objectNameSingular: string; objectNameSingular: string;
refetchFindManyQuery?: boolean;
}; };
export const useCreateOneRecord = <T>({ export const useCreateOneRecord = <T>({
@ -36,6 +35,7 @@ export const useCreateOneRecord = <T>({
const generatedEmptyRecord = generateEmptyRecord<Record<string, unknown>>({ const generatedEmptyRecord = generateEmptyRecord<Record<string, unknown>>({
id: recordId, id: recordId,
createdAt: new Date().toISOString(),
...input, ...input,
}); });
@ -53,7 +53,7 @@ export const useCreateOneRecord = <T>({
}, },
optimisticResponse: { optimisticResponse: {
[`create${capitalize(objectMetadataItem.nameSingular)}`]: [`create${capitalize(objectMetadataItem.nameSingular)}`]:
generateEmptyRecord({ id: recordId, ...input }), generatedEmptyRecord,
}, },
}); });

View File

@ -1,4 +1,5 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { generateEmptyFieldValue } from '@/object-record/utils/generateEmptyFieldValue';
export const useGenerateEmptyRecord = ({ export const useGenerateEmptyRecord = ({
objectMetadataItem, objectMetadataItem,
@ -10,157 +11,14 @@ export const useGenerateEmptyRecord = ({
// Todo replace this by runtime typing // Todo replace this by runtime typing
const validatedInput = input as { id: string } & { [key: string]: any }; const validatedInput = input as { id: string } & { [key: string]: any };
if (objectMetadataItem.nameSingular === 'company') { const emptyRecord = {} as Record<string, any>;
return {
id: validatedInput.id,
domainName: '',
accountOwnerId: null,
createdAt: new Date().toISOString(),
address: '',
people: [
{
edges: [],
__typename: 'PersonConnection',
},
],
xLink: {
label: '',
url: '',
__typename: 'Link',
},
attachments: {
edges: [],
__typename: 'AttachmentConnection',
},
activityTargets: {
edges: [],
__typename: 'ActivityTargetConnection',
},
idealCustomerProfile: null,
annualRecurringRevenue: {
amountMicros: null,
currencyCode: null,
__typename: 'Currency',
},
updatedAt: new Date().toISOString(),
employees: null,
accountOwner: null,
name: '',
linkedinLink: {
label: '',
url: '',
__typename: 'Link',
},
favorites: {
edges: [],
__typename: 'FavoriteConnection',
},
opportunities: {
edges: [],
__typename: 'OpportunityConnection',
},
__typename: 'Company',
} as T;
}
if (objectMetadataItem.nameSingular === 'person') { for (const fieldMetadataItem of objectMetadataItem.fields) {
return { emptyRecord[fieldMetadataItem.name] =
id: validatedInput.id, validatedInput[fieldMetadataItem.name] ??
activityTargets: { generateEmptyFieldValue(fieldMetadataItem);
edges: [],
__typename: 'ActivityTargetConnection',
},
opportunities: {
edges: [],
__typename: 'OpportunityConnection',
},
companyId: null,
favorites: {
edges: [],
__typename: 'FavoriteConnection',
},
phone: '',
company: null,
xLink: {
label: '',
url: '',
__typename: 'Link',
},
jobTitle: '',
pointOfContactForOpportunities: {
edges: [],
__typename: 'OpportunityConnection',
},
email: '',
attachments: {
edges: [],
__typename: 'AttachmentConnection',
},
name: {
firstName: '',
lastName: '',
__typename: 'FullName',
},
avatarUrl: '',
updatedAt: new Date().toISOString(),
createdAt: new Date().toISOString(),
city: '',
linkedinLink: {
label: '',
url: '',
__typename: 'Link',
},
__typename: 'Person',
} as T;
}
if (objectMetadataItem.nameSingular === 'opportunity') {
return {
id: validatedInput.id,
pipelineStepId: validatedInput.pipelineStepId,
closeDate: null,
updatedAt: new Date().toISOString(),
pipelineStep: null,
probability: '0',
pointOfContactId: null,
personId: null,
amount: {
amountMicros: null,
currencyCode: null,
__typename: 'Currency',
},
createdAt: new Date().toISOString(),
pointOfContact: null,
person: null,
company: null,
companyId: validatedInput.companyId,
__typename: 'Opportunity',
} as T;
}
if (objectMetadataItem.nameSingular === 'opportunity') {
return {
id: validatedInput.id,
pipelineStepId: validatedInput.pipelineStepId,
closeDate: null,
updatedAt: new Date().toISOString(),
pipelineStep: null,
probability: '0',
pointOfContactId: null,
personId: null,
amount: {
amountMicros: null,
currencyCode: null,
__typename: 'Currency',
},
createdAt: new Date().toISOString(),
pointOfContact: null,
person: null,
company: null,
companyId: validatedInput.companyId,
__typename: 'Opportunity',
} as T;
} }
return emptyRecord as T;
}; };
return { return {

View File

@ -7,7 +7,6 @@ import { capitalize } from '~/utils/string/capitalize';
type useUpdateOneRecordProps = { type useUpdateOneRecordProps = {
objectNameSingular: string; objectNameSingular: string;
refetchFindManyQuery?: boolean;
}; };
export const useUpdateOneRecord = <T>({ export const useUpdateOneRecord = <T>({

View File

@ -43,13 +43,11 @@ export const ColumnHead = ({ column }: ColumnHeadProps) => {
const Icon = getIcon(column.iconName); const Icon = getIcon(column.iconName);
return ( return (
<> <StyledTitle>
<StyledTitle> <StyledIcon>
<StyledIcon> <Icon size={theme.icon.size.md} />
<Icon size={theme.icon.size.md} /> </StyledIcon>
</StyledIcon> <StyledText>{column.label}</StyledText>
<StyledText>{column.label}</StyledText> </StyledTitle>
</StyledTitle>
</>
); );
}; };

View File

@ -1,3 +1,5 @@
import styled from '@emotion/styled';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
@ -14,6 +16,11 @@ type ColumnHeadWithDropdownProps = {
primaryColumnKey: string; primaryColumnKey: string;
}; };
const StyledDropdown = styled(Dropdown)`
display: flex;
flex: 1;
`;
export const ColumnHeadWithDropdown = ({ export const ColumnHeadWithDropdown = ({
column, column,
isFirstColumn, isFirstColumn,
@ -22,7 +29,7 @@ export const ColumnHeadWithDropdown = ({
}: ColumnHeadWithDropdownProps) => { }: ColumnHeadWithDropdownProps) => {
return ( return (
<DropdownScope dropdownScopeId={column.fieldMetadataId + '-header'}> <DropdownScope dropdownScopeId={column.fieldMetadataId + '-header'}>
<Dropdown <StyledDropdown
clickableComponent={<ColumnHead column={column} />} clickableComponent={<ColumnHead column={column} />}
dropdownComponents={ dropdownComponents={
<RecordTableColumnDropdownMenu <RecordTableColumnDropdownMenu

View File

@ -10,15 +10,17 @@ export const RecordTableBody = () => {
const tableRowIds = useRecoilValue(tableRowIdsState); const tableRowIds = useRecoilValue(tableRowIdsState);
return ( return (
<tbody> <>
{tableRowIds.map((rowId, rowIndex) => ( <tbody>
<RowIdContext.Provider value={rowId} key={rowId}> {tableRowIds.map((rowId, rowIndex) => (
<RowIndexContext.Provider value={rowIndex}> <RowIdContext.Provider value={rowId} key={rowId}>
<RecordTableRow key={rowId} rowId={rowId} /> <RowIndexContext.Provider value={rowIndex}>
</RowIndexContext.Provider> <RecordTableRow key={rowId} rowId={rowId} />
</RowIdContext.Provider> </RowIndexContext.Provider>
))} </RowIdContext.Provider>
))}
</tbody>
<RecordTableBodyFetchMoreLoader /> <RecordTableBodyFetchMoreLoader />
</tbody> </>
); );
}; };

View File

@ -30,11 +30,15 @@ export const RecordTableBodyFetchMoreLoader = () => {
onChange: onLastRowVisible, onChange: onLastRowVisible,
}); });
return isFetchingMoreObjects ? ( return (
<StyledRow ref={tbodyRef} selected={false}> <tbody ref={tbodyRef}>
<td style={{ height: 50 }} colSpan={1000}> {isFetchingMoreObjects ? (
Loading more... <StyledRow selected={false}>
</td> <td style={{ height: 50 }} colSpan={1000}>
</StyledRow> Loading more...
) : null; </td>
</StyledRow>
) : null}
</tbody>
);
}; };

View File

@ -0,0 +1,57 @@
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { FieldMetadataType } from '~/generated/graphql';
export const generateEmptyFieldValue = (
fieldMetadataItem: FieldMetadataItem,
) => {
switch (fieldMetadataItem.type) {
case FieldMetadataType.Email:
case FieldMetadataType.Phone:
case FieldMetadataType.Text: {
return '';
}
case FieldMetadataType.Link: {
return {
label: '',
url: '',
__typename: 'Link',
};
}
case FieldMetadataType.FullName: {
return {
firstName: '',
lastName: '',
__typename: 'FullName',
};
}
case FieldMetadataType.DateTime: {
return null;
}
case FieldMetadataType.Number:
case FieldMetadataType.Rating:
case FieldMetadataType.Numeric: {
return null;
}
case FieldMetadataType.Uuid: {
return '';
}
case FieldMetadataType.Boolean: {
return true;
}
case FieldMetadataType.Relation: {
return null;
}
case FieldMetadataType.Currency: {
return {
amountMicros: null,
currencyCode: null,
__typename: 'Currency',
};
}
case FieldMetadataType.MultiSelect:
case FieldMetadataType.Select: {
throw new Error('Not implemented yet');
}
}
};

View File

@ -5,7 +5,9 @@ export const isFieldMetadataItemAvailable = (
fieldMetadataItem: FieldMetadataItem, fieldMetadataItem: FieldMetadataItem,
) => ) =>
fieldMetadataItem.type !== 'UUID' && fieldMetadataItem.type !== 'UUID' &&
(fieldMetadataItem.type !== 'RELATION' || !(
parseFieldRelationType(fieldMetadataItem) === 'TO_ONE_OBJECT') && fieldMetadataItem.type === 'RELATION' &&
parseFieldRelationType(fieldMetadataItem) !== 'TO_ONE_OBJECT'
) &&
!fieldMetadataItem.isSystem && !fieldMetadataItem.isSystem &&
!!fieldMetadataItem.isActive; !!fieldMetadataItem.isActive;

View File

@ -111,9 +111,9 @@ export const SettingsObjectFieldPreview = ({
{objectMetadataItem?.labelPlural} {objectMetadataItem?.labelPlural}
</StyledObjectName> </StyledObjectName>
{objectMetadataItem?.isCustom ? ( {objectMetadataItem?.isCustom ? (
<Tag color="orange" text="Custom" /> <Tag color="orange" text="Custom" weight="medium" />
) : ( ) : (
<Tag color="blue" text="Standard" /> <Tag color="blue" text="Standard" weight="medium" />
)} )}
</StyledObjectSummary> </StyledObjectSummary>
<SettingsObjectFieldPreviewValueEffect <SettingsObjectFieldPreviewValueEffect

View File

@ -79,9 +79,9 @@ export const SettingsAboutSection = ({
{name} {name}
</StyledName> </StyledName>
{isCustom ? ( {isCustom ? (
<StyledTag color="orange" text="Custom" /> <StyledTag color="orange" text="Custom" weight="medium" />
) : ( ) : (
<StyledTag color="blue" text="Standard" /> <StyledTag color="blue" text="Standard" weight="medium" />
)} )}
<DropdownScope dropdownScopeId={dropdownScopeId}> <DropdownScope dropdownScopeId={dropdownScopeId}>
<Dropdown <Dropdown

View File

@ -51,9 +51,9 @@ export const SettingsObjectItemTableRow = ({
</StyledNameTableCell> </StyledNameTableCell>
<TableCell> <TableCell>
{objectItem.isCustom ? ( {objectItem.isCustom ? (
<Tag color="orange" text="Custom" /> <Tag color="orange" text="Custom" weight="medium" />
) : ( ) : (
<Tag color="blue" text="Standard" /> <Tag color="blue" text="Standard" weight="medium" />
)} )}
</TableCell> </TableCell>
<TableCell align="right"> <TableCell align="right">

View File

@ -5,6 +5,7 @@ import { themeColorSchema } from '@/ui/theme/utils/themeColorSchema';
const StyledTag = styled.h3<{ const StyledTag = styled.h3<{
color: ThemeColor; color: ThemeColor;
weight: TagWeight;
}>` }>`
align-items: center; align-items: center;
background: ${({ color, theme }) => theme.tag.background[color]}; background: ${({ color, theme }) => theme.tag.background[color]};
@ -13,7 +14,10 @@ const StyledTag = styled.h3<{
display: inline-flex; display: inline-flex;
font-size: ${({ theme }) => theme.font.size.md}; font-size: ${({ theme }) => theme.font.size.md};
font-style: normal; font-style: normal;
font-weight: ${({ theme }) => theme.font.weight.regular}; font-weight: ${({ theme, weight }) =>
weight === 'regular'
? theme.font.weight.regular
: theme.font.weight.medium};
height: ${({ theme }) => theme.spacing(5)}; height: ${({ theme }) => theme.spacing(5)};
margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
@ -26,18 +30,28 @@ const StyledContent = styled.span`
white-space: nowrap; white-space: nowrap;
`; `;
type TagWeight = 'regular' | 'medium';
type TagProps = { type TagProps = {
className?: string; className?: string;
color: ThemeColor; color: ThemeColor;
text: string; text: string;
onClick?: () => void; onClick?: () => void;
weight?: TagWeight;
}; };
export const Tag = ({ className, color, text, onClick }: TagProps) => ( export const Tag = ({
className,
color,
text,
onClick,
weight = 'regular',
}: TagProps) => (
<StyledTag <StyledTag
className={className} className={className}
color={themeColorSchema.catch('gray').parse(color)} color={themeColorSchema.catch('gray').parse(color)}
onClick={onClick} onClick={onClick}
weight={weight}
> >
<StyledContent>{text}</StyledContent> <StyledContent>{text}</StyledContent>
</StyledTag> </StyledTag>

View File

@ -102,7 +102,11 @@ export const Dropdown = ({
return ( return (
<div ref={containerRef} className={className}> <div ref={containerRef} className={className}>
{clickableComponent && ( {clickableComponent && (
<div ref={refs.setReference} onClick={toggleDropdown}> <div
ref={refs.setReference}
onClick={toggleDropdown}
className={className}
>
{clickableComponent} {clickableComponent}
</div> </div>
)} )}

View File

@ -18,7 +18,9 @@ const StyledMainContainer = styled.div`
flex-direction: row; flex-direction: row;
gap: ${({ theme }) => theme.spacing(2)}; gap: ${({ theme }) => theme.spacing(2)};
min-height: 0; min-height: 0;
padding: ${({ theme }) => theme.spacing(0, 3)}; padding-bottom: ${({ theme }) => theme.spacing(3)};
padding-left: 0;
padding-right: ${({ theme }) => theme.spacing(3)};
width: 100%; width: 100%;
@media (max-width: ${MOBILE_VIEWPORT}px) { @media (max-width: ${MOBILE_VIEWPORT}px) {

View File

@ -94,7 +94,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
{ {
name: objectMetadata.targetTableName, name: objectMetadata.targetTableName,
action: 'alter', action: 'alter',
schemaName: objectMetadata.dataSource.schema,
columns: this.workspaceMigrationFactory.createColumnActions( columns: this.workspaceMigrationFactory.createColumnActions(
WorkspaceMigrationColumnActionType.CREATE, WorkspaceMigrationColumnActionType.CREATE,
createdFieldMetadata, createdFieldMetadata,
@ -205,7 +204,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
{ {
name: objectMetadata.targetTableName, name: objectMetadata.targetTableName,
action: 'alter', action: 'alter',
schemaName: objectMetadata.dataSource.schema,
columns: this.workspaceMigrationFactory.createColumnActions( columns: this.workspaceMigrationFactory.createColumnActions(
WorkspaceMigrationColumnActionType.ALTER, WorkspaceMigrationColumnActionType.ALTER,
existingFieldMetadata, existingFieldMetadata,

View File

@ -230,13 +230,11 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
{ {
name: createdObjectMetadata.targetTableName, name: createdObjectMetadata.targetTableName,
action: 'create', action: 'create',
schemaName: createdObjectMetadata.dataSource.schema,
} satisfies WorkspaceMigrationTableAction, } satisfies WorkspaceMigrationTableAction,
// Add activity target relation // Add activity target relation
{ {
name: activityTargetObjectMetadata.targetTableName, name: activityTargetObjectMetadata.targetTableName,
action: 'alter', action: 'alter',
schemaName: activityTargetObjectMetadata.dataSource.schema,
columns: [ columns: [
{ {
action: WorkspaceMigrationColumnActionType.CREATE, action: WorkspaceMigrationColumnActionType.CREATE,
@ -249,7 +247,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
{ {
name: activityTargetObjectMetadata.targetTableName, name: activityTargetObjectMetadata.targetTableName,
action: 'alter', action: 'alter',
schemaName: activityTargetObjectMetadata.dataSource.schema,
columns: [ columns: [
{ {
action: WorkspaceMigrationColumnActionType.RELATION, action: WorkspaceMigrationColumnActionType.RELATION,
@ -263,7 +260,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
{ {
name: createdObjectMetadata.targetTableName, name: createdObjectMetadata.targetTableName,
action: 'alter', action: 'alter',
schemaName: createdObjectMetadata.dataSource.schema,
columns: [ columns: [
{ {
action: WorkspaceMigrationColumnActionType.CREATE, action: WorkspaceMigrationColumnActionType.CREATE,

View File

@ -200,9 +200,6 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
name: objectMetadataMap[relationMetadataInput.toObjectMetadataId] name: objectMetadataMap[relationMetadataInput.toObjectMetadataId]
.targetTableName, .targetTableName,
action: 'alter', action: 'alter',
schemaName:
objectMetadataMap[relationMetadataInput.toObjectMetadataId]
.dataSource.schema,
columns: [ columns: [
{ {
action: WorkspaceMigrationColumnActionType.CREATE, action: WorkspaceMigrationColumnActionType.CREATE,
@ -217,9 +214,6 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
name: objectMetadataMap[relationMetadataInput.toObjectMetadataId] name: objectMetadataMap[relationMetadataInput.toObjectMetadataId]
.targetTableName, .targetTableName,
action: 'alter', action: 'alter',
schemaName:
objectMetadataMap[relationMetadataInput.toObjectMetadataId]
.dataSource.schema,
columns: [ columns: [
{ {
action: WorkspaceMigrationColumnActionType.RELATION, action: WorkspaceMigrationColumnActionType.RELATION,

View File

@ -39,7 +39,6 @@ export type WorkspaceMigrationColumnRelation = {
columnName: string; columnName: string;
referencedTableName: string; referencedTableName: string;
referencedTableColumnName: string; referencedTableColumnName: string;
referencedSchema?: string;
isUnique?: boolean; isUnique?: boolean;
}; };
@ -60,7 +59,6 @@ export type WorkspaceMigrationColumnAction = {
export type WorkspaceMigrationTableAction = { export type WorkspaceMigrationTableAction = {
name: string; name: string;
action: 'create' | 'alter'; action: 'create' | 'alter';
schemaName: string;
columns?: WorkspaceMigrationColumnAction[]; columns?: WorkspaceMigrationColumnAction[];
}; };

View File

@ -63,11 +63,13 @@ export class WorkspaceMigrationRunnerService {
}, []); }, []);
const queryRunner = workspaceDataSource?.createQueryRunner(); const queryRunner = workspaceDataSource?.createQueryRunner();
const schemaName =
this.workspaceDataSourceService.getSchemaName(workspaceId);
// Loop over each migration and create or update the table // Loop over each migration and create or update the table
// TODO: Should be done in a transaction // TODO: Should be done in a transaction
for (const migration of flattenedPendingMigrations) { for (const migration of flattenedPendingMigrations) {
await this.handleTableChanges(queryRunner, migration); await this.handleTableChanges(queryRunner, schemaName, migration);
} }
// Update appliedAt date for each migration // Update appliedAt date for each migration
@ -96,20 +98,17 @@ export class WorkspaceMigrationRunnerService {
*/ */
private async handleTableChanges( private async handleTableChanges(
queryRunner: QueryRunner, queryRunner: QueryRunner,
schemaName: string,
tableMigration: WorkspaceMigrationTableAction, tableMigration: WorkspaceMigrationTableAction,
) { ) {
switch (tableMigration.action) { switch (tableMigration.action) {
case 'create': case 'create':
await this.createTable( await this.createTable(queryRunner, schemaName, tableMigration.name);
queryRunner,
tableMigration.schemaName,
tableMigration.name,
);
break; break;
case 'alter': case 'alter':
await this.handleColumnChanges( await this.handleColumnChanges(
queryRunner, queryRunner,
tableMigration.schemaName, schemaName,
tableMigration.name, tableMigration.name,
tableMigration?.columns, tableMigration?.columns,
); );
@ -293,7 +292,6 @@ export class WorkspaceMigrationRunnerService {
new TableForeignKey({ new TableForeignKey({
columnNames: [migrationColumn.columnName], columnNames: [migrationColumn.columnName],
referencedColumnNames: [migrationColumn.referencedTableColumnName], referencedColumnNames: [migrationColumn.referencedTableColumnName],
referencedSchema: migrationColumn.referencedSchema,
referencedTableName: migrationColumn.referencedTableName, referencedTableName: migrationColumn.referencedTableName,
onDelete: 'CASCADE', onDelete: 'CASCADE',
}), }),

View File

@ -92,8 +92,8 @@ export class CompanyObjectMetadata extends BaseObjectMetadata {
description: description:
'Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you', 'Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you',
icon: 'IconTarget', icon: 'IconTarget',
defaultValue: { value: false },
}) })
@IsNullable()
idealCustomerProfile: boolean; idealCustomerProfile: boolean;
// Relations // Relations

View File

@ -393,7 +393,6 @@ export class WorkspaceSyncMetadataService {
{ {
name: object.targetTableName, name: object.targetTableName,
action: 'create', action: 'create',
schemaName: object.dataSource.schema,
} satisfies WorkspaceMigrationTableAction, } satisfies WorkspaceMigrationTableAction,
...Object.values(object.fields) ...Object.values(object.fields)
.filter((field) => field.type !== FieldMetadataType.RELATION) .filter((field) => field.type !== FieldMetadataType.RELATION)
@ -402,7 +401,6 @@ export class WorkspaceSyncMetadataService {
({ ({
name: object.targetTableName, name: object.targetTableName,
action: 'alter', action: 'alter',
schemaName: object.dataSource.schema,
columns: this.workspaceMigrationFactory.createColumnActions( columns: this.workspaceMigrationFactory.createColumnActions(
WorkspaceMigrationColumnActionType.CREATE, WorkspaceMigrationColumnActionType.CREATE,
field, field,
@ -434,8 +432,6 @@ export class WorkspaceSyncMetadataService {
{ {
name: objectsInDbById[field.objectMetadataId].targetTableName, name: objectsInDbById[field.objectMetadataId].targetTableName,
action: 'alter', action: 'alter',
schemaName:
objectsInDbById[field.objectMetadataId].dataSource.schema,
columns: this.workspaceMigrationFactory.createColumnActions( columns: this.workspaceMigrationFactory.createColumnActions(
WorkspaceMigrationColumnActionType.CREATE, WorkspaceMigrationColumnActionType.CREATE,
field, field,
@ -457,8 +453,6 @@ export class WorkspaceSyncMetadataService {
{ {
name: objectsInDbById[field.objectMetadataId].targetTableName, name: objectsInDbById[field.objectMetadataId].targetTableName,
action: 'alter', action: 'alter',
schemaName:
objectsInDbById[field.objectMetadataId].dataSource.schema,
columns: [ columns: [
{ {
action: WorkspaceMigrationColumnActionType.DROP, action: WorkspaceMigrationColumnActionType.DROP,
@ -524,13 +518,11 @@ export class WorkspaceSyncMetadataService {
{ {
name: toObjectMetadata.targetTableName, name: toObjectMetadata.targetTableName,
action: 'alter', action: 'alter',
schemaName: toObjectMetadata.dataSource.schema,
columns: [ columns: [
{ {
action: WorkspaceMigrationColumnActionType.RELATION, action: WorkspaceMigrationColumnActionType.RELATION,
columnName: `${camelCase(toFieldMetadata.name)}Id`, columnName: `${camelCase(toFieldMetadata.name)}Id`,
referencedTableName: fromObjectMetadata.targetTableName, referencedTableName: fromObjectMetadata.targetTableName,
referencedSchema: fromObjectMetadata.dataSource.schema,
referencedTableColumnName: 'id', referencedTableColumnName: 'id',
isUnique: isUnique:
relation.relationType === RelationMetadataType.ONE_TO_ONE, relation.relationType === RelationMetadataType.ONE_TO_ONE,