fixes: loosen up front validation, add resolveEntityRelationUniversalIdentifiers to update and restore (#18015)
closes https://github.com/twentyhq/private-issues/issues/419
This commit is contained in:
+1
@@ -4,6 +4,7 @@ import {
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export type BarLineChartConvertibleFields = {
|
||||
aggregateFieldMetadataId?: string;
|
||||
primaryAxisGroupByFieldMetadataId?: string;
|
||||
primaryAxisGroupBySubFieldName?: string | null;
|
||||
primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null;
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ import {
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export type PieChartConvertibleFields = {
|
||||
aggregateFieldMetadataId?: string;
|
||||
groupByFieldMetadataId?: string;
|
||||
groupBySubFieldName?: string | null;
|
||||
dateGranularity?: ObjectRecordGroupByDateGranularity | null;
|
||||
|
||||
+7
@@ -19,6 +19,9 @@ describe('convertBarOrLineChartConfigToPieChart', () => {
|
||||
TEST_BAR_CHART_CONFIGURATION.primaryAxisGroupBySubFieldName,
|
||||
dateGranularity: TEST_BAR_CHART_CONFIGURATION.primaryAxisDateGranularity,
|
||||
orderBy: TEST_BAR_CHART_CONFIGURATION.primaryAxisOrderBy,
|
||||
splitMultiValueFields: TEST_BAR_CHART_CONFIGURATION.splitMultiValueFields,
|
||||
aggregateFieldMetadataId:
|
||||
TEST_BAR_CHART_CONFIGURATION.aggregateFieldMetadataId,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -34,6 +37,10 @@ describe('convertBarOrLineChartConfigToPieChart', () => {
|
||||
TEST_LINE_CHART_CONFIGURATION.primaryAxisGroupBySubFieldName,
|
||||
dateGranularity: TEST_LINE_CHART_CONFIGURATION.primaryAxisDateGranularity,
|
||||
orderBy: TEST_LINE_CHART_CONFIGURATION.primaryAxisOrderBy,
|
||||
splitMultiValueFields:
|
||||
TEST_LINE_CHART_CONFIGURATION.splitMultiValueFields,
|
||||
aggregateFieldMetadataId:
|
||||
TEST_LINE_CHART_CONFIGURATION.aggregateFieldMetadataId,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+6
@@ -12,12 +12,15 @@ describe('convertPieChartConfigToBarOrLineChart', () => {
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
aggregateFieldMetadataId:
|
||||
TEST_PIE_CHART_CONFIGURATION.aggregateFieldMetadataId,
|
||||
primaryAxisGroupByFieldMetadataId:
|
||||
TEST_PIE_CHART_CONFIGURATION.groupByFieldMetadataId,
|
||||
primaryAxisGroupBySubFieldName:
|
||||
TEST_PIE_CHART_CONFIGURATION.groupBySubFieldName,
|
||||
primaryAxisDateGranularity: TEST_PIE_CHART_CONFIGURATION.dateGranularity,
|
||||
primaryAxisOrderBy: TEST_PIE_CHART_CONFIGURATION.orderBy,
|
||||
splitMultiValueFields: TEST_PIE_CHART_CONFIGURATION.splitMultiValueFields,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,10 +36,13 @@ describe('convertPieChartConfigToBarOrLineChart', () => {
|
||||
const result = convertPieChartConfigToBarOrLineChart(minimalPieConfig);
|
||||
|
||||
expect(result).toEqual({
|
||||
aggregateFieldMetadataId:
|
||||
TEST_PIE_CHART_CONFIGURATION.aggregateFieldMetadataId,
|
||||
primaryAxisGroupByFieldMetadataId: undefined,
|
||||
primaryAxisGroupBySubFieldName: null,
|
||||
primaryAxisDateGranularity: null,
|
||||
primaryAxisOrderBy: null,
|
||||
splitMultiValueFields: TEST_PIE_CHART_CONFIGURATION.splitMultiValueFields,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+1
@@ -15,6 +15,7 @@ export const convertBarOrLineChartConfigToPieChart = (
|
||||
}
|
||||
|
||||
return {
|
||||
aggregateFieldMetadataId: configuration.aggregateFieldMetadataId,
|
||||
groupByFieldMetadataId: configuration.primaryAxisGroupByFieldMetadataId,
|
||||
groupBySubFieldName: configuration.primaryAxisGroupBySubFieldName,
|
||||
dateGranularity: configuration.primaryAxisDateGranularity,
|
||||
|
||||
+1
@@ -10,6 +10,7 @@ export const convertPieChartConfigToBarOrLineChart = (
|
||||
}
|
||||
|
||||
return {
|
||||
aggregateFieldMetadataId: configuration.aggregateFieldMetadataId,
|
||||
primaryAxisGroupByFieldMetadataId: configuration.groupByFieldMetadataId,
|
||||
primaryAxisGroupBySubFieldName: configuration.groupBySubFieldName,
|
||||
primaryAxisDateGranularity: configuration.dateGranularity,
|
||||
|
||||
@@ -179,6 +179,11 @@ export const WidgetRenderer = ({ widget }: WidgetRendererProps) => {
|
||||
{hasAccess ? (
|
||||
<ErrorBoundary
|
||||
FallbackComponent={PageLayoutWidgetInvalidConfigDisplay}
|
||||
resetKeys={[
|
||||
widget.id,
|
||||
widget.configuration,
|
||||
widget.objectMetadataId,
|
||||
]}
|
||||
>
|
||||
<WidgetContentRenderer widget={widget} />
|
||||
</ErrorBoundary>
|
||||
|
||||
+1
-22
@@ -1,14 +1,10 @@
|
||||
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
||||
import { PageLayoutWidgetNoDataDisplay } from '@/page-layout/widgets/components/PageLayoutWidgetNoDataDisplay';
|
||||
import { WidgetSkeletonLoader } from '@/page-layout/widgets/components/WidgetSkeletonLoader';
|
||||
import { GraphWidgetAggregateChartRenderer } from '@/page-layout/widgets/graph/graphWidgetAggregateChart/components/GraphWidgetAggregateChartRenderer';
|
||||
import { GraphWidgetBarChartRenderer } from '@/page-layout/widgets/graph/graphWidgetBarChart/components/GraphWidgetBarChartRenderer';
|
||||
import { GraphWidgetLineChartRenderer } from '@/page-layout/widgets/graph/graphWidgetLineChart/components/GraphWidgetLineChartRenderer';
|
||||
import { GraphWidgetPieChartRenderer } from '@/page-layout/widgets/graph/graphWidgetPieChart/components/GraphWidgetPieChartRenderer';
|
||||
import { areChartConfigurationFieldsValidForQuery } from '@/page-layout/widgets/graph/utils/areChartConfigurationFieldsValidForQuery';
|
||||
import { useCurrentWidget } from '@/page-layout/widgets/hooks/useCurrentWidget';
|
||||
import { lazy, Suspense } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { WidgetConfigurationType } from '~/generated-metadata/graphql';
|
||||
|
||||
const GraphWidgetGaugeChart = lazy(() =>
|
||||
@@ -19,26 +15,9 @@ const GraphWidgetGaugeChart = lazy(() =>
|
||||
})),
|
||||
);
|
||||
|
||||
export type GraphWidgetProps = {
|
||||
objectMetadataId: string;
|
||||
};
|
||||
|
||||
export const GraphWidget = ({ objectMetadataId }: GraphWidgetProps) => {
|
||||
export const GraphWidget = () => {
|
||||
const widget = useCurrentWidget();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItemById({
|
||||
objectId: objectMetadataId,
|
||||
});
|
||||
|
||||
const hasValidConfiguration = areChartConfigurationFieldsValidForQuery(
|
||||
widget.configuration,
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
if (!isDefined(widget.configuration) || !hasValidConfiguration) {
|
||||
return <PageLayoutWidgetNoDataDisplay />;
|
||||
}
|
||||
|
||||
const configurationType = widget.configuration?.configurationType;
|
||||
|
||||
switch (configurationType) {
|
||||
|
||||
+7
-6
@@ -1,6 +1,7 @@
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { PageLayoutWidgetNoDataDisplay } from '@/page-layout/widgets/components/PageLayoutWidgetNoDataDisplay';
|
||||
import { GraphWidget } from '@/page-layout/widgets/graph/components/GraphWidget';
|
||||
import { hasMinimalRequiredConfigForGraph } from '@/page-layout/widgets/graph/utils/hasMinimalRequiredConfigForGraph';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type GraphWidgetRendererProps = {
|
||||
@@ -8,13 +9,13 @@ type GraphWidgetRendererProps = {
|
||||
};
|
||||
|
||||
export const GraphWidgetRenderer = ({ widget }: GraphWidgetRendererProps) => {
|
||||
if (!isDefined(widget.configuration)) {
|
||||
if (
|
||||
!isDefined(widget.configuration) ||
|
||||
!isDefined(widget.objectMetadataId) ||
|
||||
!hasMinimalRequiredConfigForGraph(widget.configuration)
|
||||
) {
|
||||
return <PageLayoutWidgetNoDataDisplay />;
|
||||
}
|
||||
|
||||
if (!isDefined(widget.objectMetadataId)) {
|
||||
return <PageLayoutWidgetNoDataDisplay />;
|
||||
}
|
||||
|
||||
return <GraphWidget objectMetadataId={widget.objectMetadataId} />;
|
||||
return <GraphWidget />;
|
||||
};
|
||||
|
||||
-213
@@ -1,213 +0,0 @@
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import {
|
||||
AggregateOperations,
|
||||
FieldMetadataType,
|
||||
WidgetConfigurationType,
|
||||
type AggregateChartConfiguration,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
import { areChartConfigurationFieldsValidForQuery } from '@/page-layout/widgets/graph/utils/areChartConfigurationFieldsValidForQuery';
|
||||
|
||||
describe('areChartConfigurationFieldsValidForQuery', () => {
|
||||
const createMockObjectMetadataItem = (
|
||||
fields: Array<{
|
||||
id: string;
|
||||
type: FieldMetadataType;
|
||||
options?: Array<{ value: string; label: string }>;
|
||||
}>,
|
||||
): ObjectMetadataItem =>
|
||||
({
|
||||
id: 'object-1',
|
||||
nameSingular: 'opportunity',
|
||||
namePlural: 'opportunities',
|
||||
fields: fields.map((f) => ({
|
||||
id: f.id,
|
||||
name: f.id,
|
||||
type: f.type,
|
||||
label: f.id,
|
||||
options: f.options,
|
||||
})),
|
||||
}) as ObjectMetadataItem;
|
||||
|
||||
const createAggregateConfig = (ratioAggregateConfig?: {
|
||||
fieldMetadataId: string;
|
||||
optionValue: string;
|
||||
}): AggregateChartConfiguration => ({
|
||||
__typename: 'AggregateChartConfiguration',
|
||||
configurationType: WidgetConfigurationType.AGGREGATE_CHART,
|
||||
aggregateFieldMetadataId: 'aggregate-field',
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
ratioAggregateConfig: ratioAggregateConfig ?? null,
|
||||
});
|
||||
|
||||
describe('AggregateChartConfiguration with ratioAggregateConfig', () => {
|
||||
it('should return true when ratioAggregateConfig is undefined', () => {
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'aggregate-field', type: FieldMetadataType.NUMBER },
|
||||
]);
|
||||
|
||||
const result = areChartConfigurationFieldsValidForQuery(
|
||||
createAggregateConfig(undefined),
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when ratio field does not exist', () => {
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'aggregate-field', type: FieldMetadataType.NUMBER },
|
||||
]);
|
||||
|
||||
const result = areChartConfigurationFieldsValidForQuery(
|
||||
createAggregateConfig({
|
||||
fieldMetadataId: 'non-existent-field',
|
||||
optionValue: 'true',
|
||||
}),
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for BOOLEAN field with "true" optionValue', () => {
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'aggregate-field', type: FieldMetadataType.NUMBER },
|
||||
{ id: 'boolean-field', type: FieldMetadataType.BOOLEAN },
|
||||
]);
|
||||
|
||||
const result = areChartConfigurationFieldsValidForQuery(
|
||||
createAggregateConfig({
|
||||
fieldMetadataId: 'boolean-field',
|
||||
optionValue: 'true',
|
||||
}),
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for BOOLEAN field with "false" optionValue', () => {
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'aggregate-field', type: FieldMetadataType.NUMBER },
|
||||
{ id: 'boolean-field', type: FieldMetadataType.BOOLEAN },
|
||||
]);
|
||||
|
||||
const result = areChartConfigurationFieldsValidForQuery(
|
||||
createAggregateConfig({
|
||||
fieldMetadataId: 'boolean-field',
|
||||
optionValue: 'false',
|
||||
}),
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for BOOLEAN field with invalid optionValue', () => {
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'aggregate-field', type: FieldMetadataType.NUMBER },
|
||||
{ id: 'boolean-field', type: FieldMetadataType.BOOLEAN },
|
||||
]);
|
||||
|
||||
const result = areChartConfigurationFieldsValidForQuery(
|
||||
createAggregateConfig({
|
||||
fieldMetadataId: 'boolean-field',
|
||||
optionValue: 'invalid',
|
||||
}),
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for SELECT field with valid option', () => {
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'aggregate-field', type: FieldMetadataType.NUMBER },
|
||||
{
|
||||
id: 'select-field',
|
||||
type: FieldMetadataType.SELECT,
|
||||
options: [
|
||||
{ value: 'WON', label: 'Won' },
|
||||
{ value: 'LOST', label: 'Lost' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const result = areChartConfigurationFieldsValidForQuery(
|
||||
createAggregateConfig({
|
||||
fieldMetadataId: 'select-field',
|
||||
optionValue: 'WON',
|
||||
}),
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for SELECT field with invalid option', () => {
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'aggregate-field', type: FieldMetadataType.NUMBER },
|
||||
{
|
||||
id: 'select-field',
|
||||
type: FieldMetadataType.SELECT,
|
||||
options: [
|
||||
{ value: 'WON', label: 'Won' },
|
||||
{ value: 'LOST', label: 'Lost' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const result = areChartConfigurationFieldsValidForQuery(
|
||||
createAggregateConfig({
|
||||
fieldMetadataId: 'select-field',
|
||||
optionValue: 'INVALID_OPTION',
|
||||
}),
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true for MULTI_SELECT field with valid option', () => {
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'aggregate-field', type: FieldMetadataType.NUMBER },
|
||||
{
|
||||
id: 'multiselect-field',
|
||||
type: FieldMetadataType.MULTI_SELECT,
|
||||
options: [
|
||||
{ value: 'urgent', label: 'Urgent' },
|
||||
{ value: 'important', label: 'Important' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const result = areChartConfigurationFieldsValidForQuery(
|
||||
createAggregateConfig({
|
||||
fieldMetadataId: 'multiselect-field',
|
||||
optionValue: 'urgent',
|
||||
}),
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for unsupported field type with ratioConfig', () => {
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'aggregate-field', type: FieldMetadataType.NUMBER },
|
||||
{ id: 'text-field', type: FieldMetadataType.TEXT },
|
||||
]);
|
||||
|
||||
const result = areChartConfigurationFieldsValidForQuery(
|
||||
createAggregateConfig({
|
||||
fieldMetadataId: 'text-field',
|
||||
optionValue: 'some-value',
|
||||
}),
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
type RatioAggregateConfig,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
const fieldExists = (
|
||||
fieldId: string | undefined | null,
|
||||
objectMetadataItem: ObjectMetadataItem,
|
||||
): boolean => {
|
||||
if (!isDefined(fieldId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return objectMetadataItem.fields.some((field) => field.id === fieldId);
|
||||
};
|
||||
|
||||
const isRatioConfigValid = (
|
||||
ratioConfig: RatioAggregateConfig | null | undefined,
|
||||
objectMetadataItem: ObjectMetadataItem,
|
||||
): boolean => {
|
||||
if (!isDefined(ratioConfig)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const field = objectMetadataItem.fields.find(
|
||||
(f) => f.id === ratioConfig.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(field)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (field.type === FieldMetadataType.BOOLEAN) {
|
||||
return (
|
||||
ratioConfig.optionValue === 'true' || ratioConfig.optionValue === 'false'
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
field.type === FieldMetadataType.SELECT ||
|
||||
field.type === FieldMetadataType.MULTI_SELECT
|
||||
) {
|
||||
const options = field.options ?? [];
|
||||
return options.some((option) => option.value === ratioConfig.optionValue);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
export const areChartConfigurationFieldsValidForQuery = (
|
||||
configuration: PageLayoutWidget['configuration'],
|
||||
objectMetadataItem?: ObjectMetadataItem | null,
|
||||
): boolean => {
|
||||
if (!isDefined(configuration)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isDefined(objectMetadataItem) || !isDefined(objectMetadataItem.fields)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (configuration.__typename) {
|
||||
case 'BarChartConfiguration':
|
||||
case 'LineChartConfiguration':
|
||||
return (
|
||||
fieldExists(
|
||||
configuration.aggregateFieldMetadataId,
|
||||
objectMetadataItem,
|
||||
) &&
|
||||
fieldExists(
|
||||
configuration.primaryAxisGroupByFieldMetadataId,
|
||||
objectMetadataItem,
|
||||
) &&
|
||||
(!isDefined(configuration.secondaryAxisGroupByFieldMetadataId) ||
|
||||
fieldExists(
|
||||
configuration.secondaryAxisGroupByFieldMetadataId,
|
||||
objectMetadataItem,
|
||||
))
|
||||
);
|
||||
|
||||
case 'PieChartConfiguration':
|
||||
return (
|
||||
fieldExists(
|
||||
configuration.aggregateFieldMetadataId,
|
||||
objectMetadataItem,
|
||||
) &&
|
||||
fieldExists(configuration.groupByFieldMetadataId, objectMetadataItem)
|
||||
);
|
||||
|
||||
case 'AggregateChartConfiguration':
|
||||
return (
|
||||
fieldExists(
|
||||
configuration.aggregateFieldMetadataId,
|
||||
objectMetadataItem,
|
||||
) &&
|
||||
isRatioConfigValid(
|
||||
configuration.ratioAggregateConfig,
|
||||
objectMetadataItem,
|
||||
)
|
||||
);
|
||||
|
||||
case 'GaugeChartConfiguration':
|
||||
return fieldExists(
|
||||
configuration.aggregateFieldMetadataId,
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
case 'IframeConfiguration':
|
||||
return isString(configuration.url) && configuration.url.trim().length > 0;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type WidgetConfiguration } from '~/generated-metadata/graphql';
|
||||
|
||||
export const hasMinimalRequiredConfigForGraph = (
|
||||
configuration: WidgetConfiguration | FieldsConfiguration | FieldConfiguration,
|
||||
): boolean => {
|
||||
if (
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration')
|
||||
) {
|
||||
return (
|
||||
isDefined(configuration.aggregateFieldMetadataId) &&
|
||||
isDefined(configuration.primaryAxisGroupByFieldMetadataId)
|
||||
);
|
||||
}
|
||||
|
||||
if (isWidgetConfigurationOfType(configuration, 'PieChartConfiguration')) {
|
||||
return (
|
||||
isDefined(configuration.aggregateFieldMetadataId) &&
|
||||
isDefined(configuration.groupByFieldMetadataId)
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'GaugeChartConfiguration')
|
||||
) {
|
||||
return isDefined(configuration.aggregateFieldMetadataId);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
@@ -32,6 +32,7 @@ export const TEST_BAR_CHART_CONFIGURATION: TypedBarChartConfiguration = {
|
||||
primaryAxisOrderBy: GraphOrderBy.FIELD_ASC,
|
||||
displayDataLabel: true,
|
||||
axisNameDisplay: AxisNameDisplay.NONE,
|
||||
splitMultiValueFields: false,
|
||||
};
|
||||
|
||||
export const TEST_BAR_CHART_CONFIGURATION_HORIZONTAL: TypedBarChartConfiguration =
|
||||
@@ -50,6 +51,7 @@ export const TEST_LINE_CHART_CONFIGURATION: TypedLineChartConfiguration = {
|
||||
primaryAxisDateGranularity: ObjectRecordGroupByDateGranularity.DAY,
|
||||
displayDataLabel: true,
|
||||
axisNameDisplay: AxisNameDisplay.NONE,
|
||||
splitMultiValueFields: false,
|
||||
};
|
||||
|
||||
export const TEST_PIE_CHART_CONFIGURATION: TypedPieChartConfiguration = {
|
||||
@@ -62,6 +64,7 @@ export const TEST_PIE_CHART_CONFIGURATION: TypedPieChartConfiguration = {
|
||||
dateGranularity: ObjectRecordGroupByDateGranularity.MONTH,
|
||||
orderBy: GraphOrderBy.VALUE_DESC,
|
||||
displayDataLabel: true,
|
||||
splitMultiValueFields: false,
|
||||
};
|
||||
|
||||
export const TEST_AGGREGATE_CHART_CONFIGURATION: TypedAggregateChartConfiguration =
|
||||
|
||||
+29
-4
@@ -459,10 +459,7 @@ export class PageLayoutUpdateService {
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
objectMetadataId: widgetInput.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
},
|
||||
flatEntityMaps: { flatPageLayoutTabMaps, flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -505,12 +502,26 @@ export class PageLayoutUpdateService {
|
||||
|
||||
const updatedConfiguration = widgetInput.configuration ?? null;
|
||||
|
||||
const {
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
foreignKeyValues: {
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
objectMetadataId: widgetInput.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatPageLayoutTabMaps, flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
...existingWidget,
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
title: widgetInput.title,
|
||||
type: widgetInput.type,
|
||||
objectMetadataId: widgetInput.objectMetadataId ?? null,
|
||||
objectMetadataUniversalIdentifier,
|
||||
gridPosition: widgetInput.gridPosition,
|
||||
position: widgetInput.position ?? null,
|
||||
configuration: updatedConfiguration,
|
||||
@@ -536,12 +547,26 @@ export class PageLayoutUpdateService {
|
||||
|
||||
const restoredConfiguration = widgetInput.configuration ?? null;
|
||||
|
||||
const {
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
foreignKeyValues: {
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
objectMetadataId: widgetInput.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatPageLayoutTabMaps, flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
...existingWidget,
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
title: widgetInput.title,
|
||||
type: widgetInput.type,
|
||||
objectMetadataId: widgetInput.objectMetadataId ?? null,
|
||||
objectMetadataUniversalIdentifier,
|
||||
gridPosition: widgetInput.gridPosition,
|
||||
position: widgetInput.position ?? null,
|
||||
configuration: restoredConfiguration,
|
||||
|
||||
Reference in New Issue
Block a user