mirror of
https://github.com/twentyhq/twenty.git
synced 2024-11-27 11:03:40 +03:00
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:
parent
69ffa0d229
commit
756b30815e
@ -28,7 +28,6 @@ export const ActivityBodyEditor = ({
|
||||
const [body, setBody] = useState<string | null>(null);
|
||||
const { updateOneRecord } = useUpdateOneRecord({
|
||||
objectNameSingular: 'activity',
|
||||
refetchFindManyQuery: true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -82,7 +82,6 @@ export const ActivityEditor = ({
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const { updateOneRecord: updateOneActivity } = useUpdateOneRecord<Activity>({
|
||||
objectNameSingular: 'activity',
|
||||
refetchFindManyQuery: true,
|
||||
});
|
||||
|
||||
const { FieldContextProvider: DueAtFieldContextProvider } = useFieldContext({
|
||||
|
@ -24,7 +24,6 @@ export const useOpenCreateActivityDrawer = () => {
|
||||
});
|
||||
const { createOneRecord: createOneActivity } = useCreateOneRecord<Activity>({
|
||||
objectNameSingular: 'activity',
|
||||
refetchFindManyQuery: true,
|
||||
});
|
||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
@ -10,7 +10,6 @@ import {
|
||||
IconCheckbox,
|
||||
IconSearch,
|
||||
IconSettings,
|
||||
IconTargetArrow,
|
||||
} from '@/ui/display/icon';
|
||||
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
|
||||
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
|
||||
@ -70,12 +69,6 @@ export const MainNavigationDrawerItems = () => {
|
||||
<NavigationDrawerSection>
|
||||
<NavigationDrawerSectionTitle label="Workspace" />
|
||||
<ObjectMetadataNavItems />
|
||||
<NavigationDrawerItem
|
||||
label="Opportunities"
|
||||
to="/objects/opportunities"
|
||||
active={location.pathname === '/objects/opportunities'}
|
||||
Icon={IconTargetArrow}
|
||||
/>
|
||||
</NavigationDrawerSection>
|
||||
</>
|
||||
);
|
||||
|
@ -12,20 +12,45 @@ export const ObjectMetadataNavItems = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeObjectMetadataItems.map((objectMetadataItem) =>
|
||||
objectMetadataItem.nameSingular === 'opportunity' ? null : (
|
||||
<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}`);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
{[
|
||||
...activeObjectMetadataItems
|
||||
.filter((item) =>
|
||||
['person', 'company', 'opportunity'].includes(item.nameSingular),
|
||||
)
|
||||
.sort((objectMetadataItemA, _) => {
|
||||
if (objectMetadataItemA.nameSingular === 'person') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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}`);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -38,7 +38,7 @@ const initializeValue = (
|
||||
|
||||
return {
|
||||
amount: convertCurrencyMicrosToCurrency(fieldValue.amountMicros),
|
||||
currencyCode: fieldValue.currencyCode,
|
||||
currencyCode: CurrencyCode.USD,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,6 @@ import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
type useCreateOneRecordProps = {
|
||||
objectNameSingular: string;
|
||||
refetchFindManyQuery?: boolean;
|
||||
};
|
||||
|
||||
export const useCreateOneRecord = <T>({
|
||||
@ -36,6 +35,7 @@ export const useCreateOneRecord = <T>({
|
||||
|
||||
const generatedEmptyRecord = generateEmptyRecord<Record<string, unknown>>({
|
||||
id: recordId,
|
||||
createdAt: new Date().toISOString(),
|
||||
...input,
|
||||
});
|
||||
|
||||
@ -53,7 +53,7 @@ export const useCreateOneRecord = <T>({
|
||||
},
|
||||
optimisticResponse: {
|
||||
[`create${capitalize(objectMetadataItem.nameSingular)}`]:
|
||||
generateEmptyRecord({ id: recordId, ...input }),
|
||||
generatedEmptyRecord,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { generateEmptyFieldValue } from '@/object-record/utils/generateEmptyFieldValue';
|
||||
|
||||
export const useGenerateEmptyRecord = ({
|
||||
objectMetadataItem,
|
||||
@ -10,157 +11,14 @@ export const useGenerateEmptyRecord = ({
|
||||
// Todo replace this by runtime typing
|
||||
const validatedInput = input as { id: string } & { [key: string]: any };
|
||||
|
||||
if (objectMetadataItem.nameSingular === 'company') {
|
||||
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;
|
||||
}
|
||||
const emptyRecord = {} as Record<string, any>;
|
||||
|
||||
if (objectMetadataItem.nameSingular === 'person') {
|
||||
return {
|
||||
id: validatedInput.id,
|
||||
activityTargets: {
|
||||
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;
|
||||
for (const fieldMetadataItem of objectMetadataItem.fields) {
|
||||
emptyRecord[fieldMetadataItem.name] =
|
||||
validatedInput[fieldMetadataItem.name] ??
|
||||
generateEmptyFieldValue(fieldMetadataItem);
|
||||
}
|
||||
return emptyRecord as T;
|
||||
};
|
||||
|
||||
return {
|
||||
|
@ -7,7 +7,6 @@ import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
type useUpdateOneRecordProps = {
|
||||
objectNameSingular: string;
|
||||
refetchFindManyQuery?: boolean;
|
||||
};
|
||||
|
||||
export const useUpdateOneRecord = <T>({
|
||||
|
@ -43,13 +43,11 @@ export const ColumnHead = ({ column }: ColumnHeadProps) => {
|
||||
const Icon = getIcon(column.iconName);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledTitle>
|
||||
<StyledIcon>
|
||||
<Icon size={theme.icon.size.md} />
|
||||
</StyledIcon>
|
||||
<StyledText>{column.label}</StyledText>
|
||||
</StyledTitle>
|
||||
</>
|
||||
<StyledTitle>
|
||||
<StyledIcon>
|
||||
<Icon size={theme.icon.size.md} />
|
||||
</StyledIcon>
|
||||
<StyledText>{column.label}</StyledText>
|
||||
</StyledTitle>
|
||||
);
|
||||
};
|
||||
|
@ -1,3 +1,5 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
|
||||
@ -14,6 +16,11 @@ type ColumnHeadWithDropdownProps = {
|
||||
primaryColumnKey: string;
|
||||
};
|
||||
|
||||
const StyledDropdown = styled(Dropdown)`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
export const ColumnHeadWithDropdown = ({
|
||||
column,
|
||||
isFirstColumn,
|
||||
@ -22,7 +29,7 @@ export const ColumnHeadWithDropdown = ({
|
||||
}: ColumnHeadWithDropdownProps) => {
|
||||
return (
|
||||
<DropdownScope dropdownScopeId={column.fieldMetadataId + '-header'}>
|
||||
<Dropdown
|
||||
<StyledDropdown
|
||||
clickableComponent={<ColumnHead column={column} />}
|
||||
dropdownComponents={
|
||||
<RecordTableColumnDropdownMenu
|
||||
|
@ -10,15 +10,17 @@ export const RecordTableBody = () => {
|
||||
const tableRowIds = useRecoilValue(tableRowIdsState);
|
||||
|
||||
return (
|
||||
<tbody>
|
||||
{tableRowIds.map((rowId, rowIndex) => (
|
||||
<RowIdContext.Provider value={rowId} key={rowId}>
|
||||
<RowIndexContext.Provider value={rowIndex}>
|
||||
<RecordTableRow key={rowId} rowId={rowId} />
|
||||
</RowIndexContext.Provider>
|
||||
</RowIdContext.Provider>
|
||||
))}
|
||||
<>
|
||||
<tbody>
|
||||
{tableRowIds.map((rowId, rowIndex) => (
|
||||
<RowIdContext.Provider value={rowId} key={rowId}>
|
||||
<RowIndexContext.Provider value={rowIndex}>
|
||||
<RecordTableRow key={rowId} rowId={rowId} />
|
||||
</RowIndexContext.Provider>
|
||||
</RowIdContext.Provider>
|
||||
))}
|
||||
</tbody>
|
||||
<RecordTableBodyFetchMoreLoader />
|
||||
</tbody>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -30,11 +30,15 @@ export const RecordTableBodyFetchMoreLoader = () => {
|
||||
onChange: onLastRowVisible,
|
||||
});
|
||||
|
||||
return isFetchingMoreObjects ? (
|
||||
<StyledRow ref={tbodyRef} selected={false}>
|
||||
<td style={{ height: 50 }} colSpan={1000}>
|
||||
Loading more...
|
||||
</td>
|
||||
</StyledRow>
|
||||
) : null;
|
||||
return (
|
||||
<tbody ref={tbodyRef}>
|
||||
{isFetchingMoreObjects ? (
|
||||
<StyledRow selected={false}>
|
||||
<td style={{ height: 50 }} colSpan={1000}>
|
||||
Loading more...
|
||||
</td>
|
||||
</StyledRow>
|
||||
) : null}
|
||||
</tbody>
|
||||
);
|
||||
};
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
||||
};
|
@ -5,7 +5,9 @@ export const isFieldMetadataItemAvailable = (
|
||||
fieldMetadataItem: FieldMetadataItem,
|
||||
) =>
|
||||
fieldMetadataItem.type !== 'UUID' &&
|
||||
(fieldMetadataItem.type !== 'RELATION' ||
|
||||
parseFieldRelationType(fieldMetadataItem) === 'TO_ONE_OBJECT') &&
|
||||
!(
|
||||
fieldMetadataItem.type === 'RELATION' &&
|
||||
parseFieldRelationType(fieldMetadataItem) !== 'TO_ONE_OBJECT'
|
||||
) &&
|
||||
!fieldMetadataItem.isSystem &&
|
||||
!!fieldMetadataItem.isActive;
|
||||
|
@ -111,9 +111,9 @@ export const SettingsObjectFieldPreview = ({
|
||||
{objectMetadataItem?.labelPlural}
|
||||
</StyledObjectName>
|
||||
{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>
|
||||
<SettingsObjectFieldPreviewValueEffect
|
||||
|
@ -79,9 +79,9 @@ export const SettingsAboutSection = ({
|
||||
{name}
|
||||
</StyledName>
|
||||
{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}>
|
||||
<Dropdown
|
||||
|
@ -51,9 +51,9 @@ export const SettingsObjectItemTableRow = ({
|
||||
</StyledNameTableCell>
|
||||
<TableCell>
|
||||
{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 align="right">
|
||||
|
@ -5,6 +5,7 @@ import { themeColorSchema } from '@/ui/theme/utils/themeColorSchema';
|
||||
|
||||
const StyledTag = styled.h3<{
|
||||
color: ThemeColor;
|
||||
weight: TagWeight;
|
||||
}>`
|
||||
align-items: center;
|
||||
background: ${({ color, theme }) => theme.tag.background[color]};
|
||||
@ -13,7 +14,10 @@ const StyledTag = styled.h3<{
|
||||
display: inline-flex;
|
||||
font-size: ${({ theme }) => theme.font.size.md};
|
||||
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)};
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
@ -26,18 +30,28 @@ const StyledContent = styled.span`
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
type TagWeight = 'regular' | 'medium';
|
||||
|
||||
type TagProps = {
|
||||
className?: string;
|
||||
color: ThemeColor;
|
||||
text: string;
|
||||
onClick?: () => void;
|
||||
weight?: TagWeight;
|
||||
};
|
||||
|
||||
export const Tag = ({ className, color, text, onClick }: TagProps) => (
|
||||
export const Tag = ({
|
||||
className,
|
||||
color,
|
||||
text,
|
||||
onClick,
|
||||
weight = 'regular',
|
||||
}: TagProps) => (
|
||||
<StyledTag
|
||||
className={className}
|
||||
color={themeColorSchema.catch('gray').parse(color)}
|
||||
onClick={onClick}
|
||||
weight={weight}
|
||||
>
|
||||
<StyledContent>{text}</StyledContent>
|
||||
</StyledTag>
|
||||
|
@ -102,7 +102,11 @@ export const Dropdown = ({
|
||||
return (
|
||||
<div ref={containerRef} className={className}>
|
||||
{clickableComponent && (
|
||||
<div ref={refs.setReference} onClick={toggleDropdown}>
|
||||
<div
|
||||
ref={refs.setReference}
|
||||
onClick={toggleDropdown}
|
||||
className={className}
|
||||
>
|
||||
{clickableComponent}
|
||||
</div>
|
||||
)}
|
||||
|
@ -18,7 +18,9 @@ const StyledMainContainer = styled.div`
|
||||
flex-direction: row;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
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%;
|
||||
|
||||
@media (max-width: ${MOBILE_VIEWPORT}px) {
|
||||
|
@ -94,7 +94,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
{
|
||||
name: objectMetadata.targetTableName,
|
||||
action: 'alter',
|
||||
schemaName: objectMetadata.dataSource.schema,
|
||||
columns: this.workspaceMigrationFactory.createColumnActions(
|
||||
WorkspaceMigrationColumnActionType.CREATE,
|
||||
createdFieldMetadata,
|
||||
@ -205,7 +204,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
{
|
||||
name: objectMetadata.targetTableName,
|
||||
action: 'alter',
|
||||
schemaName: objectMetadata.dataSource.schema,
|
||||
columns: this.workspaceMigrationFactory.createColumnActions(
|
||||
WorkspaceMigrationColumnActionType.ALTER,
|
||||
existingFieldMetadata,
|
||||
|
@ -230,13 +230,11 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
{
|
||||
name: createdObjectMetadata.targetTableName,
|
||||
action: 'create',
|
||||
schemaName: createdObjectMetadata.dataSource.schema,
|
||||
} satisfies WorkspaceMigrationTableAction,
|
||||
// Add activity target relation
|
||||
{
|
||||
name: activityTargetObjectMetadata.targetTableName,
|
||||
action: 'alter',
|
||||
schemaName: activityTargetObjectMetadata.dataSource.schema,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.CREATE,
|
||||
@ -249,7 +247,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
{
|
||||
name: activityTargetObjectMetadata.targetTableName,
|
||||
action: 'alter',
|
||||
schemaName: activityTargetObjectMetadata.dataSource.schema,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.RELATION,
|
||||
@ -263,7 +260,6 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
{
|
||||
name: createdObjectMetadata.targetTableName,
|
||||
action: 'alter',
|
||||
schemaName: createdObjectMetadata.dataSource.schema,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.CREATE,
|
||||
|
@ -200,9 +200,6 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
||||
name: objectMetadataMap[relationMetadataInput.toObjectMetadataId]
|
||||
.targetTableName,
|
||||
action: 'alter',
|
||||
schemaName:
|
||||
objectMetadataMap[relationMetadataInput.toObjectMetadataId]
|
||||
.dataSource.schema,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.CREATE,
|
||||
@ -217,9 +214,6 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
||||
name: objectMetadataMap[relationMetadataInput.toObjectMetadataId]
|
||||
.targetTableName,
|
||||
action: 'alter',
|
||||
schemaName:
|
||||
objectMetadataMap[relationMetadataInput.toObjectMetadataId]
|
||||
.dataSource.schema,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.RELATION,
|
||||
|
@ -39,7 +39,6 @@ export type WorkspaceMigrationColumnRelation = {
|
||||
columnName: string;
|
||||
referencedTableName: string;
|
||||
referencedTableColumnName: string;
|
||||
referencedSchema?: string;
|
||||
isUnique?: boolean;
|
||||
};
|
||||
|
||||
@ -60,7 +59,6 @@ export type WorkspaceMigrationColumnAction = {
|
||||
export type WorkspaceMigrationTableAction = {
|
||||
name: string;
|
||||
action: 'create' | 'alter';
|
||||
schemaName: string;
|
||||
columns?: WorkspaceMigrationColumnAction[];
|
||||
};
|
||||
|
||||
|
@ -63,11 +63,13 @@ export class WorkspaceMigrationRunnerService {
|
||||
}, []);
|
||||
|
||||
const queryRunner = workspaceDataSource?.createQueryRunner();
|
||||
const schemaName =
|
||||
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||
|
||||
// Loop over each migration and create or update the table
|
||||
// TODO: Should be done in a transaction
|
||||
for (const migration of flattenedPendingMigrations) {
|
||||
await this.handleTableChanges(queryRunner, migration);
|
||||
await this.handleTableChanges(queryRunner, schemaName, migration);
|
||||
}
|
||||
|
||||
// Update appliedAt date for each migration
|
||||
@ -96,20 +98,17 @@ export class WorkspaceMigrationRunnerService {
|
||||
*/
|
||||
private async handleTableChanges(
|
||||
queryRunner: QueryRunner,
|
||||
schemaName: string,
|
||||
tableMigration: WorkspaceMigrationTableAction,
|
||||
) {
|
||||
switch (tableMigration.action) {
|
||||
case 'create':
|
||||
await this.createTable(
|
||||
queryRunner,
|
||||
tableMigration.schemaName,
|
||||
tableMigration.name,
|
||||
);
|
||||
await this.createTable(queryRunner, schemaName, tableMigration.name);
|
||||
break;
|
||||
case 'alter':
|
||||
await this.handleColumnChanges(
|
||||
queryRunner,
|
||||
tableMigration.schemaName,
|
||||
schemaName,
|
||||
tableMigration.name,
|
||||
tableMigration?.columns,
|
||||
);
|
||||
@ -293,7 +292,6 @@ export class WorkspaceMigrationRunnerService {
|
||||
new TableForeignKey({
|
||||
columnNames: [migrationColumn.columnName],
|
||||
referencedColumnNames: [migrationColumn.referencedTableColumnName],
|
||||
referencedSchema: migrationColumn.referencedSchema,
|
||||
referencedTableName: migrationColumn.referencedTableName,
|
||||
onDelete: 'CASCADE',
|
||||
}),
|
||||
|
@ -92,8 +92,8 @@ export class CompanyObjectMetadata extends BaseObjectMetadata {
|
||||
description:
|
||||
'Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you',
|
||||
icon: 'IconTarget',
|
||||
defaultValue: { value: false },
|
||||
})
|
||||
@IsNullable()
|
||||
idealCustomerProfile: boolean;
|
||||
|
||||
// Relations
|
||||
|
@ -393,7 +393,6 @@ export class WorkspaceSyncMetadataService {
|
||||
{
|
||||
name: object.targetTableName,
|
||||
action: 'create',
|
||||
schemaName: object.dataSource.schema,
|
||||
} satisfies WorkspaceMigrationTableAction,
|
||||
...Object.values(object.fields)
|
||||
.filter((field) => field.type !== FieldMetadataType.RELATION)
|
||||
@ -402,7 +401,6 @@ export class WorkspaceSyncMetadataService {
|
||||
({
|
||||
name: object.targetTableName,
|
||||
action: 'alter',
|
||||
schemaName: object.dataSource.schema,
|
||||
columns: this.workspaceMigrationFactory.createColumnActions(
|
||||
WorkspaceMigrationColumnActionType.CREATE,
|
||||
field,
|
||||
@ -434,8 +432,6 @@ export class WorkspaceSyncMetadataService {
|
||||
{
|
||||
name: objectsInDbById[field.objectMetadataId].targetTableName,
|
||||
action: 'alter',
|
||||
schemaName:
|
||||
objectsInDbById[field.objectMetadataId].dataSource.schema,
|
||||
columns: this.workspaceMigrationFactory.createColumnActions(
|
||||
WorkspaceMigrationColumnActionType.CREATE,
|
||||
field,
|
||||
@ -457,8 +453,6 @@ export class WorkspaceSyncMetadataService {
|
||||
{
|
||||
name: objectsInDbById[field.objectMetadataId].targetTableName,
|
||||
action: 'alter',
|
||||
schemaName:
|
||||
objectsInDbById[field.objectMetadataId].dataSource.schema,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.DROP,
|
||||
@ -524,13 +518,11 @@ export class WorkspaceSyncMetadataService {
|
||||
{
|
||||
name: toObjectMetadata.targetTableName,
|
||||
action: 'alter',
|
||||
schemaName: toObjectMetadata.dataSource.schema,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.RELATION,
|
||||
columnName: `${camelCase(toFieldMetadata.name)}Id`,
|
||||
referencedTableName: fromObjectMetadata.targetTableName,
|
||||
referencedSchema: fromObjectMetadata.dataSource.schema,
|
||||
referencedTableColumnName: 'id',
|
||||
isUnique:
|
||||
relation.relationType === RelationMetadataType.ONE_TO_ONE,
|
||||
|
Loading…
Reference in New Issue
Block a user