ce1ffa8550
## Refactor page layout widget types into shared package and expose from SDK ### Why Widget configuration types were defined only on the server, forcing SDK consumer apps to import from deep internal `twenty-shared/dist` paths — fragile and breaks on structural changes. Server DTOs also had no compile-time guarantee they matched the canonical types. ### What changed - **`twenty-shared`**: Migrated `ChartFilter`, `GridPosition`, `RatioAggregateConfig` and all 20 widget configuration variants into `twenty-shared/types`. `PageLayoutWidgetConfiguration` (base, with `SerializedRelation`) and `PageLayoutWidgetUniversalConfiguration` (derived via `FormatRecordSerializedRelationProperties`) are now the single source of truth. - **`twenty-sdk`**: Re-exported `AggregateOperations`, `ObjectRecordGroupByDateGranularity`, `PageLayoutTabLayoutMode`, and `PageLayoutWidgetUniversalConfiguration` so consumer apps import from `twenty-sdk` directly. - **`twenty-server`**: All widget DTOs now `implements` their shared type for compile-time enforcement. Added helpers to convert nested `fieldMetadataId` ↔ `fieldMetadataUniversalIdentifier` inside chart filters. Removed redundant local type re-exports.
76 lines
3.0 KiB
TypeScript
76 lines
3.0 KiB
TypeScript
import { msg } from '@lingui/core/macro';
|
|
import { type GridPosition } from 'twenty-shared/types';
|
|
|
|
import { WIDGET_GRID_MAX_COLUMNS } from 'src/engine/metadata-modules/page-layout-widget/constants/widget-grid-max-columns.constant';
|
|
import { WIDGET_GRID_MAX_ROWS } from 'src/engine/metadata-modules/page-layout-widget/constants/widget-grid-max-rows.constant';
|
|
import {
|
|
PageLayoutWidgetExceptionCode,
|
|
PageLayoutWidgetExceptionMessageKey,
|
|
generatePageLayoutWidgetExceptionMessage,
|
|
} from 'src/engine/metadata-modules/page-layout-widget/exceptions/page-layout-widget.exception';
|
|
import { type FlatEntityValidationError } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/types/failed-flat-entity-validation.type';
|
|
|
|
// TODO: remove in favor of validatePageLayoutWidgetGridPosition once gridPosition is deprecated
|
|
export const validateWidgetGridPosition = (
|
|
gridPosition: GridPosition,
|
|
widgetTitle: string,
|
|
): FlatEntityValidationError[] => {
|
|
const errors: FlatEntityValidationError[] = [];
|
|
|
|
const { row, column, rowSpan, columnSpan } = gridPosition;
|
|
|
|
if (column >= WIDGET_GRID_MAX_COLUMNS) {
|
|
errors.push({
|
|
code: PageLayoutWidgetExceptionCode.INVALID_PAGE_LAYOUT_WIDGET_DATA,
|
|
message: generatePageLayoutWidgetExceptionMessage(
|
|
PageLayoutWidgetExceptionMessageKey.INVALID_WIDGET_POSITION,
|
|
widgetTitle,
|
|
undefined,
|
|
`column ${column} exceeds grid width (max column is ${WIDGET_GRID_MAX_COLUMNS - 1})`,
|
|
),
|
|
userFriendlyMessage: msg`Widget extends beyond grid width`,
|
|
});
|
|
}
|
|
|
|
if (column + columnSpan > WIDGET_GRID_MAX_COLUMNS) {
|
|
errors.push({
|
|
code: PageLayoutWidgetExceptionCode.INVALID_PAGE_LAYOUT_WIDGET_DATA,
|
|
message: generatePageLayoutWidgetExceptionMessage(
|
|
PageLayoutWidgetExceptionMessageKey.INVALID_WIDGET_POSITION,
|
|
widgetTitle,
|
|
undefined,
|
|
`widget extends beyond grid width (column ${column} + columnSpan ${columnSpan} > ${WIDGET_GRID_MAX_COLUMNS})`,
|
|
),
|
|
userFriendlyMessage: msg`Widget extends beyond grid width`,
|
|
});
|
|
}
|
|
|
|
if (row >= WIDGET_GRID_MAX_ROWS) {
|
|
errors.push({
|
|
code: PageLayoutWidgetExceptionCode.INVALID_PAGE_LAYOUT_WIDGET_DATA,
|
|
message: generatePageLayoutWidgetExceptionMessage(
|
|
PageLayoutWidgetExceptionMessageKey.INVALID_WIDGET_POSITION,
|
|
widgetTitle,
|
|
undefined,
|
|
`row ${row} exceeds maximum allowed rows (${WIDGET_GRID_MAX_ROWS})`,
|
|
),
|
|
userFriendlyMessage: msg`Widget row exceeds grid height`,
|
|
});
|
|
}
|
|
|
|
if (row + rowSpan > WIDGET_GRID_MAX_ROWS) {
|
|
errors.push({
|
|
code: PageLayoutWidgetExceptionCode.INVALID_PAGE_LAYOUT_WIDGET_DATA,
|
|
message: generatePageLayoutWidgetExceptionMessage(
|
|
PageLayoutWidgetExceptionMessageKey.INVALID_WIDGET_POSITION,
|
|
widgetTitle,
|
|
undefined,
|
|
`widget extends beyond grid height (row ${row} + rowSpan ${rowSpan} > ${WIDGET_GRID_MAX_ROWS})`,
|
|
),
|
|
userFriendlyMessage: msg`Widget extends beyond grid height`,
|
|
});
|
|
}
|
|
|
|
return errors;
|
|
};
|