Chart editor - Part 1 (#14820)
This PR is the first part of the creation of the Chart editor. https://github.com/user-attachments/assets/8b0af8ea-be41-4506-84cb-e40f5521cbf0 Done: - Bar chart settings (except filters) - Line chart settings (except filters) In progress: - Pie chart settings - Number chart settings - Gauge chart settings Left to do: - Loosen the backend validation to allow the user to save a partial configuration, validate the graph configuration in the frontend and display a error friendly message in the graph if the config is not completed yet - Implement the filter edition - Finish the other graph types settings
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
import { registerEnumType } from '@nestjs/graphql';
|
||||
|
||||
import { AggregateOperations } from './aggregate-operations.constant';
|
||||
|
||||
export enum ExtendedAggregateOperations {
|
||||
MIN = AggregateOperations.MIN,
|
||||
MAX = AggregateOperations.MAX,
|
||||
AVG = AggregateOperations.AVG,
|
||||
SUM = AggregateOperations.SUM,
|
||||
COUNT = AggregateOperations.COUNT,
|
||||
COUNT_UNIQUE_VALUES = AggregateOperations.COUNT_UNIQUE_VALUES,
|
||||
COUNT_EMPTY = AggregateOperations.COUNT_EMPTY,
|
||||
COUNT_NOT_EMPTY = AggregateOperations.COUNT_NOT_EMPTY,
|
||||
COUNT_TRUE = AggregateOperations.COUNT_TRUE,
|
||||
COUNT_FALSE = AggregateOperations.COUNT_FALSE,
|
||||
PERCENTAGE_EMPTY = AggregateOperations.PERCENTAGE_EMPTY,
|
||||
PERCENTAGE_NOT_EMPTY = AggregateOperations.PERCENTAGE_NOT_EMPTY,
|
||||
EARLIEST = 'EARLIEST',
|
||||
LATEST = 'LATEST',
|
||||
}
|
||||
|
||||
registerEnumType(ExtendedAggregateOperations, {
|
||||
name: 'ExtendedAggregateOperations',
|
||||
});
|
||||
+15
-14
@@ -14,10 +14,11 @@ import { GraphQLJSON } from 'graphql-type-json';
|
||||
|
||||
import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
|
||||
import { GraphOrderBy } from 'src/engine/core-modules/page-layout/enums/graph-order-by.enum';
|
||||
import { ExtendedAggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/extended-aggregate-operations.constant';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { AxisNameDisplay } from 'src/engine/core-modules/page-layout/enums/axis-name-display.enum';
|
||||
import { GraphOrderBy } from 'src/engine/core-modules/page-layout/enums/graph-order-by.enum';
|
||||
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
|
||||
|
||||
@ObjectType('BarChartConfiguration')
|
||||
export class BarChartConfigurationDTO {
|
||||
@@ -31,10 +32,10 @@ export class BarChartConfigurationDTO {
|
||||
@IsNotEmpty()
|
||||
aggregateFieldMetadataId: string;
|
||||
|
||||
@Field(() => AggregateOperations)
|
||||
@IsEnum(AggregateOperations)
|
||||
@Field(() => ExtendedAggregateOperations)
|
||||
@IsEnum(ExtendedAggregateOperations)
|
||||
@IsNotEmpty()
|
||||
aggregateOperation: AggregateOperations;
|
||||
aggregateOperation: ExtendedAggregateOperations;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsUUID()
|
||||
@@ -61,15 +62,15 @@ export class BarChartConfigurationDTO {
|
||||
@IsOptional()
|
||||
omitNullValues?: boolean;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
xAxisName?: string;
|
||||
@Field(() => AxisNameDisplay)
|
||||
@IsEnum(AxisNameDisplay)
|
||||
@IsNotEmpty()
|
||||
axisNameDisplay: AxisNameDisplay;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
yAxisName?: string;
|
||||
@Field(() => Boolean)
|
||||
@IsBoolean()
|
||||
@IsNotEmpty()
|
||||
displayDataLabel: boolean;
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
@IsNumber()
|
||||
|
||||
+13
-13
@@ -1,6 +1,7 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import {
|
||||
IsBoolean,
|
||||
IsEnum,
|
||||
IsNotEmpty,
|
||||
IsObject,
|
||||
@@ -12,9 +13,9 @@ import { GraphQLJSON } from 'graphql-type-json';
|
||||
|
||||
import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
|
||||
import { ExtendedAggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/extended-aggregate-operations.constant';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
|
||||
|
||||
@ObjectType('GaugeChartConfiguration')
|
||||
export class GaugeChartConfigurationDTO {
|
||||
@@ -28,20 +29,19 @@ export class GaugeChartConfigurationDTO {
|
||||
@IsNotEmpty()
|
||||
aggregateFieldMetadataId: string;
|
||||
|
||||
@Field(() => AggregateOperations)
|
||||
@IsEnum(AggregateOperations)
|
||||
@Field(() => ExtendedAggregateOperations)
|
||||
@IsEnum(ExtendedAggregateOperations)
|
||||
@IsNotEmpty()
|
||||
aggregateOperation: AggregateOperations;
|
||||
aggregateOperation: ExtendedAggregateOperations;
|
||||
|
||||
@Field(() => AggregateOperations)
|
||||
@IsEnum(AggregateOperations)
|
||||
@IsNotEmpty()
|
||||
aggregateOperationTotal: AggregateOperations;
|
||||
@Field(() => Boolean)
|
||||
@IsBoolean()
|
||||
displayDataLabel: boolean;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
aggregateFieldMetadataIdTotal: string;
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
color?: string;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
|
||||
+13
-12
@@ -14,8 +14,9 @@ import { GraphQLJSON } from 'graphql-type-json';
|
||||
|
||||
import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { ExtendedAggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/extended-aggregate-operations.constant';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { AxisNameDisplay } from 'src/engine/core-modules/page-layout/enums/axis-name-display.enum';
|
||||
import { GraphOrderBy } from 'src/engine/core-modules/page-layout/enums/graph-order-by.enum';
|
||||
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
|
||||
|
||||
@@ -31,10 +32,10 @@ export class LineChartConfigurationDTO {
|
||||
@IsNotEmpty()
|
||||
aggregateFieldMetadataId: string;
|
||||
|
||||
@Field(() => AggregateOperations)
|
||||
@IsEnum(AggregateOperations)
|
||||
@Field(() => ExtendedAggregateOperations)
|
||||
@IsEnum(ExtendedAggregateOperations)
|
||||
@IsNotEmpty()
|
||||
aggregateOperation: AggregateOperations;
|
||||
aggregateOperation: ExtendedAggregateOperations;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsUUID()
|
||||
@@ -61,15 +62,15 @@ export class LineChartConfigurationDTO {
|
||||
@IsOptional()
|
||||
omitNullValues?: boolean;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
xAxisName?: string;
|
||||
@Field(() => AxisNameDisplay)
|
||||
@IsEnum(AxisNameDisplay)
|
||||
@IsNotEmpty()
|
||||
axisNameDisplay: AxisNameDisplay;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
yAxisName?: string;
|
||||
@Field(() => Boolean)
|
||||
@IsBoolean()
|
||||
@IsNotEmpty()
|
||||
displayDataLabel: boolean;
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
@IsNumber()
|
||||
|
||||
+11
-5
@@ -1,6 +1,7 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import {
|
||||
IsBoolean,
|
||||
IsEnum,
|
||||
IsNotEmpty,
|
||||
IsObject,
|
||||
@@ -12,9 +13,9 @@ import { GraphQLJSON } from 'graphql-type-json';
|
||||
|
||||
import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
|
||||
import { ExtendedAggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/extended-aggregate-operations.constant';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
|
||||
|
||||
@ObjectType('NumberChartConfiguration')
|
||||
export class NumberChartConfigurationDTO {
|
||||
@@ -28,16 +29,21 @@ export class NumberChartConfigurationDTO {
|
||||
@IsNotEmpty()
|
||||
aggregateFieldMetadataId: string;
|
||||
|
||||
@Field(() => AggregateOperations)
|
||||
@IsEnum(AggregateOperations)
|
||||
@Field(() => ExtendedAggregateOperations)
|
||||
@IsEnum(ExtendedAggregateOperations)
|
||||
@IsNotEmpty()
|
||||
aggregateOperation: AggregateOperations;
|
||||
aggregateOperation: ExtendedAggregateOperations;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
label?: string;
|
||||
|
||||
@Field(() => Boolean)
|
||||
@IsBoolean()
|
||||
@IsNotEmpty()
|
||||
displayDataLabel: boolean;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
|
||||
+12
-6
@@ -1,6 +1,7 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import {
|
||||
IsBoolean,
|
||||
IsEnum,
|
||||
IsNotEmpty,
|
||||
IsObject,
|
||||
@@ -12,10 +13,10 @@ import { GraphQLJSON } from 'graphql-type-json';
|
||||
|
||||
import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
|
||||
import { GraphOrderBy } from 'src/engine/core-modules/page-layout/enums/graph-order-by.enum';
|
||||
import { ExtendedAggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/extended-aggregate-operations.constant';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { GraphOrderBy } from 'src/engine/core-modules/page-layout/enums/graph-order-by.enum';
|
||||
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
|
||||
|
||||
@ObjectType('PieChartConfiguration')
|
||||
export class PieChartConfigurationDTO {
|
||||
@@ -29,10 +30,10 @@ export class PieChartConfigurationDTO {
|
||||
@IsNotEmpty()
|
||||
aggregateFieldMetadataId: string;
|
||||
|
||||
@Field(() => AggregateOperations)
|
||||
@IsEnum(AggregateOperations)
|
||||
@Field(() => ExtendedAggregateOperations)
|
||||
@IsEnum(ExtendedAggregateOperations)
|
||||
@IsNotEmpty()
|
||||
aggregateOperation: AggregateOperations;
|
||||
aggregateOperation: ExtendedAggregateOperations;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsUUID()
|
||||
@@ -44,6 +45,11 @@ export class PieChartConfigurationDTO {
|
||||
@IsNotEmpty()
|
||||
orderBy: GraphOrderBy;
|
||||
|
||||
@Field(() => Boolean)
|
||||
@IsBoolean()
|
||||
@IsNotEmpty()
|
||||
displayDataLabel: boolean;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { registerEnumType } from '@nestjs/graphql';
|
||||
|
||||
export enum AxisNameDisplay {
|
||||
NONE = 'NONE',
|
||||
X = 'X',
|
||||
Y = 'Y',
|
||||
BOTH = 'BOTH',
|
||||
}
|
||||
|
||||
registerEnumType(AxisNameDisplay, {
|
||||
name: 'AxisNameDisplay',
|
||||
description: 'Which axes should display labels',
|
||||
});
|
||||
+25
-2
@@ -1,6 +1,7 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { AxisNameDisplay } from 'src/engine/core-modules/page-layout/enums/axis-name-display.enum';
|
||||
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { PAGE_LAYOUT_TAB_SEEDS } from 'src/engine/workspace-manager/dev-seeder/core/constants/page-layout-tab-seeds.constant';
|
||||
@@ -94,6 +95,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
graphType: 'NUMBER',
|
||||
aggregateFieldMetadataId: opportunityAmountFieldId,
|
||||
aggregateOperation: AggregateOperations.SUM,
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: opportunityObject?.id ?? null,
|
||||
@@ -115,6 +117,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
graphType: 'NUMBER',
|
||||
aggregateFieldMetadataId: rocketIdFieldId,
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: rocketObject?.id ?? null,
|
||||
@@ -140,6 +143,8 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
aggregateOperation: AggregateOperations.SUM,
|
||||
groupByFieldMetadataIdX: opportunityCloseDateFieldId,
|
||||
orderByX: 'FIELD_ASC',
|
||||
axisNameDisplay: AxisNameDisplay.NONE,
|
||||
displayDataLabel: false,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: opportunityObject?.id ?? null,
|
||||
@@ -165,6 +170,8 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
aggregateOperation: AggregateOperations.SUM,
|
||||
groupByFieldMetadataIdX: opportunityStageFieldId,
|
||||
orderByX: 'FIELD_DESC',
|
||||
axisNameDisplay: AxisNameDisplay.NONE,
|
||||
displayDataLabel: false,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: opportunityObject?.id ?? null,
|
||||
@@ -191,6 +198,8 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
groupByFieldMetadataIdX: rocketCreatedAtFieldId,
|
||||
orderByX: 'FIELD_ASC',
|
||||
axisNameDisplay: AxisNameDisplay.NONE,
|
||||
displayDataLabel: false,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: rocketObject?.id ?? null,
|
||||
@@ -212,6 +221,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
graphType: 'NUMBER',
|
||||
aggregateFieldMetadataId: opportunityIdFieldId,
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: opportunityObject?.id ?? null,
|
||||
@@ -235,6 +245,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
graphType: 'NUMBER',
|
||||
aggregateFieldMetadataId: companyIdFieldId,
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: companyObject?.id ?? null,
|
||||
@@ -259,6 +270,8 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
groupByFieldMetadataIdX: companyCreatedAtFieldId,
|
||||
orderByX: 'FIELD_ASC',
|
||||
axisNameDisplay: AxisNameDisplay.NONE,
|
||||
displayDataLabel: false,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: companyObject?.id ?? null,
|
||||
@@ -283,6 +296,8 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
groupByFieldMetadataIdX: companyEmployeesFieldId,
|
||||
orderByX: 'FIELD_ASC',
|
||||
axisNameDisplay: AxisNameDisplay.NONE,
|
||||
displayDataLabel: false,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: companyObject?.id ?? null,
|
||||
@@ -306,6 +321,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
graphType: 'NUMBER',
|
||||
aggregateFieldMetadataId: companyArrFieldId,
|
||||
aggregateOperation: AggregateOperations.SUM,
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: companyObject?.id ?? null,
|
||||
@@ -330,6 +346,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
aggregateOperation: AggregateOperations.SUM,
|
||||
groupByFieldMetadataId: companyNameFieldId,
|
||||
orderBy: 'VALUE_DESC',
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: companyObject?.id ?? null,
|
||||
@@ -351,8 +368,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
graphType: 'GAUGE',
|
||||
aggregateFieldMetadataId: companyArrFieldId,
|
||||
aggregateOperation: AggregateOperations.AVG,
|
||||
aggregateFieldMetadataIdTotal: companyArrFieldId,
|
||||
aggregateOperationTotal: AggregateOperations.MAX,
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: companyObject?.id ?? null,
|
||||
@@ -374,6 +390,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
graphType: 'NUMBER',
|
||||
aggregateFieldMetadataId: companyLinkedinLinkFieldId,
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: companyObject?.id ?? null,
|
||||
@@ -398,6 +415,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
groupByFieldMetadataId: companyLinkedinLinkFieldId,
|
||||
orderBy: 'VALUE_DESC',
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: companyObject?.id ?? null,
|
||||
@@ -418,6 +436,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
graphType: 'NUMBER',
|
||||
aggregateFieldMetadataId: personIdFieldId,
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: personObject?.id ?? null,
|
||||
@@ -442,6 +461,8 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
groupByFieldMetadataIdX: personCityFieldId,
|
||||
orderByX: 'FIELD_DESC',
|
||||
axisNameDisplay: AxisNameDisplay.NONE,
|
||||
displayDataLabel: false,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: personObject?.id ?? null,
|
||||
@@ -468,6 +489,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
groupByFieldMetadataId: personJobTitleFieldId,
|
||||
orderBy: 'VALUE_DESC',
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: personObject?.id ?? null,
|
||||
@@ -486,6 +508,7 @@ export const getPageLayoutWidgetDataSeeds = (
|
||||
graphType: 'NUMBER',
|
||||
aggregateFieldMetadataId: taskIdFieldId,
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
displayDataLabel: true,
|
||||
}
|
||||
: null,
|
||||
objectMetadataId: taskObject?.id ?? null,
|
||||
|
||||
Reference in New Issue
Block a user