Add createdBy field on custom object creation (#6529)
In this PR, I'm: - adding createdBy field (type ACTOR) on custom objects when created - moving `name` and `position` default column to the set of columns automatically creation on object creation - fixing a bug on mutations (update / create), if the targetted object has a 'data' custom field, it was conflicting with the payload ==> I feel we need to refactor this part of the code but we can keep this for a bit later as we plan to move out of pg_graphql <img width="1198" alt="image" src="https://github.com/user-attachments/assets/891c4a97-bab1-415c-8551-dabd5996a794">
This commit is contained in:
@ -90,6 +90,7 @@ export const generateEmptyFieldValue = (
|
|||||||
case FieldMetadataType.Actor: {
|
case FieldMetadataType.Actor: {
|
||||||
return {
|
return {
|
||||||
source: 'MANUAL',
|
source: 'MANUAL',
|
||||||
|
workspaceMemberId: null,
|
||||||
name: '',
|
name: '',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,15 +2,15 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface';
|
|
||||||
import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
|
import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
|
||||||
|
import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface';
|
||||||
import { CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
import { CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||||
|
|
||||||
import { stringifyWithoutKeyQuote } from 'src/engine/api/graphql/workspace-query-builder/utils/stringify-without-key-quote.util';
|
import { stringifyWithoutKeyQuote } from 'src/engine/api/graphql/workspace-query-builder/utils/stringify-without-key-quote.util';
|
||||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||||
|
|
||||||
import { FieldsStringFactory } from './fields-string.factory';
|
|
||||||
import { ArgsAliasFactory } from './args-alias.factory';
|
import { ArgsAliasFactory } from './args-alias.factory';
|
||||||
|
import { FieldsStringFactory } from './fields-string.factory';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreateManyQueryFactory {
|
export class CreateManyQueryFactory {
|
||||||
@ -30,8 +30,9 @@ export class CreateManyQueryFactory {
|
|||||||
options.fieldMetadataCollection,
|
options.fieldMetadataCollection,
|
||||||
options.objectMetadataCollection,
|
options.objectMetadataCollection,
|
||||||
);
|
);
|
||||||
const computedArgs = this.argsAliasFactory.create(
|
|
||||||
args,
|
const computedArgsData = this.argsAliasFactory.create(
|
||||||
|
args.data,
|
||||||
options.fieldMetadataCollection,
|
options.fieldMetadataCollection,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ export class CreateManyQueryFactory {
|
|||||||
insertInto${computeObjectTargetTable(
|
insertInto${computeObjectTargetTable(
|
||||||
options.objectMetadataItem,
|
options.objectMetadataItem,
|
||||||
)}Collection(objects: ${stringifyWithoutKeyQuote(
|
)}Collection(objects: ${stringifyWithoutKeyQuote(
|
||||||
computedArgs.data.map((datum) => ({
|
computedArgsData.map((datum) => ({
|
||||||
id: uuidv4(),
|
id: uuidv4(),
|
||||||
...datum,
|
...datum,
|
||||||
})),
|
})),
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
|
||||||
import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface';
|
|
||||||
import {
|
import {
|
||||||
RecordFilter,
|
RecordFilter,
|
||||||
RecordOrderBy,
|
RecordOrderBy,
|
||||||
} from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
|
} from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
|
||||||
|
import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface';
|
||||||
import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||||
|
|
||||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||||
|
|||||||
@ -7,9 +7,9 @@ import {
|
|||||||
import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface';
|
import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface';
|
||||||
import { UpdateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
import { UpdateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||||
|
|
||||||
import { stringifyWithoutKeyQuote } from 'src/engine/api/graphql/workspace-query-builder/utils/stringify-without-key-quote.util';
|
|
||||||
import { FieldsStringFactory } from 'src/engine/api/graphql/workspace-query-builder/factories/fields-string.factory';
|
|
||||||
import { ArgsAliasFactory } from 'src/engine/api/graphql/workspace-query-builder/factories/args-alias.factory';
|
import { ArgsAliasFactory } from 'src/engine/api/graphql/workspace-query-builder/factories/args-alias.factory';
|
||||||
|
import { FieldsStringFactory } from 'src/engine/api/graphql/workspace-query-builder/factories/fields-string.factory';
|
||||||
|
import { stringifyWithoutKeyQuote } from 'src/engine/api/graphql/workspace-query-builder/utils/stringify-without-key-quote.util';
|
||||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||||
|
|
||||||
export interface UpdateManyQueryFactoryOptions
|
export interface UpdateManyQueryFactoryOptions
|
||||||
@ -37,13 +37,13 @@ export class UpdateManyQueryFactory {
|
|||||||
options.objectMetadataCollection,
|
options.objectMetadataCollection,
|
||||||
);
|
);
|
||||||
|
|
||||||
const computedArgs = this.argsAliasFactory.create(
|
const computedArgsData = this.argsAliasFactory.create(
|
||||||
args,
|
args.data,
|
||||||
options.fieldMetadataCollection,
|
options.fieldMetadataCollection,
|
||||||
);
|
);
|
||||||
|
|
||||||
const argsData = {
|
const argsData = {
|
||||||
...computedArgs.data,
|
...computedArgsData,
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import { Injectable, Logger } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
|
||||||
import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface';
|
|
||||||
import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
|
import { Record as IRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/record.interface';
|
||||||
|
import { WorkspaceQueryBuilderOptions } from 'src/engine/api/graphql/workspace-query-builder/interfaces/workspace-query-builder-options.interface';
|
||||||
import { UpdateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
import { UpdateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||||
|
|
||||||
import { stringifyWithoutKeyQuote } from 'src/engine/api/graphql/workspace-query-builder/utils/stringify-without-key-quote.util';
|
import { stringifyWithoutKeyQuote } from 'src/engine/api/graphql/workspace-query-builder/utils/stringify-without-key-quote.util';
|
||||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||||
|
|
||||||
import { FieldsStringFactory } from './fields-string.factory';
|
|
||||||
import { ArgsAliasFactory } from './args-alias.factory';
|
import { ArgsAliasFactory } from './args-alias.factory';
|
||||||
|
import { FieldsStringFactory } from './fields-string.factory';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UpdateOneQueryFactory {
|
export class UpdateOneQueryFactory {
|
||||||
@ -28,13 +28,14 @@ export class UpdateOneQueryFactory {
|
|||||||
options.fieldMetadataCollection,
|
options.fieldMetadataCollection,
|
||||||
options.objectMetadataCollection,
|
options.objectMetadataCollection,
|
||||||
);
|
);
|
||||||
const computedArgs = this.argsAliasFactory.create(
|
|
||||||
args,
|
const computedArgsData = this.argsAliasFactory.create(
|
||||||
|
args.data,
|
||||||
options.fieldMetadataCollection,
|
options.fieldMetadataCollection,
|
||||||
);
|
);
|
||||||
|
|
||||||
const argsData = {
|
const argsData = {
|
||||||
...computedArgs.data,
|
...computedArgsData,
|
||||||
id: undefined, // do not allow updating an existing object's id
|
id: undefined, // do not allow updating an existing object's id
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
@ -45,7 +46,7 @@ export class UpdateOneQueryFactory {
|
|||||||
options.objectMetadataItem,
|
options.objectMetadataItem,
|
||||||
)}Collection(set: ${stringifyWithoutKeyQuote(
|
)}Collection(set: ${stringifyWithoutKeyQuote(
|
||||||
argsData,
|
argsData,
|
||||||
)}, filter: { id: { eq: "${computedArgs.id}" } }) {
|
)}, filter: { id: { eq: "${args.id}" } }) {
|
||||||
affectedCount
|
affectedCount
|
||||||
records {
|
records {
|
||||||
${fieldsString}
|
${fieldsString}
|
||||||
|
|||||||
@ -265,6 +265,20 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
|||||||
workspaceId: objectMetadataInput.workspaceId,
|
workspaceId: objectMetadataInput.workspaceId,
|
||||||
defaultValue: 'now',
|
defaultValue: 'now',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.createdBy,
|
||||||
|
type: FieldMetadataType.ACTOR,
|
||||||
|
name: 'createdBy',
|
||||||
|
label: 'Created By',
|
||||||
|
icon: 'IconCreativeCommonsSa',
|
||||||
|
description: 'The creator of the record',
|
||||||
|
isNullable: false,
|
||||||
|
isActive: true,
|
||||||
|
isCustom: false,
|
||||||
|
isSystem: false,
|
||||||
|
workspaceId: objectMetadataInput.workspaceId,
|
||||||
|
defaultValue: { name: "''", source: "'MANUAL'" },
|
||||||
|
},
|
||||||
{
|
{
|
||||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.position,
|
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.position,
|
||||||
type: FieldMetadataType.POSITION,
|
type: FieldMetadataType.POSITION,
|
||||||
|
|||||||
@ -208,31 +208,4 @@ export const buildMigrationsForCustomObjectRelations = (
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: computeObjectTargetTable(createdObjectMetadata),
|
|
||||||
action: WorkspaceMigrationTableActionType.ALTER,
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
action: WorkspaceMigrationColumnActionType.CREATE,
|
|
||||||
columnName: 'position',
|
|
||||||
columnType: 'float',
|
|
||||||
isNullable: true,
|
|
||||||
defaultValue: null,
|
|
||||||
} satisfies WorkspaceMigrationColumnCreate,
|
|
||||||
],
|
|
||||||
} satisfies WorkspaceMigrationTableAction,
|
|
||||||
// This is temporary until we implement mainIdentifier
|
|
||||||
{
|
|
||||||
name: computeObjectTargetTable(createdObjectMetadata),
|
|
||||||
action: WorkspaceMigrationTableActionType.ALTER,
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
action: WorkspaceMigrationColumnActionType.CREATE,
|
|
||||||
columnName: 'name',
|
|
||||||
columnType: 'text',
|
|
||||||
defaultValue: "'Untitled'",
|
|
||||||
isNullable: false,
|
|
||||||
} satisfies WorkspaceMigrationColumnCreate,
|
|
||||||
],
|
|
||||||
} satisfies WorkspaceMigrationTableAction,
|
|
||||||
];
|
];
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
import { TableColumnOptions } from 'typeorm';
|
import { TableColumnOptions } from 'typeorm';
|
||||||
|
|
||||||
export const customTableDefaultColumns: TableColumnOptions[] = [
|
import { FieldActorSource } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
|
||||||
|
|
||||||
|
export const customTableDefaultColumns = (
|
||||||
|
tableName: string,
|
||||||
|
): TableColumnOptions[] => [
|
||||||
{
|
{
|
||||||
name: 'id',
|
name: 'id',
|
||||||
type: 'uuid',
|
type: 'uuid',
|
||||||
@ -22,4 +26,30 @@ export const customTableDefaultColumns: TableColumnOptions[] = [
|
|||||||
type: 'timestamptz',
|
type: 'timestamptz',
|
||||||
isNullable: true,
|
isNullable: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'position',
|
||||||
|
type: 'float',
|
||||||
|
isNullable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text',
|
||||||
|
isNullable: false,
|
||||||
|
default: "'Untitled'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'createdBySource',
|
||||||
|
type: 'enum',
|
||||||
|
enumName: `${tableName}_createdBySource_enum`,
|
||||||
|
enum: Object.values(FieldActorSource),
|
||||||
|
isNullable: false,
|
||||||
|
default: `'${FieldActorSource.MANUAL}'`,
|
||||||
|
},
|
||||||
|
{ name: 'createdByWorkspaceMemberId', type: 'uuid', isNullable: true },
|
||||||
|
{
|
||||||
|
name: 'createdByName',
|
||||||
|
type: 'text',
|
||||||
|
isNullable: false,
|
||||||
|
default: "''",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@ -227,7 +227,7 @@ export class WorkspaceMigrationRunnerService {
|
|||||||
new Table({
|
new Table({
|
||||||
name: tableName,
|
name: tableName,
|
||||||
schema: schemaName,
|
schema: schemaName,
|
||||||
columns: customTableDefaultColumns,
|
columns: customTableDefaultColumns(tableName),
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user