Reset Tab Page Layout (#19453)
## Context - Add "Reset to default" for page layout tabs and widgets — backend mutation resets overrides, reactivates deactivated children, and deletes custom children - Fix override write bug where mutating an overridable property (e.g. widget title) on a standard-app entity incorrectly overwrote the base column instead of writing to the overrides JSONB — PageLayoutUpdateService now uses resolveFlatEntityOverridableProperties for accurate diffing and routes properties through sanitizeOverridableEntityInput - Deprecate isOverridden - We need more time to think about this feature. Currently this adds too much complexity for a very small benefit https://github.com/user-attachments/assets/a84546c8-1e15-4d9e-a489-0825cf8b8ed2
This commit is contained in:
@@ -584,7 +584,7 @@ type ViewField {
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
deletedAt: DateTime
|
||||
isOverridden: Boolean!
|
||||
isOverridden: Boolean @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
|
||||
enum AggregateOperations {
|
||||
@@ -693,7 +693,7 @@ type ViewFieldGroup {
|
||||
updatedAt: DateTime!
|
||||
deletedAt: DateTime
|
||||
viewFields: [ViewField!]!
|
||||
isOverridden: Boolean!
|
||||
isOverridden: Boolean! @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
|
||||
type View {
|
||||
@@ -899,7 +899,7 @@ type PageLayoutWidget {
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
deletedAt: DateTime
|
||||
isOverridden: Boolean!
|
||||
isOverridden: Boolean @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
|
||||
enum WidgetType {
|
||||
@@ -1233,7 +1233,7 @@ type PageLayoutTab {
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
deletedAt: DateTime
|
||||
isOverridden: Boolean!
|
||||
isOverridden: Boolean @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
|
||||
type PageLayout {
|
||||
@@ -3471,6 +3471,7 @@ type Mutation {
|
||||
destroyPageLayout(id: String!): Boolean!
|
||||
updatePageLayoutWithTabsAndWidgets(id: String!, input: UpdatePageLayoutWithTabsInput!): PageLayout!
|
||||
resetPageLayoutWidgetToDefault(id: String!): PageLayoutWidget!
|
||||
resetPageLayoutTabToDefault(id: String!): PageLayoutTab!
|
||||
createPageLayoutWidget(input: CreatePageLayoutWidgetInput!): PageLayoutWidget!
|
||||
updatePageLayoutWidget(id: String!, input: UpdatePageLayoutWidgetInput!): PageLayoutWidget!
|
||||
destroyPageLayoutWidget(id: String!): Boolean!
|
||||
|
||||
@@ -416,7 +416,8 @@ export interface ViewField {
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
isOverridden: Scalars['Boolean']
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: Scalars['Boolean']
|
||||
__typename: 'ViewField'
|
||||
}
|
||||
|
||||
@@ -493,6 +494,7 @@ export interface ViewFieldGroup {
|
||||
updatedAt: Scalars['DateTime']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
viewFields: ViewField[]
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden: Scalars['Boolean']
|
||||
__typename: 'ViewFieldGroup'
|
||||
}
|
||||
@@ -672,7 +674,8 @@ export interface PageLayoutWidget {
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
isOverridden: Scalars['Boolean']
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: Scalars['Boolean']
|
||||
__typename: 'PageLayoutWidget'
|
||||
}
|
||||
|
||||
@@ -956,7 +959,8 @@ export interface PageLayoutTab {
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
isOverridden: Scalars['Boolean']
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: Scalars['Boolean']
|
||||
__typename: 'PageLayoutTab'
|
||||
}
|
||||
|
||||
@@ -2919,6 +2923,7 @@ export interface Mutation {
|
||||
destroyPageLayout: Scalars['Boolean']
|
||||
updatePageLayoutWithTabsAndWidgets: PageLayout
|
||||
resetPageLayoutWidgetToDefault: PageLayoutWidget
|
||||
resetPageLayoutTabToDefault: PageLayoutTab
|
||||
createPageLayoutWidget: PageLayoutWidget
|
||||
updatePageLayoutWidget: PageLayoutWidget
|
||||
destroyPageLayoutWidget: Scalars['Boolean']
|
||||
@@ -3525,6 +3530,7 @@ export interface ViewFieldGenqlSelection{
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
@@ -3599,6 +3605,7 @@ export interface ViewFieldGroupGenqlSelection{
|
||||
updatedAt?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
viewFields?: ViewFieldGenqlSelection
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
@@ -3770,6 +3777,7 @@ export interface PageLayoutWidgetGenqlSelection{
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
@@ -4081,6 +4089,7 @@ export interface PageLayoutTabGenqlSelection{
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
__typename?: boolean | number
|
||||
__scalar?: boolean | number
|
||||
@@ -6187,6 +6196,7 @@ export interface MutationGenqlSelection{
|
||||
destroyPageLayout?: { __args: {id: Scalars['String']} }
|
||||
updatePageLayoutWithTabsAndWidgets?: (PageLayoutGenqlSelection & { __args: {id: Scalars['String'], input: UpdatePageLayoutWithTabsInput} })
|
||||
resetPageLayoutWidgetToDefault?: (PageLayoutWidgetGenqlSelection & { __args: {id: Scalars['String']} })
|
||||
resetPageLayoutTabToDefault?: (PageLayoutTabGenqlSelection & { __args: {id: Scalars['String']} })
|
||||
createPageLayoutWidget?: (PageLayoutWidgetGenqlSelection & { __args: {input: CreatePageLayoutWidgetInput} })
|
||||
updatePageLayoutWidget?: (PageLayoutWidgetGenqlSelection & { __args: {id: Scalars['String'], input: UpdatePageLayoutWidgetInput} })
|
||||
destroyPageLayoutWidget?: { __args: {id: Scalars['String']} }
|
||||
|
||||
@@ -7812,6 +7812,15 @@ export default {
|
||||
]
|
||||
}
|
||||
],
|
||||
"resetPageLayoutTabToDefault": [
|
||||
113,
|
||||
{
|
||||
"id": [
|
||||
1,
|
||||
"String!"
|
||||
]
|
||||
}
|
||||
],
|
||||
"createPageLayoutWidget": [
|
||||
75,
|
||||
{
|
||||
|
||||
File diff suppressed because one or more lines are too long
-1
@@ -10,7 +10,6 @@ export const PAGE_LAYOUT_TAB_FRAGMENT = gql`
|
||||
icon
|
||||
position
|
||||
layoutMode
|
||||
isOverridden
|
||||
widgets {
|
||||
...PageLayoutWidgetFragment
|
||||
}
|
||||
|
||||
-5
@@ -68,7 +68,6 @@ const mixedGraphsPageLayoutMocks = {
|
||||
title: 'Mixed Graphs',
|
||||
position: 0,
|
||||
pageLayoutId: 'mixed-graphs-layout',
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -93,7 +92,6 @@ const mixedGraphsPageLayoutMocks = {
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
aggregateFieldMetadataId: idField.id,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -119,7 +117,6 @@ const mixedGraphsPageLayoutMocks = {
|
||||
aggregateFieldMetadataId: idField.id,
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -146,7 +143,6 @@ const mixedGraphsPageLayoutMocks = {
|
||||
groupByFieldMetadataId: createdAtField.id,
|
||||
orderBy: GraphOrderBy.VALUE_DESC,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -176,7 +172,6 @@ const mixedGraphsPageLayoutMocks = {
|
||||
axisNameDisplay: AxisNameDisplay.BOTH,
|
||||
displayDataLabel: false,
|
||||
} satisfies BarChartConfiguration,
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
|
||||
-4
@@ -30,7 +30,6 @@ const createInitialTabs = (): PageLayoutTab[] => [
|
||||
icon: 'IconPlus',
|
||||
pageLayoutId: 'test-layout',
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -43,7 +42,6 @@ const createInitialTabs = (): PageLayoutTab[] => [
|
||||
position: 1,
|
||||
pageLayoutId: 'test-layout',
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -56,7 +54,6 @@ const createInitialTabs = (): PageLayoutTab[] => [
|
||||
position: 2,
|
||||
pageLayoutId: 'test-layout',
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -86,7 +83,6 @@ const PageLayoutTabListPlayground = ({
|
||||
position: nextIndex,
|
||||
pageLayoutId: 'test-layout',
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-14
@@ -26,7 +26,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -50,7 +49,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -66,7 +64,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 200,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -90,7 +87,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -106,7 +102,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 300,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -130,7 +125,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -146,7 +140,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 400,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -170,7 +163,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -186,7 +178,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 500,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -210,7 +201,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -226,7 +216,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 600,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -250,7 +239,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -266,7 +254,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 700,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_COMPANY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -290,7 +277,6 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-2
@@ -26,7 +26,6 @@ export const DEFAULT_MESSAGE_THREAD_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: DEFAULT_MESSAGE_THREAD_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -50,7 +49,6 @@ export const DEFAULT_MESSAGE_THREAD_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -26,7 +26,6 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -53,7 +52,6 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -77,7 +75,6 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -100,7 +97,6 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 150,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -124,7 +120,6 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -147,7 +142,6 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 200,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -171,7 +165,6 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -187,7 +180,6 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 300,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_NOTE_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -211,7 +203,6 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-14
@@ -26,7 +26,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -50,7 +49,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -66,7 +64,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 200,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -90,7 +87,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -106,7 +102,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 300,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -130,7 +125,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -146,7 +140,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 400,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -170,7 +163,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -186,7 +178,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 500,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -210,7 +201,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -226,7 +216,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 600,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -250,7 +239,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -266,7 +254,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 700,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -290,7 +277,6 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-14
@@ -26,7 +26,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -50,7 +49,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -66,7 +64,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 200,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -90,7 +87,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -106,7 +102,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 300,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -130,7 +125,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -146,7 +140,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 400,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -170,7 +163,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -186,7 +178,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 500,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -210,7 +201,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -226,7 +216,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 600,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -250,7 +239,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -266,7 +254,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 700,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_PERSON_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -290,7 +277,6 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -26,7 +26,6 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -50,7 +49,6 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -66,7 +64,6 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 200,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -90,7 +87,6 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -106,7 +102,6 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 300,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -130,7 +125,6 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -146,7 +140,6 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 400,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -170,7 +163,6 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -186,7 +178,6 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 500,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -210,7 +201,6 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -26,7 +26,6 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -50,7 +49,6 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -74,7 +72,6 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -97,7 +94,6 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 150,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -121,7 +117,6 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -144,7 +139,6 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 200,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -168,7 +162,6 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -184,7 +177,6 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
position: 300,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_TASK_RECORD_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -208,7 +200,6 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -31,7 +31,6 @@ export const DEFAULT_WORKFLOW_PAGE_LAYOUT: PageLayout = {
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
icon: 'IconSettings',
|
||||
pageLayoutId: DEFAULT_WORKFLOW_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -55,7 +54,6 @@ export const DEFAULT_WORKFLOW_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-4
@@ -32,7 +32,6 @@ export const DEFAULT_WORKFLOW_RUN_PAGE_LAYOUT: PageLayout = {
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
icon: 'IconHome',
|
||||
pageLayoutId: DEFAULT_WORKFLOW_RUN_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -56,7 +55,6 @@ export const DEFAULT_WORKFLOW_RUN_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -73,7 +71,6 @@ export const DEFAULT_WORKFLOW_RUN_PAGE_LAYOUT: PageLayout = {
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
icon: 'IconSettings',
|
||||
pageLayoutId: DEFAULT_WORKFLOW_RUN_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -97,7 +94,6 @@ export const DEFAULT_WORKFLOW_RUN_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-4
@@ -32,7 +32,6 @@ export const DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT: PageLayout = {
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -56,7 +55,6 @@ export const DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -73,7 +71,6 @@ export const DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT: PageLayout = {
|
||||
position: 200,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
pageLayoutId: DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT_ID,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -97,7 +94,6 @@ export const DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT: PageLayout = {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-1
@@ -6,7 +6,6 @@ export const PAGE_LAYOUT_WIDGET_FRAGMENT = gql`
|
||||
title
|
||||
type
|
||||
objectMetadataId
|
||||
isOverridden
|
||||
createdAt
|
||||
updatedAt
|
||||
deletedAt
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
import { PAGE_LAYOUT_TAB_FRAGMENT } from '@/dashboards/graphql/fragments/pageLayoutTabFragment';
|
||||
|
||||
export const RESET_PAGE_LAYOUT_TAB_TO_DEFAULT = gql`
|
||||
${PAGE_LAYOUT_TAB_FRAGMENT}
|
||||
mutation ResetPageLayoutTabToDefault($id: String!) {
|
||||
resetPageLayoutTabToDefault(id: $id) {
|
||||
...PageLayoutTabFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
-2
@@ -25,7 +25,6 @@ const makeWidget = (
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
type: WidgetType.FIELDS,
|
||||
isOverridden: false,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
position: {
|
||||
@@ -51,7 +50,6 @@ const makeTab = (
|
||||
layoutMode,
|
||||
pageLayoutId: '',
|
||||
widgets,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-2
@@ -25,7 +25,6 @@ const makeWidget = (
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
type: WidgetType.FIELDS,
|
||||
isOverridden: false,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
position: {
|
||||
@@ -51,7 +50,6 @@ const makeTab = (
|
||||
layoutMode,
|
||||
pageLayoutId: '',
|
||||
widgets,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-2
@@ -82,7 +82,6 @@ describe('useCreatePageLayoutGraphWidget', () => {
|
||||
position: 0,
|
||||
pageLayoutId: '',
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -166,7 +165,6 @@ describe('useCreatePageLayoutGraphWidget', () => {
|
||||
position: 0,
|
||||
pageLayoutId: '',
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-1
@@ -311,7 +311,6 @@ describe('useCreatePageLayoutTab', () => {
|
||||
position: 0,
|
||||
pageLayoutId: 'test-layout',
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-2
@@ -26,7 +26,6 @@ const makeWidget = (
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
type: WidgetType.FIELDS,
|
||||
isOverridden: false,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
position: {
|
||||
@@ -50,7 +49,6 @@ const makeTab = (
|
||||
position,
|
||||
pageLayoutId: '',
|
||||
widgets,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-2
@@ -25,7 +25,6 @@ const makeWidget = (
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
type: WidgetType.FIELDS,
|
||||
isOverridden: false,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
position: {
|
||||
@@ -50,7 +49,6 @@ const makeTab = (
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: '',
|
||||
widgets,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-2
@@ -25,7 +25,6 @@ const makeWidget = (
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
type: WidgetType.FIELDS,
|
||||
isOverridden: false,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
position: {
|
||||
@@ -50,7 +49,6 @@ const makeTab = (
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: '',
|
||||
widgets,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-2
@@ -25,7 +25,6 @@ const makeWidget = (
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
type: WidgetType.FIELDS,
|
||||
isOverridden: false,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
position: {
|
||||
@@ -50,7 +49,6 @@ const makeTab = (
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: '',
|
||||
widgets,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-2
@@ -92,7 +92,6 @@ describe('usePageLayoutDraftState', () => {
|
||||
title: 'Tab 1',
|
||||
position: 0,
|
||||
pageLayoutId: '',
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -113,7 +112,6 @@ describe('usePageLayoutDraftState', () => {
|
||||
displayDataLabel: false,
|
||||
},
|
||||
objectMetadataId: null,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-5
@@ -39,7 +39,6 @@ describe('usePageLayoutWithRelationWidgets', () => {
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: 'test-layout',
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -63,7 +62,6 @@ describe('usePageLayoutWithRelationWidgets', () => {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -86,7 +84,6 @@ describe('usePageLayoutWithRelationWidgets', () => {
|
||||
__typename: 'NotesConfiguration',
|
||||
configurationType: WidgetConfigurationType.NOTES,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -115,7 +112,6 @@ describe('usePageLayoutWithRelationWidgets', () => {
|
||||
primaryAxisOrderBy: GraphOrderBy.FIELD_ASC,
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
@@ -240,7 +236,6 @@ describe('usePageLayoutWithRelationWidgets', () => {
|
||||
primaryAxisOrderBy: GraphOrderBy.FIELD_ASC,
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -59,7 +59,6 @@ export const useCreatePageLayoutTab = ({
|
||||
pageLayoutId: pageLayoutId,
|
||||
layoutMode: getDefaultTabLayoutMode(pageLayoutDraft.type),
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FindOnePageLayoutDocument } from '~/generated-metadata/graphql';
|
||||
|
||||
import { useExitLayoutCustomizationMode } from '@/layout-customization/hooks/useExitLayoutCustomizationMode';
|
||||
import { useInvalidateMetadataStore } from '@/metadata-store/hooks/useInvalidateMetadataStore';
|
||||
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
|
||||
import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
|
||||
import { pageLayoutCurrentLayoutsComponentState } from '@/page-layout/states/pageLayoutCurrentLayoutsComponentState';
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { pageLayoutPersistedComponentState } from '@/page-layout/states/pageLayoutPersistedComponentState';
|
||||
import { type PageLayout } from '@/page-layout/types/PageLayout';
|
||||
import { convertPageLayoutToTabLayouts } from '@/page-layout/utils/convertPageLayoutToTabLayouts';
|
||||
import { evictViewMetadataForViewIds } from '@/page-layout/utils/evictViewMetadataForViewIds';
|
||||
import { toDraftPageLayout } from '@/page-layout/utils/toDraftPageLayout';
|
||||
import { transformPageLayout } from '@/page-layout/utils/transformPageLayout';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
||||
|
||||
export const useRefreshPageLayoutAfterReset = (
|
||||
pageLayoutIdFromProps: string,
|
||||
) => {
|
||||
const pageLayoutId = useAvailableComponentInstanceIdOrThrow(
|
||||
PageLayoutComponentInstanceContext,
|
||||
pageLayoutIdFromProps,
|
||||
);
|
||||
|
||||
const client = useApolloClient();
|
||||
const store = useStore();
|
||||
|
||||
const { setIsPageLayoutInEditMode } =
|
||||
useSetIsPageLayoutInEditMode(pageLayoutId);
|
||||
const { exitLayoutCustomizationMode } = useExitLayoutCustomizationMode();
|
||||
const { invalidateMetadataStore } = useInvalidateMetadataStore();
|
||||
|
||||
const pageLayoutPersistedState = useAtomComponentStateCallbackState(
|
||||
pageLayoutPersistedComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const pageLayoutDraftState = useAtomComponentStateCallbackState(
|
||||
pageLayoutDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const pageLayoutCurrentLayoutsState = useAtomComponentStateCallbackState(
|
||||
pageLayoutCurrentLayoutsComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const refreshPageLayoutAfterReset = useCallback(
|
||||
async (collectAffectedViewIds: (layout: PageLayout) => Set<string>) => {
|
||||
const { data } = await client.query({
|
||||
query: FindOnePageLayoutDocument,
|
||||
variables: { id: pageLayoutId },
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
|
||||
let affectedViewIds = new Set<string>();
|
||||
|
||||
if (isDefined(data?.getPageLayout)) {
|
||||
const freshLayout = transformPageLayout(data.getPageLayout);
|
||||
|
||||
affectedViewIds = collectAffectedViewIds(freshLayout);
|
||||
|
||||
store.set(pageLayoutPersistedState, freshLayout);
|
||||
store.set(pageLayoutDraftState, toDraftPageLayout(freshLayout));
|
||||
store.set(
|
||||
pageLayoutCurrentLayoutsState,
|
||||
convertPageLayoutToTabLayouts(freshLayout),
|
||||
);
|
||||
}
|
||||
|
||||
setIsPageLayoutInEditMode(false);
|
||||
exitLayoutCustomizationMode();
|
||||
evictViewMetadataForViewIds(store, affectedViewIds);
|
||||
invalidateMetadataStore();
|
||||
},
|
||||
[
|
||||
client,
|
||||
pageLayoutId,
|
||||
store,
|
||||
pageLayoutPersistedState,
|
||||
pageLayoutDraftState,
|
||||
pageLayoutCurrentLayoutsState,
|
||||
setIsPageLayoutInEditMode,
|
||||
exitLayoutCustomizationMode,
|
||||
invalidateMetadataStore,
|
||||
],
|
||||
);
|
||||
|
||||
return { refreshPageLayoutAfterReset };
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useCallback } from 'react';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { RESET_PAGE_LAYOUT_TAB_TO_DEFAULT } from '@/page-layout/graphql/mutations/resetPageLayoutTabToDefault';
|
||||
import { useRefreshPageLayoutAfterReset } from '@/page-layout/hooks/useRefreshPageLayoutAfterReset';
|
||||
import { collectViewIdsFromWidgets } from '@/page-layout/utils/collectViewIdsFromWidgets';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
|
||||
export const useResetPageLayoutTabToDefault = (
|
||||
pageLayoutIdFromProps: string,
|
||||
) => {
|
||||
const [resetMutation] = useMutation(RESET_PAGE_LAYOUT_TAB_TO_DEFAULT);
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const { refreshPageLayoutAfterReset } = useRefreshPageLayoutAfterReset(
|
||||
pageLayoutIdFromProps,
|
||||
);
|
||||
|
||||
const resetPageLayoutTabToDefault = useCallback(
|
||||
async (tabId: string) => {
|
||||
try {
|
||||
await resetMutation({ variables: { id: tabId } });
|
||||
await refreshPageLayoutAfterReset((layout) =>
|
||||
collectViewIdsFromWidgets(
|
||||
layout.tabs.find((tab) => tab.id === tabId)?.widgets ?? [],
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'pageLayoutTab',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
}
|
||||
},
|
||||
[
|
||||
resetMutation,
|
||||
refreshPageLayoutAfterReset,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
);
|
||||
|
||||
return { resetPageLayoutTabToDefault };
|
||||
};
|
||||
+18
-99
@@ -1,115 +1,36 @@
|
||||
import { useInvalidateMetadataStore } from '@/metadata-store/hooks/useInvalidateMetadataStore';
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
|
||||
import { fieldsWidgetEditorModeDraftComponentState } from '@/page-layout/states/fieldsWidgetEditorModeDraftComponentState';
|
||||
import { fieldsWidgetEditorModePersistedComponentState } from '@/page-layout/states/fieldsWidgetEditorModePersistedComponentState';
|
||||
import { fieldsWidgetGroupsDraftComponentState } from '@/page-layout/states/fieldsWidgetGroupsDraftComponentState';
|
||||
import { fieldsWidgetGroupsPersistedComponentState } from '@/page-layout/states/fieldsWidgetGroupsPersistedComponentState';
|
||||
import { fieldsWidgetUngroupedFieldsDraftComponentState } from '@/page-layout/states/fieldsWidgetUngroupedFieldsDraftComponentState';
|
||||
import { fieldsWidgetUngroupedFieldsPersistedComponentState } from '@/page-layout/states/fieldsWidgetUngroupedFieldsPersistedComponentState';
|
||||
import { hasInitializedFieldsWidgetGroupsDraftComponentState } from '@/page-layout/states/hasInitializedFieldsWidgetGroupsDraftComponentState';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { ResetPageLayoutWidgetToDefaultDocument } from '~/generated-metadata/graphql';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { useRefreshPageLayoutAfterReset } from '@/page-layout/hooks/useRefreshPageLayoutAfterReset';
|
||||
import { collectViewIdsFromWidgets } from '@/page-layout/utils/collectViewIdsFromWidgets';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
|
||||
export const useResetPageLayoutWidgetToDefault = (
|
||||
pageLayoutIdFromProps?: string,
|
||||
pageLayoutIdFromProps: string,
|
||||
) => {
|
||||
const pageLayoutId = useAvailableComponentInstanceIdOrThrow(
|
||||
PageLayoutComponentInstanceContext,
|
||||
pageLayoutIdFromProps,
|
||||
);
|
||||
|
||||
const [resetMutation] = useMutation(ResetPageLayoutWidgetToDefaultDocument);
|
||||
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
const { invalidateMetadataStore } = useInvalidateMetadataStore();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const hasInitializedState = useAtomComponentStateCallbackState(
|
||||
hasInitializedFieldsWidgetGroupsDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const groupsDraftState = useAtomComponentStateCallbackState(
|
||||
fieldsWidgetGroupsDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const groupsPersistedState = useAtomComponentStateCallbackState(
|
||||
fieldsWidgetGroupsPersistedComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const ungroupedDraftState = useAtomComponentStateCallbackState(
|
||||
fieldsWidgetUngroupedFieldsDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const ungroupedPersistedState = useAtomComponentStateCallbackState(
|
||||
fieldsWidgetUngroupedFieldsPersistedComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const editorModeDraftState = useAtomComponentStateCallbackState(
|
||||
fieldsWidgetEditorModeDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const editorModePersistedState = useAtomComponentStateCallbackState(
|
||||
fieldsWidgetEditorModePersistedComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const clearWidgetDraftState = useCallback(
|
||||
(widgetId: string) => {
|
||||
const removeWidgetEntry = <T>(prev: Record<string, T>) => {
|
||||
const { [widgetId]: _, ...rest } = prev;
|
||||
|
||||
return rest;
|
||||
};
|
||||
|
||||
store.set(hasInitializedState, removeWidgetEntry);
|
||||
store.set(groupsDraftState, removeWidgetEntry);
|
||||
store.set(groupsPersistedState, removeWidgetEntry);
|
||||
store.set(ungroupedDraftState, removeWidgetEntry);
|
||||
store.set(ungroupedPersistedState, removeWidgetEntry);
|
||||
store.set(editorModeDraftState, removeWidgetEntry);
|
||||
store.set(editorModePersistedState, removeWidgetEntry);
|
||||
},
|
||||
[
|
||||
store,
|
||||
hasInitializedState,
|
||||
groupsDraftState,
|
||||
groupsPersistedState,
|
||||
ungroupedDraftState,
|
||||
ungroupedPersistedState,
|
||||
editorModeDraftState,
|
||||
editorModePersistedState,
|
||||
],
|
||||
const { refreshPageLayoutAfterReset } = useRefreshPageLayoutAfterReset(
|
||||
pageLayoutIdFromProps,
|
||||
);
|
||||
|
||||
const resetPageLayoutWidgetToDefault = useCallback(
|
||||
async (widgetId: string) => {
|
||||
try {
|
||||
await resetMutation({
|
||||
variables: { id: widgetId },
|
||||
});
|
||||
|
||||
closeSidePanelMenu();
|
||||
clearWidgetDraftState(widgetId);
|
||||
invalidateMetadataStore();
|
||||
await resetMutation({ variables: { id: widgetId } });
|
||||
await refreshPageLayoutAfterReset((layout) =>
|
||||
collectViewIdsFromWidgets(
|
||||
layout.tabs
|
||||
.flatMap((tab) => tab.widgets)
|
||||
.filter((widget) => widget.id === widgetId),
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
@@ -123,9 +44,7 @@ export const useResetPageLayoutWidgetToDefault = (
|
||||
},
|
||||
[
|
||||
resetMutation,
|
||||
closeSidePanelMenu,
|
||||
clearWidgetDraftState,
|
||||
invalidateMetadataStore,
|
||||
refreshPageLayoutAfterReset,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
|
||||
@@ -22,7 +22,6 @@ describe('addWidgetToTab', () => {
|
||||
},
|
||||
gridPosition: { row: 0, column: 0, rowSpan: 2, columnSpan: 2 },
|
||||
objectMetadataId: null,
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -36,7 +35,6 @@ describe('addWidgetToTab', () => {
|
||||
position: 0,
|
||||
pageLayoutId: 'layout-1',
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -48,7 +46,6 @@ describe('addWidgetToTab', () => {
|
||||
position: 1,
|
||||
pageLayoutId: 'layout-1',
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
|
||||
-2
@@ -28,7 +28,6 @@ describe('convertLayoutsToWidgets', () => {
|
||||
aggregateFieldMetadataId: 'id',
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -53,7 +52,6 @@ describe('convertLayoutsToWidgets', () => {
|
||||
orderBy: GraphOrderBy.VALUE_DESC,
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
|
||||
-5
@@ -38,7 +38,6 @@ describe('convertPageLayoutToTabLayouts', () => {
|
||||
},
|
||||
gridPosition: { row: 0, column: 0, rowSpan: 2, columnSpan: 2 },
|
||||
objectMetadataId: 'object-metadata-1',
|
||||
isOverridden: false,
|
||||
createdAt: '2025-01-01T00:00:00.000Z',
|
||||
updatedAt: '2025-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
@@ -59,13 +58,11 @@ describe('convertPageLayoutToTabLayouts', () => {
|
||||
},
|
||||
gridPosition: { row: 2, column: 0, rowSpan: 2, columnSpan: 2 },
|
||||
objectMetadataId: 'object-metadata-1',
|
||||
isOverridden: false,
|
||||
createdAt: '2025-01-01T00:00:00.000Z',
|
||||
updatedAt: '2025-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
},
|
||||
],
|
||||
isOverridden: false,
|
||||
createdAt: '2025-01-01T00:00:00.000Z',
|
||||
updatedAt: '2025-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
@@ -118,13 +115,11 @@ describe('convertPageLayoutToTabLayouts', () => {
|
||||
},
|
||||
gridPosition: { row: 0, column: 0, rowSpan: 4, columnSpan: 4 },
|
||||
objectMetadataId: null,
|
||||
isOverridden: false,
|
||||
createdAt: '2025-01-01T00:00:00.000Z',
|
||||
updatedAt: '2025-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
},
|
||||
],
|
||||
isOverridden: false,
|
||||
createdAt: '2025-01-01T00:00:00.000Z',
|
||||
updatedAt: '2025-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
|
||||
+1
-2
@@ -50,8 +50,7 @@ describe('createDefaultRecordTableWidget', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should set objectMetadataId to null and isOverridden to false', () => {
|
||||
it('should set objectMetadataId to null', () => {
|
||||
expect(widget.objectMetadataId).toBeNull();
|
||||
expect(widget.isOverridden).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
-1
@@ -28,7 +28,6 @@ const createMockWidget = (
|
||||
objectMetadataId: null,
|
||||
gridPosition: { row: 0, column: 0, rowSpan: 1, columnSpan: 1 },
|
||||
pageLayoutTabId: 'tab-1',
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01',
|
||||
updatedAt: '2024-01-01',
|
||||
...overrides,
|
||||
|
||||
-1
@@ -28,7 +28,6 @@ describe('filterVisibleWidgets', () => {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
|
||||
-1
@@ -9,7 +9,6 @@ describe('getPageLayoutTabListInitialActiveTabId', () => {
|
||||
title: `Tab ${id}`,
|
||||
position: 0,
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
});
|
||||
|
||||
-1
@@ -14,7 +14,6 @@ describe('getTabsByDisplayMode', () => {
|
||||
title: `Tab ${id}`,
|
||||
position: 0,
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
});
|
||||
|
||||
-2
@@ -28,7 +28,6 @@ describe('getTabsWithVisibleWidgets', () => {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
@@ -46,7 +45,6 @@ describe('getTabsWithVisibleWidgets', () => {
|
||||
title: `Tab ${id}`,
|
||||
position: 0,
|
||||
widgets,
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
|
||||
-2
@@ -40,7 +40,6 @@ const createMockWidget = (
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: null,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
@@ -58,7 +57,6 @@ const createMockTab = (
|
||||
title: `Tab ${id}`,
|
||||
position: 0,
|
||||
widgets,
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
|
||||
-1
@@ -27,7 +27,6 @@ describe('prepareGridLayoutItemsWithPlaceholders', () => {
|
||||
aggregateFieldMetadataId: 'field-id',
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
|
||||
-5
@@ -30,7 +30,6 @@ describe('removeWidgetFromTab', () => {
|
||||
},
|
||||
gridPosition: { row: 0, column: 0, rowSpan: 2, columnSpan: 2 },
|
||||
objectMetadataId: null,
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -51,13 +50,11 @@ describe('removeWidgetFromTab', () => {
|
||||
},
|
||||
gridPosition: { row: 2, column: 0, rowSpan: 2, columnSpan: 2 },
|
||||
objectMetadataId: null,
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
},
|
||||
],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -81,13 +78,11 @@ describe('removeWidgetFromTab', () => {
|
||||
},
|
||||
gridPosition: { row: 0, column: 0, rowSpan: 2, columnSpan: 2 },
|
||||
objectMetadataId: null,
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
},
|
||||
],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
|
||||
-1
@@ -13,7 +13,6 @@ const makeWidget = (id: string, index: number): PageLayoutWidget =>
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: id,
|
||||
type: WidgetType.FIELDS,
|
||||
isOverridden: false,
|
||||
gridPosition: { row: 0, column: 0, rowSpan: 1, columnSpan: 1 },
|
||||
configuration: {
|
||||
__typename: 'FieldsConfiguration',
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { getWidgetConfigurationViewId } from '@/page-layout/utils/getWidgetConfigurationViewId';
|
||||
|
||||
export const collectViewIdsFromWidgets = (
|
||||
widgets: PageLayoutWidget[],
|
||||
): Set<string> => {
|
||||
const viewIds = new Set<string>();
|
||||
|
||||
for (const widget of widgets) {
|
||||
const viewId = getWidgetConfigurationViewId(widget.configuration);
|
||||
|
||||
if (isDefined(viewId)) {
|
||||
viewIds.add(viewId);
|
||||
}
|
||||
}
|
||||
|
||||
return viewIds;
|
||||
};
|
||||
@@ -46,7 +46,6 @@ export const createDefaultFieldWidget = ({
|
||||
index: positionIndex,
|
||||
},
|
||||
objectMetadataId: objectMetadataId ?? null,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -42,7 +42,6 @@ export const createDefaultFieldsWidget = ({
|
||||
index: positionIndex,
|
||||
},
|
||||
objectMetadataId: objectMetadataId ?? null,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-1
@@ -34,7 +34,6 @@ export const createDefaultFrontComponentWidget = (
|
||||
columnSpan: gridPosition.columnSpan,
|
||||
},
|
||||
objectMetadataId: null,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -84,7 +84,6 @@ export const createDefaultGraphWidget = ({
|
||||
columnSpan: gridPosition.columnSpan,
|
||||
},
|
||||
objectMetadataId: resolvedObjectMetadataId,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -34,7 +34,6 @@ export const createDefaultIframeWidget = (
|
||||
columnSpan: gridPosition.columnSpan,
|
||||
},
|
||||
objectMetadataId: objectMetadataId ?? null,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -31,7 +31,6 @@ export const createDefaultRecordTableWidget = (
|
||||
columnSpan: gridPosition.columnSpan,
|
||||
},
|
||||
objectMetadataId: null,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
-1
@@ -34,7 +34,6 @@ export const createDefaultStandaloneRichTextWidget = (
|
||||
columnSpan: gridPosition.columnSpan,
|
||||
},
|
||||
objectMetadataId: objectMetadataId ?? null,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { useStore } from 'jotai';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
type MetadataEntityKey,
|
||||
metadataStoreState,
|
||||
} from '@/metadata-store/states/metadataStoreState';
|
||||
|
||||
const VIEW_RELATED_METADATA_KEYS: MetadataEntityKey[] = [
|
||||
'viewFields',
|
||||
'viewFieldGroups',
|
||||
];
|
||||
|
||||
export const evictViewMetadataForViewIds = (
|
||||
store: ReturnType<typeof useStore>,
|
||||
viewIds: Set<string>,
|
||||
) => {
|
||||
if (viewIds.size === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const key of VIEW_RELATED_METADATA_KEYS) {
|
||||
store.set(metadataStoreState.atomFamily(key), (prev) => ({
|
||||
...prev,
|
||||
current: (prev.current as { viewId?: string }[]).filter(
|
||||
(item) => !isDefined(item.viewId) || !viewIds.has(item.viewId),
|
||||
),
|
||||
currentCollectionHash: undefined,
|
||||
}));
|
||||
}
|
||||
};
|
||||
@@ -41,7 +41,6 @@ const getRelationFieldWidgetToInsert = (
|
||||
fieldMetadataId: field.id,
|
||||
fieldDisplayMode: FieldDisplayMode.CARD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
deletedAt: null,
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { type DraftPageLayout } from '@/page-layout/types/DraftPageLayout';
|
||||
import { type PageLayout } from '@/page-layout/types/PageLayout';
|
||||
|
||||
export const toDraftPageLayout = (pageLayout: PageLayout): DraftPageLayout => ({
|
||||
id: pageLayout.id,
|
||||
name: pageLayout.name,
|
||||
type: pageLayout.type,
|
||||
objectMetadataId: pageLayout.objectMetadataId,
|
||||
tabs: pageLayout.tabs,
|
||||
defaultTabToFocusOnMobileAndSidePanelId:
|
||||
pageLayout.defaultTabToFocusOnMobileAndSidePanelId,
|
||||
});
|
||||
-18
@@ -149,7 +149,6 @@ const createPageLayoutWithWidget = (
|
||||
position: 0,
|
||||
pageLayoutId: PAGE_LAYOUT_TEST_INSTANCE_ID,
|
||||
widgets: [widget],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -272,7 +271,6 @@ export const WithNumberChart: Story = {
|
||||
aggregateFieldMetadataId: idField.id,
|
||||
displayDataLabel: true,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -359,7 +357,6 @@ export const WithGaugeChart: Story = {
|
||||
aggregateFieldMetadataId: idField.id,
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -450,7 +447,6 @@ export const WithBarChart: Story = {
|
||||
axisNameDisplay: AxisNameDisplay.BOTH,
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -544,7 +540,6 @@ export const SmallWidget: Story = {
|
||||
aggregateFieldMetadataId: idField.id,
|
||||
displayDataLabel: true,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -642,7 +637,6 @@ export const MediumWidget: Story = {
|
||||
axisNameDisplay: AxisNameDisplay.BOTH,
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -740,7 +734,6 @@ export const LargeWidget: Story = {
|
||||
axisNameDisplay: AxisNameDisplay.BOTH,
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -834,7 +827,6 @@ export const WideWidget: Story = {
|
||||
aggregateFieldMetadataId: idField.id,
|
||||
displayDataLabel: true,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -932,7 +924,6 @@ export const TallWidget: Story = {
|
||||
axisNameDisplay: AxisNameDisplay.BOTH,
|
||||
displayDataLabel: false,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1026,7 +1017,6 @@ export const WithManyToOneRelationFieldWidget: Story = {
|
||||
fieldMetadataId: accountOwnerField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1145,7 +1135,6 @@ export const WithOneToManyRelationFieldWidget: Story = {
|
||||
fieldMetadataId: companyPeopleField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1256,7 +1245,6 @@ export const OneToManyRelationFieldWidgetWithSeeAllButton: Story = {
|
||||
fieldMetadataId: companyPeopleField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1394,7 +1382,6 @@ export const OnMobile: Story = {
|
||||
aggregateFieldMetadataId: idField.id,
|
||||
displayDataLabel: true,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1492,7 +1479,6 @@ export const InSidePanel: Story = {
|
||||
aggregateFieldMetadataId: idField.id,
|
||||
displayDataLabel: true,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1651,7 +1637,6 @@ export const Catalog: CatalogStory<Story, typeof WidgetRenderer> = {
|
||||
aggregateFieldMetadataId: idField.id,
|
||||
displayDataLabel: true,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1744,7 +1729,6 @@ export const Catalog: CatalogStory<Story, typeof WidgetRenderer> = {
|
||||
position: 0,
|
||||
pageLayoutId: PAGE_LAYOUT_TEST_INSTANCE_ID,
|
||||
widgets: [widget],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1757,7 +1741,6 @@ export const Catalog: CatalogStory<Story, typeof WidgetRenderer> = {
|
||||
position: 1,
|
||||
pageLayoutId: PAGE_LAYOUT_TEST_INSTANCE_ID,
|
||||
widgets: [],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1772,7 +1755,6 @@ export const Catalog: CatalogStory<Story, typeof WidgetRenderer> = {
|
||||
position: 0,
|
||||
pageLayoutId: PAGE_LAYOUT_TEST_INSTANCE_ID,
|
||||
widgets: [widget],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
|
||||
-18
@@ -297,7 +297,6 @@ const createPageLayoutWithWidget = (
|
||||
position: 0,
|
||||
pageLayoutId: PAGE_LAYOUT_TEST_INSTANCE_ID,
|
||||
widgets: [widget],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -351,7 +350,6 @@ export const TextFieldWidget: Story = {
|
||||
fieldMetadataId: nameField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -445,7 +443,6 @@ export const AddressFieldWidget: Story = {
|
||||
fieldMetadataId: addressField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -542,7 +539,6 @@ export const NumberFieldWidget: Story = {
|
||||
fieldMetadataId: employeesField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -636,7 +632,6 @@ export const LinkFieldWidget: Story = {
|
||||
fieldMetadataId: linkedinField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -730,7 +725,6 @@ export const ManyToOneRelationFieldWidget: Story = {
|
||||
fieldMetadataId: accountOwnerField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -834,7 +828,6 @@ export const OneToManyRelationFieldWidget: Story = {
|
||||
fieldMetadataId: companyPeopleField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -930,7 +923,6 @@ export const BooleanFieldWidget: Story = {
|
||||
fieldMetadataId: idealCustomerProfileField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1023,7 +1015,6 @@ export const CurrencyFieldWidget: Story = {
|
||||
fieldMetadataId: annualRecurringRevenueField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1116,7 +1107,6 @@ export const EmailsFieldWidget: Story = {
|
||||
fieldMetadataId: personEmailsField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1210,7 +1200,6 @@ export const PhonesFieldWidget: Story = {
|
||||
fieldMetadataId: personPhonesField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1304,7 +1293,6 @@ export const SelectFieldWidget: Story = {
|
||||
fieldMetadataId: opportunityStageField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1399,7 +1387,6 @@ export const MultiSelectFieldWidget: Story = {
|
||||
fieldMetadataId: companyWorkPolicyField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1497,7 +1484,6 @@ export const TimelineActivityRelationFieldWidget: Story = {
|
||||
fieldMetadataId: timelineActivityWorkspaceMemberField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.FIELD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1596,7 +1582,6 @@ export const ManyToOneRelationCardWidget: Story = {
|
||||
fieldMetadataId: accountOwnerField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.CARD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1708,7 +1693,6 @@ export const OneToManyRelationCardWidget: Story = {
|
||||
fieldMetadataId: companyPeopleField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.CARD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1803,7 +1787,6 @@ export const TimelineActivityRelationCardWidget: Story = {
|
||||
fieldMetadataId: timelineActivityWorkspaceMemberField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.CARD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -1964,7 +1947,6 @@ export const OneToManyRelationCardWidgetWithProgressiveLoading: Story = {
|
||||
fieldMetadataId: companyPeopleField.id,
|
||||
fieldDisplayMode: FieldDisplayMode.CARD,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
|
||||
-4
@@ -147,7 +147,6 @@ const createPageLayoutWithWidget = (
|
||||
position: 0,
|
||||
pageLayoutId: PAGE_LAYOUT_TEST_INSTANCE_ID,
|
||||
widgets: [widget],
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -177,7 +176,6 @@ const createFieldsWidget = (viewId: string | null): PageLayoutWidget => ({
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId,
|
||||
},
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01T00:00:00Z',
|
||||
updatedAt: '2024-01-01T00:00:00Z',
|
||||
deletedAt: null,
|
||||
@@ -217,7 +215,6 @@ const createViewField = (
|
||||
isVisible: true,
|
||||
size: 200,
|
||||
aggregateOperation: null,
|
||||
isOverridden: false,
|
||||
viewId: FIELDS_VIEW_ID,
|
||||
...(viewFieldGroupId !== undefined && { viewFieldGroupId }),
|
||||
});
|
||||
@@ -233,7 +230,6 @@ const createViewFieldGroup = (
|
||||
name,
|
||||
position,
|
||||
isVisible,
|
||||
isOverridden: false,
|
||||
viewId: FIELDS_VIEW_ID,
|
||||
viewFields,
|
||||
});
|
||||
|
||||
-2
@@ -13,7 +13,6 @@ const buildViewField = (
|
||||
isVisible: true,
|
||||
size: 100,
|
||||
aggregateOperation: null,
|
||||
isOverridden: false,
|
||||
...overrides,
|
||||
});
|
||||
|
||||
@@ -24,7 +23,6 @@ const buildExistingViewField = (overrides: Partial<ViewField>): ViewField => ({
|
||||
isVisible: true,
|
||||
size: 100,
|
||||
aggregateOperation: null,
|
||||
isOverridden: false,
|
||||
...overrides,
|
||||
});
|
||||
|
||||
|
||||
-1
@@ -358,7 +358,6 @@ export const SidePanelPageLayoutRecordPageWidgetTypeSelect = () => {
|
||||
index: positionIndex,
|
||||
},
|
||||
objectMetadataId: null,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
|
||||
+54
-2
@@ -1,7 +1,9 @@
|
||||
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useDeletePageLayoutTab } from '@/page-layout/hooks/useDeletePageLayoutTab';
|
||||
import { useDuplicatePageLayoutTab } from '@/page-layout/hooks/useDuplicatePageLayoutTab';
|
||||
import { useMovePageLayoutTab } from '@/page-layout/hooks/useMovePageLayoutTab';
|
||||
import { useResetPageLayoutTabToDefault } from '@/page-layout/hooks/useResetPageLayoutTabToDefault';
|
||||
import { useSetAsPinnedTab } from '@/page-layout/hooks/useSetAsPinnedTab';
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { pageLayoutTabSettingsOpenTabIdComponentState } from '@/page-layout/states/pageLayoutTabSettingsOpenTabIdComponentState';
|
||||
@@ -11,16 +13,20 @@ import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
||||
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { TAB_SETTINGS_SELECTABLE_ITEM_IDS } from '@/side-panel/pages/page-layout/constants/settings/TabSettingsSelectableItemIds';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
IconChevronLeft,
|
||||
IconChevronRight,
|
||||
IconCopyPlus,
|
||||
IconPinned,
|
||||
IconRefreshDot,
|
||||
IconTrash,
|
||||
} from 'twenty-ui/display';
|
||||
import { PageLayoutType } from '~/generated-metadata/graphql';
|
||||
@@ -30,12 +36,17 @@ type SidePanelPageLayoutTabSettingsContentProps = {
|
||||
recordId: string;
|
||||
};
|
||||
|
||||
const RESET_TAB_TO_DEFAULT_MODAL_ID = 'reset-tab-to-default-modal';
|
||||
|
||||
export const SidePanelPageLayoutTabSettingsContent = ({
|
||||
pageLayoutId,
|
||||
recordId,
|
||||
}: SidePanelPageLayoutTabSettingsContentProps) => {
|
||||
const { t } = useLingui();
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
|
||||
const pageLayoutDraft = useAtomComponentStateValue(
|
||||
pageLayoutDraftComponentState,
|
||||
pageLayoutId,
|
||||
@@ -63,6 +74,9 @@ export const SidePanelPageLayoutTabSettingsContent = ({
|
||||
tabListInstanceId,
|
||||
});
|
||||
const { setAsPinnedTab } = useSetAsPinnedTab(pageLayoutId);
|
||||
const { resetPageLayoutTabToDefault } =
|
||||
useResetPageLayoutTabToDefault(pageLayoutId);
|
||||
const { openModal } = useModal();
|
||||
|
||||
if (!isDefined(pageLayoutTabSettingsOpenTabId)) {
|
||||
return null;
|
||||
@@ -70,7 +84,7 @@ export const SidePanelPageLayoutTabSettingsContent = ({
|
||||
|
||||
const tabsSorted = sortTabsByPosition(pageLayoutDraft.tabs);
|
||||
const currentIndex = tabsSorted.findIndex(
|
||||
(t) => t.id === pageLayoutTabSettingsOpenTabId,
|
||||
(tabItem) => tabItem.id === pageLayoutTabSettingsOpenTabId,
|
||||
);
|
||||
if (currentIndex < 0) return null;
|
||||
const tab = tabsSorted[currentIndex];
|
||||
@@ -83,17 +97,34 @@ export const SidePanelPageLayoutTabSettingsContent = ({
|
||||
const canSetAsPinned =
|
||||
isRecordPage && !isAlreadyPinned && tabsSorted.length > 1;
|
||||
|
||||
const isCustomTab =
|
||||
isDefined(currentWorkspace?.workspaceCustomApplication) &&
|
||||
tab.applicationId === currentWorkspace.workspaceCustomApplication.id;
|
||||
|
||||
const canShowResetToDefault = !isCustomTab;
|
||||
|
||||
const handleDelete = () => {
|
||||
deleteTab(tab.id);
|
||||
setPageLayoutTabSettingsOpenTabId(null);
|
||||
closeSidePanelMenu();
|
||||
};
|
||||
|
||||
const handleResetToDefault = () => {
|
||||
openModal(RESET_TAB_TO_DEFAULT_MODAL_ID);
|
||||
};
|
||||
|
||||
const handleConfirmReset = () => {
|
||||
resetPageLayoutTabToDefault(tab.id);
|
||||
};
|
||||
|
||||
const selectableItemIds = [
|
||||
...(canMoveLeft ? [TAB_SETTINGS_SELECTABLE_ITEM_IDS.MOVE_LEFT] : []),
|
||||
...(canMoveRight ? [TAB_SETTINGS_SELECTABLE_ITEM_IDS.MOVE_RIGHT] : []),
|
||||
...(canSetAsPinned ? [TAB_SETTINGS_SELECTABLE_ITEM_IDS.SET_AS_PINNED] : []),
|
||||
TAB_SETTINGS_SELECTABLE_ITEM_IDS.DUPLICATE,
|
||||
...(canShowResetToDefault
|
||||
? [TAB_SETTINGS_SELECTABLE_ITEM_IDS.RESET_TO_DEFAULT]
|
||||
: []),
|
||||
...(canDelete ? [TAB_SETTINGS_SELECTABLE_ITEM_IDS.DELETE] : []),
|
||||
];
|
||||
|
||||
@@ -151,6 +182,19 @@ export const SidePanelPageLayoutTabSettingsContent = ({
|
||||
onClick={() => duplicateTab(tab.id)}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
{canShowResetToDefault && (
|
||||
<SelectableListItem
|
||||
itemId={TAB_SETTINGS_SELECTABLE_ITEM_IDS.RESET_TO_DEFAULT}
|
||||
onEnter={handleResetToDefault}
|
||||
>
|
||||
<CommandMenuItem
|
||||
id={TAB_SETTINGS_SELECTABLE_ITEM_IDS.RESET_TO_DEFAULT}
|
||||
Icon={IconRefreshDot}
|
||||
label={t`Reset to default`}
|
||||
onClick={handleResetToDefault}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
)}
|
||||
{canDelete && (
|
||||
<SelectableListItem
|
||||
itemId={TAB_SETTINGS_SELECTABLE_ITEM_IDS.DELETE}
|
||||
@@ -166,6 +210,14 @@ export const SidePanelPageLayoutTabSettingsContent = ({
|
||||
)}
|
||||
</SidePanelGroup>
|
||||
</SidePanelList>
|
||||
<ConfirmationModal
|
||||
modalInstanceId={RESET_TAB_TO_DEFAULT_MODAL_ID}
|
||||
title={t`Reset to default`}
|
||||
subtitle={t`This will cancel all modifications done on the tab and its widgets. Edit mode will be canceled and the page will refresh. This action cannot be undone.`}
|
||||
onConfirmClick={handleConfirmReset}
|
||||
confirmButtonText={t`Reset`}
|
||||
confirmButtonAccent="danger"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+1
@@ -3,5 +3,6 @@ export const TAB_SETTINGS_SELECTABLE_ITEM_IDS = {
|
||||
MOVE_RIGHT: 'tab-move-right',
|
||||
SET_AS_PINNED: 'tab-set-as-pinned',
|
||||
DUPLICATE: 'tab-duplicate',
|
||||
RESET_TO_DEFAULT: 'tab-reset-to-default',
|
||||
DELETE: 'tab-delete',
|
||||
} as const;
|
||||
|
||||
@@ -10,7 +10,6 @@ export const VIEW_FIELD_FRAGMENT = gql`
|
||||
size
|
||||
aggregateOperation
|
||||
viewFieldGroupId
|
||||
isOverridden
|
||||
createdAt
|
||||
updatedAt
|
||||
deletedAt
|
||||
|
||||
@@ -9,7 +9,6 @@ export const VIEW_FIELD_GROUP_FRAGMENT = gql`
|
||||
position
|
||||
isVisible
|
||||
viewId
|
||||
isOverridden
|
||||
createdAt
|
||||
updatedAt
|
||||
deletedAt
|
||||
|
||||
@@ -12,7 +12,6 @@ export type ViewField = {
|
||||
size: number;
|
||||
aggregateOperation?: AggregateOperations | null;
|
||||
viewFieldGroupId?: string | null;
|
||||
isOverridden: boolean;
|
||||
definition?:
|
||||
| ColumnDefinition<FieldMetadata>
|
||||
| RecordBoardFieldDefinition<FieldMetadata>;
|
||||
|
||||
@@ -6,6 +6,5 @@ export type ViewFieldGroup = {
|
||||
position: number;
|
||||
isVisible: boolean;
|
||||
viewId: string;
|
||||
isOverridden: boolean;
|
||||
viewFields: ViewField[];
|
||||
};
|
||||
|
||||
@@ -60,7 +60,6 @@ describe('mapViewFieldsToColumnDefinitions', () => {
|
||||
position: 1,
|
||||
size: 1,
|
||||
isVisible: false,
|
||||
isOverridden: false,
|
||||
definition: {
|
||||
fieldMetadataId: '1',
|
||||
label: 'label 1',
|
||||
@@ -79,7 +78,6 @@ describe('mapViewFieldsToColumnDefinitions', () => {
|
||||
position: 2,
|
||||
size: 2,
|
||||
isVisible: false,
|
||||
isOverridden: false,
|
||||
definition: {
|
||||
fieldMetadataId: '2',
|
||||
label: 'label 2',
|
||||
@@ -98,7 +96,6 @@ describe('mapViewFieldsToColumnDefinitions', () => {
|
||||
position: 3,
|
||||
size: 3,
|
||||
isVisible: true,
|
||||
isOverridden: false,
|
||||
definition: {
|
||||
fieldMetadataId: '3',
|
||||
label: 'label 3',
|
||||
@@ -191,7 +188,6 @@ describe('mapColumnDefinitionsToViewFields', () => {
|
||||
fieldMetadataId: 1,
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
isOverridden: false,
|
||||
definition: columnDefinitions[0],
|
||||
size: undefined,
|
||||
},
|
||||
@@ -201,7 +197,6 @@ describe('mapColumnDefinitionsToViewFields', () => {
|
||||
position: 2,
|
||||
size: 200,
|
||||
isVisible: false,
|
||||
isOverridden: false,
|
||||
definition: columnDefinitions[1],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -12,7 +12,6 @@ export const mapBoardFieldDefinitionsToViewFields = (
|
||||
size: 0,
|
||||
position: fieldDefinition.position,
|
||||
isVisible: fieldDefinition.isVisible ?? true,
|
||||
isOverridden: false,
|
||||
definition: fieldDefinition,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -12,7 +12,6 @@ export const mapColumnDefinitionsToViewFields = (
|
||||
position: columnDefinition.position,
|
||||
size: columnDefinition.size,
|
||||
isVisible: columnDefinition.isVisible ?? true,
|
||||
isOverridden: false,
|
||||
definition: columnDefinition,
|
||||
}));
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@ export const mapRecordFieldToViewField = (recordField: RecordField) => {
|
||||
position: recordField.position,
|
||||
size: recordField.size,
|
||||
aggregateOperation: recordField.aggregateOperation,
|
||||
isOverridden: false,
|
||||
};
|
||||
|
||||
return viewField;
|
||||
|
||||
@@ -129,7 +129,6 @@ export const createTestWidget = (
|
||||
gridPosition: { row: 0, column: 0, rowSpan: 2, columnSpan: 2 },
|
||||
objectMetadataId: TEST_OBJECT_METADATA_ID,
|
||||
configuration: TEST_BAR_CHART_CONFIGURATION,
|
||||
isOverridden: false,
|
||||
createdAt: '2024-01-01',
|
||||
updatedAt: '2024-01-01',
|
||||
deletedAt: null,
|
||||
|
||||
+5
-2
@@ -55,8 +55,11 @@ export class PageLayoutTabDTO {
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date | null;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isOverridden: boolean;
|
||||
@Field(() => Boolean, {
|
||||
nullable: true,
|
||||
deprecationReason: 'isOverridden is deprecated',
|
||||
})
|
||||
isOverridden?: boolean;
|
||||
|
||||
@HideField()
|
||||
overrides?: PageLayoutTabOverrides | null;
|
||||
|
||||
+1
-20
@@ -7,7 +7,6 @@ import {
|
||||
import {
|
||||
Args,
|
||||
Context,
|
||||
Float,
|
||||
Mutation,
|
||||
Parent,
|
||||
Query,
|
||||
@@ -15,7 +14,6 @@ import {
|
||||
} from '@nestjs/graphql';
|
||||
|
||||
import { PermissionFlagType } from 'twenty-shared/constants';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
@@ -32,7 +30,6 @@ import { PageLayoutTabDTO } from 'src/engine/metadata-modules/page-layout-tab/dt
|
||||
import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout-tab/services/page-layout-tab.service';
|
||||
import { resolvePageLayoutTabTitle } from 'src/engine/metadata-modules/page-layout-tab/utils/resolve-page-layout-tab-title.util';
|
||||
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
|
||||
import { resolveOverridableEntityProperty } from 'src/engine/metadata-modules/utils/resolve-overridable-entity-property.util';
|
||||
import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor';
|
||||
|
||||
@MetadataResolver(() => PageLayoutTabDTO)
|
||||
@@ -51,31 +48,15 @@ export class PageLayoutTabResolver {
|
||||
@Parent() tab: PageLayoutTabDTO,
|
||||
@Context() context: I18nContext,
|
||||
): Promise<string> {
|
||||
const resolvedTitle = resolveOverridableEntityProperty(tab, 'title');
|
||||
const i18n = this.i18nService.getI18nInstance(context.req.locale);
|
||||
|
||||
return resolvePageLayoutTabTitle({
|
||||
title: resolvedTitle,
|
||||
title: tab.title,
|
||||
applicationId: tab.applicationId,
|
||||
i18nInstance: i18n,
|
||||
});
|
||||
}
|
||||
|
||||
@ResolveField(() => Float)
|
||||
position(@Parent() tab: PageLayoutTabDTO): number {
|
||||
return resolveOverridableEntityProperty(tab, 'position');
|
||||
}
|
||||
|
||||
@ResolveField(() => String, { nullable: true })
|
||||
icon(@Parent() tab: PageLayoutTabDTO): string | null | undefined {
|
||||
return resolveOverridableEntityProperty(tab, 'icon');
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isOverridden(@Parent() tab: PageLayoutTabDTO): boolean {
|
||||
return isDefined(tab.overrides) && Object.keys(tab.overrides).length > 0;
|
||||
}
|
||||
|
||||
@Query(() => [PageLayoutTabDTO])
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async getPageLayoutTabs(
|
||||
|
||||
+3
-4
@@ -1,5 +1,3 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
import { type PageLayoutTabDTO } from 'src/engine/metadata-modules/page-layout-tab/dtos/page-layout-tab.dto';
|
||||
|
||||
@@ -11,13 +9,14 @@ export const fromFlatPageLayoutTabToPageLayoutTabDto = (
|
||||
updatedAt,
|
||||
deletedAt,
|
||||
widgetIds: _widgetIds,
|
||||
overrides,
|
||||
...rest
|
||||
} = flatPageLayoutTab;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
isOverridden:
|
||||
isDefined(rest.overrides) && Object.keys(rest.overrides).length > 0,
|
||||
...(overrides ?? {}),
|
||||
isOverridden: false,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
deletedAt: deletedAt ? new Date(deletedAt) : null,
|
||||
|
||||
+5
-2
@@ -74,8 +74,11 @@ export class PageLayoutWidgetDTO {
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isOverridden: boolean;
|
||||
@Field(() => Boolean, {
|
||||
nullable: true,
|
||||
deprecationReason: 'isOverridden is deprecated',
|
||||
})
|
||||
isOverridden?: boolean;
|
||||
|
||||
@HideField()
|
||||
overrides?: PageLayoutWidgetOverrides | null;
|
||||
|
||||
-25
@@ -6,9 +6,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { Args, Mutation, Parent, Query, ResolveField } from '@nestjs/graphql';
|
||||
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
import { PermissionFlagType } from 'twenty-shared/constants';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
@@ -23,7 +21,6 @@ import { PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout-wid
|
||||
import { WidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/dtos/widget-configuration.interface';
|
||||
import { PageLayoutWidgetService } from 'src/engine/metadata-modules/page-layout-widget/services/page-layout-widget.service';
|
||||
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
|
||||
import { resolveOverridableEntityProperty } from 'src/engine/metadata-modules/utils/resolve-overridable-entity-property.util';
|
||||
import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor';
|
||||
|
||||
@MetadataResolver(() => PageLayoutWidgetDTO)
|
||||
@@ -98,30 +95,8 @@ export class PageLayoutWidgetResolver {
|
||||
});
|
||||
}
|
||||
|
||||
@ResolveField(() => String)
|
||||
title(@Parent() widget: PageLayoutWidgetDTO): string {
|
||||
return resolveOverridableEntityProperty(widget, 'title');
|
||||
}
|
||||
|
||||
@ResolveField(() => GraphQLJSON, { nullable: true })
|
||||
position(@Parent() widget: PageLayoutWidgetDTO) {
|
||||
return resolveOverridableEntityProperty(widget, 'position');
|
||||
}
|
||||
|
||||
@ResolveField(() => GraphQLJSON, { nullable: true })
|
||||
conditionalDisplay(@Parent() widget: PageLayoutWidgetDTO) {
|
||||
return resolveOverridableEntityProperty(widget, 'conditionalDisplay');
|
||||
}
|
||||
|
||||
@ResolveField(() => WidgetConfiguration, { nullable: true })
|
||||
configuration(@Parent() widget: PageLayoutWidgetDTO) {
|
||||
return widget.configuration;
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isOverridden(@Parent() widget: PageLayoutWidgetDTO): boolean {
|
||||
return (
|
||||
isDefined(widget.overrides) && Object.keys(widget.overrides).length > 0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-6
@@ -1,18 +1,22 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/page-layout-widget.dto';
|
||||
|
||||
export const fromFlatPageLayoutWidgetToPageLayoutWidgetDto = (
|
||||
flatPageLayoutWidget: FlatPageLayoutWidget,
|
||||
): PageLayoutWidgetDTO => {
|
||||
const { createdAt, updatedAt, deletedAt, objectMetadataId, ...rest } =
|
||||
flatPageLayoutWidget;
|
||||
const {
|
||||
createdAt,
|
||||
updatedAt,
|
||||
deletedAt,
|
||||
objectMetadataId,
|
||||
overrides,
|
||||
...rest
|
||||
} = flatPageLayoutWidget;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
isOverridden:
|
||||
isDefined(rest.overrides) && Object.keys(rest.overrides).length > 0,
|
||||
...(overrides ?? {}),
|
||||
isOverridden: false,
|
||||
objectMetadataId: objectMetadataId ?? undefined,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
|
||||
+13
@@ -15,6 +15,7 @@ import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorato
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { PageLayoutTabDTO } from 'src/engine/metadata-modules/page-layout-tab/dtos/page-layout-tab.dto';
|
||||
import { PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/page-layout-widget.dto';
|
||||
import { CreatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout.input';
|
||||
import { UpdatePageLayoutWithTabsInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-with-tabs.input';
|
||||
@@ -136,4 +137,16 @@ export class PageLayoutResolver {
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => PageLayoutTabDTO)
|
||||
@UseGuards(SettingsPermissionGuard(PermissionFlagType.LAYOUTS))
|
||||
async resetPageLayoutTabToDefault(
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<Omit<PageLayoutTabDTO, 'widgets'>> {
|
||||
return this.pageLayoutResetService.resetPageLayoutTabToDefault({
|
||||
id,
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+308
@@ -7,10 +7,19 @@ import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadat
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { splitEntitiesByResetStrategy } from 'src/engine/metadata-modules/flat-entity/utils/split-entities-by-reset-strategy.util';
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { isFlatPageLayoutWidgetConfigurationOfType } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/is-flat-page-layout-widget-configuration-of-type.util';
|
||||
import { type FlatViewFieldGroup } from 'src/engine/metadata-modules/flat-view-field-group/types/flat-view-field-group.type';
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
import { type PageLayoutTabDTO } from 'src/engine/metadata-modules/page-layout-tab/dtos/page-layout-tab.dto';
|
||||
import {
|
||||
PageLayoutTabException,
|
||||
PageLayoutTabExceptionCode,
|
||||
PageLayoutTabExceptionMessageKey,
|
||||
generatePageLayoutTabExceptionMessage,
|
||||
} from 'src/engine/metadata-modules/page-layout-tab/exceptions/page-layout-tab.exception';
|
||||
import { fromFlatPageLayoutTabToPageLayoutTabDto } from 'src/engine/metadata-modules/page-layout-tab/utils/from-flat-page-layout-tab-to-page-layout-tab-dto.util';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import {
|
||||
PageLayoutWidgetException,
|
||||
@@ -20,6 +29,7 @@ import {
|
||||
} from 'src/engine/metadata-modules/page-layout-widget/exceptions/page-layout-widget.exception';
|
||||
import { type PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/page-layout-widget.dto';
|
||||
import { fromFlatPageLayoutWidgetToPageLayoutWidgetDto } from 'src/engine/metadata-modules/page-layout-widget/utils/from-flat-page-layout-widget-to-page-layout-widget-dto.util';
|
||||
import { ViewService } from 'src/engine/metadata-modules/view/services/view.service';
|
||||
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';
|
||||
import { DashboardSyncService } from 'src/modules/dashboard-sync/services/dashboard-sync.service';
|
||||
@@ -33,6 +43,7 @@ export class PageLayoutResetService {
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
private readonly dashboardSyncService: DashboardSyncService,
|
||||
private readonly viewService: ViewService,
|
||||
) {}
|
||||
|
||||
async resetPageLayoutWidgetToDefault({
|
||||
@@ -187,6 +198,303 @@ export class PageLayoutResetService {
|
||||
return fromFlatPageLayoutWidgetToPageLayoutWidgetDto(updatedWidget);
|
||||
}
|
||||
|
||||
async resetPageLayoutTabToDefault({
|
||||
id,
|
||||
workspaceId,
|
||||
}: {
|
||||
id: string;
|
||||
workspaceId: string;
|
||||
}): Promise<Omit<PageLayoutTabDTO, 'widgets'>> {
|
||||
const {
|
||||
flatPageLayoutTabMaps,
|
||||
flatPageLayoutWidgetMaps,
|
||||
flatViewFieldGroupMaps,
|
||||
flatViewFieldMaps,
|
||||
} =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatPageLayoutTabMaps',
|
||||
'flatPageLayoutWidgetMaps',
|
||||
'flatViewFieldGroupMaps',
|
||||
'flatViewFieldMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const tab = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: flatPageLayoutTabMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(tab) || isDefined(tab.deletedAt)) {
|
||||
throw new PageLayoutTabException(
|
||||
generatePageLayoutTabExceptionMessage(
|
||||
PageLayoutTabExceptionMessageKey.PAGE_LAYOUT_TAB_NOT_FOUND,
|
||||
id,
|
||||
),
|
||||
PageLayoutTabExceptionCode.PAGE_LAYOUT_TAB_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
if (
|
||||
tab.applicationUniversalIdentifier ===
|
||||
workspaceCustomFlatApplication.universalIdentifier
|
||||
) {
|
||||
throw new PageLayoutTabException(
|
||||
`Custom tab "${id}" cannot be reset to default`,
|
||||
PageLayoutTabExceptionCode.INVALID_PAGE_LAYOUT_TAB_DATA,
|
||||
);
|
||||
}
|
||||
|
||||
const now = new Date().toISOString();
|
||||
|
||||
const tabToUpdate: FlatPageLayoutTab = {
|
||||
...tab,
|
||||
overrides: null,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
const {
|
||||
widgetsToUpdate,
|
||||
widgetsToDelete,
|
||||
viewFieldGroupsToUpdate,
|
||||
viewFieldGroupsToDelete,
|
||||
viewFieldsToUpdate,
|
||||
viewFieldsToDelete,
|
||||
orphanedViewIds,
|
||||
} = this.computeTabChildResetOperations({
|
||||
tabId: id,
|
||||
flatPageLayoutWidgetMaps,
|
||||
flatViewFieldGroupMaps,
|
||||
flatViewFieldMaps,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
now,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
allFlatEntityOperationByMetadataName: {
|
||||
pageLayoutTab: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToUpdate: [tabToUpdate],
|
||||
flatEntityToDelete: [],
|
||||
},
|
||||
pageLayoutWidget: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToUpdate: widgetsToUpdate,
|
||||
flatEntityToDelete: widgetsToDelete,
|
||||
},
|
||||
viewFieldGroup: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToUpdate: viewFieldGroupsToUpdate,
|
||||
flatEntityToDelete: viewFieldGroupsToDelete,
|
||||
},
|
||||
viewField: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToUpdate: viewFieldsToUpdate,
|
||||
flatEntityToDelete: viewFieldsToDelete,
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
isSystemBuild: false,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
},
|
||||
);
|
||||
|
||||
if (validateAndBuildResult.status === 'fail') {
|
||||
throw new WorkspaceMigrationBuilderException(
|
||||
validateAndBuildResult,
|
||||
'Multiple validation errors occurred while resetting page layout tab to default',
|
||||
);
|
||||
}
|
||||
|
||||
await this.destroyOrphanedFieldsWidgetViews({
|
||||
viewIds: orphanedViewIds,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
const { flatPageLayoutTabMaps: recomputedTabMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatPageLayoutTabMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const updatedTab = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: recomputedTabMaps,
|
||||
});
|
||||
|
||||
await this.dashboardSyncService.updateLinkedDashboardsUpdatedAtByTabId({
|
||||
tabId: id,
|
||||
workspaceId,
|
||||
updatedAt: new Date(updatedTab.updatedAt),
|
||||
});
|
||||
|
||||
return fromFlatPageLayoutTabToPageLayoutTabDto(updatedTab);
|
||||
}
|
||||
|
||||
private computeTabChildResetOperations({
|
||||
tabId,
|
||||
flatPageLayoutWidgetMaps,
|
||||
flatViewFieldGroupMaps,
|
||||
flatViewFieldMaps,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
now,
|
||||
}: {
|
||||
tabId: string;
|
||||
flatPageLayoutWidgetMaps: {
|
||||
byUniversalIdentifier: Record<string, FlatPageLayoutWidget | undefined>;
|
||||
};
|
||||
flatViewFieldGroupMaps: {
|
||||
byUniversalIdentifier: Record<string, FlatViewFieldGroup | undefined>;
|
||||
};
|
||||
flatViewFieldMaps: {
|
||||
byUniversalIdentifier: Record<string, FlatViewField | undefined>;
|
||||
};
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
now: string;
|
||||
}): {
|
||||
widgetsToUpdate: FlatPageLayoutWidget[];
|
||||
widgetsToDelete: FlatPageLayoutWidget[];
|
||||
viewFieldGroupsToUpdate: FlatViewFieldGroup[];
|
||||
viewFieldGroupsToDelete: FlatViewFieldGroup[];
|
||||
viewFieldsToUpdate: FlatViewField[];
|
||||
viewFieldsToDelete: FlatViewField[];
|
||||
orphanedViewIds: string[];
|
||||
} {
|
||||
const existingWidgets = Object.values(
|
||||
flatPageLayoutWidgetMaps.byUniversalIdentifier,
|
||||
)
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(widget) =>
|
||||
widget.pageLayoutTabId === tabId && !isDefined(widget.deletedAt),
|
||||
);
|
||||
|
||||
const { toHardDelete: widgetsToDelete, toReset: widgetsToReset } =
|
||||
splitEntitiesByResetStrategy({
|
||||
entities: existingWidgets,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
now,
|
||||
});
|
||||
|
||||
let allViewFieldGroupsToUpdate: FlatViewFieldGroup[] = [];
|
||||
let allViewFieldGroupsToDelete: FlatViewFieldGroup[] = [];
|
||||
let allViewFieldsToUpdate: FlatViewField[] = [];
|
||||
let allViewFieldsToDelete: FlatViewField[] = [];
|
||||
|
||||
for (const widget of widgetsToReset) {
|
||||
if (
|
||||
!isFlatPageLayoutWidgetConfigurationOfType(
|
||||
widget,
|
||||
WidgetConfigurationType.FIELDS,
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const viewId = widget.configuration.viewId;
|
||||
|
||||
if (!isDefined(viewId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const {
|
||||
viewFieldGroupsToUpdate,
|
||||
viewFieldGroupsToDelete,
|
||||
viewFieldsToUpdate,
|
||||
viewFieldsToDelete,
|
||||
} = this.computeFieldsWidgetChildResetOperations({
|
||||
viewId,
|
||||
flatViewFieldGroupMaps,
|
||||
flatViewFieldMaps,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
now,
|
||||
});
|
||||
|
||||
allViewFieldGroupsToUpdate = [
|
||||
...allViewFieldGroupsToUpdate,
|
||||
...viewFieldGroupsToUpdate,
|
||||
];
|
||||
allViewFieldGroupsToDelete = [
|
||||
...allViewFieldGroupsToDelete,
|
||||
...viewFieldGroupsToDelete,
|
||||
];
|
||||
allViewFieldsToUpdate = [...allViewFieldsToUpdate, ...viewFieldsToUpdate];
|
||||
allViewFieldsToDelete = [...allViewFieldsToDelete, ...viewFieldsToDelete];
|
||||
}
|
||||
|
||||
const orphanedViewIds =
|
||||
this.collectOrphanedViewIdsFromDeletedWidgets(widgetsToDelete);
|
||||
|
||||
return {
|
||||
widgetsToUpdate: widgetsToReset,
|
||||
widgetsToDelete,
|
||||
viewFieldGroupsToUpdate: allViewFieldGroupsToUpdate,
|
||||
viewFieldGroupsToDelete: allViewFieldGroupsToDelete,
|
||||
viewFieldsToUpdate: allViewFieldsToUpdate,
|
||||
viewFieldsToDelete: allViewFieldsToDelete,
|
||||
orphanedViewIds,
|
||||
};
|
||||
}
|
||||
|
||||
private collectOrphanedViewIdsFromDeletedWidgets(
|
||||
widgets: FlatPageLayoutWidget[],
|
||||
): string[] {
|
||||
const viewIds: string[] = [];
|
||||
|
||||
for (const widget of widgets) {
|
||||
if (
|
||||
widget.configuration.configurationType !==
|
||||
WidgetConfigurationType.FIELDS
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const viewId = (widget.configuration as { viewId?: string | null })
|
||||
.viewId;
|
||||
|
||||
if (typeof viewId === 'string') {
|
||||
viewIds.push(viewId);
|
||||
}
|
||||
}
|
||||
|
||||
return viewIds;
|
||||
}
|
||||
|
||||
private async destroyOrphanedFieldsWidgetViews({
|
||||
viewIds,
|
||||
workspaceId,
|
||||
}: {
|
||||
viewIds: string[];
|
||||
workspaceId: string;
|
||||
}): Promise<void> {
|
||||
for (const viewId of viewIds) {
|
||||
try {
|
||||
await this.viewService.destroyOne({
|
||||
destroyViewInput: { id: viewId },
|
||||
workspaceId,
|
||||
});
|
||||
} catch (error) {
|
||||
this.logger.warn(
|
||||
`Failed to destroy orphaned view ${viewId} during tab reset: ${error}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private computeFieldsWidgetChildResetOperations({
|
||||
viewId,
|
||||
flatViewFieldGroupMaps,
|
||||
|
||||
+115
-18
@@ -33,6 +33,9 @@ import {
|
||||
generatePageLayoutExceptionMessage,
|
||||
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
|
||||
import { fromFlatPageLayoutWithTabsAndWidgetsToPageLayoutDto } from 'src/engine/metadata-modules/page-layout/utils/from-flat-page-layout-with-tabs-and-widgets-to-page-layout-dto.util';
|
||||
import { isCallerOverridingEntity } from 'src/engine/metadata-modules/utils/is-caller-overriding-entity.util';
|
||||
import { resolveFlatEntityOverridableProperties } from 'src/engine/metadata-modules/utils/resolve-flat-entity-overridable-properties.util';
|
||||
import { sanitizeOverridableEntityInput } from 'src/engine/metadata-modules/utils/sanitize-overridable-entity-input.util';
|
||||
import { ViewService } from 'src/engine/metadata-modules/view/services/view.service';
|
||||
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';
|
||||
@@ -277,6 +280,10 @@ export class PageLayoutUpdateService {
|
||||
.filter(isDefined)
|
||||
.filter((tab) => tab.pageLayoutId === existingPageLayout.id);
|
||||
|
||||
const resolvedExistingTabs = existingTabs.map(
|
||||
resolveFlatEntityOverridableProperties,
|
||||
);
|
||||
|
||||
const {
|
||||
toCreate: entitiesToCreate,
|
||||
toUpdate: entitiesToUpdate,
|
||||
@@ -286,7 +293,7 @@ export class PageLayoutUpdateService {
|
||||
FlatPageLayoutTab,
|
||||
UpdatePageLayoutTabWithWidgetsInput
|
||||
>({
|
||||
existingObjects: existingTabs,
|
||||
existingObjects: resolvedExistingTabs,
|
||||
receivedObjects: tabs,
|
||||
propertiesToCompare: FLAT_PAGE_LAYOUT_TAB_EDITABLE_PROPERTIES,
|
||||
isEntityIncluded: (entity) => entity.isActive,
|
||||
@@ -329,11 +336,33 @@ export class PageLayoutUpdateService {
|
||||
flatEntityMaps: flatPageLayoutTabMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
...existingTab,
|
||||
const shouldOverride = isCallerOverridingEntity({
|
||||
callerApplicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
entityApplicationUniversalIdentifier:
|
||||
existingTab.applicationUniversalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
const editableProperties = {
|
||||
title: tabInput.title,
|
||||
position: tabInput.position,
|
||||
...(tabInput.icon !== undefined && { icon: tabInput.icon }),
|
||||
layoutMode: tabInput.layoutMode ?? existingTab.layoutMode,
|
||||
};
|
||||
|
||||
const { overrides, updatedEditableProperties } =
|
||||
sanitizeOverridableEntityInput({
|
||||
metadataName: 'pageLayoutTab',
|
||||
existingFlatEntity: existingTab,
|
||||
updatedEditableProperties: editableProperties,
|
||||
shouldOverride,
|
||||
});
|
||||
|
||||
return {
|
||||
...existingTab,
|
||||
...updatedEditableProperties,
|
||||
overrides,
|
||||
updatedAt: now.toISOString(),
|
||||
};
|
||||
},
|
||||
@@ -346,11 +375,33 @@ export class PageLayoutUpdateService {
|
||||
flatEntityMaps: flatPageLayoutTabMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
...existingTab,
|
||||
const shouldOverride = isCallerOverridingEntity({
|
||||
callerApplicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
entityApplicationUniversalIdentifier:
|
||||
existingTab.applicationUniversalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
const editableProperties = {
|
||||
title: tabInput.title,
|
||||
position: tabInput.position,
|
||||
...(tabInput.icon !== undefined && { icon: tabInput.icon }),
|
||||
layoutMode: tabInput.layoutMode ?? existingTab.layoutMode,
|
||||
};
|
||||
|
||||
const { overrides, updatedEditableProperties } =
|
||||
sanitizeOverridableEntityInput({
|
||||
metadataName: 'pageLayoutTab',
|
||||
existingFlatEntity: existingTab,
|
||||
updatedEditableProperties: editableProperties,
|
||||
shouldOverride,
|
||||
});
|
||||
|
||||
return {
|
||||
...existingTab,
|
||||
...updatedEditableProperties,
|
||||
overrides,
|
||||
isActive: true,
|
||||
updatedAt: now.toISOString(),
|
||||
};
|
||||
@@ -493,6 +544,10 @@ export class PageLayoutUpdateService {
|
||||
.filter(isDefined)
|
||||
.filter((widget) => widget.pageLayoutTabId === tabId);
|
||||
|
||||
const resolvedExistingWidgets = existingWidgets.map(
|
||||
resolveFlatEntityOverridableProperties,
|
||||
);
|
||||
|
||||
const {
|
||||
toCreate: entitiesToCreate,
|
||||
toUpdate: entitiesToUpdate,
|
||||
@@ -502,7 +557,7 @@ export class PageLayoutUpdateService {
|
||||
FlatPageLayoutWidget,
|
||||
UpdatePageLayoutWidgetWithIdInput
|
||||
>({
|
||||
existingObjects: existingWidgets,
|
||||
existingObjects: resolvedExistingWidgets,
|
||||
receivedObjects: widgets,
|
||||
propertiesToCompare: FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES,
|
||||
isEntityIncluded: (entity) => entity.isActive,
|
||||
@@ -555,16 +610,37 @@ export class PageLayoutUpdateService {
|
||||
flatEntityMaps: flatPageLayoutWidgetMaps,
|
||||
});
|
||||
|
||||
const shouldOverride = isCallerOverridingEntity({
|
||||
callerApplicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
entityApplicationUniversalIdentifier:
|
||||
existingWidget.applicationUniversalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
const commonProperties = buildFlatPageLayoutWidgetCommonProperties({
|
||||
widgetInput,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
const updatedConfiguration = widgetInput.configuration ?? null;
|
||||
|
||||
const { overrides, updatedEditableProperties } =
|
||||
sanitizeOverridableEntityInput({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
existingFlatEntity: existingWidget,
|
||||
updatedEditableProperties: {
|
||||
...commonProperties,
|
||||
configuration: updatedConfiguration,
|
||||
},
|
||||
shouldOverride,
|
||||
});
|
||||
|
||||
return {
|
||||
...existingWidget,
|
||||
...buildFlatPageLayoutWidgetCommonProperties({
|
||||
widgetInput,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}),
|
||||
configuration: updatedConfiguration,
|
||||
...updatedEditableProperties,
|
||||
overrides,
|
||||
updatedAt: now.toISOString(),
|
||||
...(isDefined(updatedConfiguration) && {
|
||||
universalConfiguration:
|
||||
@@ -591,16 +667,37 @@ export class PageLayoutUpdateService {
|
||||
flatEntityMaps: flatPageLayoutWidgetMaps,
|
||||
});
|
||||
|
||||
const shouldOverride = isCallerOverridingEntity({
|
||||
callerApplicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
entityApplicationUniversalIdentifier:
|
||||
existingWidget.applicationUniversalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
const commonProperties = buildFlatPageLayoutWidgetCommonProperties({
|
||||
widgetInput,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
const restoredConfiguration = widgetInput.configuration ?? null;
|
||||
|
||||
const { overrides, updatedEditableProperties } =
|
||||
sanitizeOverridableEntityInput({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
existingFlatEntity: existingWidget,
|
||||
updatedEditableProperties: {
|
||||
...commonProperties,
|
||||
configuration: restoredConfiguration,
|
||||
},
|
||||
shouldOverride,
|
||||
});
|
||||
|
||||
return {
|
||||
...existingWidget,
|
||||
...buildFlatPageLayoutWidgetCommonProperties({
|
||||
widgetInput,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}),
|
||||
configuration: restoredConfiguration,
|
||||
...updatedEditableProperties,
|
||||
overrides,
|
||||
isActive: true,
|
||||
updatedAt: now.toISOString(),
|
||||
...(isDefined(restoredConfiguration) && {
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type FlatEntityWithOverrides = {
|
||||
[key: string]: unknown;
|
||||
overrides: Record<string, unknown> | null;
|
||||
};
|
||||
|
||||
export const resolveFlatEntityOverridableProperties = <
|
||||
T extends FlatEntityWithOverrides,
|
||||
>(
|
||||
flatEntity: T,
|
||||
): T => {
|
||||
if (!isDefined(flatEntity.overrides)) {
|
||||
return flatEntity;
|
||||
}
|
||||
|
||||
return {
|
||||
...flatEntity,
|
||||
...flatEntity.overrides,
|
||||
};
|
||||
};
|
||||
+4
-1
@@ -38,7 +38,10 @@ export class ViewFieldGroupDTO {
|
||||
@Field(() => [ViewFieldDTO])
|
||||
viewFields?: ViewFieldDTO[];
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
@Field(() => Boolean, {
|
||||
nullable: false,
|
||||
deprecationReason: 'isOverridden is deprecated',
|
||||
})
|
||||
isOverridden: boolean;
|
||||
|
||||
@HideField()
|
||||
|
||||
+2
-29
@@ -2,7 +2,6 @@ import { UseFilters, UseGuards, UsePipes } from '@nestjs/common';
|
||||
import {
|
||||
Args,
|
||||
Context,
|
||||
Float,
|
||||
Mutation,
|
||||
Parent,
|
||||
Query,
|
||||
@@ -10,7 +9,6 @@ import {
|
||||
} from '@nestjs/graphql';
|
||||
|
||||
import { isArray } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
@@ -19,14 +17,12 @@ import { type IDataloaders } from 'src/engine/dataloaders/dataloader.interface';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { resolveOverridableEntityProperty } from 'src/engine/metadata-modules/utils/resolve-overridable-entity-property.util';
|
||||
import { CreateViewFieldGroupInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/create-view-field-group.input';
|
||||
import { DeleteViewFieldGroupInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/delete-view-field-group.input';
|
||||
import { DestroyViewFieldGroupInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/destroy-view-field-group.input';
|
||||
import { UpdateViewFieldGroupInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/update-view-field-group.input';
|
||||
import { UpsertFieldsWidgetInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/upsert-fields-widget.input';
|
||||
import { ViewFieldGroupDTO } from 'src/engine/metadata-modules/view-field-group/dtos/view-field-group.dto';
|
||||
import { ViewFieldGroupEntity } from 'src/engine/metadata-modules/view-field-group/entities/view-field-group.entity';
|
||||
import { FieldsWidgetUpsertService } from 'src/engine/metadata-modules/view-field-group/services/fields-widget-upsert.service';
|
||||
import { ViewFieldGroupService } from 'src/engine/metadata-modules/view-field-group/services/view-field-group.service';
|
||||
import { ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto';
|
||||
@@ -43,35 +39,12 @@ export class ViewFieldGroupResolver {
|
||||
private readonly fieldsWidgetUpsertService: FieldsWidgetUpsertService,
|
||||
) {}
|
||||
|
||||
@ResolveField(() => String)
|
||||
name(@Parent() viewFieldGroup: ViewFieldGroupDTO): string {
|
||||
return resolveOverridableEntityProperty(viewFieldGroup, 'name');
|
||||
}
|
||||
|
||||
@ResolveField(() => Float)
|
||||
position(@Parent() viewFieldGroup: ViewFieldGroupDTO): number {
|
||||
return resolveOverridableEntityProperty(viewFieldGroup, 'position');
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isVisible(@Parent() viewFieldGroup: ViewFieldGroupDTO): boolean {
|
||||
return resolveOverridableEntityProperty(viewFieldGroup, 'isVisible');
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isOverridden(@Parent() viewFieldGroup: ViewFieldGroupDTO): boolean {
|
||||
return (
|
||||
isDefined(viewFieldGroup.overrides) &&
|
||||
Object.keys(viewFieldGroup.overrides).length > 0
|
||||
);
|
||||
}
|
||||
|
||||
@Query(() => [ViewFieldGroupDTO])
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async getViewFieldGroups(
|
||||
@Args('viewId', { type: () => String }) viewId: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<ViewFieldGroupEntity[]> {
|
||||
): Promise<ViewFieldGroupDTO[]> {
|
||||
return this.viewFieldGroupService.findByViewId(workspace.id, viewId);
|
||||
}
|
||||
|
||||
@@ -80,7 +53,7 @@ export class ViewFieldGroupResolver {
|
||||
async getViewFieldGroup(
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<ViewFieldGroupEntity | null> {
|
||||
): Promise<ViewFieldGroupDTO | null> {
|
||||
return this.viewFieldGroupService.findById(id, workspace.id);
|
||||
}
|
||||
|
||||
|
||||
+40
-23
@@ -1,11 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IsNull, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { fromCreateViewFieldGroupInputToFlatViewFieldGroupToCreate } from 'src/engine/metadata-modules/flat-view-field-group/utils/from-create-view-field-group-input-to-flat-view-field-group-to-create.util';
|
||||
@@ -17,7 +16,6 @@ import { DeleteViewFieldGroupInput } from 'src/engine/metadata-modules/view-fiel
|
||||
import { DestroyViewFieldGroupInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/destroy-view-field-group.input';
|
||||
import { UpdateViewFieldGroupInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/update-view-field-group.input';
|
||||
import { ViewFieldGroupDTO } from 'src/engine/metadata-modules/view-field-group/dtos/view-field-group.dto';
|
||||
import { ViewFieldGroupEntity } from 'src/engine/metadata-modules/view-field-group/entities/view-field-group.entity';
|
||||
import {
|
||||
ViewFieldGroupException,
|
||||
ViewFieldGroupExceptionCode,
|
||||
@@ -31,8 +29,6 @@ export class ViewFieldGroupService {
|
||||
constructor(
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
@InjectRepository(ViewFieldGroupEntity)
|
||||
private readonly viewFieldGroupRepository: Repository<ViewFieldGroupEntity>,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
@@ -342,30 +338,51 @@ export class ViewFieldGroupService {
|
||||
async findByViewId(
|
||||
workspaceId: string,
|
||||
viewId: string,
|
||||
): Promise<ViewFieldGroupEntity[]> {
|
||||
return this.viewFieldGroupRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
viewId,
|
||||
isActive: true,
|
||||
deletedAt: IsNull(),
|
||||
},
|
||||
order: { position: 'ASC' },
|
||||
});
|
||||
): Promise<ViewFieldGroupDTO[]> {
|
||||
const { flatViewFieldGroupMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewFieldGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return Object.values(flatViewFieldGroupMaps.byUniversalIdentifier)
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(group) =>
|
||||
group.viewId === viewId &&
|
||||
group.isActive &&
|
||||
!isDefined(group.deletedAt),
|
||||
)
|
||||
.map(fromFlatViewFieldGroupToViewFieldGroupDto)
|
||||
.sort((a, b) => a.position - b.position);
|
||||
}
|
||||
|
||||
async findById(
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
): Promise<ViewFieldGroupEntity | null> {
|
||||
const viewFieldGroup = await this.viewFieldGroupRepository.findOne({
|
||||
where: {
|
||||
id,
|
||||
workspaceId,
|
||||
deletedAt: IsNull(),
|
||||
},
|
||||
): Promise<ViewFieldGroupDTO | null> {
|
||||
const { flatViewFieldGroupMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewFieldGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatViewFieldGroup = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: flatViewFieldGroupMaps,
|
||||
});
|
||||
|
||||
return viewFieldGroup || null;
|
||||
if (
|
||||
!isDefined(flatViewFieldGroup) ||
|
||||
isDefined(flatViewFieldGroup.deletedAt)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fromFlatViewFieldGroupToViewFieldGroupDto(flatViewFieldGroup);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,17 +1,16 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatViewFieldGroup } from 'src/engine/metadata-modules/flat-view-field-group/types/flat-view-field-group.type';
|
||||
import { type ViewFieldGroupDTO } from 'src/engine/metadata-modules/view-field-group/dtos/view-field-group.dto';
|
||||
|
||||
export const fromFlatViewFieldGroupToViewFieldGroupDto = (
|
||||
flatViewFieldGroup: FlatViewFieldGroup,
|
||||
): ViewFieldGroupDTO => {
|
||||
const { createdAt, updatedAt, deletedAt, ...rest } = flatViewFieldGroup;
|
||||
const { createdAt, updatedAt, deletedAt, overrides, ...rest } =
|
||||
flatViewFieldGroup;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
isOverridden:
|
||||
isDefined(rest.overrides) && Object.keys(rest.overrides).length > 0,
|
||||
...(overrides ?? {}),
|
||||
isOverridden: false,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
deletedAt: deletedAt ? new Date(deletedAt) : null,
|
||||
|
||||
+2
-3
@@ -20,7 +20,6 @@ import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { CreateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/create-view-field.input';
|
||||
import { UpdateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/update-view-field.input';
|
||||
import { ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto';
|
||||
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import {
|
||||
generateViewFieldExceptionMessage,
|
||||
generateViewFieldUserFriendlyExceptionMessage,
|
||||
@@ -45,7 +44,7 @@ export class ViewFieldController {
|
||||
async findMany(
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
@Query('viewId') viewId?: string,
|
||||
): Promise<ViewFieldEntity[]> {
|
||||
): Promise<ViewFieldDTO[]> {
|
||||
if (viewId) {
|
||||
return this.viewFieldService.findByViewId(workspace.id, viewId);
|
||||
}
|
||||
@@ -58,7 +57,7 @@ export class ViewFieldController {
|
||||
async findOne(
|
||||
@Param('id') id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<ViewFieldEntity> {
|
||||
): Promise<ViewFieldDTO> {
|
||||
const viewField = await this.viewFieldService.findById(id, workspace.id);
|
||||
|
||||
if (!isDefined(viewField)) {
|
||||
|
||||
+5
-2
@@ -51,8 +51,11 @@ export class ViewFieldDTO {
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date | null;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isOverridden: boolean;
|
||||
@Field(() => Boolean, {
|
||||
nullable: true,
|
||||
deprecationReason: 'isOverridden is deprecated',
|
||||
})
|
||||
isOverridden?: boolean;
|
||||
|
||||
@HideField()
|
||||
overrides?: ViewFieldOverrides | null;
|
||||
|
||||
+3
-54
@@ -1,30 +1,16 @@
|
||||
import { UseFilters, UseGuards } from '@nestjs/common';
|
||||
import {
|
||||
Args,
|
||||
Float,
|
||||
Int,
|
||||
Mutation,
|
||||
Parent,
|
||||
Query,
|
||||
ResolveField,
|
||||
} from '@nestjs/graphql';
|
||||
|
||||
import { AggregateOperations } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Args, Mutation, Query } from '@nestjs/graphql';
|
||||
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { resolveOverridableEntityProperty } from 'src/engine/metadata-modules/utils/resolve-overridable-entity-property.util';
|
||||
import { CreateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/create-view-field.input';
|
||||
import { DeleteViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/delete-view-field.input';
|
||||
import { DestroyViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/destroy-view-field.input';
|
||||
import { UpdateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/update-view-field.input';
|
||||
import { ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto';
|
||||
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import { ViewFieldService } from 'src/engine/metadata-modules/view-field/services/view-field.service';
|
||||
import { CreateViewFieldPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/create-view-field-permission.guard';
|
||||
import { DeleteViewFieldPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/delete-view-field-permission.guard';
|
||||
@@ -38,49 +24,12 @@ import { ViewGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/view/
|
||||
export class ViewFieldResolver {
|
||||
constructor(private readonly viewFieldService: ViewFieldService) {}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isVisible(@Parent() viewField: ViewFieldDTO): boolean {
|
||||
return resolveOverridableEntityProperty(viewField, 'isVisible');
|
||||
}
|
||||
|
||||
@ResolveField(() => Int)
|
||||
size(@Parent() viewField: ViewFieldDTO): number {
|
||||
return resolveOverridableEntityProperty(viewField, 'size');
|
||||
}
|
||||
|
||||
@ResolveField(() => Float)
|
||||
position(@Parent() viewField: ViewFieldDTO): number {
|
||||
return resolveOverridableEntityProperty(viewField, 'position');
|
||||
}
|
||||
|
||||
@ResolveField(() => AggregateOperations, { nullable: true })
|
||||
aggregateOperation(
|
||||
@Parent() viewField: ViewFieldDTO,
|
||||
): AggregateOperations | null | undefined {
|
||||
return resolveOverridableEntityProperty(viewField, 'aggregateOperation');
|
||||
}
|
||||
|
||||
@ResolveField(() => UUIDScalarType, { nullable: true })
|
||||
viewFieldGroupId(
|
||||
@Parent() viewField: ViewFieldDTO,
|
||||
): string | null | undefined {
|
||||
return resolveOverridableEntityProperty(viewField, 'viewFieldGroupId');
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isOverridden(@Parent() viewField: ViewFieldDTO): boolean {
|
||||
return (
|
||||
isDefined(viewField.overrides) &&
|
||||
Object.keys(viewField.overrides).length > 0
|
||||
);
|
||||
}
|
||||
|
||||
@Query(() => [ViewFieldDTO])
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async getViewFields(
|
||||
@Args('viewId', { type: () => String }) viewId: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<ViewFieldEntity[]> {
|
||||
): Promise<ViewFieldDTO[]> {
|
||||
return this.viewFieldService.findByViewId(workspace.id, viewId);
|
||||
}
|
||||
|
||||
@@ -89,7 +38,7 @@ export class ViewFieldResolver {
|
||||
async getViewField(
|
||||
@Args('id', { type: () => String }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<ViewFieldEntity | null> {
|
||||
): Promise<ViewFieldDTO | null> {
|
||||
return this.viewFieldService.findById(id, workspace.id);
|
||||
}
|
||||
|
||||
|
||||
+51
-35
@@ -1,11 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IsNull, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { fromCreateViewFieldInputToFlatViewFieldToCreate } from 'src/engine/metadata-modules/flat-view-field/utils/from-create-view-field-input-to-flat-view-field-to-create.util';
|
||||
@@ -17,7 +16,6 @@ import { DeleteViewFieldInput } from 'src/engine/metadata-modules/view-field/dto
|
||||
import { DestroyViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/destroy-view-field.input';
|
||||
import { UpdateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/update-view-field.input';
|
||||
import { ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto';
|
||||
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import {
|
||||
ViewFieldException,
|
||||
ViewFieldExceptionCode,
|
||||
@@ -31,8 +29,6 @@ export class ViewFieldService {
|
||||
constructor(
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
@InjectRepository(ViewFieldEntity)
|
||||
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
@@ -345,47 +341,67 @@ export class ViewFieldService {
|
||||
});
|
||||
}
|
||||
|
||||
async findByWorkspaceId(workspaceId: string): Promise<ViewFieldEntity[]> {
|
||||
return this.viewFieldRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
isActive: true,
|
||||
deletedAt: IsNull(),
|
||||
},
|
||||
order: { position: 'ASC' },
|
||||
relations: ['workspace', 'view'],
|
||||
});
|
||||
async findByWorkspaceId(workspaceId: string): Promise<ViewFieldDTO[]> {
|
||||
const { flatViewFieldMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewFieldMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return Object.values(flatViewFieldMaps.byUniversalIdentifier)
|
||||
.filter(isDefined)
|
||||
.filter((field) => field.isActive && !isDefined(field.deletedAt))
|
||||
.map(fromFlatViewFieldToViewFieldDto)
|
||||
.sort((a, b) => a.position - b.position);
|
||||
}
|
||||
|
||||
async findByViewId(
|
||||
workspaceId: string,
|
||||
viewId: string,
|
||||
): Promise<ViewFieldEntity[]> {
|
||||
return this.viewFieldRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
viewId,
|
||||
isActive: true,
|
||||
deletedAt: IsNull(),
|
||||
},
|
||||
order: { position: 'ASC' },
|
||||
relations: ['workspace', 'view'],
|
||||
});
|
||||
): Promise<ViewFieldDTO[]> {
|
||||
const { flatViewFieldMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewFieldMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return Object.values(flatViewFieldMaps.byUniversalIdentifier)
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(field) =>
|
||||
field.viewId === viewId &&
|
||||
field.isActive &&
|
||||
!isDefined(field.deletedAt),
|
||||
)
|
||||
.map(fromFlatViewFieldToViewFieldDto)
|
||||
.sort((a, b) => a.position - b.position);
|
||||
}
|
||||
|
||||
async findById(
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
): Promise<ViewFieldEntity | null> {
|
||||
const viewField = await this.viewFieldRepository.findOne({
|
||||
where: {
|
||||
id,
|
||||
workspaceId,
|
||||
deletedAt: IsNull(),
|
||||
},
|
||||
relations: ['workspace', 'view'],
|
||||
): Promise<ViewFieldDTO | null> {
|
||||
const { flatViewFieldMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewFieldMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatViewField = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: id,
|
||||
flatEntityMaps: flatViewFieldMaps,
|
||||
});
|
||||
|
||||
return viewField || null;
|
||||
if (!isDefined(flatViewField) || isDefined(flatViewField.deletedAt)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fromFlatViewFieldToViewFieldDto(flatViewField);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -1,17 +1,15 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
import { type ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto';
|
||||
|
||||
export const fromFlatViewFieldToViewFieldDto = (
|
||||
flatViewField: FlatViewField,
|
||||
): ViewFieldDTO => {
|
||||
const { createdAt, updatedAt, deletedAt, ...rest } = flatViewField;
|
||||
const { createdAt, updatedAt, deletedAt, overrides, ...rest } = flatViewField;
|
||||
|
||||
return {
|
||||
...rest,
|
||||
isOverridden:
|
||||
isDefined(rest.overrides) && Object.keys(rest.overrides).length > 0,
|
||||
...(overrides ?? {}),
|
||||
isOverridden: false,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
deletedAt: deletedAt ? new Date(deletedAt) : null,
|
||||
|
||||
-3
@@ -9,7 +9,6 @@ const TAB_OVERRIDE_GQL_FIELDS = `
|
||||
title
|
||||
position
|
||||
icon
|
||||
isOverridden
|
||||
pageLayoutId
|
||||
createdAt
|
||||
updatedAt
|
||||
@@ -79,7 +78,6 @@ describe('Page layout tab override behavior', () => {
|
||||
});
|
||||
|
||||
expect(data.updatePageLayoutTab.title).toBe(overriddenTitle);
|
||||
expect(data.updatePageLayoutTab.isOverridden).toBe(true);
|
||||
});
|
||||
|
||||
it('should return the overridden title when querying the tab', async () => {
|
||||
@@ -108,7 +106,6 @@ describe('Page layout tab override behavior', () => {
|
||||
});
|
||||
|
||||
expect(data.updatePageLayoutTab.title).toBe(seededTabOriginalTitle);
|
||||
expect(data.updatePageLayoutTab.isOverridden).toBe(false);
|
||||
});
|
||||
|
||||
it('should override position on a seeded tab', async () => {
|
||||
|
||||
+3
-6
@@ -11,7 +11,6 @@ const WIDGET_OVERRIDE_GQL_FIELDS = `
|
||||
type
|
||||
pageLayoutTabId
|
||||
conditionalDisplay
|
||||
isOverridden
|
||||
createdAt
|
||||
updatedAt
|
||||
deletedAt
|
||||
@@ -80,7 +79,6 @@ describe('Page layout widget override behavior', () => {
|
||||
});
|
||||
|
||||
expect(data.updatePageLayoutWidget.title).toBe(overriddenTitle);
|
||||
expect(data.updatePageLayoutWidget.isOverridden).toBe(true);
|
||||
});
|
||||
|
||||
it('should return the overridden title when querying the widget', async () => {
|
||||
@@ -123,7 +121,6 @@ describe('Page layout widget override behavior', () => {
|
||||
});
|
||||
|
||||
expect(data.updatePageLayoutWidget.title).toBe(seededWidgetOriginalTitle);
|
||||
expect(data.updatePageLayoutWidget.isOverridden).toBe(false);
|
||||
});
|
||||
|
||||
it('should override conditionalDisplay independently from title', async () => {
|
||||
@@ -155,9 +152,9 @@ describe('Page layout widget override behavior', () => {
|
||||
});
|
||||
|
||||
expect(conditionalData.updatePageLayoutWidget.title).toBe(overriddenTitle);
|
||||
expect(
|
||||
conditionalData.updatePageLayoutWidget.conditionalDisplay,
|
||||
).toEqual(overriddenConditionalDisplay);
|
||||
expect(conditionalData.updatePageLayoutWidget.conditionalDisplay).toEqual(
|
||||
overriddenConditionalDisplay,
|
||||
);
|
||||
|
||||
await updateOnePageLayoutWidget({
|
||||
expectToFail: false,
|
||||
|
||||
Reference in New Issue
Block a user