[BREAKING_CHANGE_VIEW_SORT] Refactor view sort to v2 (#17609)
Fixes https://github.com/twentyhq/core-team-issues/issues/2187 --------- Co-authored-by: prastoin <paul@twenty.com> Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
@@ -237,6 +237,7 @@ export enum AllMetadataName {
|
||||
viewFilter = 'viewFilter',
|
||||
viewFilterGroup = 'viewFilterGroup',
|
||||
viewGroup = 'viewGroup',
|
||||
viewSort = 'viewSort',
|
||||
webhook = 'webhook'
|
||||
}
|
||||
|
||||
@@ -1372,6 +1373,11 @@ export type DeleteViewGroupInput = {
|
||||
id: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type DeleteViewSortInput = {
|
||||
/** The id of the view sort to delete. */
|
||||
id: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type DeletedWorkspaceMember = {
|
||||
__typename?: 'DeletedWorkspaceMember';
|
||||
avatarUrl?: Maybe<Scalars['String']>;
|
||||
@@ -1401,6 +1407,11 @@ export type DestroyViewGroupInput = {
|
||||
id: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type DestroyViewSortInput = {
|
||||
/** The id of the view sort to destroy. */
|
||||
id: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type DomainRecord = {
|
||||
__typename?: 'DomainRecord';
|
||||
key: Scalars['String'];
|
||||
@@ -2744,7 +2755,7 @@ export type MutationDeleteCoreViewGroupArgs = {
|
||||
|
||||
|
||||
export type MutationDeleteCoreViewSortArgs = {
|
||||
id: Scalars['String'];
|
||||
input: DeleteViewSortInput;
|
||||
};
|
||||
|
||||
|
||||
@@ -2870,7 +2881,7 @@ export type MutationDestroyCoreViewGroupArgs = {
|
||||
|
||||
|
||||
export type MutationDestroyCoreViewSortArgs = {
|
||||
id: Scalars['String'];
|
||||
input: DestroyViewSortInput;
|
||||
};
|
||||
|
||||
|
||||
@@ -3156,7 +3167,6 @@ export type MutationUpdateCoreViewGroupArgs = {
|
||||
|
||||
|
||||
export type MutationUpdateCoreViewSortArgs = {
|
||||
id: Scalars['String'];
|
||||
input: UpdateViewSortInput;
|
||||
};
|
||||
|
||||
@@ -5022,10 +5032,14 @@ export type UpdateViewInput = {
|
||||
};
|
||||
|
||||
export type UpdateViewSortInput = {
|
||||
/** The id of the view sort to update */
|
||||
id: Scalars['UUID'];
|
||||
/** The view sort to update */
|
||||
update: UpdateViewSortInputUpdates;
|
||||
};
|
||||
|
||||
export type UpdateViewSortInputUpdates = {
|
||||
direction?: InputMaybe<ViewSortDirection>;
|
||||
fieldMetadataId?: InputMaybe<Scalars['UUID']>;
|
||||
id?: InputMaybe<Scalars['UUID']>;
|
||||
viewId?: InputMaybe<Scalars['UUID']>;
|
||||
};
|
||||
|
||||
export type UpdateWebhookInput = {
|
||||
@@ -6272,7 +6286,7 @@ export type UpsertFieldsWidgetMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UpsertFieldsWidgetMutation = { __typename?: 'Mutation', upsertFieldsWidget: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> } };
|
||||
export type UpsertFieldsWidgetMutation = { __typename?: 'Mutation', upsertFieldsWidget: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> } };
|
||||
|
||||
export type FindAllRecordPageLayoutsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -6844,18 +6858,18 @@ export type ViewFilterFragmentFragment = { __typename?: 'CoreViewFilter', id: st
|
||||
|
||||
export type ViewFilterGroupFragmentFragment = { __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string };
|
||||
|
||||
export type ViewFragmentFragment = { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> };
|
||||
export type ViewFragmentFragment = { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> };
|
||||
|
||||
export type ViewGroupFragmentFragment = { __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null };
|
||||
|
||||
export type ViewSortFragmentFragment = { __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string };
|
||||
export type ViewSortFragmentFragment = { __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string };
|
||||
|
||||
export type CreateCoreViewMutationVariables = Exact<{
|
||||
input: CreateViewInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type CreateCoreViewMutation = { __typename?: 'Mutation', createCoreView: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> } };
|
||||
export type CreateCoreViewMutation = { __typename?: 'Mutation', createCoreView: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> } };
|
||||
|
||||
export type CreateCoreViewFieldMutationVariables = Exact<{
|
||||
input: CreateViewFieldInput;
|
||||
@@ -6897,7 +6911,7 @@ export type CreateCoreViewSortMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type CreateCoreViewSortMutation = { __typename?: 'Mutation', createCoreViewSort: { __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string } };
|
||||
export type CreateCoreViewSortMutation = { __typename?: 'Mutation', createCoreViewSort: { __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string } };
|
||||
|
||||
export type CreateManyCoreViewFieldGroupsMutationVariables = Exact<{
|
||||
inputs: Array<CreateViewFieldGroupInput> | CreateViewFieldGroupInput;
|
||||
@@ -6963,7 +6977,7 @@ export type DeleteCoreViewGroupMutationVariables = Exact<{
|
||||
export type DeleteCoreViewGroupMutation = { __typename?: 'Mutation', deleteCoreViewGroup: { __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null } };
|
||||
|
||||
export type DeleteCoreViewSortMutationVariables = Exact<{
|
||||
id: Scalars['String'];
|
||||
input: DeleteViewSortInput;
|
||||
}>;
|
||||
|
||||
|
||||
@@ -7005,7 +7019,7 @@ export type DestroyCoreViewGroupMutationVariables = Exact<{
|
||||
export type DestroyCoreViewGroupMutation = { __typename?: 'Mutation', destroyCoreViewGroup: { __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null } };
|
||||
|
||||
export type DestroyCoreViewSortMutationVariables = Exact<{
|
||||
id: Scalars['String'];
|
||||
input: DestroyViewSortInput;
|
||||
}>;
|
||||
|
||||
|
||||
@@ -7017,7 +7031,7 @@ export type UpdateCoreViewMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateCoreViewMutation = { __typename?: 'Mutation', updateCoreView: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> } };
|
||||
export type UpdateCoreViewMutation = { __typename?: 'Mutation', updateCoreView: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> } };
|
||||
|
||||
export type UpdateCoreViewFieldMutationVariables = Exact<{
|
||||
input: UpdateViewFieldInput;
|
||||
@@ -7056,26 +7070,25 @@ export type UpdateCoreViewGroupMutationVariables = Exact<{
|
||||
export type UpdateCoreViewGroupMutation = { __typename?: 'Mutation', updateCoreViewGroup: { __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null } };
|
||||
|
||||
export type UpdateCoreViewSortMutationVariables = Exact<{
|
||||
id: Scalars['String'];
|
||||
input: UpdateViewSortInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateCoreViewSortMutation = { __typename?: 'Mutation', updateCoreViewSort: { __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string } };
|
||||
export type UpdateCoreViewSortMutation = { __typename?: 'Mutation', updateCoreViewSort: { __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string } };
|
||||
|
||||
export type FindAllCoreViewsQueryVariables = Exact<{
|
||||
viewTypes?: InputMaybe<Array<ViewType> | ViewType>;
|
||||
}>;
|
||||
|
||||
|
||||
export type FindAllCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> }> };
|
||||
export type FindAllCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> }> };
|
||||
|
||||
export type FindFieldsWidgetCoreViewsQueryVariables = Exact<{
|
||||
viewTypes?: InputMaybe<Array<ViewType> | ViewType>;
|
||||
}>;
|
||||
|
||||
|
||||
export type FindFieldsWidgetCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> }> };
|
||||
export type FindFieldsWidgetCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> }> };
|
||||
|
||||
export type FindManyCoreViewFieldsQueryVariables = Exact<{
|
||||
viewId: Scalars['String'];
|
||||
@@ -7110,7 +7123,7 @@ export type FindManyCoreViewSortsQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type FindManyCoreViewSortsQuery = { __typename?: 'Query', getCoreViewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }> };
|
||||
export type FindManyCoreViewSortsQuery = { __typename?: 'Query', getCoreViewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string }> };
|
||||
|
||||
export type FindManyCoreViewsQueryVariables = Exact<{
|
||||
objectMetadataId?: InputMaybe<Scalars['String']>;
|
||||
@@ -7118,14 +7131,14 @@ export type FindManyCoreViewsQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type FindManyCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> }> };
|
||||
export type FindManyCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> }> };
|
||||
|
||||
export type FindOneCoreViewQueryVariables = Exact<{
|
||||
id: Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type FindOneCoreViewQuery = { __typename?: 'Query', getCoreView?: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> } | null };
|
||||
export type FindOneCoreViewQuery = { __typename?: 'Query', getCoreView?: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, mainGroupByFieldMetadataId?: string | null, shouldHideEmptyGroups: boolean, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, visibility: ViewVisibility, createdByUserWorkspaceId?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFieldGroups: Array<{ __typename?: 'CoreViewFieldGroup', id: string, name: string, position: number, isVisible: boolean, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }> }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> } | null };
|
||||
|
||||
export type FindOneCoreViewFieldQueryVariables = Exact<{
|
||||
id: Scalars['String'];
|
||||
@@ -7160,7 +7173,7 @@ export type FindOneCoreViewSortQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type FindOneCoreViewSortQuery = { __typename?: 'Query', getCoreViewSort?: { __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string } | null };
|
||||
export type FindOneCoreViewSortQuery = { __typename?: 'Query', getCoreViewSort?: { __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string, createdAt: string, deletedAt?: string | null, updatedAt: string } | null };
|
||||
|
||||
export type DeleteWorkspaceInvitationMutationVariables = Exact<{
|
||||
appTokenId: Scalars['String'];
|
||||
@@ -8250,6 +8263,9 @@ export const ViewSortFragmentFragmentDoc = gql`
|
||||
fieldMetadataId
|
||||
direction
|
||||
viewId
|
||||
createdAt
|
||||
deletedAt
|
||||
updatedAt
|
||||
}
|
||||
`;
|
||||
export const ViewGroupFragmentFragmentDoc = gql`
|
||||
@@ -15601,8 +15617,8 @@ export type DeleteCoreViewGroupMutationHookResult = ReturnType<typeof useDeleteC
|
||||
export type DeleteCoreViewGroupMutationResult = Apollo.MutationResult<DeleteCoreViewGroupMutation>;
|
||||
export type DeleteCoreViewGroupMutationOptions = Apollo.BaseMutationOptions<DeleteCoreViewGroupMutation, DeleteCoreViewGroupMutationVariables>;
|
||||
export const DeleteCoreViewSortDocument = gql`
|
||||
mutation DeleteCoreViewSort($id: String!) {
|
||||
deleteCoreViewSort(id: $id)
|
||||
mutation DeleteCoreViewSort($input: DeleteViewSortInput!) {
|
||||
deleteCoreViewSort(input: $input)
|
||||
}
|
||||
`;
|
||||
export type DeleteCoreViewSortMutationFn = Apollo.MutationFunction<DeleteCoreViewSortMutation, DeleteCoreViewSortMutationVariables>;
|
||||
@@ -15620,7 +15636,7 @@ export type DeleteCoreViewSortMutationFn = Apollo.MutationFunction<DeleteCoreVie
|
||||
* @example
|
||||
* const [deleteCoreViewSortMutation, { data, loading, error }] = useDeleteCoreViewSortMutation({
|
||||
* variables: {
|
||||
* id: // value for 'id'
|
||||
* input: // value for 'input'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
@@ -15793,8 +15809,8 @@ export type DestroyCoreViewGroupMutationHookResult = ReturnType<typeof useDestro
|
||||
export type DestroyCoreViewGroupMutationResult = Apollo.MutationResult<DestroyCoreViewGroupMutation>;
|
||||
export type DestroyCoreViewGroupMutationOptions = Apollo.BaseMutationOptions<DestroyCoreViewGroupMutation, DestroyCoreViewGroupMutationVariables>;
|
||||
export const DestroyCoreViewSortDocument = gql`
|
||||
mutation DestroyCoreViewSort($id: String!) {
|
||||
destroyCoreViewSort(id: $id)
|
||||
mutation DestroyCoreViewSort($input: DestroyViewSortInput!) {
|
||||
destroyCoreViewSort(input: $input)
|
||||
}
|
||||
`;
|
||||
export type DestroyCoreViewSortMutationFn = Apollo.MutationFunction<DestroyCoreViewSortMutation, DestroyCoreViewSortMutationVariables>;
|
||||
@@ -15812,7 +15828,7 @@ export type DestroyCoreViewSortMutationFn = Apollo.MutationFunction<DestroyCoreV
|
||||
* @example
|
||||
* const [destroyCoreViewSortMutation, { data, loading, error }] = useDestroyCoreViewSortMutation({
|
||||
* variables: {
|
||||
* id: // value for 'id'
|
||||
* input: // value for 'input'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
@@ -16024,8 +16040,8 @@ export type UpdateCoreViewGroupMutationHookResult = ReturnType<typeof useUpdateC
|
||||
export type UpdateCoreViewGroupMutationResult = Apollo.MutationResult<UpdateCoreViewGroupMutation>;
|
||||
export type UpdateCoreViewGroupMutationOptions = Apollo.BaseMutationOptions<UpdateCoreViewGroupMutation, UpdateCoreViewGroupMutationVariables>;
|
||||
export const UpdateCoreViewSortDocument = gql`
|
||||
mutation UpdateCoreViewSort($id: String!, $input: UpdateViewSortInput!) {
|
||||
updateCoreViewSort(id: $id, input: $input) {
|
||||
mutation UpdateCoreViewSort($input: UpdateViewSortInput!) {
|
||||
updateCoreViewSort(input: $input) {
|
||||
...ViewSortFragment
|
||||
}
|
||||
}
|
||||
@@ -16045,7 +16061,6 @@ export type UpdateCoreViewSortMutationFn = Apollo.MutationFunction<UpdateCoreVie
|
||||
* @example
|
||||
* const [updateCoreViewSortMutation, { data, loading, error }] = useUpdateCoreViewSortMutation({
|
||||
* variables: {
|
||||
* id: // value for 'id'
|
||||
* input: // value for 'input'
|
||||
* },
|
||||
* });
|
||||
|
||||
+1
@@ -44,6 +44,7 @@ export const useMetadataErrorHandler = () => {
|
||||
frontComponent: t`front component`,
|
||||
navigationMenuItem: t`navigation menu item`,
|
||||
webhook: t`webhook`,
|
||||
viewSort: t`view sort`,
|
||||
} as const satisfies Record<AllMetadataName, string>;
|
||||
|
||||
const handleMetadataError = (
|
||||
|
||||
@@ -6,5 +6,8 @@ export const VIEW_SORT_FRAGMENT = gql`
|
||||
fieldMetadataId
|
||||
direction
|
||||
viewId
|
||||
createdAt
|
||||
deletedAt
|
||||
updatedAt
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const DELETE_CORE_VIEW_SORT = gql`
|
||||
mutation DeleteCoreViewSort($id: String!) {
|
||||
deleteCoreViewSort(id: $id)
|
||||
mutation DeleteCoreViewSort($input: DeleteViewSortInput!) {
|
||||
deleteCoreViewSort(input: $input)
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const DESTROY_CORE_VIEW_SORT = gql`
|
||||
mutation DestroyCoreViewSort($id: String!) {
|
||||
destroyCoreViewSort(id: $id)
|
||||
mutation DestroyCoreViewSort($input: DestroyViewSortInput!) {
|
||||
destroyCoreViewSort(input: $input)
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -3,8 +3,8 @@ import { gql } from '@apollo/client';
|
||||
|
||||
export const UPDATE_CORE_VIEW_SORT = gql`
|
||||
${VIEW_SORT_FRAGMENT}
|
||||
mutation UpdateCoreViewSort($id: String!, $input: UpdateViewSortInput!) {
|
||||
updateCoreViewSort(id: $id, input: $input) {
|
||||
mutation UpdateCoreViewSort($input: UpdateViewSortInput!) {
|
||||
updateCoreViewSort(input: $input) {
|
||||
...ViewSortFragment
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -16,6 +16,7 @@ import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jes
|
||||
import { mockedCoreViews } from '~/testing/mock-data/generated/metadata/views/mock-views-data';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
|
||||
import { useApplyCurrentViewSortsToCurrentRecordSorts } from '@/views/hooks/useApplyCurrentViewSortsToCurrentRecordSorts';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
|
||||
const mockObjectMetadataItemNameSingular = 'company';
|
||||
|
||||
@@ -38,7 +39,8 @@ describe('useApplyCurrentViewSortsToCurrentRecordSorts', () => {
|
||||
throw new Error('Missing mock field metadata item with type TEXT');
|
||||
}
|
||||
|
||||
const mockViewSort: CoreViewSortEssential = {
|
||||
const mockViewSort: ViewSort = {
|
||||
__typename: 'ViewSort',
|
||||
id: 'sort-1',
|
||||
fieldMetadataId: mockFieldMetadataItem.id,
|
||||
direction: ViewSortDirection.ASC,
|
||||
@@ -103,6 +105,7 @@ describe('useApplyCurrentViewSortsToCurrentRecordSorts', () => {
|
||||
|
||||
expect(result.current.currentRecordSorts).toEqual([
|
||||
{
|
||||
__typename: 'ViewSort',
|
||||
id: mockViewSort.id,
|
||||
fieldMetadataId: mockViewSort.fieldMetadataId,
|
||||
direction: mockViewSort.direction,
|
||||
|
||||
+247
-78
@@ -1,107 +1,276 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { CREATE_CORE_VIEW_SORT } from '@/views/graphql/mutations/createCoreViewSort';
|
||||
import { DESTROY_CORE_VIEW_SORT } from '@/views/graphql/mutations/destroyCoreViewSort';
|
||||
import { UPDATE_CORE_VIEW_SORT } from '@/views/graphql/mutations/updateCoreViewSort';
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useTriggerViewSortOptimisticEffect } from '@/views/optimistic-effects/hooks/useTriggerViewSortOptimisticEffect';
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import { type GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CoreViewSort } from '~/generated-metadata/graphql';
|
||||
import {
|
||||
type CreateCoreViewSortMutationVariables,
|
||||
type DeleteCoreViewSortMutationVariables,
|
||||
type DestroyCoreViewSortMutationVariables,
|
||||
type UpdateCoreViewSortMutationVariables,
|
||||
useCreateCoreViewSortMutation,
|
||||
useDeleteCoreViewSortMutation,
|
||||
useDestroyCoreViewSortMutation,
|
||||
useUpdateCoreViewSortMutation,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePerformViewSortAPIPersist = () => {
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const { triggerViewSortOptimisticEffect } =
|
||||
useTriggerViewSortOptimisticEffect();
|
||||
const [createCoreViewSortMutation] = useCreateCoreViewSortMutation();
|
||||
const [updateCoreViewSortMutation] = useUpdateCoreViewSortMutation();
|
||||
const [deleteCoreViewSortMutation] = useDeleteCoreViewSortMutation();
|
||||
const [destroyCoreViewSortMutation] = useDestroyCoreViewSortMutation();
|
||||
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
const performViewSortAPICreate = useCallback(
|
||||
(
|
||||
viewSortsToCreate: CoreViewSortEssential[],
|
||||
view: Pick<GraphQLView, 'id'>,
|
||||
) => {
|
||||
if (!viewSortsToCreate.length) return;
|
||||
return Promise.all(
|
||||
viewSortsToCreate.map((viewSort) =>
|
||||
apolloClient.mutate({
|
||||
mutation: CREATE_CORE_VIEW_SORT,
|
||||
variables: {
|
||||
input: {
|
||||
id: viewSort.id,
|
||||
fieldMetadataId: viewSort.fieldMetadataId,
|
||||
viewId: view.id,
|
||||
direction: viewSort.direction,
|
||||
} satisfies Partial<CoreViewSort>,
|
||||
},
|
||||
update: (_cache, { data }) => {
|
||||
const createdViewSort = data?.createCoreViewSort;
|
||||
if (!isDefined(createdViewSort)) return;
|
||||
async (
|
||||
createCoreViewSortInputs: CreateCoreViewSortMutationVariables[],
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof createCoreViewSortMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (createCoreViewSortInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
triggerViewSortOptimisticEffect({
|
||||
createdViewSorts: [createdViewSort],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
createCoreViewSortInputs.map((variables) =>
|
||||
createCoreViewSortMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const createdViewSort = data?.createCoreViewSort;
|
||||
if (!isDefined(createdViewSort)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewSortOptimisticEffect({
|
||||
createdViewSorts: [createdViewSort],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewSort',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[apolloClient, triggerViewSortOptimisticEffect],
|
||||
[
|
||||
triggerViewSortOptimisticEffect,
|
||||
createCoreViewSortMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
);
|
||||
|
||||
const performViewSortAPIUpdate = useCallback(
|
||||
(viewSortsToUpdate: CoreViewSortEssential[]) => {
|
||||
if (!viewSortsToUpdate.length) return;
|
||||
return Promise.all(
|
||||
viewSortsToUpdate.map((viewSort) =>
|
||||
apolloClient.mutate({
|
||||
mutation: UPDATE_CORE_VIEW_SORT,
|
||||
variables: {
|
||||
id: viewSort.id,
|
||||
input: {
|
||||
direction: viewSort.direction,
|
||||
} satisfies Partial<CoreViewSort>,
|
||||
},
|
||||
update: (_cache, { data }) => {
|
||||
const updatedViewSort = data?.updateCoreViewSort;
|
||||
if (!isDefined(updatedViewSort)) return;
|
||||
async (
|
||||
updateCoreViewSortInputs: UpdateCoreViewSortMutationVariables[],
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof updateCoreViewSortMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (updateCoreViewSortInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
triggerViewSortOptimisticEffect({
|
||||
updatedViewSorts: [updatedViewSort],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
updateCoreViewSortInputs.map((variables) =>
|
||||
updateCoreViewSortMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const updatedViewSort = data?.updateCoreViewSort;
|
||||
if (!isDefined(updatedViewSort)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewSortOptimisticEffect({
|
||||
updatedViewSorts: [updatedViewSort],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewSort',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[apolloClient, triggerViewSortOptimisticEffect],
|
||||
[
|
||||
triggerViewSortOptimisticEffect,
|
||||
updateCoreViewSortMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
);
|
||||
|
||||
const performViewSortAPIDelete = useCallback(
|
||||
(viewSortsToDelete: Pick<CoreViewSortEssential, 'id' | 'viewId'>[]) => {
|
||||
if (!viewSortsToDelete.length) return;
|
||||
return Promise.all(
|
||||
viewSortsToDelete.map((viewSort) =>
|
||||
apolloClient.mutate({
|
||||
mutation: DESTROY_CORE_VIEW_SORT,
|
||||
variables: {
|
||||
id: viewSort.id,
|
||||
},
|
||||
update: (_cache) => {
|
||||
triggerViewSortOptimisticEffect({
|
||||
deletedViewSorts: [viewSort],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
async (
|
||||
deleteCoreViewSortInputs: DeleteCoreViewSortMutationVariables[],
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof deleteCoreViewSortMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (deleteCoreViewSortInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
deleteCoreViewSortInputs.map((variables) =>
|
||||
deleteCoreViewSortMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const deletedViewSort = data?.deleteCoreViewSort;
|
||||
|
||||
if (!isDefined(deletedViewSort)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewSortOptimisticEffect({
|
||||
deletedViewSorts: [
|
||||
{
|
||||
id: variables.input.id,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewSort',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[apolloClient, triggerViewSortOptimisticEffect],
|
||||
[
|
||||
triggerViewSortOptimisticEffect,
|
||||
deleteCoreViewSortMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
);
|
||||
|
||||
const performViewSortAPIDestroy = useCallback(
|
||||
async (
|
||||
destroyCoreViewSortInputs: DestroyCoreViewSortMutationVariables[],
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof destroyCoreViewSortMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (destroyCoreViewSortInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
destroyCoreViewSortInputs.map((variables) =>
|
||||
destroyCoreViewSortMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewSort',
|
||||
operationType: CrudOperationType.DESTROY,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[destroyCoreViewSortMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
return {
|
||||
performViewSortAPICreate,
|
||||
performViewSortAPIUpdate,
|
||||
performViewSortAPIDelete,
|
||||
performViewSortAPIDestroy,
|
||||
};
|
||||
};
|
||||
|
||||
+8
-1
@@ -106,7 +106,14 @@ export const useApplyCoreViewsForObjectMetadataId = () => {
|
||||
);
|
||||
}
|
||||
|
||||
if (!isDeeplyEqual(coreView.viewSorts, existingView.viewSorts)) {
|
||||
if (
|
||||
!isDeeplyEqual(
|
||||
coreView.viewSorts.map((viewSort) =>
|
||||
removePropertiesFromRecord(viewSort, ['createdAt', 'updatedAt']),
|
||||
),
|
||||
existingView.viewSorts,
|
||||
)
|
||||
) {
|
||||
const view = convertCoreViewToView(coreView);
|
||||
jotaiStore.set(
|
||||
currentRecordSortsComponentState.atomFamily({
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ export const useAreViewSortsDifferentFromRecordSorts = () => {
|
||||
return false;
|
||||
}
|
||||
const viewSortsFromCurrentRecordSorts = currentRecordSorts.map(
|
||||
(recordSort) => mapRecordSortToViewSort(recordSort, currentView.id),
|
||||
(recordSort) => mapRecordSortToViewSort(recordSort),
|
||||
);
|
||||
|
||||
const viewSortsToCreate = getViewSortsToCreate(
|
||||
|
||||
@@ -197,7 +197,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
});
|
||||
|
||||
const viewSortsToCreate = currentRecordSorts
|
||||
.map((recordSort) => mapRecordSortToViewSort(recordSort, newViewId))
|
||||
.map((recordSort) => mapRecordSortToViewSort(recordSort))
|
||||
.map((viewSort) => ({
|
||||
...viewSort,
|
||||
id: v4(),
|
||||
@@ -230,7 +230,20 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
await performViewSortAPICreate(viewSortsToCreate, { id: newViewId });
|
||||
const createViewSortInputs = viewSortsToCreate.map((viewSort) => ({
|
||||
input: {
|
||||
id: viewSort.id,
|
||||
fieldMetadataId: viewSort.fieldMetadataId,
|
||||
viewId: newViewId,
|
||||
direction: viewSort.direction,
|
||||
},
|
||||
}));
|
||||
|
||||
const sortResult = await performViewSortAPICreate(createViewSortInputs);
|
||||
|
||||
if (sortResult.status === 'failed') {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
await refreshCoreViewsByObjectMetadataId(objectMetadataItem.id);
|
||||
|
||||
@@ -36,9 +36,7 @@ export const useSaveRecordSortsToViewSorts = () => {
|
||||
|
||||
const currentRecordSorts = store.get(currentRecordSortsCallbackState);
|
||||
|
||||
const newViewSorts = currentRecordSorts.map((recordSort) =>
|
||||
mapRecordSortToViewSort(recordSort, currentView.id),
|
||||
);
|
||||
const newViewSorts = currentRecordSorts.map(mapRecordSortToViewSort);
|
||||
|
||||
const viewSortsToCreate = getViewSortsToCreate(
|
||||
currentViewSorts,
|
||||
@@ -55,13 +53,48 @@ export const useSaveRecordSortsToViewSorts = () => {
|
||||
newViewSorts,
|
||||
);
|
||||
|
||||
await performViewSortAPICreate(viewSortsToCreate, currentView);
|
||||
await performViewSortAPIUpdate(viewSortsToUpdate);
|
||||
await performViewSortAPIDelete(viewSortsToDelete);
|
||||
const createViewSortInputs = viewSortsToCreate.map((viewSort) => ({
|
||||
input: {
|
||||
id: viewSort.id,
|
||||
fieldMetadataId: viewSort.fieldMetadataId,
|
||||
viewId: currentView.id,
|
||||
direction: viewSort.direction,
|
||||
},
|
||||
}));
|
||||
|
||||
const updateViewSortInputs = viewSortsToUpdate.map((viewSort) => ({
|
||||
input: {
|
||||
id: viewSort.id,
|
||||
update: {
|
||||
direction: viewSort.direction,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const deleteViewSortInputs = viewSortsToDelete.map((viewSort) => ({
|
||||
input: {
|
||||
id: viewSort.id,
|
||||
},
|
||||
}));
|
||||
|
||||
const createResult = await performViewSortAPICreate(createViewSortInputs);
|
||||
if (createResult.status === 'failed') {
|
||||
return;
|
||||
}
|
||||
|
||||
const updateResult = await performViewSortAPIUpdate(updateViewSortInputs);
|
||||
if (updateResult.status === 'failed') {
|
||||
return;
|
||||
}
|
||||
|
||||
const deleteResult = await performViewSortAPIDelete(deleteViewSortInputs);
|
||||
if (deleteResult.status === 'failed') {
|
||||
return;
|
||||
}
|
||||
}, [
|
||||
store,
|
||||
canPersistChanges,
|
||||
currentView,
|
||||
store,
|
||||
currentRecordSortsCallbackState,
|
||||
performViewSortAPICreate,
|
||||
performViewSortAPIUpdate,
|
||||
|
||||
+39
-34
@@ -1,11 +1,11 @@
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CoreViewSort } from '~/generated-metadata/graphql';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
export const useTriggerViewSortOptimisticEffect = () => {
|
||||
const store = useStore();
|
||||
@@ -21,7 +21,7 @@ export const useTriggerViewSortOptimisticEffect = () => {
|
||||
}: {
|
||||
createdViewSorts?: Omit<CoreViewSort, 'workspaceId'>[];
|
||||
updatedViewSorts?: Omit<CoreViewSort, 'workspaceId'>[];
|
||||
deletedViewSorts?: Pick<CoreViewSort, 'id' | 'viewId'>[];
|
||||
deletedViewSorts?: Pick<CoreViewSort, 'id'>[];
|
||||
}) => {
|
||||
const coreViews = store.get(coreViewsState.atom);
|
||||
let newCoreViews = [...coreViews];
|
||||
@@ -93,40 +93,45 @@ export const useTriggerViewSortOptimisticEffect = () => {
|
||||
}
|
||||
});
|
||||
|
||||
deletedViewSorts.forEach(
|
||||
(deletedViewSort: Pick<CoreViewSort, 'id' | 'viewId'>) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: deletedViewSort.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewSorts: (existingViewSorts, { readField }) =>
|
||||
existingViewSorts.filter(
|
||||
(viewSort) =>
|
||||
readField('id', viewSort) !== deletedViewSort.id,
|
||||
),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === deletedViewSort.viewId,
|
||||
);
|
||||
deletedViewSorts.forEach((deletedViewSort: Pick<CoreViewSort, 'id'>) => {
|
||||
const viewId = coreViews.find((coreView) =>
|
||||
coreView.viewSorts.some(
|
||||
(viewSort) => viewSort.id === deletedViewSort.id,
|
||||
),
|
||||
)?.id;
|
||||
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== deletedViewSort.viewId,
|
||||
if (!viewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewSorts: (existingViewSorts, { readField }) =>
|
||||
existingViewSorts.filter(
|
||||
(viewSort) => readField('id', viewSort) !== deletedViewSort.id,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewSorts: toBeModifiedCoreView.viewSorts.filter(
|
||||
(viewSort) => viewSort.id !== deletedViewSort.id,
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === viewId,
|
||||
);
|
||||
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter((coreView) => coreView.id !== viewId),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewSorts: toBeModifiedCoreView.viewSorts.filter(
|
||||
(viewSort) => viewSort.id !== deletedViewSort.id,
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
if (!isDeeplyEqual(coreViews, newCoreViews)) {
|
||||
store.set(coreViewsState.atom, newCoreViews);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import {
|
||||
type AggregateOperations,
|
||||
type CoreViewField,
|
||||
@@ -6,6 +5,7 @@ import {
|
||||
type CoreViewFilter,
|
||||
type CoreViewFilterGroup,
|
||||
type CoreViewGroup,
|
||||
type CoreViewSort,
|
||||
type ViewCalendarLayout,
|
||||
type ViewKey,
|
||||
type ViewOpenRecordIn,
|
||||
@@ -43,7 +43,7 @@ export type CoreViewWithRelations = {
|
||||
CoreViewFilterGroup,
|
||||
'workspaceId' | 'createdAt' | 'updatedAt'
|
||||
>[];
|
||||
viewSorts: CoreViewSortEssential[];
|
||||
viewSorts: Omit<CoreViewSort, 'workspaceId' | 'createdAt' | 'updatedAt'>[];
|
||||
mainGroupByFieldMetadataId?: string | null;
|
||||
shouldHideEmptyGroups: boolean;
|
||||
kanbanAggregateOperation?: AggregateOperations | null;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { type AggregateOperations } from '@/object-record/record-table/constants/AggregateOperations';
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import { type ViewField } from '@/views/types/ViewField';
|
||||
import { type ViewFilter } from '@/views/types/ViewFilter';
|
||||
import { type ViewFilterGroup } from '@/views/types/ViewFilterGroup';
|
||||
@@ -11,6 +10,7 @@ import {
|
||||
type ViewVisibility,
|
||||
type ViewCalendarLayout,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
export type GraphQLView = {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -26,7 +26,7 @@ export type GraphQLView = {
|
||||
viewFields: ViewField[];
|
||||
viewFilters: ViewFilter[];
|
||||
viewFilterGroups?: ViewFilterGroup[];
|
||||
viewSorts: CoreViewSortEssential[];
|
||||
viewSorts: ViewSort[];
|
||||
viewGroups: ViewGroup[];
|
||||
position: number;
|
||||
icon: string;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { type AggregateOperations } from '@/object-record/record-table/constants/AggregateOperations';
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import { type ViewField } from '@/views/types/ViewField';
|
||||
import { type ViewFieldGroup } from '@/views/types/ViewFieldGroup';
|
||||
import { type ViewFilter } from '@/views/types/ViewFilter';
|
||||
@@ -12,6 +11,7 @@ import {
|
||||
type ViewCalendarLayout,
|
||||
type ViewVisibility,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
|
||||
export type View = {
|
||||
id: string;
|
||||
@@ -25,7 +25,7 @@ export type View = {
|
||||
viewGroups: ViewGroup[];
|
||||
viewFilters: ViewFilter[];
|
||||
viewFilterGroups?: ViewFilterGroup[];
|
||||
viewSorts: CoreViewSortEssential[];
|
||||
viewSorts: ViewSort[];
|
||||
kanbanAggregateOperation: AggregateOperations | null;
|
||||
kanbanAggregateOperationFieldMetadataId: string | null;
|
||||
mainGroupByFieldMetadataId?: string | null;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { type ViewSortDirection } from '~/generated-metadata/graphql';
|
||||
|
||||
export type ViewSort = {
|
||||
__typename: 'ViewSort';
|
||||
id: string;
|
||||
fieldMetadataId: string;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
direction: ViewSortDirection;
|
||||
viewId?: string;
|
||||
};
|
||||
+13
-12
@@ -1,9 +1,10 @@
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import { ViewSortDirection } from '~/generated-metadata/graphql';
|
||||
import { getViewSortsToCreate } from '@/views/utils/getViewSortsToCreate';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
|
||||
describe('getViewSortsToCreate', () => {
|
||||
const baseSort: CoreViewSortEssential = {
|
||||
const baseSort: ViewSort = {
|
||||
__typename: 'ViewSort',
|
||||
id: 'sort-1',
|
||||
fieldMetadataId: 'field-1',
|
||||
direction: ViewSortDirection.ASC,
|
||||
@@ -11,14 +12,14 @@ describe('getViewSortsToCreate', () => {
|
||||
};
|
||||
|
||||
it('should return all sorts when current sorts array is empty', () => {
|
||||
const currentViewSorts: CoreViewSortEssential[] = [];
|
||||
const newViewSorts: CoreViewSortEssential[] = [
|
||||
const currentViewSorts: ViewSort[] = [];
|
||||
const newViewSorts: ViewSort[] = [
|
||||
{ ...baseSort },
|
||||
{
|
||||
...baseSort,
|
||||
id: 'sort-2',
|
||||
fieldMetadataId: 'field-2',
|
||||
} satisfies CoreViewSortEssential,
|
||||
} satisfies ViewSort,
|
||||
];
|
||||
|
||||
const result = getViewSortsToCreate(currentViewSorts, newViewSorts);
|
||||
@@ -27,8 +28,8 @@ describe('getViewSortsToCreate', () => {
|
||||
});
|
||||
|
||||
it('should return empty array when new sorts array is empty', () => {
|
||||
const currentViewSorts: CoreViewSortEssential[] = [baseSort];
|
||||
const newViewSorts: CoreViewSortEssential[] = [];
|
||||
const currentViewSorts: ViewSort[] = [baseSort];
|
||||
const newViewSorts: ViewSort[] = [];
|
||||
|
||||
const result = getViewSortsToCreate(currentViewSorts, newViewSorts);
|
||||
|
||||
@@ -41,11 +42,11 @@ describe('getViewSortsToCreate', () => {
|
||||
...baseSort,
|
||||
id: 'sort-2',
|
||||
fieldMetadataId: 'field-2',
|
||||
} satisfies CoreViewSortEssential;
|
||||
} satisfies ViewSort;
|
||||
|
||||
const currentViewSorts: CoreViewSortEssential[] = [existingSort];
|
||||
const currentViewSorts: ViewSort[] = [existingSort];
|
||||
|
||||
const newViewSorts: CoreViewSortEssential[] = [
|
||||
const newViewSorts: ViewSort[] = [
|
||||
existingSort,
|
||||
newSortWithDifferentFieldMetadataId,
|
||||
];
|
||||
@@ -56,8 +57,8 @@ describe('getViewSortsToCreate', () => {
|
||||
});
|
||||
|
||||
it('should handle empty arrays for both inputs', () => {
|
||||
const currentViewSorts: CoreViewSortEssential[] = [];
|
||||
const newViewSorts: CoreViewSortEssential[] = [];
|
||||
const currentViewSorts: ViewSort[] = [];
|
||||
const newViewSorts: ViewSort[] = [];
|
||||
|
||||
const result = getViewSortsToCreate(currentViewSorts, newViewSorts);
|
||||
|
||||
|
||||
+15
-16
@@ -1,9 +1,10 @@
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
import { ViewSortDirection } from '~/generated-metadata/graphql';
|
||||
import { getViewSortsToDelete } from '@/views/utils/getViewSortsToDelete';
|
||||
|
||||
describe('getViewSortsToDelete', () => {
|
||||
const baseSort: CoreViewSortEssential = {
|
||||
const baseSort: ViewSort = {
|
||||
__typename: 'ViewSort',
|
||||
id: 'sort-1',
|
||||
fieldMetadataId: 'field-1',
|
||||
direction: ViewSortDirection.ASC,
|
||||
@@ -11,8 +12,8 @@ describe('getViewSortsToDelete', () => {
|
||||
};
|
||||
|
||||
it('should return empty array when current sorts array is empty', () => {
|
||||
const currentViewSorts: CoreViewSortEssential[] = [];
|
||||
const newViewSorts: CoreViewSortEssential[] = [baseSort];
|
||||
const currentViewSorts: ViewSort[] = [];
|
||||
const newViewSorts: ViewSort[] = [baseSort];
|
||||
|
||||
const result = getViewSortsToDelete(currentViewSorts, newViewSorts);
|
||||
|
||||
@@ -21,8 +22,8 @@ describe('getViewSortsToDelete', () => {
|
||||
|
||||
it('should return all current sorts when new sorts array is empty', () => {
|
||||
const existingSort = { ...baseSort };
|
||||
const currentViewSorts: CoreViewSortEssential[] = [existingSort];
|
||||
const newViewSorts: CoreViewSortEssential[] = [];
|
||||
const currentViewSorts: ViewSort[] = [existingSort];
|
||||
const newViewSorts: ViewSort[] = [];
|
||||
|
||||
const result = getViewSortsToDelete(currentViewSorts, newViewSorts);
|
||||
|
||||
@@ -37,11 +38,8 @@ describe('getViewSortsToDelete', () => {
|
||||
fieldMetadataId: 'field-2',
|
||||
};
|
||||
|
||||
const currentViewSorts: CoreViewSortEssential[] = [
|
||||
sortToDelete,
|
||||
sortToKeep,
|
||||
];
|
||||
const newViewSorts: CoreViewSortEssential[] = [sortToKeep];
|
||||
const currentViewSorts: ViewSort[] = [sortToDelete, sortToKeep];
|
||||
const newViewSorts: ViewSort[] = [sortToKeep];
|
||||
|
||||
const result = getViewSortsToDelete(currentViewSorts, newViewSorts);
|
||||
|
||||
@@ -49,8 +47,8 @@ describe('getViewSortsToDelete', () => {
|
||||
});
|
||||
|
||||
it('should handle empty arrays for both inputs', () => {
|
||||
const currentViewSorts: CoreViewSortEssential[] = [];
|
||||
const newViewSorts: CoreViewSortEssential[] = [];
|
||||
const currentViewSorts: ViewSort[] = [];
|
||||
const newViewSorts: ViewSort[] = [];
|
||||
|
||||
const result = getViewSortsToDelete(currentViewSorts, newViewSorts);
|
||||
|
||||
@@ -60,14 +58,15 @@ describe('getViewSortsToDelete', () => {
|
||||
it('should not delete sorts that match in both fieldMetadataId and direction', () => {
|
||||
const existingSort = { ...baseSort };
|
||||
const matchingSort = {
|
||||
__typename: 'ViewSort',
|
||||
id: 'sort-2',
|
||||
fieldMetadataId: 'field-1',
|
||||
direction: ViewSortDirection.ASC,
|
||||
viewId: 'view-1',
|
||||
};
|
||||
} as ViewSort;
|
||||
|
||||
const currentViewSorts: CoreViewSortEssential[] = [existingSort];
|
||||
const newViewSorts: CoreViewSortEssential[] = [matchingSort];
|
||||
const currentViewSorts: ViewSort[] = [existingSort];
|
||||
const newViewSorts: ViewSort[] = [matchingSort];
|
||||
|
||||
const result = getViewSortsToDelete(currentViewSorts, newViewSorts);
|
||||
|
||||
|
||||
+14
-13
@@ -1,9 +1,10 @@
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
import { ViewSortDirection } from '~/generated-metadata/graphql';
|
||||
import { getViewSortsToUpdate } from '@/views/utils/getViewSortsToUpdate';
|
||||
|
||||
describe('getViewSortsToUpdate', () => {
|
||||
const baseSort: CoreViewSortEssential = {
|
||||
const baseSort: ViewSort = {
|
||||
__typename: 'ViewSort',
|
||||
id: 'sort-1',
|
||||
fieldMetadataId: 'field-1',
|
||||
direction: ViewSortDirection.ASC,
|
||||
@@ -11,8 +12,8 @@ describe('getViewSortsToUpdate', () => {
|
||||
};
|
||||
|
||||
it('should return empty array when current sorts array is empty', () => {
|
||||
const currentViewSorts: CoreViewSortEssential[] = [];
|
||||
const newViewSorts: CoreViewSortEssential[] = [baseSort];
|
||||
const currentViewSorts: ViewSort[] = [];
|
||||
const newViewSorts: ViewSort[] = [baseSort];
|
||||
|
||||
const result = getViewSortsToUpdate(currentViewSorts, newViewSorts);
|
||||
|
||||
@@ -20,8 +21,8 @@ describe('getViewSortsToUpdate', () => {
|
||||
});
|
||||
|
||||
it('should return empty array when new sorts array is empty', () => {
|
||||
const currentViewSorts: CoreViewSortEssential[] = [baseSort];
|
||||
const newViewSorts: CoreViewSortEssential[] = [];
|
||||
const currentViewSorts: ViewSort[] = [baseSort];
|
||||
const newViewSorts: ViewSort[] = [];
|
||||
|
||||
const result = getViewSortsToUpdate(currentViewSorts, newViewSorts);
|
||||
|
||||
@@ -33,10 +34,10 @@ describe('getViewSortsToUpdate', () => {
|
||||
const updatedSort = {
|
||||
...baseSort,
|
||||
direction: ViewSortDirection.DESC,
|
||||
} satisfies CoreViewSortEssential;
|
||||
} satisfies ViewSort;
|
||||
|
||||
const currentViewSorts: CoreViewSortEssential[] = [existingSort];
|
||||
const newViewSorts: CoreViewSortEssential[] = [updatedSort];
|
||||
const currentViewSorts: ViewSort[] = [existingSort];
|
||||
const newViewSorts: ViewSort[] = [updatedSort];
|
||||
|
||||
const result = getViewSortsToUpdate(currentViewSorts, newViewSorts);
|
||||
|
||||
@@ -47,8 +48,8 @@ describe('getViewSortsToUpdate', () => {
|
||||
const existingSort = { ...baseSort };
|
||||
const sameSort = { ...baseSort };
|
||||
|
||||
const currentViewSorts: CoreViewSortEssential[] = [existingSort];
|
||||
const newViewSorts: CoreViewSortEssential[] = [sameSort];
|
||||
const currentViewSorts: ViewSort[] = [existingSort];
|
||||
const newViewSorts: ViewSort[] = [sameSort];
|
||||
|
||||
const result = getViewSortsToUpdate(currentViewSorts, newViewSorts);
|
||||
|
||||
@@ -56,8 +57,8 @@ describe('getViewSortsToUpdate', () => {
|
||||
});
|
||||
|
||||
it('should handle empty arrays for both inputs', () => {
|
||||
const currentViewSorts: CoreViewSortEssential[] = [];
|
||||
const newViewSorts: CoreViewSortEssential[] = [];
|
||||
const currentViewSorts: ViewSort[] = [];
|
||||
const newViewSorts: ViewSort[] = [];
|
||||
|
||||
const result = getViewSortsToUpdate(currentViewSorts, newViewSorts);
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { CoreViewSort } from '~/generated-metadata/graphql';
|
||||
import type { ViewSort } from '@/views/types/ViewSort';
|
||||
|
||||
export const convertCoreViewSortToViewSort = (
|
||||
coreViewSort: Pick<
|
||||
CoreViewSort,
|
||||
'id' | 'direction' | 'fieldMetadataId' | 'viewId'
|
||||
>,
|
||||
): ViewSort => {
|
||||
return {
|
||||
__typename: 'ViewSort',
|
||||
id: coreViewSort.id,
|
||||
direction: coreViewSort.direction,
|
||||
fieldMetadataId: coreViewSort.fieldMetadataId,
|
||||
viewId: coreViewSort.viewId,
|
||||
};
|
||||
};
|
||||
@@ -9,6 +9,7 @@ import { convertCoreViewKeyToViewKey } from '@/views/utils/convertCoreViewKeyToV
|
||||
import { convertCoreViewOpenRecordInToViewOpenRecordIn } from '@/views/utils/convertCoreViewOpenRecordInToViewOpenRecordIn';
|
||||
import { convertCoreViewTypeToViewType } from '@/views/utils/convertCoreViewTypeToViewType';
|
||||
import { ViewVisibility } from '~/generated-metadata/graphql';
|
||||
import { convertCoreViewSortToViewSort } from '@/views/utils/convertCoreViewSortToViewSort';
|
||||
|
||||
export const convertCoreViewToView = (
|
||||
coreView: CoreViewWithRelations,
|
||||
@@ -41,7 +42,7 @@ export const convertCoreViewToView = (
|
||||
viewFilterGroups: coreView.viewFilterGroups?.map(
|
||||
convertCoreViewFilterGroupToViewFilterGroup,
|
||||
),
|
||||
viewSorts: coreView.viewSorts,
|
||||
viewSorts: coreView.viewSorts?.map(convertCoreViewSortToViewSort),
|
||||
mainGroupByFieldMetadataId: coreView.mainGroupByFieldMetadataId ?? null,
|
||||
shouldHideEmptyGroups: coreView.shouldHideEmptyGroups,
|
||||
kanbanAggregateOperation: coreView.kanbanAggregateOperation ?? null,
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CoreViewSort } from '~/generated-metadata/graphql';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
import { compareStrictlyExceptForNullAndUndefined } from '~/utils/compareStrictlyExceptForNullAndUndefined';
|
||||
|
||||
export const getViewSortsToCreate = (
|
||||
currentViewSorts: Pick<CoreViewSort, 'fieldMetadataId'>[],
|
||||
newViewSorts: CoreViewSortEssential[],
|
||||
currentViewSorts: ViewSort[],
|
||||
newViewSorts: ViewSort[],
|
||||
) => {
|
||||
return newViewSorts.filter((newViewSort) => {
|
||||
const correspondingViewSort = currentViewSorts.find(
|
||||
(currentViewSort) =>
|
||||
currentViewSort.fieldMetadataId === newViewSort.fieldMetadataId,
|
||||
const correspondingViewSort = currentViewSorts.find((currentViewSort) =>
|
||||
compareStrictlyExceptForNullAndUndefined(
|
||||
currentViewSort.id,
|
||||
newViewSort.id,
|
||||
),
|
||||
);
|
||||
|
||||
const shouldCreateBecauseViewSortIsNew = !isDefined(correspondingViewSort);
|
||||
|
||||
@@ -1,14 +1,22 @@
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
import { compareStrictlyExceptForNullAndUndefined } from '~/utils/compareStrictlyExceptForNullAndUndefined';
|
||||
|
||||
const isSameSortTarget = (sortA: ViewSort, sortB: ViewSort): boolean =>
|
||||
sortA.fieldMetadataId === sortB.fieldMetadataId &&
|
||||
sortA.direction === sortB.direction;
|
||||
|
||||
export const getViewSortsToDelete = (
|
||||
currentViewSorts: CoreViewSortEssential[],
|
||||
newViewSorts: Pick<CoreViewSortEssential, 'fieldMetadataId'>[],
|
||||
currentViewSorts: ViewSort[],
|
||||
newViewSorts: ViewSort[],
|
||||
) => {
|
||||
return currentViewSorts.filter(
|
||||
(currentViewSort) =>
|
||||
!newViewSorts.some(
|
||||
(newViewSort) =>
|
||||
newViewSort.fieldMetadataId === currentViewSort.fieldMetadataId,
|
||||
compareStrictlyExceptForNullAndUndefined(
|
||||
currentViewSort.id,
|
||||
newViewSort.id,
|
||||
) || isSameSortTarget(currentViewSort, newViewSort),
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import { areViewSortsEqual } from '@/views/utils/areViewSortsEqual';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
import { compareStrictlyExceptForNullAndUndefined } from '~/utils/compareStrictlyExceptForNullAndUndefined';
|
||||
|
||||
export const getViewSortsToUpdate = (
|
||||
currentViewSorts: Pick<
|
||||
CoreViewSortEssential,
|
||||
'fieldMetadataId' | 'direction'
|
||||
>[],
|
||||
newViewSorts: CoreViewSortEssential[],
|
||||
currentViewSorts: ViewSort[],
|
||||
newViewSorts: ViewSort[],
|
||||
) => {
|
||||
return newViewSorts.filter((newViewSort) => {
|
||||
const correspondingViewSort = currentViewSorts.find(
|
||||
(currentViewSort) =>
|
||||
currentViewSort.fieldMetadataId === newViewSort.fieldMetadataId,
|
||||
const correspondingViewSort = currentViewSorts.find((currentViewSort) =>
|
||||
compareStrictlyExceptForNullAndUndefined(
|
||||
currentViewSort.id,
|
||||
newViewSort.id,
|
||||
),
|
||||
);
|
||||
|
||||
if (!isDefined(correspondingViewSort)) {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { type RecordSort } from '@/object-record/record-sort/types/RecordSort';
|
||||
import { type CoreViewSort } from '~/generated-metadata/graphql';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
|
||||
export const mapRecordSortToViewSort = (
|
||||
recordSort: RecordSort,
|
||||
viewId: string,
|
||||
): Pick<CoreViewSort, 'id' | 'fieldMetadataId' | 'direction' | 'viewId'> => {
|
||||
export const mapRecordSortToViewSort = (recordSort: RecordSort): ViewSort => {
|
||||
return {
|
||||
...recordSort,
|
||||
viewId,
|
||||
__typename: 'ViewSort',
|
||||
id: recordSort.id,
|
||||
fieldMetadataId: recordSort.fieldMetadataId,
|
||||
direction: recordSort.direction,
|
||||
};
|
||||
};
|
||||
|
||||
+1
@@ -97,6 +97,7 @@ export const fromFieldManifestToUniversalFlatFieldMetadata = ({
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
+1
@@ -42,6 +42,7 @@ export const fromViewManifestToUniversalFlatView = ({
|
||||
viewFilterGroupUniversalIdentifiers: [],
|
||||
viewGroupUniversalIdentifiers: [],
|
||||
viewFieldGroupUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
deletedAt: null,
|
||||
|
||||
+4
@@ -31,6 +31,7 @@ import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entiti
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
import { JsonbProperty } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/jsonb-property.type';
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
|
||||
// This entity is used as a reference test case for type utilities in:
|
||||
// Modifying relations or properties may require updating type test expectations for Typecheck to pass.
|
||||
@@ -206,4 +207,7 @@ export class FieldMetadataEntity<
|
||||
|
||||
@OneToMany(() => ViewEntity, (view) => view.mainGroupByFieldMetadata)
|
||||
mainGroupByFieldMetadataViews: Relation<ViewEntity[]>;
|
||||
|
||||
@OneToMany(() => ViewSortEntity, (viewSort) => viewSort.fieldMetadata)
|
||||
viewSorts: Relation<ViewSortEntity[]>;
|
||||
}
|
||||
|
||||
+10
-1
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY should match snapshot 1`] = `
|
||||
{
|
||||
@@ -299,6 +299,15 @@ exports[`ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY should ma
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"viewSort": {
|
||||
"propertiesToCompare": [
|
||||
"direction",
|
||||
"fieldMetadataUniversalIdentifier",
|
||||
"viewUniversalIdentifier",
|
||||
"deletedAt",
|
||||
],
|
||||
"propertiesToStringify": [],
|
||||
},
|
||||
"webhook": {
|
||||
"propertiesToCompare": [
|
||||
"targetUrl",
|
||||
|
||||
+32
@@ -1162,6 +1162,38 @@ export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
|
||||
universalProperty: undefined,
|
||||
},
|
||||
},
|
||||
viewSort: {
|
||||
direction: {
|
||||
toCompare: true,
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
fieldMetadataId: {
|
||||
toCompare: true,
|
||||
toStringify: false,
|
||||
universalProperty: 'fieldMetadataUniversalIdentifier',
|
||||
},
|
||||
createdAt: {
|
||||
toCompare: false,
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
updatedAt: {
|
||||
toCompare: false,
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
viewId: {
|
||||
toCompare: true,
|
||||
toStringify: false,
|
||||
universalProperty: 'viewUniversalIdentifier',
|
||||
},
|
||||
deletedAt: {
|
||||
toCompare: true,
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
},
|
||||
viewFilterGroup: {
|
||||
viewId: {
|
||||
toCompare: true,
|
||||
|
||||
+10
@@ -240,6 +240,16 @@ export const ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY = {
|
||||
workspace: null,
|
||||
application: null,
|
||||
},
|
||||
viewSort: {
|
||||
application: null,
|
||||
workspace: null,
|
||||
fieldMetadata: {
|
||||
foreignKey: 'fieldMetadataId',
|
||||
},
|
||||
view: {
|
||||
foreignKey: 'viewId',
|
||||
},
|
||||
},
|
||||
} as const satisfies ManyToOneMetadataRelationsProperties;
|
||||
|
||||
// satisfies with complex mapped types involving nested generics doesn't always catch missing required keys
|
||||
|
||||
+18
@@ -420,6 +420,24 @@ export const ALL_MANY_TO_ONE_METADATA_RELATIONS = {
|
||||
workspace: null,
|
||||
application: null,
|
||||
},
|
||||
viewSort: {
|
||||
application: null,
|
||||
workspace: null,
|
||||
fieldMetadata: {
|
||||
foreignKey: 'fieldMetadataId',
|
||||
universalForeignKey: 'fieldMetadataUniversalIdentifier',
|
||||
inverseOneToManyProperty: null,
|
||||
isNullable: false,
|
||||
metadataName: 'fieldMetadata',
|
||||
},
|
||||
view: {
|
||||
foreignKey: 'viewId',
|
||||
universalForeignKey: 'viewUniversalIdentifier',
|
||||
inverseOneToManyProperty: 'viewSorts',
|
||||
isNullable: false,
|
||||
metadataName: 'view',
|
||||
},
|
||||
},
|
||||
} as const satisfies ManyToOneMetadataRelationsProperties;
|
||||
|
||||
// satisfies with complex mapped types involving nested generics doesn't always catch missing required keys
|
||||
|
||||
+2
@@ -24,6 +24,7 @@ import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-g
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
|
||||
export const ALL_METADATA_ENTITY_BY_METADATA_NAME = {
|
||||
viewField: ViewFieldEntity,
|
||||
@@ -49,4 +50,5 @@ export const ALL_METADATA_ENTITY_BY_METADATA_NAME = {
|
||||
commandMenuItem: CommandMenuItemEntity,
|
||||
navigationMenuItem: NavigationMenuItemEntity,
|
||||
webhook: WebhookEntity,
|
||||
viewSort: ViewSortEntity,
|
||||
} as const satisfies Record<AllMetadataName, EntityTarget<ObjectLiteral>>;
|
||||
|
||||
+4
@@ -53,6 +53,10 @@ export const ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION = {
|
||||
viewFilterGroup: {
|
||||
view: true,
|
||||
},
|
||||
viewSort: {
|
||||
fieldMetadata: true,
|
||||
view: true,
|
||||
},
|
||||
role: {},
|
||||
roleTarget: {
|
||||
role: true,
|
||||
|
||||
+1
@@ -44,6 +44,7 @@ export const ALL_METADATA_SERIALIZED_RELATION = {
|
||||
rowLevelPermissionPredicate: {},
|
||||
rowLevelPermissionPredicateGroup: {},
|
||||
viewFilterGroup: {},
|
||||
viewSort: {},
|
||||
frontComponent: {},
|
||||
webhook: {},
|
||||
} as const satisfies MetadataSerializedRelationProperties;
|
||||
|
||||
+6
@@ -37,6 +37,11 @@ export const ALL_ONE_TO_MANY_METADATA_RELATIONS = {
|
||||
commandMenuItem: {},
|
||||
navigationMenuItem: {},
|
||||
fieldMetadata: {
|
||||
viewSorts: {
|
||||
flatEntityForeignKeyAggregator: 'viewSortIds',
|
||||
metadataName: 'viewSort',
|
||||
universalFlatEntityForeignKeyAggregator: 'viewSortUniversalIdentifiers',
|
||||
},
|
||||
fieldPermissions: null,
|
||||
indexFieldMetadatas: null,
|
||||
viewFields: {
|
||||
@@ -202,6 +207,7 @@ export const ALL_ONE_TO_MANY_METADATA_RELATIONS = {
|
||||
},
|
||||
frontComponent: {},
|
||||
webhook: {},
|
||||
viewSort: {},
|
||||
} as const satisfies OneToManyMetadataRelationsProperties;
|
||||
|
||||
// satisfies with complex mapped types involving nested generics doesn't always catch missing required keys
|
||||
|
||||
+5
@@ -35,6 +35,8 @@ import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entiti
|
||||
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
import { WorkspaceFlatViewSortMapCacheService } from 'src/engine/metadata-modules/flat-view-sort/services/workspace-flat-view-sort-map-cache.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -46,6 +48,7 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
|
||||
ViewFilterEntity,
|
||||
ViewFilterGroupEntity,
|
||||
ViewGroupEntity,
|
||||
ViewSortEntity,
|
||||
IndexMetadataEntity,
|
||||
IndexFieldMetadataEntity,
|
||||
FieldMetadataEntity,
|
||||
@@ -71,6 +74,7 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
|
||||
WorkspaceFlatIndexMapCacheService,
|
||||
WorkspaceFlatFieldMetadataMapCacheService,
|
||||
WorkspaceFlatViewGroupMapCacheService,
|
||||
WorkspaceFlatViewSortMapCacheService,
|
||||
WorkspaceFlatPageLayoutMapCacheService,
|
||||
WorkspaceFlatPageLayoutTabMapCacheService,
|
||||
WorkspaceFlatPageLayoutWidgetMapCacheService,
|
||||
@@ -88,6 +92,7 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
|
||||
WorkspaceFlatIndexMapCacheService,
|
||||
WorkspaceFlatFieldMetadataMapCacheService,
|
||||
WorkspaceFlatViewGroupMapCacheService,
|
||||
WorkspaceFlatViewSortMapCacheService,
|
||||
WorkspaceFlatPageLayoutMapCacheService,
|
||||
WorkspaceFlatPageLayoutTabMapCacheService,
|
||||
WorkspaceFlatPageLayoutWidgetMapCacheService,
|
||||
|
||||
+3
-1
@@ -17,7 +17,7 @@ type FieldMetadataOneToManySyncableRelations =
|
||||
type Assertions = [
|
||||
// FieldMetadataEntity OneToMany relations (all targets):
|
||||
// - indexFieldMetadatas, fieldPermissions, viewFields, viewFilters,
|
||||
// - kanbanAggregateOperationViews, calendarViews, mainGroupByFieldMetadataViews
|
||||
// - kanbanAggregateOperationViews, calendarViews, mainGroupByFieldMetadataViews, viewSorts
|
||||
Expect<
|
||||
Equal<
|
||||
FieldMetadataOneToManyRelations,
|
||||
@@ -28,6 +28,7 @@ type Assertions = [
|
||||
| 'kanbanAggregateOperationViews'
|
||||
| 'calendarViews'
|
||||
| 'mainGroupByFieldMetadataViews'
|
||||
| 'viewSorts'
|
||||
>
|
||||
>,
|
||||
|
||||
@@ -40,6 +41,7 @@ type Assertions = [
|
||||
| 'kanbanAggregateOperationViews'
|
||||
| 'calendarViews'
|
||||
| 'mainGroupByFieldMetadataViews'
|
||||
| 'viewSorts'
|
||||
>
|
||||
>,
|
||||
];
|
||||
|
||||
+2
-1
@@ -10,7 +10,7 @@ type FieldMetadataRelatedProperties =
|
||||
type Assertions = [
|
||||
// FieldMetadataEntity has both ManyToOne and OneToMany relations
|
||||
// ManyToOne: object, workspace, application, relationTargetFieldMetadata, relationTargetObjectMetadata
|
||||
// OneToMany: indexFieldMetadatas, fieldPermissions, viewFields, viewFilters, kanbanAggregateOperationViews, calendarViews, mainGroupByFieldMetadataViews
|
||||
// OneToMany: indexFieldMetadatas, fieldPermissions, viewFields, viewFilters, kanbanAggregateOperationViews, calendarViews, mainGroupByFieldMetadataViews, viewSorts
|
||||
Expect<
|
||||
Equal<
|
||||
FieldMetadataRelatedProperties,
|
||||
@@ -26,6 +26,7 @@ type Assertions = [
|
||||
| 'kanbanAggregateOperationViews'
|
||||
| 'calendarViews'
|
||||
| 'mainGroupByFieldMetadataViews'
|
||||
| 'viewSorts'
|
||||
>
|
||||
>,
|
||||
];
|
||||
|
||||
+27
@@ -33,6 +33,8 @@ import { type FlatViewFilterMaps } from 'src/engine/metadata-modules/flat-view-f
|
||||
import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
|
||||
import { type FlatViewGroupMaps } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group-maps.type';
|
||||
import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
|
||||
import { type FlatViewSortMaps } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort-maps.type';
|
||||
import { type FlatViewSort } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort.type';
|
||||
import { type FlatViewMaps } from 'src/engine/metadata-modules/flat-view/types/flat-view-maps.type';
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
import { type FlatWebhookMaps } from 'src/engine/metadata-modules/flat-webhook/types/flat-webhook-maps.type';
|
||||
@@ -65,6 +67,7 @@ import { type UniversalFlatViewFilterGroup } from 'src/engine/workspace-manager/
|
||||
import { type UniversalFlatViewFilter } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-filter.type';
|
||||
import { type UniversalFlatViewGroup } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-group.type';
|
||||
import { type UniversalFlatView } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view.type';
|
||||
import { type UniversalFlatViewSort } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-sort.type';
|
||||
import { type UniversalFlatWebhook } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-webhook.type';
|
||||
import {
|
||||
type FlatCreateAgentAction,
|
||||
@@ -250,6 +253,14 @@ import {
|
||||
type UniversalDeleteWebhookAction,
|
||||
type UniversalUpdateWebhookAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/webhook/types/workspace-migration-webhook-action.type';
|
||||
import {
|
||||
type FlatCreateViewSortAction,
|
||||
type FlatDeleteViewSortAction,
|
||||
type FlatUpdateViewSortAction,
|
||||
type UniversalCreateViewSortAction,
|
||||
type UniversalDeleteViewSortAction,
|
||||
type UniversalUpdateViewSortAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-sort/types/workspace-migration-view-sort-action.type';
|
||||
|
||||
export type AllFlatEntityTypesByMetadataName = {
|
||||
fieldMetadata: {
|
||||
@@ -351,6 +362,22 @@ export type AllFlatEntityTypesByMetadataName = {
|
||||
universalFlatEntity: UniversalFlatViewGroup;
|
||||
entity: MetadataEntity<'viewGroup'>;
|
||||
};
|
||||
viewSort: {
|
||||
flatEntityMaps: FlatViewSortMaps;
|
||||
universalActions: {
|
||||
create: UniversalCreateViewSortAction;
|
||||
update: UniversalUpdateViewSortAction;
|
||||
delete: UniversalDeleteViewSortAction;
|
||||
};
|
||||
flatActions: {
|
||||
create: FlatCreateViewSortAction;
|
||||
update: FlatUpdateViewSortAction;
|
||||
delete: FlatDeleteViewSortAction;
|
||||
};
|
||||
flatEntity: FlatViewSort;
|
||||
universalFlatEntity: UniversalFlatViewSort;
|
||||
entity: MetadataEntity<'viewSort'>;
|
||||
};
|
||||
rowLevelPermissionPredicate: {
|
||||
flatEntityMaps: FlatRowLevelPermissionPredicateMaps;
|
||||
universalActions: {
|
||||
|
||||
+9
-1
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`getMetadataRelatedMetadataNames should return related metadata names for agent 1`] = `[]`;
|
||||
|
||||
@@ -13,6 +13,7 @@ exports[`getMetadataRelatedMetadataNames should return related metadata names fo
|
||||
[
|
||||
"objectMetadata",
|
||||
"fieldMetadata",
|
||||
"viewSort",
|
||||
"viewField",
|
||||
"viewFilter",
|
||||
"view",
|
||||
@@ -149,4 +150,11 @@ exports[`getMetadataRelatedMetadataNames should return related metadata names fo
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`getMetadataRelatedMetadataNames should return related metadata names for viewSort 1`] = `
|
||||
[
|
||||
"fieldMetadata",
|
||||
"view",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`getMetadataRelatedMetadataNames should return related metadata names for webhook 1`] = `[]`;
|
||||
|
||||
+1
@@ -8,6 +8,7 @@ exports[`sortMetadataNamesChildrenFirst should return metadata names sorted with
|
||||
"viewFilter",
|
||||
"commandMenuItem",
|
||||
"pageLayoutWidget",
|
||||
"viewSort",
|
||||
"index",
|
||||
"pageLayout",
|
||||
"roleTarget",
|
||||
|
||||
+2
@@ -53,6 +53,8 @@ export const getFlatFieldMetadataMock = <T extends FieldMetadataType>(
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
...overrides,
|
||||
};
|
||||
|
||||
+2
@@ -73,6 +73,8 @@ export const getRelationTargetFlatFieldMetadataMock = ({
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
universalSettings: settings,
|
||||
};
|
||||
};
|
||||
|
||||
+4
@@ -147,6 +147,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"updatedAt": Any<String>,
|
||||
"viewFieldUniversalIdentifiers": [],
|
||||
"viewFilterUniversalIdentifiers": [],
|
||||
"viewSortUniversalIdentifiers": [],
|
||||
},
|
||||
{
|
||||
"applicationUniversalIdentifier": Any<String>,
|
||||
@@ -182,6 +183,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"updatedAt": Any<String>,
|
||||
"viewFieldUniversalIdentifiers": [],
|
||||
"viewFilterUniversalIdentifiers": [],
|
||||
"viewSortUniversalIdentifiers": [],
|
||||
},
|
||||
{
|
||||
"applicationUniversalIdentifier": Any<String>,
|
||||
@@ -215,6 +217,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"updatedAt": Any<String>,
|
||||
"viewFieldUniversalIdentifiers": [],
|
||||
"viewFilterUniversalIdentifiers": [],
|
||||
"viewSortUniversalIdentifiers": [],
|
||||
},
|
||||
{
|
||||
"applicationUniversalIdentifier": Any<String>,
|
||||
@@ -250,6 +253,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"updatedAt": Any<String>,
|
||||
"viewFieldUniversalIdentifiers": [],
|
||||
"viewFilterUniversalIdentifiers": [],
|
||||
"viewSortUniversalIdentifiers": [],
|
||||
},
|
||||
],
|
||||
"indexMetadatas": [
|
||||
|
||||
+15
@@ -20,6 +20,7 @@ import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-
|
||||
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
|
||||
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
|
||||
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
|
||||
@Injectable()
|
||||
@WorkspaceCache('flatFieldMetadataMaps')
|
||||
@@ -39,6 +40,8 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
private readonly viewFilterRepository: Repository<ViewFilterEntity>,
|
||||
@InjectRepository(ViewGroupEntity)
|
||||
private readonly viewGroupRepository: Repository<ViewGroupEntity>,
|
||||
@InjectRepository(ViewSortEntity)
|
||||
private readonly viewSortRepository: Repository<ViewSortEntity>,
|
||||
@InjectRepository(ViewEntity)
|
||||
private readonly viewRepository: Repository<ViewEntity>,
|
||||
) {
|
||||
@@ -54,6 +57,7 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
applications,
|
||||
viewFields,
|
||||
viewFilters,
|
||||
viewSorts,
|
||||
views,
|
||||
] = await Promise.all([
|
||||
this.fieldMetadataRepository.find({
|
||||
@@ -80,6 +84,11 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
select: ['id', 'universalIdentifier', 'fieldMetadataId'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.viewSortRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier', 'fieldMetadataId'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.viewRepository.find({
|
||||
where: { workspaceId },
|
||||
select: [
|
||||
@@ -99,6 +108,7 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
calendarViewsByFieldId,
|
||||
kanbanViewsByFieldId,
|
||||
mainGroupByFieldMetadataViewsByFieldId,
|
||||
viewSortsByFieldId,
|
||||
] = (
|
||||
[
|
||||
{
|
||||
@@ -121,6 +131,10 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
entities: views,
|
||||
foreignKey: 'mainGroupByFieldMetadataId',
|
||||
},
|
||||
{
|
||||
entities: viewSorts,
|
||||
foreignKey: 'fieldMetadataId',
|
||||
},
|
||||
] as const
|
||||
).map(regroupEntitiesByRelatedEntityId);
|
||||
|
||||
@@ -147,6 +161,7 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
|
||||
mainGroupByFieldMetadataViewsByFieldId.get(
|
||||
fieldMetadataEntity.id,
|
||||
) || [],
|
||||
viewSorts: viewSortsByFieldId.get(fieldMetadataEntity.id) || [],
|
||||
},
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
|
||||
+5
@@ -127,6 +127,11 @@ export const fromFieldMetadataEntityToFlatFieldMetadata = ({
|
||||
fieldMetadataEntity.mainGroupByFieldMetadataViews?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
viewSortIds: fieldMetadataEntity.viewSorts?.map(({ id }) => id) ?? [],
|
||||
viewSortUniversalIdentifiers:
|
||||
fieldMetadataEntity.viewSorts?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
universalSettings: settingsWithUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+1
@@ -57,5 +57,6 @@ export const getDefaultFlatFieldMetadata = ({
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
universalSettings: settings ?? null,
|
||||
viewSortUniversalIdentifiers: [],
|
||||
} as const satisfies UniversalFlatFieldMetadata;
|
||||
};
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { type MetadataEntityPropertyName } from 'src/engine/metadata-modules/flat-entity/constant/all-entity-properties-configuration-by-metadata-name.constant';
|
||||
|
||||
export const FLAT_VIEW_SORT_EDITABLE_PROPERTIES = [
|
||||
'direction',
|
||||
] as const satisfies MetadataEntityPropertyName<'viewSort'>[];
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
|
||||
|
||||
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
|
||||
import { FlatViewSortMaps } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort-maps.type';
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { fromViewSortEntityToFlatViewSort } from 'src/engine/metadata-modules/flat-view-sort/utils/from-view-sort-entity-to-flat-view-sort.util';
|
||||
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
|
||||
|
||||
@Injectable()
|
||||
@WorkspaceCache('flatViewSortMaps')
|
||||
export class WorkspaceFlatViewSortMapCacheService extends WorkspaceCacheProvider<FlatViewSortMaps> {
|
||||
constructor(
|
||||
@InjectRepository(ViewSortEntity)
|
||||
private readonly viewSortRepository: Repository<ViewSortEntity>,
|
||||
@InjectRepository(ViewEntity)
|
||||
private readonly viewRepository: Repository<ViewEntity>,
|
||||
@InjectRepository(ApplicationEntity)
|
||||
private readonly applicationRepository: Repository<ApplicationEntity>,
|
||||
@InjectRepository(FieldMetadataEntity)
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async computeForCache(workspaceId: string): Promise<FlatViewSortMaps> {
|
||||
const [existingViewSorts, applications, views, fieldMetadatas] =
|
||||
await Promise.all([
|
||||
this.viewSortRepository.find({
|
||||
where: { workspaceId },
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.applicationRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.viewRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.fieldMetadataRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
]);
|
||||
|
||||
const applicationIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(applications);
|
||||
const viewIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(views);
|
||||
const fieldMetadataIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(fieldMetadatas);
|
||||
|
||||
const flatViewSortMaps = createEmptyFlatEntityMaps();
|
||||
|
||||
for (const viewSort of existingViewSorts) {
|
||||
const flatViewSort = fromViewSortEntityToFlatViewSort({
|
||||
entity: viewSort,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
viewIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
});
|
||||
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity: flatViewSort,
|
||||
flatEntityMapsToMutate: flatViewSortMaps,
|
||||
});
|
||||
}
|
||||
|
||||
return flatViewSortMaps;
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatViewSort } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort.type';
|
||||
|
||||
export type FlatViewSortMaps = FlatEntityMaps<FlatViewSort>;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
|
||||
export type FlatViewSort = FlatEntityFrom<ViewSortEntity>;
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type CreateViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/create-view-sort.input';
|
||||
import { ViewSortDirection } from 'src/engine/metadata-modules/view-sort/enums/view-sort-direction';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type UniversalFlatViewSort } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-sort.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
|
||||
export const fromCreateViewSortInputToFlatViewSortToCreate = ({
|
||||
createViewSortInput: rawCreateViewSortInput,
|
||||
flatApplication,
|
||||
flatFieldMetadataMaps,
|
||||
flatViewMaps,
|
||||
}: {
|
||||
createViewSortInput: CreateViewSortInput;
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatViewMaps' | 'flatFieldMetadataMaps'
|
||||
>): UniversalFlatViewSort & {
|
||||
id: string;
|
||||
} => {
|
||||
const { viewId, fieldMetadataId, ...createViewSortInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawCreateViewSortInput,
|
||||
['fieldMetadataId', 'id', 'viewId'],
|
||||
);
|
||||
|
||||
const createdAt = new Date().toISOString();
|
||||
const viewSortId = createViewSortInput.id ?? v4();
|
||||
|
||||
const { fieldMetadataUniversalIdentifier, viewUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewSort',
|
||||
foreignKeyValues: {
|
||||
fieldMetadataId,
|
||||
viewId,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatFieldMetadataMaps,
|
||||
flatViewMaps,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
id: viewSortId,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier: createViewSortInput.universalIdentifier ?? v4(),
|
||||
direction: createViewSortInput.direction ?? ViewSortDirection.ASC,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
};
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatViewSortMaps } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort-maps.type';
|
||||
import { type DeleteViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/delete-view-sort.input';
|
||||
import {
|
||||
ViewSortException,
|
||||
ViewSortExceptionCode,
|
||||
} from 'src/engine/metadata-modules/view-sort/exceptions/view-sort.exception';
|
||||
import { type UniversalFlatViewSort } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-sort.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
|
||||
export const fromDeleteViewSortInputToFlatViewSortOrThrow = ({
|
||||
deleteViewSortInput: rawDeleteViewSortInput,
|
||||
flatViewSortMaps,
|
||||
}: {
|
||||
deleteViewSortInput: DeleteViewSortInput;
|
||||
flatViewSortMaps: FlatViewSortMaps;
|
||||
}): UniversalFlatViewSort => {
|
||||
const { id: viewSortId } = extractAndSanitizeObjectStringFields(
|
||||
rawDeleteViewSortInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatViewSortToDelete = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: viewSortId,
|
||||
flatEntityMaps: flatViewSortMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(existingFlatViewSortToDelete)) {
|
||||
throw new ViewSortException(
|
||||
t`View sort not found`,
|
||||
ViewSortExceptionCode.VIEW_SORT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...existingFlatViewSortToDelete,
|
||||
deletedAt: new Date().toISOString(),
|
||||
};
|
||||
};
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatViewSortMaps } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort-maps.type';
|
||||
import { type DestroyViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/destroy-view-sort.input';
|
||||
import {
|
||||
ViewSortException,
|
||||
ViewSortExceptionCode,
|
||||
} from 'src/engine/metadata-modules/view-sort/exceptions/view-sort.exception';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { type UniversalFlatViewSort } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-sort.type';
|
||||
|
||||
export const fromDestroyViewSortInputToFlatViewSortOrThrow = ({
|
||||
destroyViewSortInput,
|
||||
flatViewSortMaps,
|
||||
}: {
|
||||
destroyViewSortInput: DestroyViewSortInput;
|
||||
flatViewSortMaps: FlatViewSortMaps;
|
||||
}): UniversalFlatViewSort => {
|
||||
const { id: viewSortId } = extractAndSanitizeObjectStringFields(
|
||||
destroyViewSortInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatViewSortToDestroy = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: viewSortId,
|
||||
flatEntityMaps: flatViewSortMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(existingFlatViewSortToDestroy)) {
|
||||
throw new ViewSortException(
|
||||
t`View sort not found`,
|
||||
ViewSortExceptionCode.VIEW_SORT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return existingFlatViewSortToDestroy;
|
||||
};
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_VIEW_SORT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-sort/constants/flat-view-sort-editable-properties.constant';
|
||||
import { type UpdateViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/update-view-sort.input';
|
||||
import {
|
||||
ViewSortException,
|
||||
ViewSortExceptionCode,
|
||||
} from 'src/engine/metadata-modules/view-sort/exceptions/view-sort.exception';
|
||||
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
|
||||
import { type UniversalFlatViewSort } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-view-sort.type';
|
||||
import { type FlatViewSortMaps } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
|
||||
export const fromUpdateViewSortInputToFlatViewSortToUpdateOrThrow = ({
|
||||
updateViewSortInput: rawUpdateViewSortInput,
|
||||
flatViewSortMaps,
|
||||
}: {
|
||||
updateViewSortInput: UpdateViewSortInput;
|
||||
flatViewSortMaps: FlatViewSortMaps;
|
||||
}): UniversalFlatViewSort => {
|
||||
const { id: viewSortToUpdateId } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawUpdateViewSortInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatViewSortToUpdate = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: viewSortToUpdateId,
|
||||
flatEntityMaps: flatViewSortMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(existingFlatViewSortToUpdate)) {
|
||||
throw new ViewSortException(
|
||||
t`View sort not found`,
|
||||
ViewSortExceptionCode.VIEW_SORT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const updatedEditableSortProperties = extractAndSanitizeObjectStringFields(
|
||||
rawUpdateViewSortInput.update,
|
||||
FLAT_VIEW_SORT_EDITABLE_PROPERTIES,
|
||||
);
|
||||
|
||||
return mergeUpdateInExistingRecord({
|
||||
existing: existingFlatViewSortToUpdate,
|
||||
properties: FLAT_VIEW_SORT_EDITABLE_PROPERTIES,
|
||||
update: updatedEditableSortProperties,
|
||||
});
|
||||
};
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import type { FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type FlatViewSort } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort.type';
|
||||
|
||||
export const fromViewSortEntityToFlatViewSort = ({
|
||||
entity: viewSortEntity,
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
viewIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'viewSort'>): FlatViewSort => {
|
||||
const viewSortEntityWithoutRelations = removePropertiesFromRecord(
|
||||
viewSortEntity,
|
||||
getMetadataEntityRelationProperties('viewSort'),
|
||||
);
|
||||
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(viewSortEntity.applicationId);
|
||||
|
||||
if (!isDefined(applicationUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Application with id ${viewSortEntity.applicationId} not found for viewSort ${viewSortEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier = viewIdToUniversalIdentifierMap.get(
|
||||
viewSortEntity.viewId,
|
||||
);
|
||||
|
||||
if (!isDefined(viewUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`View with id ${viewSortEntity.viewId} not found for viewSort ${viewSortEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const fieldMetadataUniversalIdentifier =
|
||||
fieldMetadataIdToUniversalIdentifierMap.get(viewSortEntity.fieldMetadataId);
|
||||
|
||||
if (!isDefined(fieldMetadataUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
`Field metadata with id ${viewSortEntity.fieldMetadataId} not found for viewSort ${viewSortEntity.id}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...viewSortEntityWithoutRelations,
|
||||
createdAt: viewSortEntity.createdAt.toISOString(),
|
||||
updatedAt: viewSortEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewSortEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier: viewSortEntityWithoutRelations.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
@@ -11,6 +11,7 @@ import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-g
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -23,6 +24,7 @@ import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entit
|
||||
ViewFieldGroupEntity,
|
||||
ViewFilterEntity,
|
||||
ViewGroupEntity,
|
||||
ViewSortEntity,
|
||||
ViewFilterGroupEntity,
|
||||
]),
|
||||
],
|
||||
|
||||
+15
@@ -16,6 +16,7 @@ import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities
|
||||
import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
|
||||
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
|
||||
@@ -42,6 +43,8 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceCacheProvider<Fla
|
||||
private readonly viewGroupRepository: Repository<ViewGroupEntity>,
|
||||
@InjectRepository(ViewFilterGroupEntity)
|
||||
private readonly viewFilterGroupRepository: Repository<ViewFilterGroupEntity>,
|
||||
@InjectRepository(ViewSortEntity)
|
||||
private readonly viewSortRepository: Repository<ViewSortEntity>,
|
||||
@InjectRepository(ViewFieldGroupEntity)
|
||||
private readonly viewFieldGroupRepository: Repository<ViewFieldGroupEntity>,
|
||||
) {
|
||||
@@ -58,6 +61,7 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceCacheProvider<Fla
|
||||
viewFilters,
|
||||
viewGroups,
|
||||
viewFilterGroups,
|
||||
viewSorts,
|
||||
viewFieldGroups,
|
||||
] = await Promise.all([
|
||||
this.viewRepository.find({
|
||||
@@ -99,6 +103,11 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceCacheProvider<Fla
|
||||
select: ['id', 'universalIdentifier', 'viewId'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.viewSortRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier', 'viewId'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.viewFieldGroupRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier', 'viewId'],
|
||||
@@ -111,6 +120,7 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceCacheProvider<Fla
|
||||
viewFiltersByViewId,
|
||||
viewGroupsByViewId,
|
||||
viewFilterGroupsByViewId,
|
||||
viewSortsByViewId,
|
||||
viewFieldGroupsByViewId,
|
||||
] = (
|
||||
[
|
||||
@@ -130,6 +140,10 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceCacheProvider<Fla
|
||||
entities: viewFilterGroups,
|
||||
foreignKey: 'viewId',
|
||||
},
|
||||
{
|
||||
entities: viewSorts,
|
||||
foreignKey: 'viewId',
|
||||
},
|
||||
{
|
||||
entities: viewFieldGroups,
|
||||
foreignKey: 'viewId',
|
||||
@@ -154,6 +168,7 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceCacheProvider<Fla
|
||||
viewFilters: viewFiltersByViewId.get(viewEntity.id) || [],
|
||||
viewGroups: viewGroupsByViewId.get(viewEntity.id) || [],
|
||||
viewFilterGroups: viewFilterGroupsByViewId.get(viewEntity.id) || [],
|
||||
viewSorts: viewSortsByViewId.get(viewEntity.id) || [],
|
||||
viewFieldGroups: viewFieldGroupsByViewId.get(viewEntity.id) || [],
|
||||
},
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
|
||||
+1
-4
@@ -1,7 +1,4 @@
|
||||
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
|
||||
export type FlatView = FlatEntityFrom<
|
||||
// TODO remove once viewSorts has been migrated to v2
|
||||
Omit<ViewEntity, 'viewSorts'>
|
||||
>;
|
||||
export type FlatView = FlatEntityFrom<ViewEntity>;
|
||||
|
||||
+1
@@ -91,6 +91,7 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
viewGroupUniversalIdentifiers: [],
|
||||
viewFieldGroupUniversalIdentifiers: [],
|
||||
viewFilterGroupUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
|
||||
|
||||
+5
@@ -121,5 +121,10 @@ export const fromViewEntityToFlatView = ({
|
||||
viewEntity.viewFilterGroups?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
viewSortIds: viewEntity.viewSorts?.map(({ id }) => id) ?? [],
|
||||
viewSortUniversalIdentifiers:
|
||||
viewEntity.viewSorts?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
};
|
||||
};
|
||||
|
||||
+8
@@ -38,6 +38,7 @@ const PARTIAL_ID_FIELD = {
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.UUID>;
|
||||
|
||||
const PARTIAL_CREATED_AT_FIELD = {
|
||||
@@ -65,6 +66,7 @@ const PARTIAL_CREATED_AT_FIELD = {
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.DATE_TIME>;
|
||||
|
||||
const PARTIAL_UPDATED_AT_FIELD = {
|
||||
@@ -92,6 +94,7 @@ const PARTIAL_UPDATED_AT_FIELD = {
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.DATE_TIME>;
|
||||
|
||||
const PARTIAL_DELETED_AT_FIELD = {
|
||||
@@ -119,6 +122,7 @@ const PARTIAL_DELETED_AT_FIELD = {
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.DATE_TIME>;
|
||||
|
||||
const PARTIAL_CREATED_BY_FIELD = {
|
||||
@@ -146,6 +150,7 @@ const PARTIAL_CREATED_BY_FIELD = {
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.ACTOR>;
|
||||
|
||||
const PARTIAL_UPDATED_BY_FIELD = {
|
||||
@@ -173,6 +178,7 @@ const PARTIAL_UPDATED_BY_FIELD = {
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.ACTOR>;
|
||||
|
||||
const PARTIAL_POSITION_FIELD = {
|
||||
@@ -200,6 +206,7 @@ const PARTIAL_POSITION_FIELD = {
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.POSITION>;
|
||||
|
||||
const PARTIAL_SEARCH_VECTOR_FIELD = {
|
||||
@@ -229,6 +236,7 @@ const PARTIAL_SEARCH_VECTOR_FIELD = {
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
} as const satisfies PartialSystemFlatFieldMetadata<FieldMetadataType.TS_VECTOR>;
|
||||
|
||||
export const PARTIAL_SYSTEM_FLAT_FIELD_METADATAS = {
|
||||
|
||||
+2
@@ -633,6 +633,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
viewFilterUniversalIdentifiers: [],
|
||||
viewGroupUniversalIdentifiers: [],
|
||||
viewFilterGroupUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
}
|
||||
@@ -675,6 +676,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
viewFilterUniversalIdentifiers: [],
|
||||
viewGroupUniversalIdentifiers: [],
|
||||
viewFilterGroupUniversalIdentifiers: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
}
|
||||
|
||||
+1
@@ -152,6 +152,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
viewSortUniversalIdentifiers: [],
|
||||
};
|
||||
|
||||
const searchVectorUniversalSettings: UniversalFlatFieldMetadata<FieldMetadataType.TS_VECTOR>['universalSettings'] =
|
||||
|
||||
+18
-18
@@ -21,17 +21,17 @@ import { CreateViewSortPermissionGuard } from 'src/engine/metadata-modules/view-
|
||||
import { DeleteViewSortPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/delete-view-sort-permission.guard';
|
||||
import { UpdateViewSortPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/update-view-sort-permission.guard';
|
||||
import { CreateViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/create-view-sort.input';
|
||||
import { UpdateViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/update-view-sort.input';
|
||||
import { type ViewSortDTO } from 'src/engine/metadata-modules/view-sort/dtos/view-sort.dto';
|
||||
import {
|
||||
generateViewSortExceptionMessage,
|
||||
generateViewSortUserFriendlyExceptionMessage,
|
||||
ViewSortException,
|
||||
ViewSortExceptionCode,
|
||||
ViewSortExceptionMessageKey,
|
||||
generateViewSortExceptionMessage,
|
||||
generateViewSortUserFriendlyExceptionMessage,
|
||||
} from 'src/engine/metadata-modules/view-sort/exceptions/view-sort.exception';
|
||||
import { ViewSortRestApiExceptionFilter } from 'src/engine/metadata-modules/view-sort/filters/view-sort-rest-api-exception.filter';
|
||||
import { ViewSortService } from 'src/engine/metadata-modules/view-sort/services/view-sort.service';
|
||||
import { ViewSortDirection } from 'src/engine/metadata-modules/view-sort/enums/view-sort-direction';
|
||||
|
||||
@Controller('rest/metadata/viewSorts')
|
||||
@UseGuards(WorkspaceAuthGuard)
|
||||
@@ -82,11 +82,11 @@ export class ViewSortController {
|
||||
@UseGuards(CreateViewSortPermissionGuard)
|
||||
async create(
|
||||
@Body() input: CreateViewSortInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
): Promise<ViewSortDTO> {
|
||||
return this.viewSortService.create({
|
||||
...input,
|
||||
workspaceId: workspace.id,
|
||||
return await this.viewSortService.createOne({
|
||||
createViewSortInput: input,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -94,25 +94,25 @@ export class ViewSortController {
|
||||
@UseGuards(UpdateViewSortPermissionGuard)
|
||||
async update(
|
||||
@Param('id') id: string,
|
||||
@Body() input: UpdateViewSortInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@Body() input: { direction?: ViewSortDirection },
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
): Promise<ViewSortDTO> {
|
||||
const updatedViewSort = await this.viewSortService.update(
|
||||
id,
|
||||
workspace.id,
|
||||
input,
|
||||
);
|
||||
|
||||
return updatedViewSort;
|
||||
return await this.viewSortService.updateOne({
|
||||
updateViewSortInput: { id, update: input },
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@UseGuards(DeleteViewSortPermissionGuard)
|
||||
async delete(
|
||||
@Param('id') id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
): Promise<{ success: boolean }> {
|
||||
const deletedViewSort = await this.viewSortService.delete(id, workspace.id);
|
||||
const deletedViewSort = await this.viewSortService.deleteOne({
|
||||
deleteViewSortInput: { id },
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
return { success: isDefined(deletedViewSort) };
|
||||
}
|
||||
|
||||
+15
-1
@@ -1,22 +1,36 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
import { Field, HideField, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IsEnum, IsOptional, IsUUID } from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { ViewSortDirection } from 'src/engine/metadata-modules/view-sort/enums/view-sort-direction';
|
||||
|
||||
@InputType()
|
||||
export class CreateViewSortInput {
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
@Field(() => UUIDScalarType, { nullable: true })
|
||||
id?: string;
|
||||
|
||||
@IsUUID()
|
||||
@Field(() => UUIDScalarType, { nullable: false })
|
||||
fieldMetadataId: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsEnum(ViewSortDirection)
|
||||
@Field(() => ViewSortDirection, {
|
||||
nullable: true,
|
||||
defaultValue: ViewSortDirection.ASC,
|
||||
})
|
||||
direction?: ViewSortDirection;
|
||||
|
||||
@IsUUID()
|
||||
@Field(() => UUIDScalarType, { nullable: false })
|
||||
viewId: string;
|
||||
|
||||
@HideField()
|
||||
universalIdentifier?: string;
|
||||
|
||||
@HideField()
|
||||
applicationId?: string;
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
import { IsUUID } from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
|
||||
@InputType()
|
||||
export class DeleteViewSortInput {
|
||||
@IDField(() => UUIDScalarType, {
|
||||
description: 'The id of the view sort to delete.',
|
||||
})
|
||||
@IsUUID()
|
||||
id: string;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
import { IsUUID } from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
|
||||
@InputType()
|
||||
export class DestroyViewSortInput {
|
||||
@IDField(() => UUIDScalarType, {
|
||||
description: 'The id of the view sort to destroy.',
|
||||
})
|
||||
@IsUUID()
|
||||
id: string;
|
||||
}
|
||||
+35
-3
@@ -1,6 +1,38 @@
|
||||
import { InputType, PartialType } from '@nestjs/graphql';
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { CreateViewSortInput } from './create-view-sort.input';
|
||||
import {
|
||||
IsEnum,
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
IsUUID,
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
import { Type } from 'class-transformer';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { ViewSortDirection } from 'src/engine/metadata-modules/view-sort/enums/view-sort-direction';
|
||||
|
||||
@InputType()
|
||||
export class UpdateViewSortInput extends PartialType(CreateViewSortInput) {}
|
||||
class UpdateViewSortInputUpdates {
|
||||
@IsOptional()
|
||||
@IsEnum(ViewSortDirection)
|
||||
@Field(() => ViewSortDirection, { nullable: true })
|
||||
direction?: ViewSortDirection;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class UpdateViewSortInput {
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
@Field(() => UUIDScalarType, {
|
||||
description: 'The id of the view sort to update',
|
||||
})
|
||||
id: string;
|
||||
|
||||
@Type(() => UpdateViewSortInputUpdates)
|
||||
@ValidateNested()
|
||||
@Field(() => UpdateViewSortInputUpdates, {
|
||||
description: 'The view sort to update',
|
||||
})
|
||||
update: UpdateViewSortInputUpdates;
|
||||
}
|
||||
|
||||
+30
-18
@@ -1,7 +1,7 @@
|
||||
import { UseFilters, UseGuards } from '@nestjs/common';
|
||||
import { Args, Mutation, Query } from '@nestjs/graphql';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { isDefined } from 'class-validator';
|
||||
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
@@ -17,6 +17,8 @@ import { UpdateViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/
|
||||
import { ViewSortDTO } from 'src/engine/metadata-modules/view-sort/dtos/view-sort.dto';
|
||||
import { ViewSortService } from 'src/engine/metadata-modules/view-sort/services/view-sort.service';
|
||||
import { ViewGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/view/utils/view-graphql-api-exception.filter';
|
||||
import { DeleteViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/delete-view-sort.input';
|
||||
import { DestroyViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/destroy-view-sort.input';
|
||||
|
||||
@MetadataResolver(() => ViewSortDTO)
|
||||
@UseFilters(ViewGraphqlApiExceptionFilter)
|
||||
@@ -42,40 +44,45 @@ export class ViewSortResolver {
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async getCoreViewSort(
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
): Promise<ViewSortDTO | null> {
|
||||
return this.viewSortService.findById(id, workspace.id);
|
||||
return this.viewSortService.findById(id, workspaceId);
|
||||
}
|
||||
|
||||
@Mutation(() => ViewSortDTO)
|
||||
@UseGuards(CreateViewSortPermissionGuard)
|
||||
async createCoreViewSort(
|
||||
@Args('input') input: CreateViewSortInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@Args('input') createViewSortInput: CreateViewSortInput,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
): Promise<ViewSortDTO> {
|
||||
return this.viewSortService.create({
|
||||
...input,
|
||||
workspaceId: workspace.id,
|
||||
return this.viewSortService.createOne({
|
||||
createViewSortInput,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => ViewSortDTO)
|
||||
@UseGuards(UpdateViewSortPermissionGuard)
|
||||
async updateCoreViewSort(
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@Args('input') input: UpdateViewSortInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@Args('input') updateViewSortInput: UpdateViewSortInput,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
): Promise<ViewSortDTO> {
|
||||
return this.viewSortService.update(id, workspace.id, input);
|
||||
return this.viewSortService.updateOne({
|
||||
updateViewSortInput,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => Boolean)
|
||||
@UseGuards(DeleteViewSortPermissionGuard)
|
||||
async deleteCoreViewSort(
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@Args('input') deleteViewSortInput: DeleteViewSortInput,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
): Promise<boolean> {
|
||||
const deletedViewSort = await this.viewSortService.delete(id, workspace.id);
|
||||
const deletedViewSort = await this.viewSortService.deleteOne({
|
||||
deleteViewSortInput,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
return isDefined(deletedViewSort);
|
||||
}
|
||||
@@ -83,9 +90,14 @@ export class ViewSortResolver {
|
||||
@Mutation(() => Boolean)
|
||||
@UseGuards(DestroyViewSortPermissionGuard)
|
||||
async destroyCoreViewSort(
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@Args('input') destroyViewSortInput: DestroyViewSortInput,
|
||||
@AuthWorkspace() { id: workspaceId }: WorkspaceEntity,
|
||||
): Promise<boolean> {
|
||||
return this.viewSortService.destroy(id, workspace.id);
|
||||
const destroyedViewSort = await this.viewSortService.destroyOne({
|
||||
destroyViewSortInput,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
return isDefined(destroyedViewSort);
|
||||
}
|
||||
}
|
||||
|
||||
-353
@@ -1,353 +0,0 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
||||
import { type Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
import { ViewSortDirection } from 'src/engine/metadata-modules/view-sort/enums/view-sort-direction';
|
||||
import {
|
||||
ViewSortException,
|
||||
ViewSortExceptionCode,
|
||||
ViewSortExceptionMessageKey,
|
||||
generateViewSortExceptionMessage,
|
||||
generateViewSortUserFriendlyExceptionMessage,
|
||||
} from 'src/engine/metadata-modules/view-sort/exceptions/view-sort.exception';
|
||||
import { ViewSortService } from 'src/engine/metadata-modules/view-sort/services/view-sort.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
|
||||
describe('ViewSortService', () => {
|
||||
let viewSortService: ViewSortService;
|
||||
let viewSortRepository: Repository<ViewSortEntity>;
|
||||
let applicationService: ApplicationService;
|
||||
|
||||
const mockViewSort = {
|
||||
id: 'view-sort-id',
|
||||
fieldMetadataId: 'field-id',
|
||||
viewId: 'view-id',
|
||||
workspaceId: 'workspace-id',
|
||||
direction: ViewSortDirection.ASC,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
} as ViewSortEntity;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
ViewSortService,
|
||||
{
|
||||
provide: getRepositoryToken(ViewSortEntity),
|
||||
useValue: {
|
||||
find: jest.fn(),
|
||||
findOne: jest.fn(),
|
||||
create: jest.fn(),
|
||||
save: jest.fn(),
|
||||
softDelete: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: WorkspaceCacheStorageService,
|
||||
useValue: {
|
||||
flushGraphQLOperation: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: ApplicationService,
|
||||
useValue: {
|
||||
findWorkspaceTwentyStandardAndCustomApplicationOrThrow: jest.fn(),
|
||||
},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
viewSortService = module.get<ViewSortService>(ViewSortService);
|
||||
viewSortRepository = module.get<Repository<ViewSortEntity>>(
|
||||
getRepositoryToken(ViewSortEntity),
|
||||
);
|
||||
applicationService = module.get<ApplicationService>(ApplicationService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(viewSortService).toBeDefined();
|
||||
});
|
||||
|
||||
describe('findByWorkspaceId', () => {
|
||||
it('should return view sorts for a workspace', async () => {
|
||||
const workspaceId = 'workspace-id';
|
||||
const expectedViewSorts = [mockViewSort];
|
||||
|
||||
jest
|
||||
.spyOn(viewSortRepository, 'find')
|
||||
.mockResolvedValue(expectedViewSorts);
|
||||
|
||||
const result = await viewSortService.findByWorkspaceId(workspaceId);
|
||||
|
||||
expect(viewSortRepository.find).toHaveBeenCalledWith({
|
||||
where: {
|
||||
workspaceId,
|
||||
deletedAt: expect.anything(),
|
||||
},
|
||||
relations: ['workspace', 'view'],
|
||||
});
|
||||
expect(result).toEqual(expectedViewSorts);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findByViewId', () => {
|
||||
it('should return view sorts for a view', async () => {
|
||||
const workspaceId = 'workspace-id';
|
||||
const viewId = 'view-id';
|
||||
const expectedViewSorts = [mockViewSort];
|
||||
|
||||
jest
|
||||
.spyOn(viewSortRepository, 'find')
|
||||
.mockResolvedValue(expectedViewSorts);
|
||||
|
||||
const result = await viewSortService.findByViewId(workspaceId, viewId);
|
||||
|
||||
expect(viewSortRepository.find).toHaveBeenCalledWith({
|
||||
where: {
|
||||
workspaceId,
|
||||
viewId,
|
||||
deletedAt: expect.anything(),
|
||||
},
|
||||
relations: ['workspace', 'view'],
|
||||
});
|
||||
expect(result).toEqual(expectedViewSorts);
|
||||
});
|
||||
});
|
||||
|
||||
describe('findById', () => {
|
||||
it('should return a view sort by id', async () => {
|
||||
const id = 'view-sort-id';
|
||||
const workspaceId = 'workspace-id';
|
||||
|
||||
jest.spyOn(viewSortRepository, 'findOne').mockResolvedValue(mockViewSort);
|
||||
|
||||
const result = await viewSortService.findById(id, workspaceId);
|
||||
|
||||
expect(viewSortRepository.findOne).toHaveBeenCalledWith({
|
||||
where: {
|
||||
id,
|
||||
workspaceId,
|
||||
deletedAt: expect.anything(),
|
||||
},
|
||||
relations: ['workspace', 'view'],
|
||||
});
|
||||
expect(result).toEqual(mockViewSort);
|
||||
});
|
||||
|
||||
it('should return null when view sort is not found', async () => {
|
||||
const id = 'non-existent-id';
|
||||
const workspaceId = 'workspace-id';
|
||||
|
||||
jest.spyOn(viewSortRepository, 'findOne').mockResolvedValue(null);
|
||||
|
||||
const result = await viewSortService.findById(id, workspaceId);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
const validViewSortData = {
|
||||
fieldMetadataId: 'field-id',
|
||||
viewId: 'view-id',
|
||||
workspaceId: 'workspace-id',
|
||||
direction: ViewSortDirection.ASC,
|
||||
};
|
||||
|
||||
it('should create a view sort successfully', async () => {
|
||||
const mockApplicationId = 'application-id';
|
||||
|
||||
jest
|
||||
.spyOn(
|
||||
applicationService,
|
||||
'findWorkspaceTwentyStandardAndCustomApplicationOrThrow',
|
||||
)
|
||||
.mockResolvedValue({
|
||||
workspaceCustomFlatApplication: { id: mockApplicationId },
|
||||
} as any);
|
||||
jest.spyOn(viewSortRepository, 'create').mockReturnValue(mockViewSort);
|
||||
jest.spyOn(viewSortRepository, 'save').mockResolvedValue(mockViewSort);
|
||||
|
||||
const result = await viewSortService.create(validViewSortData);
|
||||
|
||||
expect(viewSortRepository.create).toHaveBeenCalledWith({
|
||||
...validViewSortData,
|
||||
universalIdentifier: expect.any(String),
|
||||
applicationId: mockApplicationId,
|
||||
});
|
||||
expect(viewSortRepository.save).toHaveBeenCalledWith(mockViewSort);
|
||||
expect(result).toEqual(mockViewSort);
|
||||
});
|
||||
|
||||
it('should throw exception when workspaceId is missing', async () => {
|
||||
const invalidData = { ...validViewSortData, workspaceId: undefined };
|
||||
|
||||
await expect(viewSortService.create(invalidData)).rejects.toThrow(
|
||||
new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.WORKSPACE_ID_REQUIRED,
|
||||
),
|
||||
ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
{
|
||||
userFriendlyMessage: generateViewSortUserFriendlyExceptionMessage(
|
||||
ViewSortExceptionMessageKey.WORKSPACE_ID_REQUIRED,
|
||||
),
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw exception when viewId is missing', async () => {
|
||||
const invalidData = { ...validViewSortData, viewId: undefined };
|
||||
|
||||
jest
|
||||
.spyOn(
|
||||
applicationService,
|
||||
'findWorkspaceTwentyStandardAndCustomApplicationOrThrow',
|
||||
)
|
||||
.mockResolvedValue({
|
||||
workspaceCustomFlatApplication: { id: 'application-id' },
|
||||
} as any);
|
||||
|
||||
await expect(viewSortService.create(invalidData)).rejects.toThrow(
|
||||
new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.VIEW_ID_REQUIRED,
|
||||
),
|
||||
ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
{
|
||||
userFriendlyMessage: generateViewSortUserFriendlyExceptionMessage(
|
||||
ViewSortExceptionMessageKey.VIEW_ID_REQUIRED,
|
||||
),
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw exception when fieldMetadataId is missing', async () => {
|
||||
const invalidData = { ...validViewSortData, fieldMetadataId: undefined };
|
||||
|
||||
jest
|
||||
.spyOn(
|
||||
applicationService,
|
||||
'findWorkspaceTwentyStandardAndCustomApplicationOrThrow',
|
||||
)
|
||||
.mockResolvedValue({
|
||||
workspaceCustomFlatApplication: { id: 'application-id' },
|
||||
} as any);
|
||||
|
||||
await expect(viewSortService.create(invalidData)).rejects.toThrow(
|
||||
new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.FIELD_METADATA_ID_REQUIRED,
|
||||
),
|
||||
ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
{
|
||||
userFriendlyMessage: generateViewSortUserFriendlyExceptionMessage(
|
||||
ViewSortExceptionMessageKey.FIELD_METADATA_ID_REQUIRED,
|
||||
),
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('update', () => {
|
||||
it('should update a view sort successfully', async () => {
|
||||
const id = 'view-sort-id';
|
||||
const workspaceId = 'workspace-id';
|
||||
const updateData = { direction: ViewSortDirection.DESC };
|
||||
const updatedViewSort = { ...mockViewSort, ...updateData };
|
||||
|
||||
jest.spyOn(viewSortService, 'findById').mockResolvedValue(mockViewSort);
|
||||
jest.spyOn(viewSortRepository, 'save').mockResolvedValue(updatedViewSort);
|
||||
|
||||
const result = await viewSortService.update(id, workspaceId, updateData);
|
||||
|
||||
expect(viewSortService.findById).toHaveBeenCalledWith(id, workspaceId);
|
||||
expect(viewSortRepository.save).toHaveBeenCalledWith({
|
||||
id,
|
||||
...updateData,
|
||||
});
|
||||
expect(result).toEqual({ ...mockViewSort, ...updatedViewSort });
|
||||
});
|
||||
|
||||
it('should throw exception when view sort is not found', async () => {
|
||||
const id = 'non-existent-id';
|
||||
const workspaceId = 'workspace-id';
|
||||
const updateData = { direction: ViewSortDirection.DESC };
|
||||
|
||||
jest.spyOn(viewSortService, 'findById').mockResolvedValue(null);
|
||||
|
||||
await expect(
|
||||
viewSortService.update(id, workspaceId, updateData),
|
||||
).rejects.toThrow(
|
||||
new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.VIEW_SORT_NOT_FOUND,
|
||||
id,
|
||||
),
|
||||
ViewSortExceptionCode.VIEW_SORT_NOT_FOUND,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete', () => {
|
||||
it('should delete a view sort successfully', async () => {
|
||||
const id = 'view-sort-id';
|
||||
const workspaceId = 'workspace-id';
|
||||
|
||||
jest.spyOn(viewSortService, 'findById').mockResolvedValue(mockViewSort);
|
||||
jest.spyOn(viewSortRepository, 'softDelete').mockResolvedValue({} as any);
|
||||
|
||||
const result = await viewSortService.delete(id, workspaceId);
|
||||
|
||||
expect(viewSortService.findById).toHaveBeenCalledWith(id, workspaceId);
|
||||
expect(viewSortRepository.softDelete).toHaveBeenCalledWith(id);
|
||||
expect(result).toEqual(mockViewSort);
|
||||
});
|
||||
|
||||
it('should throw exception when view sort is not found', async () => {
|
||||
const id = 'non-existent-id';
|
||||
const workspaceId = 'workspace-id';
|
||||
|
||||
jest.spyOn(viewSortService, 'findById').mockResolvedValue(null);
|
||||
|
||||
await expect(viewSortService.delete(id, workspaceId)).rejects.toThrow(
|
||||
new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.VIEW_SORT_NOT_FOUND,
|
||||
id,
|
||||
),
|
||||
ViewSortExceptionCode.VIEW_SORT_NOT_FOUND,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('destroy', () => {
|
||||
it('should destroy a view sort successfully', async () => {
|
||||
const id = 'view-sort-id';
|
||||
const workspaceId = 'workspace-id';
|
||||
|
||||
jest.spyOn(viewSortRepository, 'findOne').mockResolvedValue(mockViewSort);
|
||||
jest.spyOn(viewSortRepository, 'delete').mockResolvedValue({} as any);
|
||||
|
||||
const result = await viewSortService.destroy(id, workspaceId);
|
||||
|
||||
expect(viewSortRepository.findOne).toHaveBeenCalledWith({
|
||||
where: { id, workspaceId },
|
||||
relations: ['workspace', 'view'],
|
||||
withDeleted: true,
|
||||
});
|
||||
expect(viewSortRepository.delete).toHaveBeenCalledWith(id);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
+286
-157
@@ -1,32 +1,305 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IsNull, Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { fromCreateViewSortInputToFlatViewSortToCreate } from 'src/engine/metadata-modules/flat-view-sort/utils/from-create-view-sort-input-to-flat-view-sort-to-create.util';
|
||||
import { fromDeleteViewSortInputToFlatViewSortOrThrow } from 'src/engine/metadata-modules/flat-view-sort/utils/from-delete-view-sort-input-to-flat-view-sort-or-throw.util';
|
||||
import { fromDestroyViewSortInputToFlatViewSortOrThrow } from 'src/engine/metadata-modules/flat-view-sort/utils/from-destroy-view-sort-input-to-flat-view-sort-or-throw.util';
|
||||
import { fromUpdateViewSortInputToFlatViewSortToUpdateOrThrow } from 'src/engine/metadata-modules/flat-view-sort/utils/from-update-view-sort-input-to-flat-view-sort-to-update-or-throw.util';
|
||||
import { CreateViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/create-view-sort.input';
|
||||
import { DeleteViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/delete-view-sort.input';
|
||||
import { DestroyViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/destroy-view-sort.input';
|
||||
import { UpdateViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/inputs/update-view-sort.input';
|
||||
import { ViewSortDTO } from 'src/engine/metadata-modules/view-sort/dtos/view-sort.dto';
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
import {
|
||||
ViewSortException,
|
||||
ViewSortExceptionCode,
|
||||
ViewSortExceptionMessageKey,
|
||||
generateViewSortExceptionMessage,
|
||||
generateViewSortUserFriendlyExceptionMessage,
|
||||
} from 'src/engine/metadata-modules/view-sort/exceptions/view-sort.exception';
|
||||
import { FIND_ALL_CORE_VIEWS_GRAPHQL_OPERATION } from 'src/engine/metadata-modules/view/constants/find-all-core-views-graphql-operation.constant';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { fromFlatViewSortToViewSortDto } from 'src/engine/metadata-modules/view-sort/utils/from-flat-view-sort-to-view-sort-dto.util';
|
||||
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
|
||||
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
|
||||
|
||||
// TODO migrate to v2
|
||||
@Injectable()
|
||||
export class ViewSortService {
|
||||
constructor(
|
||||
@InjectRepository(ViewSortEntity)
|
||||
private readonly viewSortRepository: Repository<ViewSortEntity>,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
createViewSortInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
createViewSortInput: CreateViewSortInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewSortDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatFieldMetadataMaps, flatViewMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatFieldMetadataMaps', 'flatViewMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatViewSortToCreate = fromCreateViewSortInputToFlatViewSortToCreate({
|
||||
createViewSortInput,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatFieldMetadataMaps,
|
||||
flatViewMaps,
|
||||
});
|
||||
|
||||
const buildAndRunResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
viewSort: {
|
||||
flatEntityToCreate: [flatViewSortToCreate],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
if (buildAndRunResult.status === 'fail') {
|
||||
throw new WorkspaceMigrationBuilderException(
|
||||
buildAndRunResult,
|
||||
'Multiple validation errors occurred while creating view sort',
|
||||
);
|
||||
}
|
||||
|
||||
const { flatViewSortMaps: recomputedExistingFlatViewSortMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewSortMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return fromFlatViewSortToViewSortDto(
|
||||
findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: flatViewSortToCreate.id,
|
||||
flatEntityMaps: recomputedExistingFlatViewSortMaps,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async updateOne({
|
||||
updateViewSortInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
updateViewSortInput: UpdateViewSortInput;
|
||||
}): Promise<ViewSortDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewSortMaps: existingFlatViewSortMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewSortMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const optimisticallyUpdatedFlatViewSort =
|
||||
fromUpdateViewSortInputToFlatViewSortToUpdateOrThrow({
|
||||
flatViewSortMaps: existingFlatViewSortMaps,
|
||||
updateViewSortInput,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
viewSort: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [optimisticallyUpdatedFlatViewSort],
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
if (validateAndBuildResult.status === 'fail') {
|
||||
throw new WorkspaceMigrationBuilderException(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while updating view sort',
|
||||
);
|
||||
}
|
||||
|
||||
const { flatViewSortMaps: recomputedExistingFlatViewSortMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewSortMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return fromFlatViewSortToViewSortDto(
|
||||
findFlatEntityByUniversalIdentifierOrThrow({
|
||||
universalIdentifier:
|
||||
optimisticallyUpdatedFlatViewSort.universalIdentifier,
|
||||
flatEntityMaps: recomputedExistingFlatViewSortMaps,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async deleteOne({
|
||||
deleteViewSortInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
deleteViewSortInput: DeleteViewSortInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewSortDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewSortMaps: existingFlatViewSortMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewSortMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const optimisticallyUpdatedFlatViewSortWithDeletedAt =
|
||||
fromDeleteViewSortInputToFlatViewSortOrThrow({
|
||||
flatViewSortMaps: existingFlatViewSortMaps,
|
||||
deleteViewSortInput,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
viewSort: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: [
|
||||
optimisticallyUpdatedFlatViewSortWithDeletedAt,
|
||||
],
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
if (validateAndBuildResult.status === 'fail') {
|
||||
throw new WorkspaceMigrationBuilderException(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while deleting view sort',
|
||||
);
|
||||
}
|
||||
|
||||
const { flatViewSortMaps: recomputedExistingFlatViewSortMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewSortMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return fromFlatViewSortToViewSortDto(
|
||||
findFlatEntityByUniversalIdentifierOrThrow({
|
||||
universalIdentifier:
|
||||
optimisticallyUpdatedFlatViewSortWithDeletedAt.universalIdentifier,
|
||||
flatEntityMaps: recomputedExistingFlatViewSortMaps,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async destroyOne({
|
||||
destroyViewSortInput,
|
||||
workspaceId,
|
||||
}: {
|
||||
destroyViewSortInput: DestroyViewSortInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewSortDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewSortMaps: existingFlatViewSortMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewSortMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const existingViewSortToDelete =
|
||||
fromDestroyViewSortInputToFlatViewSortOrThrow({
|
||||
destroyViewSortInput,
|
||||
flatViewSortMaps: existingFlatViewSortMaps,
|
||||
});
|
||||
|
||||
const existingFlatViewSort = findFlatEntityByUniversalIdentifierOrThrow({
|
||||
universalIdentifier: existingViewSortToDelete.universalIdentifier,
|
||||
flatEntityMaps: existingFlatViewSortMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
viewSort: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: [existingViewSortToDelete],
|
||||
flatEntityToUpdate: [],
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
if (validateAndBuildResult.status === 'fail') {
|
||||
throw new WorkspaceMigrationBuilderException(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while destroying view sort',
|
||||
);
|
||||
}
|
||||
|
||||
return fromFlatViewSortToViewSortDto(existingFlatViewSort);
|
||||
}
|
||||
|
||||
async findByWorkspaceId(workspaceId: string): Promise<ViewSortEntity[]> {
|
||||
return this.viewSortRepository.find({
|
||||
where: {
|
||||
@@ -66,148 +339,4 @@ export class ViewSortService {
|
||||
|
||||
return viewSort || null;
|
||||
}
|
||||
|
||||
async create(viewSortData: Partial<ViewSortEntity>): Promise<ViewSortEntity> {
|
||||
if (!isDefined(viewSortData.workspaceId)) {
|
||||
throw new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.WORKSPACE_ID_REQUIRED,
|
||||
),
|
||||
ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
{
|
||||
userFriendlyMessage: generateViewSortUserFriendlyExceptionMessage(
|
||||
ViewSortExceptionMessageKey.WORKSPACE_ID_REQUIRED,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId: viewSortData.workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (!isDefined(viewSortData.viewId)) {
|
||||
throw new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.VIEW_ID_REQUIRED,
|
||||
),
|
||||
ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
{
|
||||
userFriendlyMessage: generateViewSortUserFriendlyExceptionMessage(
|
||||
ViewSortExceptionMessageKey.VIEW_ID_REQUIRED,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (!isDefined(viewSortData.fieldMetadataId)) {
|
||||
throw new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.FIELD_METADATA_ID_REQUIRED,
|
||||
),
|
||||
ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
{
|
||||
userFriendlyMessage: generateViewSortUserFriendlyExceptionMessage(
|
||||
ViewSortExceptionMessageKey.FIELD_METADATA_ID_REQUIRED,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const viewSort = this.viewSortRepository.create({
|
||||
...viewSortData,
|
||||
universalIdentifier: v4(),
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const savedViewSort = await this.viewSortRepository.save(viewSort);
|
||||
|
||||
await this.flushGraphQLCache(viewSortData.workspaceId);
|
||||
|
||||
return savedViewSort;
|
||||
}
|
||||
|
||||
async update(
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
updateData: Partial<ViewSortEntity>,
|
||||
): Promise<ViewSortEntity> {
|
||||
const existingViewSort = await this.findById(id, workspaceId);
|
||||
|
||||
if (!isDefined(existingViewSort)) {
|
||||
throw new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.VIEW_SORT_NOT_FOUND,
|
||||
id,
|
||||
),
|
||||
ViewSortExceptionCode.VIEW_SORT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const updatedViewSort = await this.viewSortRepository.save({
|
||||
id,
|
||||
...updateData,
|
||||
});
|
||||
|
||||
await this.flushGraphQLCache(workspaceId);
|
||||
|
||||
return { ...existingViewSort, ...updatedViewSort };
|
||||
}
|
||||
|
||||
async delete(id: string, workspaceId: string): Promise<ViewSortEntity> {
|
||||
const viewSort = await this.findById(id, workspaceId);
|
||||
|
||||
if (!isDefined(viewSort)) {
|
||||
throw new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.VIEW_SORT_NOT_FOUND,
|
||||
id,
|
||||
),
|
||||
ViewSortExceptionCode.VIEW_SORT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
await this.viewSortRepository.softDelete(id);
|
||||
|
||||
await this.flushGraphQLCache(workspaceId);
|
||||
|
||||
return viewSort;
|
||||
}
|
||||
|
||||
async destroy(id: string, workspaceId: string): Promise<boolean> {
|
||||
const viewSort = await this.viewSortRepository.findOne({
|
||||
where: {
|
||||
id,
|
||||
workspaceId,
|
||||
},
|
||||
relations: ['workspace', 'view'],
|
||||
withDeleted: true,
|
||||
});
|
||||
|
||||
if (!isDefined(viewSort)) {
|
||||
throw new ViewSortException(
|
||||
generateViewSortExceptionMessage(
|
||||
ViewSortExceptionMessageKey.VIEW_SORT_NOT_FOUND,
|
||||
id,
|
||||
),
|
||||
ViewSortExceptionCode.VIEW_SORT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
await this.viewSortRepository.delete(id);
|
||||
|
||||
await this.flushGraphQLCache(workspaceId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async flushGraphQLCache(workspaceId: string): Promise<void> {
|
||||
await this.workspaceCacheStorageService.flushGraphQLOperation({
|
||||
operationName: FIND_ALL_CORE_VIEWS_GRAPHQL_OPERATION,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { type FlatViewSort } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort.type';
|
||||
import { type ViewSortDTO } from 'src/engine/metadata-modules/view-sort/dtos/view-sort.dto';
|
||||
|
||||
export const fromFlatViewSortToViewSortDto = (
|
||||
flatViewSort: FlatViewSort,
|
||||
): ViewSortDTO => {
|
||||
const { createdAt, updatedAt, deletedAt, ...rest } = flatViewSort;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
deletedAt: deletedAt ? new Date(deletedAt) : null,
|
||||
};
|
||||
};
|
||||
@@ -10,14 +10,18 @@ import { ViewSortResolver } from 'src/engine/metadata-modules/view-sort/resolver
|
||||
import { ViewSortService } from 'src/engine/metadata-modules/view-sort/services/view-sort.service';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ViewSortEntity, ViewEntity]),
|
||||
PermissionsModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
ViewPermissionsModule,
|
||||
ApplicationModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
ViewPermissionsModule,
|
||||
],
|
||||
controllers: [ViewSortController],
|
||||
providers: [ViewSortService, ViewSortResolver],
|
||||
|
||||
+2
@@ -175,6 +175,8 @@ describe('WorkspaceEntityManager', () => {
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
};
|
||||
|
||||
|
||||
+2
@@ -105,6 +105,8 @@ describe('WorkspaceRepository', () => {
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
universalSettings: null,
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ export const WORKSPACE_CACHE_KEYS_V2 = {
|
||||
flatViewGroupMaps: 'flat-maps:view-group',
|
||||
flatViewFilterMaps: 'flat-maps:view-filter',
|
||||
flatViewFilterGroupMaps: 'flat-maps:view-filter-group',
|
||||
flatViewSortMaps: 'flat-maps:view-sort',
|
||||
flatLogicFunctionMaps: 'flat-maps:logic-function',
|
||||
featureFlagsMap: 'feature-flag:feature-flags-map',
|
||||
rolesPermissions: 'metadata:permissions:roles-permissions',
|
||||
|
||||
+2
@@ -110,6 +110,8 @@ export const createStandardFieldFlatMetadata = <
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
universalSettings: settings ?? null,
|
||||
};
|
||||
};
|
||||
|
||||
+2
@@ -130,6 +130,8 @@ export const createStandardRelationFieldFlatMetadata = <
|
||||
kanbanAggregateOperationViewUniversalIdentifiers: [],
|
||||
calendarViewUniversalIdentifiers: [],
|
||||
mainGroupByFieldMetadataViewUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
universalSettings: settings,
|
||||
};
|
||||
};
|
||||
|
||||
+2
@@ -152,6 +152,8 @@ export const createStandardViewFlatMetadata = <
|
||||
viewGroupUniversalIdentifiers: [],
|
||||
viewFilterGroupIds: [],
|
||||
viewFilterGroupUniversalIdentifiers: [],
|
||||
viewSortIds: [],
|
||||
viewSortUniversalIdentifiers: [],
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
deletedAt: null,
|
||||
|
||||
+1
@@ -166,6 +166,7 @@ export const enrichCreateWorkspaceMigrationActionsWithIds = ({
|
||||
case 'commandMenuItem':
|
||||
case 'navigationMenuItem':
|
||||
case 'frontComponent':
|
||||
case 'viewSort':
|
||||
case 'webhook': {
|
||||
if (!isDefined(idByUniversalIdentifier)) {
|
||||
return action;
|
||||
|
||||
+28
@@ -36,6 +36,7 @@ import { WorkspaceMigrationViewFilterActionsBuilderService } from 'src/engine/wo
|
||||
import { WorkspaceMigrationViewGroupActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-group/workspace-migration-view-group-actions-builder.service';
|
||||
import { WorkspaceMigrationViewActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view/workspace-migration-view-actions-builder.service';
|
||||
import { WorkspaceMigrationWebhookActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/webhook/workspace-migration-webhook-actions-builder.service';
|
||||
import { WorkspaceMigrationViewSortActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-sort/workspace-migration-view-sort-actions.builder.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationBuildOrchestratorService {
|
||||
@@ -48,6 +49,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
private readonly workspaceMigrationViewFilterGroupActionsBuilderService: WorkspaceMigrationViewFilterGroupActionsBuilderService,
|
||||
private readonly workspaceMigrationViewGroupActionsBuilderService: WorkspaceMigrationViewGroupActionsBuilderService,
|
||||
private readonly workspaceMigrationViewFieldGroupActionsBuilderService: WorkspaceMigrationViewFieldGroupActionsBuilderService,
|
||||
private readonly workspaceMigrationViewSortActionsBuilderService: WorkspaceMigrationViewSortActionsBuilderService,
|
||||
private readonly workspaceMigrationLogicFunctionActionsBuilderService: WorkspaceMigrationLogicFunctionActionsBuilderService,
|
||||
private readonly workspaceMigrationRoleTargetActionsBuilderService: WorkspaceMigrationRoleTargetActionsBuilderService,
|
||||
private readonly workspaceMigrationFieldActionsBuilderService: WorkspaceMigrationFieldActionsBuilderService,
|
||||
@@ -134,6 +136,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
flatViewFilterGroupMaps,
|
||||
flatViewGroupMaps,
|
||||
flatViewFieldGroupMaps,
|
||||
flatViewSortMaps,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
@@ -355,6 +358,28 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatViewSortMaps)) {
|
||||
const { from: fromFlatViewSortMaps, to: toFlatViewSortMaps } =
|
||||
flatViewSortMaps;
|
||||
const viewSortResult =
|
||||
await this.workspaceMigrationViewSortActionsBuilderService.validateAndBuild(
|
||||
{
|
||||
additionalCacheDataMaps,
|
||||
from: fromFlatViewSortMaps,
|
||||
to: toFlatViewSortMaps,
|
||||
buildOptions,
|
||||
dependencyOptimisticFlatEntityMaps: optimisticAllFlatEntityMaps,
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (viewSortResult.status === 'fail') {
|
||||
orchestratorFailureReport.viewSort.push(...viewSortResult.errors);
|
||||
} else {
|
||||
orchestratorActionsReport.viewSort = viewSortResult.actions;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDefined(flatRowLevelPermissionPredicateGroupMaps)) {
|
||||
const {
|
||||
from: fromFlatRowLevelPermissionPredicateGroupMaps,
|
||||
@@ -763,6 +788,9 @@ export class WorkspaceMigrationBuildOrchestratorService {
|
||||
...aggregatedOrchestratorActionsReport.viewGroup.delete,
|
||||
...aggregatedOrchestratorActionsReport.viewGroup.create,
|
||||
...aggregatedOrchestratorActionsReport.viewGroup.update,
|
||||
...aggregatedOrchestratorActionsReport.viewSort.create,
|
||||
...aggregatedOrchestratorActionsReport.viewSort.update,
|
||||
...aggregatedOrchestratorActionsReport.viewSort.delete,
|
||||
///
|
||||
|
||||
// Logic functions
|
||||
|
||||
+2
@@ -5,6 +5,7 @@ exports[`ALL_UNIVERSAL_FLAT_ENTITY_FOREIGN_KEY_AGGREGATOR_PROPERTIES should matc
|
||||
"agent": [],
|
||||
"commandMenuItem": [],
|
||||
"fieldMetadata": [
|
||||
"viewSortUniversalIdentifiers",
|
||||
"viewFieldUniversalIdentifiers",
|
||||
"viewFilterUniversalIdentifiers",
|
||||
"kanbanAggregateOperationViewUniversalIdentifiers",
|
||||
@@ -56,6 +57,7 @@ exports[`ALL_UNIVERSAL_FLAT_ENTITY_FOREIGN_KEY_AGGREGATOR_PROPERTIES should matc
|
||||
"viewFilterUniversalIdentifiers",
|
||||
],
|
||||
"viewGroup": [],
|
||||
"viewSort": [],
|
||||
"webhook": [],
|
||||
}
|
||||
`;
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ export const ALL_JSONB_PROPERTIES_WITH_SERIALIZED_RELATION_BY_METADATA_NAME = {
|
||||
viewFieldGroup: {},
|
||||
viewFilter: {},
|
||||
viewFilterGroup: {},
|
||||
viewSort: {},
|
||||
index: {},
|
||||
role: {},
|
||||
roleTarget: {},
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import { type ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
import { type UniversalFlatEntityFrom } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
|
||||
export type UniversalFlatViewSort = UniversalFlatEntityFrom<
|
||||
ViewSortEntity,
|
||||
'viewSort'
|
||||
>;
|
||||
+1
-5
@@ -1,8 +1,4 @@
|
||||
import { type ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { type UniversalFlatEntityFrom } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
|
||||
// TODO remove once viewSorts has been migrated to v2
|
||||
export type UniversalFlatView = UniversalFlatEntityFrom<
|
||||
Omit<ViewEntity, 'viewSorts'>,
|
||||
'view'
|
||||
>;
|
||||
export type UniversalFlatView = UniversalFlatEntityFrom<ViewEntity, 'view'>;
|
||||
|
||||
+8
@@ -45,6 +45,8 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a crea
|
||||
"viewFieldUniversalIdentifiers": [],
|
||||
"viewFilterIds": [],
|
||||
"viewFilterUniversalIdentifiers": [],
|
||||
"viewSortIds": [],
|
||||
"viewSortUniversalIdentifiers": [],
|
||||
"workspaceId": "workspace-id-1",
|
||||
},
|
||||
},
|
||||
@@ -106,6 +108,8 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a dele
|
||||
"viewFieldUniversalIdentifiers": [],
|
||||
"viewFilterIds": [],
|
||||
"viewFilterUniversalIdentifiers": [],
|
||||
"viewSortIds": [],
|
||||
"viewSortUniversalIdentifiers": [],
|
||||
"workspaceId": "workspace-id-1",
|
||||
},
|
||||
},
|
||||
@@ -181,6 +185,8 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect create
|
||||
"viewFieldUniversalIdentifiers": [],
|
||||
"viewFilterIds": [],
|
||||
"viewFilterUniversalIdentifiers": [],
|
||||
"viewSortIds": [],
|
||||
"viewSortUniversalIdentifiers": [],
|
||||
"workspaceId": "workspace-id-1",
|
||||
},
|
||||
},
|
||||
@@ -228,6 +234,8 @@ exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect create
|
||||
"viewFieldUniversalIdentifiers": [],
|
||||
"viewFilterIds": [],
|
||||
"viewFilterUniversalIdentifiers": [],
|
||||
"viewSortIds": [],
|
||||
"viewSortUniversalIdentifiers": [],
|
||||
"workspaceId": "workspace-id-1",
|
||||
},
|
||||
},
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { type BaseFlatCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-create-workspace-migration-action.type';
|
||||
import { type BaseFlatUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-update-workspace-migration-action.type';
|
||||
import { type BaseFlatDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-flat-delete-workspace-migration-action.type';
|
||||
import { type BaseUniversalCreateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-create-workspace-migration-action.type';
|
||||
import { type BaseUniversalUpdateWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-update-workspace-migration-action.type';
|
||||
import { type BaseUniversalDeleteWorkspaceMigrationAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/base-universal-delete-workspace-migration-action.type';
|
||||
|
||||
export type FlatCreateViewSortAction =
|
||||
BaseFlatCreateWorkspaceMigrationAction<'viewSort'>;
|
||||
|
||||
export type FlatUpdateViewSortAction =
|
||||
BaseFlatUpdateWorkspaceMigrationAction<'viewSort'>;
|
||||
|
||||
export type FlatDeleteViewSortAction =
|
||||
BaseFlatDeleteWorkspaceMigrationAction<'viewSort'>;
|
||||
|
||||
export type UniversalCreateViewSortAction =
|
||||
BaseUniversalCreateWorkspaceMigrationAction<'viewSort'>;
|
||||
|
||||
export type UniversalUpdateViewSortAction =
|
||||
BaseUniversalUpdateWorkspaceMigrationAction<'viewSort'>;
|
||||
|
||||
export type UniversalDeleteViewSortAction =
|
||||
BaseUniversalDeleteWorkspaceMigrationAction<'viewSort'>;
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
|
||||
import { WorkspaceEntityMigrationBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/services/workspace-entity-migration-builder.service';
|
||||
import { UniversalUpdateViewSortAction } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-sort/types/workspace-migration-view-sort-action.type';
|
||||
import { FlatViewSortValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-view-sort-validator.service';
|
||||
import { UniversalFlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-validation-args.type';
|
||||
import { UniversalFlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-validation-result.type';
|
||||
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-update-validation-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationViewSortActionsBuilderService extends WorkspaceEntityMigrationBuilderService<
|
||||
typeof ALL_METADATA_NAME.viewSort
|
||||
> {
|
||||
constructor(
|
||||
private readonly flatViewSortValidatorService: FlatViewSortValidatorService,
|
||||
) {
|
||||
super(ALL_METADATA_NAME.viewSort);
|
||||
}
|
||||
|
||||
protected validateFlatEntityCreation(
|
||||
args: UniversalFlatEntityValidationArgs<typeof ALL_METADATA_NAME.viewSort>,
|
||||
): UniversalFlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewSort,
|
||||
'create'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewSortValidatorService.validateFlatViewSortCreation(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewSortToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'create',
|
||||
metadataName: 'viewSort',
|
||||
flatEntity: flatViewSortToValidate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityDeletion(
|
||||
args: UniversalFlatEntityValidationArgs<typeof ALL_METADATA_NAME.viewSort>,
|
||||
): UniversalFlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewSort,
|
||||
'delete'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewSortValidatorService.validateFlatViewSortDeletion(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { flatEntityToValidate: flatViewSortToValidate } = args;
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: {
|
||||
type: 'delete',
|
||||
metadataName: 'viewSort',
|
||||
universalIdentifier: flatViewSortToValidate.universalIdentifier,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
protected validateFlatEntityUpdate(
|
||||
args: FlatEntityUpdateValidationArgs<typeof ALL_METADATA_NAME.viewSort>,
|
||||
): UniversalFlatEntityValidationReturnType<
|
||||
typeof ALL_METADATA_NAME.viewSort,
|
||||
'update'
|
||||
> {
|
||||
const validationResult =
|
||||
this.flatViewSortValidatorService.validateFlatViewSortUpdate(args);
|
||||
|
||||
if (validationResult.errors.length > 0) {
|
||||
return {
|
||||
status: 'fail',
|
||||
...validationResult,
|
||||
};
|
||||
}
|
||||
|
||||
const { universalIdentifier, flatEntityUpdate } = args;
|
||||
|
||||
const updateViewSortAction: UniversalUpdateViewSortAction = {
|
||||
type: 'update',
|
||||
metadataName: 'viewSort',
|
||||
universalIdentifier,
|
||||
update: flatEntityUpdate,
|
||||
};
|
||||
|
||||
return {
|
||||
status: 'success',
|
||||
action: updateViewSortAction,
|
||||
};
|
||||
}
|
||||
}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { msg, t } from '@lingui/core/macro';
|
||||
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { ViewSortExceptionCode } from 'src/engine/metadata-modules/view-sort/exceptions/view-sort.exception';
|
||||
import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/types/failed-flat-entity-validation.type';
|
||||
import { getEmptyFlatEntityValidationError } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/utils/get-flat-entity-validation-error.util';
|
||||
import { type FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-update-validation-args.type';
|
||||
import { ViewSortDirection } from 'src/engine/metadata-modules/view-sort/enums/view-sort-direction';
|
||||
import { UniversalFlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/universal-flat-entity-validation-args.type';
|
||||
import { findManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-universal-identifier-in-universal-flat-entity-maps-or-throw.util';
|
||||
|
||||
@Injectable()
|
||||
export class FlatViewSortValidatorService {
|
||||
constructor() {}
|
||||
|
||||
validateFlatViewSortCreation({
|
||||
flatEntityToValidate: flatViewSortToValidate,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
|
||||
flatViewSortMaps: optimisticFlatViewSortMaps,
|
||||
flatViewMaps,
|
||||
flatFieldMetadataMaps,
|
||||
},
|
||||
}: UniversalFlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.viewSort
|
||||
>): FailedFlatEntityValidation<'viewSort', 'create'> {
|
||||
const validationResult = getEmptyFlatEntityValidationError({
|
||||
flatEntityMinimalInformation: {
|
||||
universalIdentifier: flatViewSortToValidate.universalIdentifier,
|
||||
viewUniversalIdentifier: flatViewSortToValidate.viewUniversalIdentifier,
|
||||
},
|
||||
metadataName: 'viewSort',
|
||||
type: 'create',
|
||||
});
|
||||
|
||||
const existingFlatViewSort = findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: flatViewSortToValidate.universalIdentifier,
|
||||
flatEntityMaps: optimisticFlatViewSortMaps,
|
||||
});
|
||||
|
||||
if (isDefined(existingFlatViewSort)) {
|
||||
const flatViewSortId = flatViewSortToValidate.universalIdentifier;
|
||||
|
||||
validationResult.errors.push({
|
||||
code: ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
message: t`View sort with id ${flatViewSortId} already exists`,
|
||||
userFriendlyMessage: msg`View sort already exists`,
|
||||
});
|
||||
}
|
||||
|
||||
const flatFieldMetadata = findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier:
|
||||
flatViewSortToValidate.fieldMetadataUniversalIdentifier,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatFieldMetadata)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
message: t`Field metadata not found`,
|
||||
userFriendlyMessage: msg`Field metadata not found`,
|
||||
});
|
||||
}
|
||||
|
||||
const flatView = findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: flatViewSortToValidate.viewUniversalIdentifier,
|
||||
flatEntityMaps: flatViewMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatView)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewSortExceptionCode.VIEW_NOT_FOUND,
|
||||
message: t`View not found`,
|
||||
userFriendlyMessage: msg`View not found`,
|
||||
});
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
const otherFlatViewSorts =
|
||||
findManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrow({
|
||||
universalIdentifiers: flatView.viewSortUniversalIdentifiers,
|
||||
flatEntityMaps: optimisticFlatViewSortMaps,
|
||||
});
|
||||
|
||||
const equivalentExistingFlatViewSortExists = otherFlatViewSorts.some(
|
||||
(flatViewSort) =>
|
||||
flatViewSort.universalIdentifier ===
|
||||
flatViewSortToValidate.universalIdentifier &&
|
||||
flatViewSort.fieldMetadataUniversalIdentifier ===
|
||||
flatViewSortToValidate.fieldMetadataUniversalIdentifier,
|
||||
);
|
||||
|
||||
if (equivalentExistingFlatViewSortExists) {
|
||||
validationResult.errors.push({
|
||||
code: ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
message: t`View sort with same fieldMetadataId and viewId already exists`,
|
||||
userFriendlyMessage: msg`View sort already exists`,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
!isDefined(flatViewSortToValidate.direction) ||
|
||||
!Object.values(ViewSortDirection).includes(
|
||||
flatViewSortToValidate.direction,
|
||||
)
|
||||
) {
|
||||
validationResult.errors.push({
|
||||
code: ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
message: t`View sort with invalid direction`,
|
||||
userFriendlyMessage: msg`View sort with invalid direction, should be ASC or DESC`,
|
||||
});
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
public validateFlatViewSortUpdate({
|
||||
universalIdentifier,
|
||||
flatEntityUpdate,
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
|
||||
flatViewSortMaps: optimisticFlatViewSortMaps,
|
||||
flatViewMaps,
|
||||
},
|
||||
}: FlatEntityUpdateValidationArgs<
|
||||
typeof ALL_METADATA_NAME.viewSort
|
||||
>): FailedFlatEntityValidation<'viewSort', 'update'> {
|
||||
const existingFlatViewSort = findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier,
|
||||
flatEntityMaps: optimisticFlatViewSortMaps,
|
||||
});
|
||||
|
||||
const validationResult = getEmptyFlatEntityValidationError({
|
||||
flatEntityMinimalInformation: {
|
||||
universalIdentifier,
|
||||
},
|
||||
metadataName: 'viewSort',
|
||||
type: 'update',
|
||||
});
|
||||
|
||||
if (!isDefined(existingFlatViewSort)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewSortExceptionCode.VIEW_SORT_NOT_FOUND,
|
||||
message: t`View sort to update not found`,
|
||||
userFriendlyMessage: msg`View sort to update not found`,
|
||||
});
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
const updatedFlatViewSort = {
|
||||
...existingFlatViewSort,
|
||||
...flatEntityUpdate,
|
||||
};
|
||||
|
||||
if (
|
||||
!isDefined(updatedFlatViewSort?.direction) ||
|
||||
!(
|
||||
updatedFlatViewSort.direction === ViewSortDirection.DESC ||
|
||||
updatedFlatViewSort.direction === ViewSortDirection.ASC
|
||||
)
|
||||
) {
|
||||
validationResult.errors.push({
|
||||
code: ViewSortExceptionCode.INVALID_VIEW_SORT_DATA,
|
||||
message: t`Correct direction is required`,
|
||||
userFriendlyMessage: msg`Correct direction is required`,
|
||||
});
|
||||
}
|
||||
|
||||
validationResult.flatEntityMinimalInformation = {
|
||||
...validationResult.flatEntityMinimalInformation,
|
||||
viewUniversalIdentifier: updatedFlatViewSort.viewUniversalIdentifier,
|
||||
};
|
||||
|
||||
const flatView = findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier: updatedFlatViewSort.viewUniversalIdentifier,
|
||||
flatEntityMaps: flatViewMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatView)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewSortExceptionCode.VIEW_NOT_FOUND,
|
||||
message: t`View sort to update parent view not found`,
|
||||
userFriendlyMessage: msg`View sort to update parent view not found`,
|
||||
});
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
public validateFlatViewSortDeletion({
|
||||
flatEntityToValidate: { universalIdentifier },
|
||||
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
|
||||
flatViewSortMaps: optimisticFlatViewSortMaps,
|
||||
},
|
||||
}: UniversalFlatEntityValidationArgs<
|
||||
typeof ALL_METADATA_NAME.viewSort
|
||||
>): FailedFlatEntityValidation<'viewSort', 'delete'> {
|
||||
const validationResult = getEmptyFlatEntityValidationError({
|
||||
flatEntityMinimalInformation: {
|
||||
universalIdentifier,
|
||||
},
|
||||
metadataName: 'viewSort',
|
||||
type: 'delete',
|
||||
});
|
||||
|
||||
const existingFlatViewSort = findFlatEntityByUniversalIdentifier({
|
||||
universalIdentifier,
|
||||
flatEntityMaps: optimisticFlatViewSortMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(existingFlatViewSort)) {
|
||||
validationResult.errors.push({
|
||||
code: ViewSortExceptionCode.VIEW_SORT_NOT_FOUND,
|
||||
message: t`View sort to delete not found`,
|
||||
userFriendlyMessage: msg`View sort to delete not found`,
|
||||
});
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
}
|
||||
+3
@@ -26,6 +26,7 @@ import { FlatViewFilterValidatorService } from 'src/engine/workspace-manager/wor
|
||||
import { FlatViewGroupValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-view-group-validator.service';
|
||||
import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-view-validator.service';
|
||||
import { FlatWebhookValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-webhook-validator.service';
|
||||
import { FlatViewSortValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-view-sort-validator.service';
|
||||
|
||||
@Module({
|
||||
imports: [FeatureFlagModule],
|
||||
@@ -36,6 +37,7 @@ import { FlatWebhookValidatorService } from 'src/engine/workspace-manager/worksp
|
||||
FlatViewFilterGroupValidatorService,
|
||||
FlatViewGroupValidatorService,
|
||||
FlatViewFieldGroupValidatorService,
|
||||
FlatViewSortValidatorService,
|
||||
FlatIndexValidatorService,
|
||||
FlatFieldMetadataValidatorService,
|
||||
FlatObjectMetadataValidatorService,
|
||||
@@ -63,6 +65,7 @@ import { FlatWebhookValidatorService } from 'src/engine/workspace-manager/worksp
|
||||
FlatViewFilterGroupValidatorService,
|
||||
FlatViewGroupValidatorService,
|
||||
FlatViewFieldGroupValidatorService,
|
||||
FlatViewSortValidatorService,
|
||||
FlatIndexValidatorService,
|
||||
FlatFieldMetadataValidatorService,
|
||||
FlatObjectMetadataValidatorService,
|
||||
|
||||
+3
@@ -26,6 +26,7 @@ import { WorkspaceMigrationViewFilterActionsBuilderService } from 'src/engine/wo
|
||||
import { WorkspaceMigrationViewGroupActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-group/workspace-migration-view-group-actions-builder.service';
|
||||
import { WorkspaceMigrationViewActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view/workspace-migration-view-actions-builder.service';
|
||||
import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/workspace-migration-builder-validators.module';
|
||||
import { WorkspaceMigrationViewSortActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-sort/workspace-migration-view-sort-actions.builder.service';
|
||||
|
||||
@Module({
|
||||
imports: [FeatureFlagModule, WorkspaceMigrationBuilderValidatorsModule],
|
||||
@@ -38,6 +39,7 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-
|
||||
WorkspaceMigrationViewFilterGroupActionsBuilderService,
|
||||
WorkspaceMigrationViewGroupActionsBuilderService,
|
||||
WorkspaceMigrationViewFieldGroupActionsBuilderService,
|
||||
WorkspaceMigrationViewSortActionsBuilderService,
|
||||
WorkspaceMigrationIndexActionsBuilderService,
|
||||
WorkspaceMigrationLogicFunctionActionsBuilderService,
|
||||
WorkspaceMigrationFieldActionsBuilderService,
|
||||
@@ -64,6 +66,7 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-
|
||||
WorkspaceMigrationViewFilterGroupActionsBuilderService,
|
||||
WorkspaceMigrationViewGroupActionsBuilderService,
|
||||
WorkspaceMigrationViewFieldGroupActionsBuilderService,
|
||||
WorkspaceMigrationViewSortActionsBuilderService,
|
||||
WorkspaceMigrationFieldActionsBuilderService,
|
||||
WorkspaceMigrationLogicFunctionActionsBuilderService,
|
||||
WorkspaceMigrationRoleActionsBuilderService,
|
||||
|
||||
+1
@@ -133,6 +133,7 @@ export const fromUniversalFlatFieldMetadataToFlatFieldMetadata = ({
|
||||
calendarViewIds: [],
|
||||
mainGroupByFieldMetadataViewIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
viewSortIds: [],
|
||||
...emptyUniversalForeignKeyAggregators,
|
||||
};
|
||||
};
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import {
|
||||
FlatCreateViewSortAction,
|
||||
UniversalCreateViewSortAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-sort/types/workspace-migration-view-sort-action.type';
|
||||
import {
|
||||
WorkspaceMigrationActionRunnerArgs,
|
||||
WorkspaceMigrationActionRunnerContext,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/workspace-migration-action-runner-args.type';
|
||||
import { resolveUniversalRelationIdentifiersToIds } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-relation-identifiers-to-ids.util';
|
||||
|
||||
@Injectable()
|
||||
export class CreateViewSortActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'create',
|
||||
'viewSort',
|
||||
) {
|
||||
override async transpileUniversalActionToFlatAction({
|
||||
action,
|
||||
allFlatEntityMaps,
|
||||
flatApplication,
|
||||
workspaceId,
|
||||
}: WorkspaceMigrationActionRunnerArgs<UniversalCreateViewSortAction>): Promise<FlatCreateViewSortAction> {
|
||||
const { fieldMetadataId, viewId } =
|
||||
resolveUniversalRelationIdentifiersToIds({
|
||||
flatEntityMaps: allFlatEntityMaps,
|
||||
metadataName: action.metadataName,
|
||||
universalForeignKeyValues: action.flatEntity,
|
||||
});
|
||||
|
||||
return {
|
||||
...action,
|
||||
flatEntity: {
|
||||
...action.flatEntity,
|
||||
fieldMetadataId,
|
||||
viewId,
|
||||
id: action.id ?? v4(),
|
||||
applicationId: flatApplication.id,
|
||||
workspaceId,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerContext<FlatCreateViewSortAction>,
|
||||
): Promise<void> {
|
||||
const { flatAction, queryRunner } = context;
|
||||
const { flatEntity } = flatAction;
|
||||
|
||||
await this.insertFlatEntitiesInRepository({
|
||||
queryRunner,
|
||||
flatEntities: [flatEntity],
|
||||
});
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerContext<FlatCreateViewSortAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
import {
|
||||
FlatDeleteViewSortAction,
|
||||
UniversalDeleteViewSortAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-sort/types/workspace-migration-view-sort-action.type';
|
||||
import {
|
||||
WorkspaceMigrationActionRunnerArgs,
|
||||
WorkspaceMigrationActionRunnerContext,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/workspace-migration-action-runner-args.type';
|
||||
|
||||
@Injectable()
|
||||
export class DeleteViewSortActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'delete',
|
||||
'viewSort',
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
override async transpileUniversalActionToFlatAction(
|
||||
context: WorkspaceMigrationActionRunnerArgs<UniversalDeleteViewSortAction>,
|
||||
): Promise<FlatDeleteViewSortAction> {
|
||||
return this.transpileUniversalDeleteActionToFlatDeleteAction(context);
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerContext<FlatDeleteViewSortAction>,
|
||||
): Promise<void> {
|
||||
const { flatAction, queryRunner, workspaceId } = context;
|
||||
|
||||
const viewSortRepository =
|
||||
queryRunner.manager.getRepository<ViewSortEntity>(ViewSortEntity);
|
||||
|
||||
await viewSortRepository.delete({
|
||||
id: flatAction.entityId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerContext<FlatDeleteViewSortAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/interfaces/workspace-migration-runner-action-handler-service.interface';
|
||||
|
||||
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
|
||||
import {
|
||||
FlatUpdateViewSortAction,
|
||||
UniversalUpdateViewSortAction,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/view-sort/types/workspace-migration-view-sort-action.type';
|
||||
import {
|
||||
WorkspaceMigrationActionRunnerArgs,
|
||||
WorkspaceMigrationActionRunnerContext,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/workspace-migration-action-runner-args.type';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { resolveUniversalUpdateRelationIdentifiersToIds } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/utils/resolve-universal-update-relation-identifiers-to-ids.util';
|
||||
|
||||
@Injectable()
|
||||
export class UpdateViewSortActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
|
||||
'update',
|
||||
'viewSort',
|
||||
) {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
override async transpileUniversalActionToFlatAction(
|
||||
context: WorkspaceMigrationActionRunnerArgs<UniversalUpdateViewSortAction>,
|
||||
): Promise<FlatUpdateViewSortAction> {
|
||||
const { action, allFlatEntityMaps } = context;
|
||||
|
||||
const flatViewSort = findFlatEntityByUniversalIdentifierOrThrow({
|
||||
flatEntityMaps: allFlatEntityMaps.flatViewSortMaps,
|
||||
universalIdentifier: action.universalIdentifier,
|
||||
});
|
||||
|
||||
const update = resolveUniversalUpdateRelationIdentifiersToIds({
|
||||
metadataName: 'viewSort',
|
||||
universalUpdate: action.update,
|
||||
allFlatEntityMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
type: 'update',
|
||||
metadataName: 'viewSort',
|
||||
entityId: flatViewSort.id,
|
||||
update,
|
||||
};
|
||||
}
|
||||
|
||||
async executeForMetadata(
|
||||
context: WorkspaceMigrationActionRunnerContext<FlatUpdateViewSortAction>,
|
||||
): Promise<void> {
|
||||
const { flatAction, queryRunner, workspaceId } = context;
|
||||
const { entityId, update } = flatAction;
|
||||
|
||||
const viewSortRepository =
|
||||
queryRunner.manager.getRepository<ViewSortEntity>(ViewSortEntity);
|
||||
|
||||
await viewSortRepository.update({ id: entityId, workspaceId }, update);
|
||||
}
|
||||
|
||||
async executeForWorkspaceSchema(
|
||||
_context: WorkspaceMigrationActionRunnerContext<FlatUpdateViewSortAction>,
|
||||
): Promise<void> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+1
@@ -62,6 +62,7 @@ export class CreateViewActionHandlerService extends WorkspaceMigrationRunnerActi
|
||||
viewGroupIds: [],
|
||||
viewFilterIds: [],
|
||||
viewFilterGroupIds: [],
|
||||
viewSortIds: [],
|
||||
...emptyUniversalForeignKeyAggregators,
|
||||
},
|
||||
};
|
||||
|
||||
+7
@@ -72,6 +72,9 @@ import { UpdateViewGroupActionHandlerService } from 'src/engine/workspace-manage
|
||||
import { CreateViewActionHandlerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/view/services/create-view-action-handler.service';
|
||||
import { DeleteViewActionHandlerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/view/services/delete-view-action-handler.service';
|
||||
import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/view/services/update-view-action-handler.service';
|
||||
import { CreateViewSortActionHandlerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/view-sort/services/create-view-sort-action-handler.service';
|
||||
import { UpdateViewSortActionHandlerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/view-sort/services/update-view-sort-action-handler.service';
|
||||
import { DeleteViewSortActionHandlerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/view-sort/services/delete-view-sort-action-handler.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -107,6 +110,10 @@ import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/wor
|
||||
UpdateViewFilterGroupActionHandlerService,
|
||||
DeleteViewFilterGroupActionHandlerService,
|
||||
|
||||
CreateViewSortActionHandlerService,
|
||||
UpdateViewSortActionHandlerService,
|
||||
DeleteViewSortActionHandlerService,
|
||||
|
||||
CreateViewGroupActionHandlerService,
|
||||
UpdateViewGroupActionHandlerService,
|
||||
DeleteViewGroupActionHandlerService,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user