Move is active to fe (#19649)
## Context Moving isActive filtering to the frontend for page layout tabs and widgets, hiding inactive entities from the UI while keeping them in state for future reactivation Next we will implement deactivated standard tab re-activation during tab creation (cc @Devessier) <img width="234" height="303" alt="📋 Menu (Slots)" src="https://github.com/user-attachments/assets/17a25ac6-55e2-4778-b7f0-e7554ed69704" />
This commit is contained in:
@@ -583,6 +583,7 @@ type ViewField {
|
||||
workspaceId: UUID!
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
isActive: Boolean!
|
||||
deletedAt: DateTime
|
||||
isOverridden: Boolean @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
@@ -691,6 +692,7 @@ type ViewFieldGroup {
|
||||
workspaceId: UUID!
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
isActive: Boolean!
|
||||
deletedAt: DateTime
|
||||
viewFields: [ViewField!]!
|
||||
isOverridden: Boolean! @deprecated(reason: "isOverridden is deprecated")
|
||||
@@ -899,6 +901,7 @@ type PageLayoutWidget {
|
||||
conditionalAvailabilityExpression: String
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
isActive: Boolean!
|
||||
deletedAt: DateTime
|
||||
isOverridden: Boolean @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
@@ -1234,6 +1237,7 @@ type PageLayoutTab {
|
||||
layoutMode: PageLayoutTabLayoutMode
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
isActive: Boolean!
|
||||
deletedAt: DateTime
|
||||
isOverridden: Boolean @deprecated(reason: "isOverridden is deprecated")
|
||||
}
|
||||
|
||||
@@ -415,6 +415,7 @@ export interface ViewField {
|
||||
workspaceId: Scalars['UUID']
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
isActive: Scalars['Boolean']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: Scalars['Boolean']
|
||||
@@ -492,6 +493,7 @@ export interface ViewFieldGroup {
|
||||
workspaceId: Scalars['UUID']
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
isActive: Scalars['Boolean']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
viewFields: ViewField[]
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
@@ -674,6 +676,7 @@ export interface PageLayoutWidget {
|
||||
conditionalAvailabilityExpression?: Scalars['String']
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
isActive: Scalars['Boolean']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: Scalars['Boolean']
|
||||
@@ -959,6 +962,7 @@ export interface PageLayoutTab {
|
||||
layoutMode?: PageLayoutTabLayoutMode
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
isActive: Scalars['Boolean']
|
||||
deletedAt?: Scalars['DateTime']
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: Scalars['Boolean']
|
||||
@@ -3631,6 +3635,7 @@ export interface ViewFieldGenqlSelection{
|
||||
workspaceId?: boolean | number
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
isActive?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
@@ -3705,6 +3710,7 @@ export interface ViewFieldGroupGenqlSelection{
|
||||
workspaceId?: boolean | number
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
isActive?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
viewFields?: ViewFieldGenqlSelection
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
@@ -3879,6 +3885,7 @@ export interface PageLayoutWidgetGenqlSelection{
|
||||
conditionalAvailabilityExpression?: boolean | number
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
isActive?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
@@ -4191,6 +4198,7 @@ export interface PageLayoutTabGenqlSelection{
|
||||
layoutMode?: boolean | number
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
isActive?: boolean | number
|
||||
deletedAt?: boolean | number
|
||||
/** @deprecated isOverridden is deprecated */
|
||||
isOverridden?: boolean | number
|
||||
|
||||
@@ -1283,6 +1283,9 @@ export default {
|
||||
"updatedAt": [
|
||||
4
|
||||
],
|
||||
"isActive": [
|
||||
6
|
||||
],
|
||||
"deletedAt": [
|
||||
4
|
||||
],
|
||||
@@ -1456,6 +1459,9 @@ export default {
|
||||
"updatedAt": [
|
||||
4
|
||||
],
|
||||
"isActive": [
|
||||
6
|
||||
],
|
||||
"deletedAt": [
|
||||
4
|
||||
],
|
||||
@@ -1903,6 +1909,9 @@ export default {
|
||||
"updatedAt": [
|
||||
4
|
||||
],
|
||||
"isActive": [
|
||||
6
|
||||
],
|
||||
"deletedAt": [
|
||||
4
|
||||
],
|
||||
@@ -2561,6 +2570,9 @@ export default {
|
||||
"updatedAt": [
|
||||
4
|
||||
],
|
||||
"isActive": [
|
||||
6
|
||||
],
|
||||
"deletedAt": [
|
||||
4
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
@@ -14,6 +14,7 @@ export const PAGE_LAYOUT_TAB_FRAGMENT = gql`
|
||||
...PageLayoutWidgetFragment
|
||||
}
|
||||
pageLayoutId
|
||||
isActive
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
|
||||
@@ -79,7 +79,9 @@ export const splitViewWithRelated = (
|
||||
const { viewFields: _viewFields, ...viewFieldGroupProperties } =
|
||||
viewFieldGroup;
|
||||
|
||||
flatViewFieldGroups.push(viewFieldGroupProperties);
|
||||
flatViewFieldGroups.push({
|
||||
...viewFieldGroupProperties,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -64,6 +64,7 @@ const mixedGraphsPageLayoutMocks = {
|
||||
tabs: [
|
||||
{
|
||||
__typename: 'PageLayoutTab',
|
||||
isActive: true,
|
||||
id: 'mixed-tab',
|
||||
title: 'Mixed Graphs',
|
||||
position: 0,
|
||||
@@ -74,6 +75,7 @@ const mixedGraphsPageLayoutMocks = {
|
||||
widgets: [
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'number-widget',
|
||||
pageLayoutTabId: 'mixed-tab',
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -98,6 +100,7 @@ const mixedGraphsPageLayoutMocks = {
|
||||
} satisfies PageLayoutWidget,
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'gauge-widget',
|
||||
pageLayoutTabId: 'mixed-tab',
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -123,6 +126,7 @@ const mixedGraphsPageLayoutMocks = {
|
||||
} satisfies PageLayoutWidget,
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'pie-widget',
|
||||
pageLayoutTabId: 'mixed-tab',
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -149,6 +153,7 @@ const mixedGraphsPageLayoutMocks = {
|
||||
} satisfies PageLayoutWidget,
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'bar-widget',
|
||||
pageLayoutTabId: 'mixed-tab',
|
||||
type: WidgetType.GRAPH,
|
||||
|
||||
+4
@@ -23,6 +23,7 @@ const StyledContainer = styled.div`
|
||||
const createInitialTabs = (): PageLayoutTab[] => [
|
||||
{
|
||||
__typename: 'PageLayoutTab',
|
||||
isActive: true,
|
||||
applicationId: '',
|
||||
id: 'overview',
|
||||
title: 'Overview',
|
||||
@@ -36,6 +37,7 @@ const createInitialTabs = (): PageLayoutTab[] => [
|
||||
},
|
||||
{
|
||||
__typename: 'PageLayoutTab',
|
||||
isActive: true,
|
||||
applicationId: '',
|
||||
id: 'revenue',
|
||||
title: 'Revenue',
|
||||
@@ -48,6 +50,7 @@ const createInitialTabs = (): PageLayoutTab[] => [
|
||||
},
|
||||
{
|
||||
__typename: 'PageLayoutTab',
|
||||
isActive: true,
|
||||
applicationId: '',
|
||||
id: 'forecasts',
|
||||
title: 'Forecasts',
|
||||
@@ -77,6 +80,7 @@ const PageLayoutTabListPlayground = ({
|
||||
...prev,
|
||||
{
|
||||
__typename: 'PageLayoutTab',
|
||||
isActive: true,
|
||||
applicationId: '',
|
||||
id: `new-tab-${nextIndex}`,
|
||||
title: `New Tab ${nextIndex}`,
|
||||
|
||||
+14
@@ -21,6 +21,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'company-tab-fields',
|
||||
isActive: true,
|
||||
title: 'Home',
|
||||
icon: 'IconHome',
|
||||
position: 100,
|
||||
@@ -33,6 +34,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'company-widget-fields',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'company-tab-fields',
|
||||
title: 'Fields',
|
||||
type: WidgetType.FIELDS,
|
||||
@@ -59,6 +61,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'company-tab-timeline',
|
||||
isActive: true,
|
||||
title: 'Timeline',
|
||||
icon: 'IconTimelineEvent',
|
||||
position: 200,
|
||||
@@ -71,6 +74,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'company-widget-timeline',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'company-tab-timeline',
|
||||
title: 'Timeline',
|
||||
type: WidgetType.TIMELINE,
|
||||
@@ -97,6 +101,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'company-tab-tasks',
|
||||
isActive: true,
|
||||
title: 'Tasks',
|
||||
icon: 'IconCheckbox',
|
||||
position: 300,
|
||||
@@ -109,6 +114,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'company-widget-tasks',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'company-tab-tasks',
|
||||
title: 'Tasks',
|
||||
type: WidgetType.TASKS,
|
||||
@@ -135,6 +141,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'company-tab-notes',
|
||||
isActive: true,
|
||||
title: 'Notes',
|
||||
icon: 'IconNotes',
|
||||
position: 400,
|
||||
@@ -147,6 +154,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'company-widget-notes',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'company-tab-notes',
|
||||
title: 'Notes',
|
||||
type: WidgetType.NOTES,
|
||||
@@ -173,6 +181,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'company-tab-files',
|
||||
isActive: true,
|
||||
title: 'Files',
|
||||
icon: 'IconPaperclip',
|
||||
position: 500,
|
||||
@@ -185,6 +194,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'company-widget-files',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'company-tab-files',
|
||||
title: 'Files',
|
||||
type: WidgetType.FILES,
|
||||
@@ -211,6 +221,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'company-tab-emails',
|
||||
isActive: true,
|
||||
title: 'Emails',
|
||||
icon: 'IconMail',
|
||||
position: 600,
|
||||
@@ -223,6 +234,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'company-widget-emails',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'company-tab-emails',
|
||||
title: 'Emails',
|
||||
type: WidgetType.EMAILS,
|
||||
@@ -249,6 +261,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'company-tab-calendar',
|
||||
isActive: true,
|
||||
title: 'Calendar',
|
||||
icon: 'IconCalendarEvent',
|
||||
position: 700,
|
||||
@@ -261,6 +274,7 @@ export const DEFAULT_COMPANY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'company-widget-calendar',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'company-tab-calendar',
|
||||
title: 'Calendar',
|
||||
type: WidgetType.CALENDAR,
|
||||
|
||||
+2
@@ -21,6 +21,7 @@ export const DEFAULT_MESSAGE_THREAD_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'message-thread-tab-home',
|
||||
isActive: true,
|
||||
title: 'Home',
|
||||
icon: 'IconHome',
|
||||
position: 100,
|
||||
@@ -33,6 +34,7 @@ export const DEFAULT_MESSAGE_THREAD_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'message-thread-widget-email-thread',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'message-thread-tab-home',
|
||||
title: 'Thread',
|
||||
type: WidgetType.EMAIL_THREAD,
|
||||
|
||||
@@ -21,6 +21,7 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'note-tab-fields',
|
||||
isActive: true,
|
||||
title: 'Home',
|
||||
icon: 'IconHome',
|
||||
position: 100,
|
||||
@@ -33,6 +34,7 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'note-widget-fields',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'note-tab-fields',
|
||||
title: 'Fields',
|
||||
type: WidgetType.FIELDS,
|
||||
@@ -59,6 +61,7 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'note-widget-note',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'note-tab-fields',
|
||||
title: 'Note',
|
||||
type: WidgetType.FIELD_RICH_TEXT,
|
||||
@@ -92,6 +95,7 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'note-tab-note',
|
||||
isActive: true,
|
||||
title: 'Note',
|
||||
icon: 'IconNotes',
|
||||
position: 150,
|
||||
@@ -104,6 +108,7 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'note-widget-note',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'note-tab-note',
|
||||
title: 'Note',
|
||||
type: WidgetType.FIELD_RICH_TEXT,
|
||||
@@ -137,6 +142,7 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'note-tab-timeline',
|
||||
isActive: true,
|
||||
title: 'Timeline',
|
||||
icon: 'IconTimelineEvent',
|
||||
position: 200,
|
||||
@@ -149,6 +155,7 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'note-widget-timeline',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'note-tab-timeline',
|
||||
title: 'Timeline',
|
||||
type: WidgetType.TIMELINE,
|
||||
@@ -175,6 +182,7 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'note-tab-files',
|
||||
isActive: true,
|
||||
title: 'Files',
|
||||
icon: 'IconPaperclip',
|
||||
position: 300,
|
||||
@@ -187,6 +195,7 @@ export const DEFAULT_NOTE_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'note-widget-files',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'note-tab-files',
|
||||
title: 'Files',
|
||||
type: WidgetType.FILES,
|
||||
|
||||
+14
@@ -21,6 +21,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'opportunity-tab-fields',
|
||||
isActive: true,
|
||||
title: 'Home',
|
||||
icon: 'IconHome',
|
||||
position: 100,
|
||||
@@ -33,6 +34,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'opportunity-widget-fields',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'opportunity-tab-fields',
|
||||
title: 'Fields',
|
||||
type: WidgetType.FIELDS,
|
||||
@@ -59,6 +61,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'opportunity-tab-timeline',
|
||||
isActive: true,
|
||||
title: 'Timeline',
|
||||
icon: 'IconTimelineEvent',
|
||||
position: 200,
|
||||
@@ -71,6 +74,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'opportunity-widget-timeline',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'opportunity-tab-timeline',
|
||||
title: 'Timeline',
|
||||
type: WidgetType.TIMELINE,
|
||||
@@ -97,6 +101,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'opportunity-tab-tasks',
|
||||
isActive: true,
|
||||
title: 'Tasks',
|
||||
icon: 'IconCheckbox',
|
||||
position: 300,
|
||||
@@ -109,6 +114,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'opportunity-widget-tasks',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'opportunity-tab-tasks',
|
||||
title: 'Tasks',
|
||||
type: WidgetType.TASKS,
|
||||
@@ -135,6 +141,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'opportunity-tab-notes',
|
||||
isActive: true,
|
||||
title: 'Notes',
|
||||
icon: 'IconNotes',
|
||||
position: 400,
|
||||
@@ -147,6 +154,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'opportunity-widget-notes',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'opportunity-tab-notes',
|
||||
title: 'Notes',
|
||||
type: WidgetType.NOTES,
|
||||
@@ -173,6 +181,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'opportunity-tab-files',
|
||||
isActive: true,
|
||||
title: 'Files',
|
||||
icon: 'IconPaperclip',
|
||||
position: 500,
|
||||
@@ -185,6 +194,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'opportunity-widget-files',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'opportunity-tab-files',
|
||||
title: 'Files',
|
||||
type: WidgetType.FILES,
|
||||
@@ -211,6 +221,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'opportunity-tab-emails',
|
||||
isActive: true,
|
||||
title: 'Emails',
|
||||
icon: 'IconMail',
|
||||
position: 600,
|
||||
@@ -223,6 +234,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'opportunity-widget-emails',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'opportunity-tab-emails',
|
||||
title: 'Emails',
|
||||
type: WidgetType.EMAILS,
|
||||
@@ -249,6 +261,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'opportunity-tab-calendar',
|
||||
isActive: true,
|
||||
title: 'Calendar',
|
||||
icon: 'IconCalendarEvent',
|
||||
position: 700,
|
||||
@@ -261,6 +274,7 @@ export const DEFAULT_OPPORTUNITY_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'opportunity-widget-calendar',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'opportunity-tab-calendar',
|
||||
title: 'Calendar',
|
||||
type: WidgetType.CALENDAR,
|
||||
|
||||
+14
@@ -21,6 +21,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'person-tab-fields',
|
||||
isActive: true,
|
||||
title: 'Home',
|
||||
icon: 'IconHome',
|
||||
position: 100,
|
||||
@@ -33,6 +34,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'person-widget-fields',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'person-tab-fields',
|
||||
title: 'Fields',
|
||||
type: WidgetType.FIELDS,
|
||||
@@ -59,6 +61,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'person-tab-timeline',
|
||||
isActive: true,
|
||||
title: 'Timeline',
|
||||
icon: 'IconTimelineEvent',
|
||||
position: 200,
|
||||
@@ -71,6 +74,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'person-widget-timeline',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'person-tab-timeline',
|
||||
title: 'Timeline',
|
||||
type: WidgetType.TIMELINE,
|
||||
@@ -97,6 +101,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'person-tab-tasks',
|
||||
isActive: true,
|
||||
title: 'Tasks',
|
||||
icon: 'IconCheckbox',
|
||||
position: 300,
|
||||
@@ -109,6 +114,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'person-widget-tasks',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'person-tab-tasks',
|
||||
title: 'Tasks',
|
||||
type: WidgetType.TASKS,
|
||||
@@ -135,6 +141,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'person-tab-notes',
|
||||
isActive: true,
|
||||
title: 'Notes',
|
||||
icon: 'IconNotes',
|
||||
position: 400,
|
||||
@@ -147,6 +154,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'person-widget-notes',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'person-tab-notes',
|
||||
title: 'Notes',
|
||||
type: WidgetType.NOTES,
|
||||
@@ -173,6 +181,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'person-tab-files',
|
||||
isActive: true,
|
||||
title: 'Files',
|
||||
icon: 'IconPaperclip',
|
||||
position: 500,
|
||||
@@ -185,6 +194,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'person-widget-files',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'person-tab-files',
|
||||
title: 'Files',
|
||||
type: WidgetType.FILES,
|
||||
@@ -211,6 +221,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'person-tab-emails',
|
||||
isActive: true,
|
||||
title: 'Emails',
|
||||
icon: 'IconMail',
|
||||
position: 600,
|
||||
@@ -223,6 +234,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'person-widget-emails',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'person-tab-emails',
|
||||
title: 'Emails',
|
||||
type: WidgetType.EMAILS,
|
||||
@@ -249,6 +261,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'person-tab-calendar',
|
||||
isActive: true,
|
||||
title: 'Calendar',
|
||||
icon: 'IconCalendarEvent',
|
||||
position: 700,
|
||||
@@ -261,6 +274,7 @@ export const DEFAULT_PERSON_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'person-widget-calendar',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'person-tab-calendar',
|
||||
title: 'Calendar',
|
||||
type: WidgetType.CALENDAR,
|
||||
|
||||
@@ -21,6 +21,7 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'default-tab-fields',
|
||||
isActive: true,
|
||||
title: 'Home',
|
||||
icon: 'IconHome',
|
||||
position: 100,
|
||||
@@ -33,6 +34,7 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'default-widget-fields',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'default-tab-fields',
|
||||
title: 'Fields',
|
||||
type: WidgetType.FIELDS,
|
||||
@@ -59,6 +61,7 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'default-tab-timeline',
|
||||
isActive: true,
|
||||
title: 'Timeline',
|
||||
icon: 'IconTimelineEvent',
|
||||
position: 200,
|
||||
@@ -71,6 +74,7 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'default-widget-timeline',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'default-tab-timeline',
|
||||
title: 'Timeline',
|
||||
type: WidgetType.TIMELINE,
|
||||
@@ -97,6 +101,7 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'default-tab-tasks',
|
||||
isActive: true,
|
||||
title: 'Tasks',
|
||||
icon: 'IconCheckbox',
|
||||
position: 300,
|
||||
@@ -109,6 +114,7 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'default-widget-tasks',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'default-tab-tasks',
|
||||
title: 'Tasks',
|
||||
type: WidgetType.TASKS,
|
||||
@@ -135,6 +141,7 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'default-tab-notes',
|
||||
isActive: true,
|
||||
title: 'Notes',
|
||||
icon: 'IconNotes',
|
||||
position: 400,
|
||||
@@ -147,6 +154,7 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'default-widget-notes',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'default-tab-notes',
|
||||
title: 'Notes',
|
||||
type: WidgetType.NOTES,
|
||||
@@ -173,6 +181,7 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'default-tab-files',
|
||||
isActive: true,
|
||||
title: 'Files',
|
||||
icon: 'IconPaperclip',
|
||||
position: 500,
|
||||
@@ -185,6 +194,7 @@ export const DEFAULT_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'default-widget-files',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'default-tab-files',
|
||||
title: 'Files',
|
||||
type: WidgetType.FILES,
|
||||
|
||||
@@ -21,6 +21,7 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'task-tab-fields',
|
||||
isActive: true,
|
||||
title: 'Home',
|
||||
icon: 'IconHome',
|
||||
position: 100,
|
||||
@@ -33,6 +34,7 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'task-widget-fields',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'task-tab-fields',
|
||||
title: 'Fields',
|
||||
type: WidgetType.FIELDS,
|
||||
@@ -56,6 +58,7 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'task-widget-note',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'task-tab-fields',
|
||||
title: 'Note',
|
||||
type: WidgetType.FIELD_RICH_TEXT,
|
||||
@@ -89,6 +92,7 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'task-tab-note',
|
||||
isActive: true,
|
||||
title: 'Note',
|
||||
icon: 'IconNotes',
|
||||
position: 150,
|
||||
@@ -101,6 +105,7 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'task-widget-note',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'task-tab-note',
|
||||
title: 'Note',
|
||||
type: WidgetType.FIELD_RICH_TEXT,
|
||||
@@ -134,6 +139,7 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'task-tab-timeline',
|
||||
isActive: true,
|
||||
title: 'Timeline',
|
||||
icon: 'IconTimelineEvent',
|
||||
position: 200,
|
||||
@@ -146,6 +152,7 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'task-widget-timeline',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'task-tab-timeline',
|
||||
title: 'Timeline',
|
||||
type: WidgetType.TIMELINE,
|
||||
@@ -172,6 +179,7 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'task-tab-files',
|
||||
isActive: true,
|
||||
title: 'Files',
|
||||
icon: 'IconPaperclip',
|
||||
position: 300,
|
||||
@@ -184,6 +192,7 @@ export const DEFAULT_TASK_RECORD_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'task-widget-files',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'task-tab-files',
|
||||
title: 'Files',
|
||||
type: WidgetType.FILES,
|
||||
|
||||
@@ -26,6 +26,7 @@ export const DEFAULT_WORKFLOW_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'workflow-tab-flow',
|
||||
isActive: true,
|
||||
title: 'Flow',
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
@@ -38,6 +39,7 @@ export const DEFAULT_WORKFLOW_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'workflow-widget-flow',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'workflow-tab-flow',
|
||||
title: 'Flow',
|
||||
type: WidgetType.WORKFLOW,
|
||||
|
||||
+4
@@ -27,6 +27,7 @@ export const DEFAULT_WORKFLOW_RUN_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'workflow-run-tab-fields',
|
||||
isActive: true,
|
||||
title: 'Home',
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
@@ -39,6 +40,7 @@ export const DEFAULT_WORKFLOW_RUN_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'workflow-run-widget-fields',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'workflow-run-tab-fields',
|
||||
title: 'Fields',
|
||||
type: WidgetType.FIELDS,
|
||||
@@ -66,6 +68,7 @@ export const DEFAULT_WORKFLOW_RUN_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'workflow-run-tab-flow',
|
||||
isActive: true,
|
||||
title: 'Flow',
|
||||
position: 200,
|
||||
layoutMode: PageLayoutTabLayoutMode.CANVAS,
|
||||
@@ -78,6 +81,7 @@ export const DEFAULT_WORKFLOW_RUN_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'workflow-run-widget-flow',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'workflow-run-tab-flow',
|
||||
title: 'Flow',
|
||||
type: WidgetType.WORKFLOW_RUN,
|
||||
|
||||
+4
@@ -27,6 +27,7 @@ export const DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'workflow-version-tab-fields',
|
||||
isActive: true,
|
||||
title: 'Home',
|
||||
icon: 'IconHome',
|
||||
position: 100,
|
||||
@@ -39,6 +40,7 @@ export const DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'workflow-version-widget-fields',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'workflow-version-tab-fields',
|
||||
title: 'Fields',
|
||||
type: WidgetType.FIELDS,
|
||||
@@ -66,6 +68,7 @@ export const DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT: PageLayout = {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id: 'workflow-version-tab-flow',
|
||||
isActive: true,
|
||||
title: 'Flow',
|
||||
icon: 'IconSettings',
|
||||
position: 200,
|
||||
@@ -78,6 +81,7 @@ export const DEFAULT_WORKFLOW_VERSION_PAGE_LAYOUT: PageLayout = {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'workflow-version-widget-flow',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'workflow-version-tab-flow',
|
||||
title: 'Flow',
|
||||
type: WidgetType.WORKFLOW_VERSION,
|
||||
|
||||
+1
@@ -8,6 +8,7 @@ export const PAGE_LAYOUT_WIDGET_FRAGMENT = gql`
|
||||
objectMetadataId
|
||||
createdAt
|
||||
updatedAt
|
||||
isActive
|
||||
deletedAt
|
||||
conditionalDisplay
|
||||
conditionalAvailabilityExpression
|
||||
|
||||
+2
@@ -24,6 +24,7 @@ const makeWidget = (
|
||||
id,
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
isActive: true,
|
||||
type: WidgetType.FIELDS,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
@@ -46,6 +47,7 @@ const makeTab = (
|
||||
id,
|
||||
applicationId: '',
|
||||
title: id,
|
||||
isActive: true,
|
||||
position,
|
||||
layoutMode,
|
||||
pageLayoutId: '',
|
||||
|
||||
+2
@@ -24,6 +24,7 @@ const makeWidget = (
|
||||
id,
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
isActive: true,
|
||||
type: WidgetType.FIELDS,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
@@ -46,6 +47,7 @@ const makeTab = (
|
||||
id,
|
||||
applicationId: '',
|
||||
title: id,
|
||||
isActive: true,
|
||||
position,
|
||||
layoutMode,
|
||||
pageLayoutId: '',
|
||||
|
||||
+2
@@ -79,6 +79,7 @@ describe('useCreatePageLayoutGraphWidget', () => {
|
||||
id: 'tab-1',
|
||||
applicationId: '',
|
||||
title: 'Tab 1',
|
||||
isActive: true,
|
||||
position: 0,
|
||||
pageLayoutId: '',
|
||||
widgets: [],
|
||||
@@ -162,6 +163,7 @@ describe('useCreatePageLayoutGraphWidget', () => {
|
||||
id: 'tab-1',
|
||||
applicationId: '',
|
||||
title: 'Tab 1',
|
||||
isActive: true,
|
||||
position: 0,
|
||||
pageLayoutId: '',
|
||||
widgets: [],
|
||||
|
||||
+1
@@ -308,6 +308,7 @@ describe('useCreatePageLayoutTab', () => {
|
||||
id: 'existing-tab',
|
||||
applicationId: '',
|
||||
title: 'Existing Tab',
|
||||
isActive: true,
|
||||
position: 0,
|
||||
pageLayoutId: 'test-layout',
|
||||
widgets: [],
|
||||
|
||||
+2
@@ -25,6 +25,7 @@ const makeWidget = (
|
||||
id,
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
isActive: true,
|
||||
type: WidgetType.FIELDS,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
@@ -46,6 +47,7 @@ const makeTab = (
|
||||
id,
|
||||
applicationId: '',
|
||||
title: id,
|
||||
isActive: true,
|
||||
position,
|
||||
pageLayoutId: '',
|
||||
widgets,
|
||||
|
||||
+2
@@ -24,6 +24,7 @@ const makeWidget = (
|
||||
id,
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
isActive: true,
|
||||
type: WidgetType.FIELDS,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
@@ -45,6 +46,7 @@ const makeTab = (
|
||||
id,
|
||||
applicationId: '',
|
||||
title: id,
|
||||
isActive: true,
|
||||
position,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: '',
|
||||
|
||||
+2
@@ -24,6 +24,7 @@ const makeWidget = (
|
||||
id,
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
isActive: true,
|
||||
type: WidgetType.FIELDS,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
@@ -45,6 +46,7 @@ const makeTab = (
|
||||
id,
|
||||
applicationId: '',
|
||||
title: id,
|
||||
isActive: true,
|
||||
position,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: '',
|
||||
|
||||
+2
@@ -24,6 +24,7 @@ const makeWidget = (
|
||||
id,
|
||||
pageLayoutTabId: tabId,
|
||||
title: id,
|
||||
isActive: true,
|
||||
type: WidgetType.FIELDS,
|
||||
gridPosition: { column: 0, columnSpan: 1, row: 0, rowSpan: 1 },
|
||||
configuration: { __typename: 'FieldsConfiguration' as const },
|
||||
@@ -45,6 +46,7 @@ const makeTab = (
|
||||
id,
|
||||
applicationId: '',
|
||||
title: id,
|
||||
isActive: true,
|
||||
position,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
pageLayoutId: '',
|
||||
|
||||
+2
@@ -90,6 +90,7 @@ describe('usePageLayoutDraftState', () => {
|
||||
id: 'tab-1',
|
||||
applicationId: '',
|
||||
title: 'Tab 1',
|
||||
isActive: true,
|
||||
position: 0,
|
||||
pageLayoutId: '',
|
||||
createdAt: new Date().toISOString(),
|
||||
@@ -100,6 +101,7 @@ describe('usePageLayoutDraftState', () => {
|
||||
id: 'widget-1',
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'New Widget',
|
||||
isActive: true,
|
||||
type: WidgetType.GRAPH,
|
||||
gridPosition: { row: 2, column: 2, rowSpan: 2, columnSpan: 2 },
|
||||
configuration: {
|
||||
|
||||
+5
@@ -35,6 +35,7 @@ describe('usePageLayoutWithRelationWidgets', () => {
|
||||
applicationId: '',
|
||||
id: 'tab-1',
|
||||
title: 'Fields',
|
||||
isActive: true,
|
||||
icon: 'IconList',
|
||||
position: 100,
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
@@ -48,6 +49,7 @@ describe('usePageLayoutWithRelationWidgets', () => {
|
||||
id: 'widget-fields',
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Fields',
|
||||
isActive: true,
|
||||
type: WidgetType.FIELDS,
|
||||
objectMetadataId: null,
|
||||
gridPosition: {
|
||||
@@ -71,6 +73,7 @@ describe('usePageLayoutWithRelationWidgets', () => {
|
||||
id: 'widget-notes',
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Notes',
|
||||
isActive: true,
|
||||
type: WidgetType.NOTES,
|
||||
objectMetadataId: null,
|
||||
gridPosition: {
|
||||
@@ -93,6 +96,7 @@ describe('usePageLayoutWithRelationWidgets', () => {
|
||||
id: 'widget-other',
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Other',
|
||||
isActive: true,
|
||||
type: WidgetType.GRAPH,
|
||||
objectMetadataId: null,
|
||||
gridPosition: {
|
||||
@@ -217,6 +221,7 @@ describe('usePageLayoutWithRelationWidgets', () => {
|
||||
id: 'widget-other',
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Other',
|
||||
isActive: true,
|
||||
type: WidgetType.GRAPH,
|
||||
objectMetadataId: null,
|
||||
gridPosition: {
|
||||
|
||||
@@ -54,6 +54,7 @@ export const useCreatePageLayoutTab = ({
|
||||
const newTab: PageLayoutTab = {
|
||||
id: newTabId,
|
||||
applicationId: '',
|
||||
isActive: true,
|
||||
title: title || `Tab ${tabsLength + 1}`,
|
||||
position: maxPosition + 1,
|
||||
pageLayoutId: pageLayoutId,
|
||||
|
||||
-1
@@ -39,7 +39,6 @@ export const useCreatePendingFieldsWidgetViews = () => {
|
||||
if (widget.type !== WidgetType.FIELDS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const viewId = getWidgetConfigurationViewId(widget.configuration);
|
||||
|
||||
return isDefined(viewId) && !persistedWidgetIds.has(widget.id);
|
||||
|
||||
@@ -2,18 +2,14 @@ import { PageLayoutComponentInstanceContext } from '@/page-layout/states/context
|
||||
import { pageLayoutCurrentLayoutsComponentState } from '@/page-layout/states/pageLayoutCurrentLayoutsComponentState';
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
|
||||
import { pageLayoutPersistedComponentState } from '@/page-layout/states/pageLayoutPersistedComponentState';
|
||||
import { removeWidgetFromTab } from '@/page-layout/utils/removeWidgetFromTab';
|
||||
import { removeWidgetLayoutFromTab } from '@/page-layout/utils/removeWidgetLayoutFromTab';
|
||||
import { useDeleteViewForFieldsWidget } from '@/page-layout/widgets/fields/hooks/useDeleteViewForFieldsWidget';
|
||||
import { useDeleteViewForRecordTableWidget } from '@/page-layout/widgets/record-table/hooks/useDeleteViewForRecordTableWidget';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { WidgetType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const useDeletePageLayoutWidget = (pageLayoutIdFromProps?: string) => {
|
||||
const pageLayoutId = useAvailableComponentInstanceIdOrThrow(
|
||||
@@ -38,16 +34,6 @@ export const useDeletePageLayoutWidget = (pageLayoutIdFromProps?: string) => {
|
||||
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
|
||||
const { deleteViewForFieldsWidget } = useDeleteViewForFieldsWidget();
|
||||
|
||||
const { deleteViewForRecordTableWidget } =
|
||||
useDeleteViewForRecordTableWidget();
|
||||
|
||||
const pageLayoutPersistedState = useAtomComponentStateCallbackState(
|
||||
pageLayoutPersistedComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const deletePageLayoutWidget = useCallback(
|
||||
@@ -61,43 +47,6 @@ export const useDeletePageLayoutWidget = (pageLayoutIdFromProps?: string) => {
|
||||
tab.widgets.some((widget) => widget.id === widgetId),
|
||||
);
|
||||
|
||||
const widgetToDelete = tabWithWidget?.widgets.find(
|
||||
(widget) => widget.id === widgetId,
|
||||
);
|
||||
|
||||
const persisted = store.get(pageLayoutPersistedState);
|
||||
const persistedWidgetIds = new Set(
|
||||
persisted?.tabs.flatMap((tab) =>
|
||||
tab.widgets.map((widget) => widget.id),
|
||||
) ?? [],
|
||||
);
|
||||
|
||||
const isWidgetPersisted = persistedWidgetIds.has(widgetId);
|
||||
|
||||
if (
|
||||
isWidgetPersisted &&
|
||||
isDefined(widgetToDelete) &&
|
||||
widgetToDelete.type === WidgetType.RECORD_TABLE &&
|
||||
'viewId' in widgetToDelete.configuration &&
|
||||
isDefined(widgetToDelete.configuration.viewId)
|
||||
) {
|
||||
deleteViewForRecordTableWidget(
|
||||
widgetToDelete.configuration.viewId as string,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
isWidgetPersisted &&
|
||||
isDefined(widgetToDelete) &&
|
||||
widgetToDelete.type === WidgetType.FIELDS &&
|
||||
'viewId' in widgetToDelete.configuration &&
|
||||
isDefined(widgetToDelete.configuration.viewId)
|
||||
) {
|
||||
deleteViewForFieldsWidget(
|
||||
widgetToDelete.configuration.viewId as string,
|
||||
);
|
||||
}
|
||||
|
||||
const tabId = tabWithWidget?.id;
|
||||
|
||||
if (isDefined(tabId)) {
|
||||
@@ -124,12 +73,9 @@ export const useDeletePageLayoutWidget = (pageLayoutIdFromProps?: string) => {
|
||||
},
|
||||
[
|
||||
closeSidePanelMenu,
|
||||
deleteViewForFieldsWidget,
|
||||
deleteViewForRecordTableWidget,
|
||||
pageLayoutCurrentLayoutsState,
|
||||
pageLayoutDraftState,
|
||||
pageLayoutEditingWidgetIdState,
|
||||
pageLayoutPersistedState,
|
||||
store,
|
||||
],
|
||||
);
|
||||
|
||||
+5
-3
@@ -27,20 +27,22 @@ export const usePageLayoutTabWithVisibleWidgetsOrThrow = (
|
||||
throw new Error('Tab not found');
|
||||
}
|
||||
|
||||
const activeWidgets = tab.widgets.filter((widget) => widget.isActive);
|
||||
|
||||
if (isPageLayoutInEditMode) {
|
||||
return {
|
||||
...tab,
|
||||
widgets:
|
||||
tab.layoutMode === PageLayoutTabLayoutMode.VERTICAL_LIST
|
||||
? sortWidgetsByVerticalListPosition(tab.widgets)
|
||||
: tab.widgets,
|
||||
? sortWidgetsByVerticalListPosition(activeWidgets)
|
||||
: activeWidgets,
|
||||
};
|
||||
}
|
||||
|
||||
const context = buildWidgetVisibilityContext({ isMobile, isInSidePanel });
|
||||
|
||||
const visibleWidgets = filterVisibleWidgets({
|
||||
widgets: tab.widgets,
|
||||
widgets: activeWidgets,
|
||||
context,
|
||||
});
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@ import { useExitLayoutCustomizationMode } from '@/layout-customization/hooks/use
|
||||
import { useInvalidateMetadataStore } from '@/metadata-store/hooks/useInvalidateMetadataStore';
|
||||
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
|
||||
import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
|
||||
import { fieldsWidgetEditorModeDraftComponentState } from '@/page-layout/states/fieldsWidgetEditorModeDraftComponentState';
|
||||
import { fieldsWidgetGroupsDraftComponentState } from '@/page-layout/states/fieldsWidgetGroupsDraftComponentState';
|
||||
import { fieldsWidgetUngroupedFieldsDraftComponentState } from '@/page-layout/states/fieldsWidgetUngroupedFieldsDraftComponentState';
|
||||
import { hasInitializedFieldsWidgetGroupsDraftComponentState } from '@/page-layout/states/hasInitializedFieldsWidgetGroupsDraftComponentState';
|
||||
import { pageLayoutCurrentLayoutsComponentState } from '@/page-layout/states/pageLayoutCurrentLayoutsComponentState';
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { pageLayoutPersistedComponentState } from '@/page-layout/states/pageLayoutPersistedComponentState';
|
||||
@@ -50,6 +54,28 @@ export const useRefreshPageLayoutAfterReset = (
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const fieldsWidgetGroupsDraftState = useAtomComponentStateCallbackState(
|
||||
fieldsWidgetGroupsDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const fieldsWidgetUngroupedFieldsDraftState =
|
||||
useAtomComponentStateCallbackState(
|
||||
fieldsWidgetUngroupedFieldsDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const fieldsWidgetEditorModeDraftState = useAtomComponentStateCallbackState(
|
||||
fieldsWidgetEditorModeDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const hasInitializedFieldsWidgetGroupsDraftState =
|
||||
useAtomComponentStateCallbackState(
|
||||
hasInitializedFieldsWidgetGroupsDraftComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const refreshPageLayoutAfterReset = useCallback(
|
||||
async (collectAffectedViewIds: (layout: PageLayout) => Set<string>) => {
|
||||
const { data } = await client.query({
|
||||
@@ -73,6 +99,11 @@ export const useRefreshPageLayoutAfterReset = (
|
||||
);
|
||||
}
|
||||
|
||||
store.set(fieldsWidgetGroupsDraftState, {});
|
||||
store.set(fieldsWidgetUngroupedFieldsDraftState, {});
|
||||
store.set(fieldsWidgetEditorModeDraftState, {});
|
||||
store.set(hasInitializedFieldsWidgetGroupsDraftState, {});
|
||||
|
||||
setIsPageLayoutInEditMode(false);
|
||||
exitLayoutCustomizationMode();
|
||||
evictViewMetadataForViewIds(store, affectedViewIds);
|
||||
@@ -85,6 +116,10 @@ export const useRefreshPageLayoutAfterReset = (
|
||||
pageLayoutPersistedState,
|
||||
pageLayoutDraftState,
|
||||
pageLayoutCurrentLayoutsState,
|
||||
fieldsWidgetGroupsDraftState,
|
||||
fieldsWidgetUngroupedFieldsDraftState,
|
||||
fieldsWidgetEditorModeDraftState,
|
||||
hasInitializedFieldsWidgetGroupsDraftState,
|
||||
setIsPageLayoutInEditMode,
|
||||
exitLayoutCustomizationMode,
|
||||
invalidateMetadataStore,
|
||||
|
||||
-47
@@ -3,18 +3,13 @@ import { pageLayoutCurrentLayoutsComponentState } from '@/page-layout/states/pag
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { pageLayoutDraggedAreaComponentState } from '@/page-layout/states/pageLayoutDraggedAreaComponentState';
|
||||
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
|
||||
import { pageLayoutPersistedComponentState } from '@/page-layout/states/pageLayoutPersistedComponentState';
|
||||
import { getWidgetConfigurationViewId } from '@/page-layout/utils/getWidgetConfigurationViewId';
|
||||
import { removeWidgetFromTab } from '@/page-layout/utils/removeWidgetFromTab';
|
||||
import { removeWidgetLayoutFromTab } from '@/page-layout/utils/removeWidgetLayoutFromTab';
|
||||
import { useDeleteViewForFieldsWidget } from '@/page-layout/widgets/fields/hooks/useDeleteViewForFieldsWidget';
|
||||
import { useDeleteViewForRecordTableWidget } from '@/page-layout/widgets/record-table/hooks/useDeleteViewForRecordTableWidget';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { WidgetType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const useRemovePageLayoutWidgetAndPreservePosition = (
|
||||
pageLayoutIdFromProps?: string,
|
||||
@@ -44,16 +39,6 @@ export const useRemovePageLayoutWidgetAndPreservePosition = (
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const { deleteViewForFieldsWidget } = useDeleteViewForFieldsWidget();
|
||||
|
||||
const { deleteViewForRecordTableWidget } =
|
||||
useDeleteViewForRecordTableWidget();
|
||||
|
||||
const pageLayoutPersistedState = useAtomComponentStateCallbackState(
|
||||
pageLayoutPersistedComponentState,
|
||||
pageLayoutId,
|
||||
);
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const removePageLayoutWidgetAndPreservePosition = useCallback(
|
||||
@@ -65,35 +50,6 @@ export const useRemovePageLayoutWidgetAndPreservePosition = (
|
||||
tab.widgets.some((widget) => widget.id === widgetId),
|
||||
);
|
||||
|
||||
const widgetToRemove = tabWithWidget?.widgets.find(
|
||||
(widget) => widget.id === widgetId,
|
||||
);
|
||||
|
||||
const persisted = store.get(pageLayoutPersistedState);
|
||||
const persistedWidgetIds = new Set(
|
||||
persisted?.tabs.flatMap((tab) =>
|
||||
tab.widgets.map((widget) => widget.id),
|
||||
) ?? [],
|
||||
);
|
||||
|
||||
const isWidgetPersisted = persistedWidgetIds.has(widgetId);
|
||||
|
||||
if (isWidgetPersisted && isDefined(widgetToRemove)) {
|
||||
const viewId = getWidgetConfigurationViewId(
|
||||
widgetToRemove.configuration,
|
||||
);
|
||||
|
||||
if (isDefined(viewId)) {
|
||||
if (widgetToRemove.type === WidgetType.RECORD_TABLE) {
|
||||
deleteViewForRecordTableWidget(viewId);
|
||||
}
|
||||
|
||||
if (widgetToRemove.type === WidgetType.FIELDS) {
|
||||
deleteViewForFieldsWidget(viewId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const tabId = tabWithWidget?.id;
|
||||
|
||||
if (!isDefined(tabId)) {
|
||||
@@ -131,13 +87,10 @@ export const useRemovePageLayoutWidgetAndPreservePosition = (
|
||||
store.set(pageLayoutEditingWidgetIdState, null);
|
||||
},
|
||||
[
|
||||
deleteViewForFieldsWidget,
|
||||
deleteViewForRecordTableWidget,
|
||||
pageLayoutCurrentLayoutsState,
|
||||
pageLayoutDraftState,
|
||||
pageLayoutDraggedAreaState,
|
||||
pageLayoutEditingWidgetIdState,
|
||||
pageLayoutPersistedState,
|
||||
store,
|
||||
],
|
||||
);
|
||||
|
||||
+7
-2
@@ -18,10 +18,15 @@ export const pageLayoutsWithRelationsSelector = createAtomSelector<
|
||||
const allFlatWidgets = get(metadataStoreState, 'pageLayoutWidgets')
|
||||
.current as FlatPageLayoutWidget[];
|
||||
|
||||
const activeFlatTabs = allFlatTabs.filter((tab) => tab.isActive);
|
||||
const activeFlatWidgets = allFlatWidgets.filter(
|
||||
(widget) => widget.isActive,
|
||||
);
|
||||
|
||||
const tabsByPageLayoutId = new Map<string, FlatPageLayoutTab[]>();
|
||||
const widgetsByTabId = new Map<string, FlatPageLayoutWidget[]>();
|
||||
|
||||
for (const tab of allFlatTabs) {
|
||||
for (const tab of activeFlatTabs) {
|
||||
const existing = tabsByPageLayoutId.get(tab.pageLayoutId);
|
||||
|
||||
if (isDefined(existing)) {
|
||||
@@ -31,7 +36,7 @@ export const pageLayoutsWithRelationsSelector = createAtomSelector<
|
||||
}
|
||||
}
|
||||
|
||||
for (const widget of allFlatWidgets) {
|
||||
for (const widget of activeFlatWidgets) {
|
||||
const existing = widgetsByTabId.get(widget.pageLayoutTabId);
|
||||
|
||||
if (isDefined(existing)) {
|
||||
|
||||
@@ -11,6 +11,7 @@ describe('addWidgetToTab', () => {
|
||||
const mockWidget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'widget-1',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Test Widget',
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -31,6 +32,7 @@ describe('addWidgetToTab', () => {
|
||||
{
|
||||
id: 'tab-1',
|
||||
applicationId: '',
|
||||
isActive: true,
|
||||
title: 'Tab 1',
|
||||
position: 0,
|
||||
pageLayoutId: 'layout-1',
|
||||
@@ -42,6 +44,7 @@ describe('addWidgetToTab', () => {
|
||||
{
|
||||
id: 'tab-2',
|
||||
applicationId: '',
|
||||
isActive: true,
|
||||
title: 'Tab 2',
|
||||
position: 1,
|
||||
pageLayoutId: 'layout-1',
|
||||
|
||||
+2
@@ -12,6 +12,7 @@ describe('convertLayoutsToWidgets', () => {
|
||||
const mockWidgets: PageLayoutWidget[] = [
|
||||
{
|
||||
id: 'widget-1',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Widget 1',
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -34,6 +35,7 @@ describe('convertLayoutsToWidgets', () => {
|
||||
},
|
||||
{
|
||||
id: 'widget-2',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Widget 2',
|
||||
type: WidgetType.GRAPH,
|
||||
|
||||
+5
@@ -20,6 +20,7 @@ describe('convertPageLayoutToTabLayouts', () => {
|
||||
{
|
||||
id: 'tab-1',
|
||||
applicationId: '',
|
||||
isActive: true,
|
||||
title: 'Tab 1',
|
||||
position: 0,
|
||||
pageLayoutId: 'page-layout-1',
|
||||
@@ -27,6 +28,7 @@ describe('convertPageLayoutToTabLayouts', () => {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'widget-1',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Widget 1',
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -45,6 +47,7 @@ describe('convertPageLayoutToTabLayouts', () => {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'widget-2',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Widget 2',
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -99,6 +102,7 @@ describe('convertPageLayoutToTabLayouts', () => {
|
||||
{
|
||||
id: 'tab-1',
|
||||
applicationId: '',
|
||||
isActive: true,
|
||||
title: 'Tab 1',
|
||||
position: 0,
|
||||
pageLayoutId: 'page-layout-1',
|
||||
@@ -106,6 +110,7 @@ describe('convertPageLayoutToTabLayouts', () => {
|
||||
{
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: 'rich-text-widget',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Rich Text',
|
||||
type: WidgetType.STANDALONE_RICH_TEXT,
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ const createMockWidget = (
|
||||
},
|
||||
): PageLayoutWidget => ({
|
||||
id: 'widget-1',
|
||||
isActive: true,
|
||||
type: WidgetType.GRAPH,
|
||||
title: 'Test',
|
||||
objectMetadataId: null,
|
||||
|
||||
+1
@@ -12,6 +12,7 @@ describe('filterVisibleWidgets', () => {
|
||||
): PageLayoutTab['widgets'][0] => ({
|
||||
__typename: 'PageLayoutWidget',
|
||||
id,
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: `Widget ${id}`,
|
||||
type: WidgetType.FIELDS,
|
||||
|
||||
+1
@@ -5,6 +5,7 @@ describe('getPageLayoutTabListInitialActiveTabId', () => {
|
||||
const createMockTab = (id: string): PageLayoutTab => ({
|
||||
id,
|
||||
applicationId: '',
|
||||
isActive: true,
|
||||
pageLayoutId: 'page-layout-1',
|
||||
title: `Tab ${id}`,
|
||||
position: 0,
|
||||
|
||||
+1
@@ -10,6 +10,7 @@ describe('getTabsByDisplayMode', () => {
|
||||
const createMockTab = (id: string): PageLayoutTab => ({
|
||||
id,
|
||||
applicationId: '',
|
||||
isActive: true,
|
||||
pageLayoutId: 'page-layout-1',
|
||||
title: `Tab ${id}`,
|
||||
position: 0,
|
||||
|
||||
+2
@@ -12,6 +12,7 @@ describe('getTabsWithVisibleWidgets', () => {
|
||||
): PageLayoutTab['widgets'][0] => ({
|
||||
__typename: 'PageLayoutWidget',
|
||||
id,
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: `Widget ${id}`,
|
||||
type: WidgetType.FIELDS,
|
||||
@@ -41,6 +42,7 @@ describe('getTabsWithVisibleWidgets', () => {
|
||||
__typename: 'PageLayoutTab',
|
||||
applicationId: '',
|
||||
id,
|
||||
isActive: true,
|
||||
pageLayoutId: 'page-layout-1',
|
||||
title: `Tab ${id}`,
|
||||
position: 0,
|
||||
|
||||
+2
@@ -10,6 +10,7 @@ import {
|
||||
describe('prepareGridLayoutItemsWithPlaceholders', () => {
|
||||
const createMockWidget = (id: string): PageLayoutWidget => ({
|
||||
id,
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: `Test Widget ${id}`,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -215,6 +216,7 @@ describe('prepareGridLayoutItemsWithPlaceholders', () => {
|
||||
expect(resultWidget.createdAt).toBe(widget.createdAt);
|
||||
expect(resultWidget.updatedAt).toBe(widget.updatedAt);
|
||||
expect(resultWidget.deletedAt).toBe(widget.deletedAt);
|
||||
expect(resultWidget.isActive).toBe(widget.isActive);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+5
@@ -12,6 +12,7 @@ describe('removeWidgetFromTab', () => {
|
||||
{
|
||||
id: 'tab-1',
|
||||
applicationId: '',
|
||||
isActive: true,
|
||||
title: 'Tab 1',
|
||||
position: 0,
|
||||
pageLayoutId: 'layout-1',
|
||||
@@ -19,6 +20,7 @@ describe('removeWidgetFromTab', () => {
|
||||
{
|
||||
__typename: 'PageLayoutWidget' as const,
|
||||
id: 'widget-1',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Widget 1',
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -37,6 +39,7 @@ describe('removeWidgetFromTab', () => {
|
||||
{
|
||||
__typename: 'PageLayoutWidget' as const,
|
||||
id: 'widget-2',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-1',
|
||||
title: 'Widget 2',
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -62,6 +65,7 @@ describe('removeWidgetFromTab', () => {
|
||||
{
|
||||
id: 'tab-2',
|
||||
applicationId: '',
|
||||
isActive: true,
|
||||
title: 'Tab 2',
|
||||
position: 1,
|
||||
pageLayoutId: 'layout-1',
|
||||
@@ -69,6 +73,7 @@ describe('removeWidgetFromTab', () => {
|
||||
{
|
||||
__typename: 'PageLayoutWidget' as const,
|
||||
id: 'widget-3',
|
||||
isActive: true,
|
||||
pageLayoutTabId: 'tab-2',
|
||||
title: 'Widget 3',
|
||||
type: WidgetType.IFRAME,
|
||||
|
||||
@@ -28,6 +28,7 @@ export const createDefaultFieldWidget = ({
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
title,
|
||||
isActive: true,
|
||||
type: WidgetType.FIELD,
|
||||
configuration: {
|
||||
__typename: 'FieldConfiguration',
|
||||
|
||||
@@ -23,6 +23,7 @@ export const createDefaultFieldsWidget = ({
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
title: 'Fields',
|
||||
isActive: true,
|
||||
type: WidgetType.FIELDS,
|
||||
configuration: {
|
||||
__typename: 'FieldsConfiguration',
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ export const createDefaultFrontComponentWidget = (
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
title,
|
||||
isActive: true,
|
||||
type: WidgetType.FRONT_COMPONENT,
|
||||
configuration: {
|
||||
__typename: 'FrontComponentConfiguration',
|
||||
|
||||
@@ -72,6 +72,7 @@ export const createDefaultGraphWidget = ({
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
title,
|
||||
isActive: true,
|
||||
type: WidgetType.GRAPH,
|
||||
configuration,
|
||||
gridPosition,
|
||||
|
||||
@@ -19,6 +19,7 @@ export const createDefaultIframeWidget = (
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
title,
|
||||
isActive: true,
|
||||
type: WidgetType.IFRAME,
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.IFRAME,
|
||||
|
||||
@@ -24,6 +24,7 @@ export const createDefaultRecordTableWidget = ({
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
title,
|
||||
isActive: true,
|
||||
type: WidgetType.RECORD_TABLE,
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.RECORD_TABLE,
|
||||
|
||||
+1
@@ -19,6 +19,7 @@ export const createDefaultStandaloneRichTextWidget = (
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
title: 'Untitled Rich Text',
|
||||
isActive: true,
|
||||
type: WidgetType.STANDALONE_RICH_TEXT,
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.STANDALONE_RICH_TEXT,
|
||||
|
||||
@@ -15,13 +15,15 @@ export const getTabsWithVisibleWidgets = ({
|
||||
isInSidePanel,
|
||||
isEditMode,
|
||||
}: GetTabsWithVisibleWidgetsParams): PageLayoutTab[] => {
|
||||
const activeTabs = tabs.filter((tab) => tab.isActive);
|
||||
|
||||
if (isEditMode) {
|
||||
return tabs;
|
||||
return activeTabs;
|
||||
}
|
||||
|
||||
const context = buildWidgetVisibilityContext({ isMobile, isInSidePanel });
|
||||
|
||||
const tabsWithFilteredWidgets = tabs.map((tab) => ({
|
||||
const tabsWithFilteredWidgets = activeTabs.map((tab) => ({
|
||||
...tab,
|
||||
widgets: filterVisibleWidgets({ widgets: tab.widgets, context }),
|
||||
}));
|
||||
@@ -30,7 +32,7 @@ export const getTabsWithVisibleWidgets = ({
|
||||
(tab) => tab.widgets.length > 0,
|
||||
);
|
||||
|
||||
if (tabsWithVisibleWidgets.length === 0 && tabs.length > 0) {
|
||||
if (tabsWithVisibleWidgets.length === 0 && activeTabs.length > 0) {
|
||||
return tabsWithFilteredWidgets.slice(0, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ const getRelationFieldWidgetToInsert = (
|
||||
id: `${DYNAMIC_RELATION_WIDGET_ID_PREFIX}${field.id}-${field.label}`,
|
||||
pageLayoutTabId: tabId,
|
||||
title: field.label,
|
||||
isActive: true,
|
||||
type: WidgetType.FIELD,
|
||||
objectMetadataId: null,
|
||||
gridPosition: {
|
||||
|
||||
+18
@@ -143,6 +143,7 @@ const createPageLayoutWithWidget = (
|
||||
tabs: [
|
||||
{
|
||||
__typename: 'PageLayoutTab',
|
||||
isActive: true,
|
||||
applicationId: '',
|
||||
id: TAB_ID_OVERVIEW,
|
||||
title: 'Overview',
|
||||
@@ -252,6 +253,7 @@ export const WithNumberChart: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_NUMBER_CHART,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -338,6 +340,7 @@ export const WithGaugeChart: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_GAUGE_CHART,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -424,6 +427,7 @@ export const WithBarChart: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_BAR_CHART,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -521,6 +525,7 @@ export const SmallWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_SMALL,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -614,6 +619,7 @@ export const MediumWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_MEDIUM,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -711,6 +717,7 @@ export const LargeWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_LARGE,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -808,6 +815,7 @@ export const WideWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_WIDE,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -901,6 +909,7 @@ export const TallWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_TALL,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -999,6 +1008,7 @@ export const WithManyToOneRelationFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_MANY_TO_ONE_RELATION,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1117,6 +1127,7 @@ export const WithOneToManyRelationFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_ONE_TO_MANY_RELATION,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1227,6 +1238,7 @@ export const OneToManyRelationFieldWidgetWithSeeAllButton: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_ONE_TO_MANY_RELATION,
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1363,6 +1375,7 @@ export const OnMobile: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-mobile',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -1460,6 +1473,7 @@ export const InSidePanel: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-side-panel',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.GRAPH,
|
||||
@@ -1617,6 +1631,7 @@ export const Catalog: CatalogStory<Story, typeof WidgetRenderer> = {
|
||||
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: WIDGET_ID_CATALOG,
|
||||
pageLayoutTabId:
|
||||
variant === 'side-column' ? 'pinned-tab' : TAB_ID_OVERVIEW,
|
||||
@@ -1723,6 +1738,7 @@ export const Catalog: CatalogStory<Story, typeof WidgetRenderer> = {
|
||||
? [
|
||||
{
|
||||
__typename: 'PageLayoutTab',
|
||||
isActive: true,
|
||||
applicationId: '',
|
||||
id: 'pinned-tab',
|
||||
title: 'Pinned Tab',
|
||||
@@ -1735,6 +1751,7 @@ export const Catalog: CatalogStory<Story, typeof WidgetRenderer> = {
|
||||
},
|
||||
{
|
||||
__typename: 'PageLayoutTab',
|
||||
isActive: true,
|
||||
applicationId: '',
|
||||
id: 'other-tab',
|
||||
title: 'Other Tab',
|
||||
@@ -1749,6 +1766,7 @@ export const Catalog: CatalogStory<Story, typeof WidgetRenderer> = {
|
||||
: [
|
||||
{
|
||||
__typename: 'PageLayoutTab',
|
||||
isActive: true,
|
||||
applicationId: '',
|
||||
id: TAB_ID_OVERVIEW,
|
||||
title: 'Overview',
|
||||
|
||||
+18
@@ -291,6 +291,7 @@ const createPageLayoutWithWidget = (
|
||||
tabs: [
|
||||
{
|
||||
__typename: 'PageLayoutTab' as const,
|
||||
isActive: true,
|
||||
applicationId: '',
|
||||
id: TAB_ID_OVERVIEW,
|
||||
title: 'Overview',
|
||||
@@ -332,6 +333,7 @@ export const TextFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-text-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -425,6 +427,7 @@ export const AddressFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-address-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -521,6 +524,7 @@ export const NumberFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-number-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -614,6 +618,7 @@ export const LinkFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-link-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -707,6 +712,7 @@ export const ManyToOneRelationFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-relation-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -810,6 +816,7 @@ export const OneToManyRelationFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-one-to-many-relation-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -905,6 +912,7 @@ export const BooleanFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-boolean-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -997,6 +1005,7 @@ export const CurrencyFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-currency-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1089,6 +1098,7 @@ export const EmailsFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-emails-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1182,6 +1192,7 @@ export const PhonesFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-phones-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1275,6 +1286,7 @@ export const SelectFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-select-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1369,6 +1381,7 @@ export const MultiSelectFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-multi-select-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1466,6 +1479,7 @@ export const TimelineActivityRelationFieldWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-timeline-activity-relation-field',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1564,6 +1578,7 @@ export const ManyToOneRelationCardWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-relation-card',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1675,6 +1690,7 @@ export const OneToManyRelationCardWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-one-to-many-relation-card',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1769,6 +1785,7 @@ export const TimelineActivityRelationCardWidget: Story = {
|
||||
render: () => {
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-timeline-activity-relation-card',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
@@ -1929,6 +1946,7 @@ export const OneToManyRelationCardWidgetWithProgressiveLoading: Story = {
|
||||
|
||||
const widget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-one-to-many-relation-card-progressive',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELD,
|
||||
|
||||
+4
@@ -141,6 +141,7 @@ const createPageLayoutWithWidget = (
|
||||
tabs: [
|
||||
{
|
||||
__typename: 'PageLayoutTab' as const,
|
||||
isActive: true,
|
||||
applicationId: '',
|
||||
id: TAB_ID_OVERVIEW,
|
||||
title: 'Overview',
|
||||
@@ -159,6 +160,7 @@ const createPageLayoutWithWidget = (
|
||||
|
||||
const createFieldsWidget = (viewId: string | null): PageLayoutWidget => ({
|
||||
__typename: 'PageLayoutWidget',
|
||||
isActive: true,
|
||||
id: 'widget-fields',
|
||||
pageLayoutTabId: TAB_ID_OVERVIEW,
|
||||
type: WidgetType.FIELDS,
|
||||
@@ -213,6 +215,7 @@ const createViewField = (
|
||||
fieldMetadataId,
|
||||
position,
|
||||
isVisible: true,
|
||||
isActive: true,
|
||||
size: 200,
|
||||
aggregateOperation: null,
|
||||
viewId: FIELDS_VIEW_ID,
|
||||
@@ -230,6 +233,7 @@ const createViewFieldGroup = (
|
||||
name,
|
||||
position,
|
||||
isVisible,
|
||||
isActive: true,
|
||||
viewId: FIELDS_VIEW_ID,
|
||||
viewFields,
|
||||
});
|
||||
|
||||
+65
-14
@@ -29,9 +29,12 @@ export const useFieldsWidgetGroups = ({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const groups = useMemo<FieldsWidgetGroup[]>(() => {
|
||||
const { groups, displayMode } = useMemo<{
|
||||
groups: FieldsWidgetGroup[];
|
||||
displayMode: FieldsWidgetDisplayMode;
|
||||
}>(() => {
|
||||
if (!isDefined(objectMetadataItem)) {
|
||||
return [];
|
||||
return { groups: [], displayMode: 'grouped' };
|
||||
}
|
||||
|
||||
if (isDefined(view) && isNonEmptyArray(view.viewFieldGroups)) {
|
||||
@@ -41,7 +44,7 @@ export const useFieldsWidgetGroups = ({
|
||||
|
||||
let globalIndex = 0;
|
||||
|
||||
return sortedGroups
|
||||
const resultGroups = sortedGroups
|
||||
.filter((group) => group.isVisible)
|
||||
.map((group) => {
|
||||
const groupFields = [...(group.viewFields ?? [])].sort(
|
||||
@@ -79,28 +82,76 @@ export const useFieldsWidgetGroups = ({
|
||||
};
|
||||
})
|
||||
.filter((group) => group.fields.length > 0);
|
||||
|
||||
return { groups: resultGroups, displayMode: 'grouped' };
|
||||
}
|
||||
|
||||
return filterDraftGroupsForDisplay(
|
||||
buildDefaultFieldsWidgetGroups({
|
||||
fields: objectMetadataItem.fields,
|
||||
objectNameSingular,
|
||||
labelIdentifierFieldMetadataItemId:
|
||||
labelIdentifierFieldMetadataItem?.id,
|
||||
}),
|
||||
);
|
||||
if (isDefined(view) && isNonEmptyArray(view.viewFields)) {
|
||||
let globalIndex = 0;
|
||||
|
||||
const fields: FieldsWidgetGroupField[] = [...view.viewFields]
|
||||
.sort((a, b) => a.position - b.position)
|
||||
.filter((viewField) => viewField.isVisible)
|
||||
.map((viewField) => {
|
||||
const fieldMetadataItem = objectMetadataItem.fields.find(
|
||||
(f) => f.id === viewField.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(fieldMetadataItem)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
fieldMetadataItem,
|
||||
position: viewField.position,
|
||||
isVisible: viewField.isVisible,
|
||||
globalIndex: globalIndex++,
|
||||
};
|
||||
})
|
||||
.filter(isDefined);
|
||||
|
||||
return {
|
||||
groups:
|
||||
fields.length > 0
|
||||
? [
|
||||
{
|
||||
id: `${viewId}-ungrouped`,
|
||||
name: '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
fields,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
displayMode: 'inline',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
groups: filterDraftGroupsForDisplay(
|
||||
buildDefaultFieldsWidgetGroups({
|
||||
fields: objectMetadataItem.fields,
|
||||
objectNameSingular,
|
||||
labelIdentifierFieldMetadataItemId:
|
||||
labelIdentifierFieldMetadataItem?.id,
|
||||
}),
|
||||
),
|
||||
displayMode: 'grouped',
|
||||
};
|
||||
}, [
|
||||
objectMetadataItem,
|
||||
objectNameSingular,
|
||||
labelIdentifierFieldMetadataItem,
|
||||
view,
|
||||
viewId,
|
||||
]);
|
||||
|
||||
const displayMode: FieldsWidgetDisplayMode = 'grouped';
|
||||
|
||||
return {
|
||||
groups,
|
||||
displayMode,
|
||||
isFromView: isDefined(view) && isNonEmptyArray(view.viewFieldGroups),
|
||||
isFromView:
|
||||
isDefined(view) &&
|
||||
(isNonEmptyArray(view.viewFieldGroups) ||
|
||||
isNonEmptyArray(view.viewFields)),
|
||||
};
|
||||
};
|
||||
|
||||
+2
@@ -10,6 +10,7 @@ const buildViewField = (
|
||||
id: v4(),
|
||||
fieldMetadataId: v4(),
|
||||
position: 0,
|
||||
isActive: true,
|
||||
isVisible: true,
|
||||
size: 100,
|
||||
aggregateOperation: null,
|
||||
@@ -20,6 +21,7 @@ const buildExistingViewField = (overrides: Partial<ViewField>): ViewField => ({
|
||||
id: v4(),
|
||||
fieldMetadataId: v4(),
|
||||
position: 0,
|
||||
isActive: true,
|
||||
isVisible: true,
|
||||
size: 100,
|
||||
aggregateOperation: null,
|
||||
|
||||
+1
-25
@@ -10,13 +10,10 @@ import { addWidgetToTab } from '@/page-layout/utils/addWidgetToTab';
|
||||
import { createDefaultFieldWidget } from '@/page-layout/utils/createDefaultFieldWidget';
|
||||
import { createDefaultFieldsWidget } from '@/page-layout/utils/createDefaultFieldsWidget';
|
||||
import { getTabListInstanceIdFromPageLayoutAndRecord } from '@/page-layout/utils/getTabListInstanceIdFromPageLayoutAndRecord';
|
||||
import { getWidgetConfigurationViewId } from '@/page-layout/utils/getWidgetConfigurationViewId';
|
||||
import { isVerticalListPosition } from '@/page-layout/utils/isVerticalListPosition';
|
||||
import { removeWidgetFromTab } from '@/page-layout/utils/removeWidgetFromTab';
|
||||
import { useFieldWidgetEligibleFields } from '@/page-layout/widgets/field/hooks/useFieldWidgetEligibleFields';
|
||||
import { getFieldWidgetDefaultDisplayMode } from '@/page-layout/widgets/field/utils/getFieldWidgetDisplayModeConfig';
|
||||
import { useDeleteViewForFieldsWidget } from '@/page-layout/widgets/fields/hooks/useDeleteViewForFieldsWidget';
|
||||
import { useDeleteViewForRecordTableWidget } from '@/page-layout/widgets/record-table/hooks/useDeleteViewForRecordTableWidget';
|
||||
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
||||
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
@@ -91,11 +88,6 @@ export const SidePanelPageLayoutRecordPageWidgetTypeSelect = () => {
|
||||
const { insertCreatedWidgetAtContext } =
|
||||
useInsertCreatedWidgetAtContext(pageLayoutId);
|
||||
|
||||
const { deleteViewForFieldsWidget } = useDeleteViewForFieldsWidget();
|
||||
|
||||
const { deleteViewForRecordTableWidget } =
|
||||
useDeleteViewForRecordTableWidget();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular: targetObjectNameSingular,
|
||||
});
|
||||
@@ -142,28 +134,11 @@ export const SidePanelPageLayoutRecordPageWidgetTypeSelect = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(existingWidget)) {
|
||||
const viewId = getWidgetConfigurationViewId(existingWidget.configuration);
|
||||
|
||||
if (isDefined(viewId)) {
|
||||
if (existingWidget.type === WidgetType.RECORD_TABLE) {
|
||||
deleteViewForRecordTableWidget(viewId);
|
||||
}
|
||||
|
||||
if (existingWidget.type === WidgetType.FIELDS) {
|
||||
deleteViewForFieldsWidget(viewId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
store.set(pageLayoutDraftState, (prev) => ({
|
||||
...prev,
|
||||
tabs: removeWidgetFromTab(prev.tabs, tabId, pageLayoutEditingWidgetId),
|
||||
}));
|
||||
}, [
|
||||
deleteViewForFieldsWidget,
|
||||
deleteViewForRecordTableWidget,
|
||||
existingWidget,
|
||||
isReplaceMode,
|
||||
pageLayoutDraftState,
|
||||
pageLayoutEditingWidgetId,
|
||||
@@ -328,6 +303,7 @@ export const SidePanelPageLayoutRecordPageWidgetTypeSelect = () => {
|
||||
const newWidget: PageLayoutWidget = {
|
||||
__typename: 'PageLayoutWidget',
|
||||
id: widgetId,
|
||||
isActive: true,
|
||||
pageLayoutTabId: tabId,
|
||||
title: frontComponent.name,
|
||||
type: WidgetType.FRONT_COMPONENT,
|
||||
|
||||
@@ -10,6 +10,7 @@ export const VIEW_FIELD_FRAGMENT = gql`
|
||||
size
|
||||
aggregateOperation
|
||||
viewFieldGroupId
|
||||
isActive
|
||||
createdAt
|
||||
updatedAt
|
||||
deletedAt
|
||||
|
||||
@@ -9,6 +9,7 @@ export const VIEW_FIELD_GROUP_FRAGMENT = gql`
|
||||
position
|
||||
isVisible
|
||||
viewId
|
||||
isActive
|
||||
createdAt
|
||||
updatedAt
|
||||
deletedAt
|
||||
|
||||
@@ -24,7 +24,7 @@ export const viewsSelector = createAtomSelector<ViewWithRelations[]>({
|
||||
flatObjectMetadataItems.map((item) => [item.id, item]),
|
||||
);
|
||||
|
||||
const flatViewFields = get(metadataStoreState, 'viewFields')
|
||||
const allFlatViewFields = get(metadataStoreState, 'viewFields')
|
||||
.current as FlatViewField[];
|
||||
const flatViewFilters = get(metadataStoreState, 'viewFilters')
|
||||
.current as FlatViewFilter[];
|
||||
@@ -34,9 +34,14 @@ export const viewsSelector = createAtomSelector<ViewWithRelations[]>({
|
||||
.current as FlatViewGroup[];
|
||||
const flatViewFilterGroups = get(metadataStoreState, 'viewFilterGroups')
|
||||
.current as FlatViewFilterGroup[];
|
||||
const flatViewFieldGroups = get(metadataStoreState, 'viewFieldGroups')
|
||||
const allFlatViewFieldGroups = get(metadataStoreState, 'viewFieldGroups')
|
||||
.current as FlatViewFieldGroup[];
|
||||
|
||||
const flatViewFields = allFlatViewFields.filter((field) => field.isActive);
|
||||
const flatViewFieldGroups = allFlatViewFieldGroups.filter(
|
||||
(group) => group.isActive,
|
||||
);
|
||||
|
||||
const viewFieldsByViewId = new Map<string, FlatViewField[]>();
|
||||
const viewFiltersByViewId = new Map<string, FlatViewFilter[]>();
|
||||
const viewSortsByViewId = new Map<string, FlatViewSort[]>();
|
||||
|
||||
@@ -8,6 +8,7 @@ export type ViewField = {
|
||||
viewId?: string;
|
||||
fieldMetadataId: string;
|
||||
position: number;
|
||||
isActive: boolean;
|
||||
isVisible: boolean;
|
||||
size: number;
|
||||
aggregateOperation?: AggregateOperations | null;
|
||||
|
||||
@@ -4,6 +4,7 @@ export type ViewFieldGroup = {
|
||||
id: string;
|
||||
name: string;
|
||||
position: number;
|
||||
isActive: boolean;
|
||||
isVisible: boolean;
|
||||
viewId: string;
|
||||
viewFields: ViewField[];
|
||||
|
||||
@@ -60,6 +60,7 @@ describe('mapViewFieldsToColumnDefinitions', () => {
|
||||
position: 1,
|
||||
size: 1,
|
||||
isVisible: false,
|
||||
isActive: true,
|
||||
definition: {
|
||||
fieldMetadataId: '1',
|
||||
label: 'label 1',
|
||||
@@ -78,6 +79,7 @@ describe('mapViewFieldsToColumnDefinitions', () => {
|
||||
position: 2,
|
||||
size: 2,
|
||||
isVisible: false,
|
||||
isActive: true,
|
||||
definition: {
|
||||
fieldMetadataId: '2',
|
||||
label: 'label 2',
|
||||
@@ -96,6 +98,7 @@ describe('mapViewFieldsToColumnDefinitions', () => {
|
||||
position: 3,
|
||||
size: 3,
|
||||
isVisible: true,
|
||||
isActive: true,
|
||||
definition: {
|
||||
fieldMetadataId: '3',
|
||||
label: 'label 3',
|
||||
@@ -188,6 +191,7 @@ describe('mapColumnDefinitionsToViewFields', () => {
|
||||
fieldMetadataId: 1,
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
isActive: true,
|
||||
definition: columnDefinitions[0],
|
||||
size: undefined,
|
||||
},
|
||||
@@ -197,6 +201,7 @@ describe('mapColumnDefinitionsToViewFields', () => {
|
||||
position: 2,
|
||||
size: 200,
|
||||
isVisible: false,
|
||||
isActive: true,
|
||||
definition: columnDefinitions[1],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -12,6 +12,7 @@ export const mapBoardFieldDefinitionsToViewFields = (
|
||||
size: 0,
|
||||
position: fieldDefinition.position,
|
||||
isVisible: fieldDefinition.isVisible ?? true,
|
||||
isActive: true,
|
||||
definition: fieldDefinition,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ export const mapColumnDefinitionsToViewFields = (
|
||||
position: columnDefinition.position,
|
||||
size: columnDefinition.size,
|
||||
isVisible: columnDefinition.isVisible ?? true,
|
||||
isActive: true,
|
||||
definition: columnDefinition,
|
||||
}));
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ export const mapRecordFieldToViewField = (recordField: RecordField) => {
|
||||
id: recordField.id,
|
||||
fieldMetadataId: recordField.fieldMetadataItemId,
|
||||
isVisible: recordField.isVisible,
|
||||
isActive: true,
|
||||
position: recordField.position,
|
||||
size: recordField.size,
|
||||
aggregateOperation: recordField.aggregateOperation,
|
||||
|
||||
@@ -133,4 +133,5 @@ export const createTestWidget = (
|
||||
updatedAt: '2024-01-01',
|
||||
deletedAt: null,
|
||||
...overrides,
|
||||
isActive: overrides.isActive ?? true,
|
||||
});
|
||||
|
||||
+5
-2
@@ -29,7 +29,9 @@ export const reconstructFlatPageLayoutWithTabsAndWidgets = ({
|
||||
}): FlatPageLayoutWithTabsAndWidgets => {
|
||||
const tabs = Object.values(flatPageLayoutTabMaps.byUniversalIdentifier)
|
||||
.filter(isDefined)
|
||||
.filter((tab) => tab.pageLayoutId === layout.id && tab.isActive)
|
||||
.filter(
|
||||
(tab) => tab.pageLayoutId === layout.id && !isDefined(tab.deletedAt),
|
||||
)
|
||||
.sort((a, b) => (a.position ?? 0) - (b.position ?? 0));
|
||||
|
||||
const tabsWithWidgets: FlatPageLayoutTabWithWidgets[] = tabs.map((tab) => {
|
||||
@@ -39,7 +41,8 @@ export const reconstructFlatPageLayoutWithTabsAndWidgets = ({
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(widget) =>
|
||||
getResolvedPageLayoutTabId(widget) === tab.id && widget.isActive,
|
||||
getResolvedPageLayoutTabId(widget) === tab.id &&
|
||||
!isDefined(widget.deletedAt),
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+3
@@ -52,6 +52,9 @@ export class PageLayoutTabDTO {
|
||||
@Field()
|
||||
updatedAt: Date;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isActive: boolean;
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date | null;
|
||||
|
||||
|
||||
+3
@@ -74,6 +74,9 @@ export class PageLayoutWidgetDTO {
|
||||
@Field()
|
||||
updatedAt: Date;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isActive: boolean;
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date;
|
||||
|
||||
|
||||
-5
@@ -898,11 +898,6 @@ export class PageLayoutUpdateService {
|
||||
for (const widget of widgetsToUpdate) {
|
||||
if (!widget.isActive) {
|
||||
directlyRemovedWidgetIds.add(widget.id);
|
||||
const viewId = this.getViewIdFromFieldsWidget(widget);
|
||||
|
||||
if (isDefined(viewId)) {
|
||||
viewIdsToDelete.add(viewId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -32,6 +32,9 @@ export class ViewFieldGroupDTO {
|
||||
@Field()
|
||||
updatedAt: Date;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isActive: boolean;
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date | null;
|
||||
|
||||
|
||||
+1
-6
@@ -349,12 +349,7 @@ export class ViewFieldGroupService {
|
||||
|
||||
return Object.values(flatViewFieldGroupMaps.byUniversalIdentifier)
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(group) =>
|
||||
group.viewId === viewId &&
|
||||
group.isActive &&
|
||||
!isDefined(group.deletedAt),
|
||||
)
|
||||
.filter((group) => group.viewId === viewId && !isDefined(group.deletedAt))
|
||||
.map(fromFlatViewFieldGroupToViewFieldGroupDto)
|
||||
.sort((a, b) => a.position - b.position);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,9 @@ export class ViewFieldDTO {
|
||||
@Field()
|
||||
updatedAt: Date;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isActive: boolean;
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date | null;
|
||||
|
||||
|
||||
+2
-7
@@ -352,7 +352,7 @@ export class ViewFieldService {
|
||||
|
||||
return Object.values(flatViewFieldMaps.byUniversalIdentifier)
|
||||
.filter(isDefined)
|
||||
.filter((field) => field.isActive && !isDefined(field.deletedAt))
|
||||
.filter((field) => !isDefined(field.deletedAt))
|
||||
.map(fromFlatViewFieldToViewFieldDto)
|
||||
.sort((a, b) => a.position - b.position);
|
||||
}
|
||||
@@ -371,12 +371,7 @@ export class ViewFieldService {
|
||||
|
||||
return Object.values(flatViewFieldMaps.byUniversalIdentifier)
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(field) =>
|
||||
field.viewId === viewId &&
|
||||
field.isActive &&
|
||||
!isDefined(field.deletedAt),
|
||||
)
|
||||
.filter((field) => field.viewId === viewId && !isDefined(field.deletedAt))
|
||||
.map(fromFlatViewFieldToViewFieldDto)
|
||||
.sort((a, b) => a.position - b.position);
|
||||
}
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ import { type MetadataEventBatch } from 'src/engine/subscriptions/metadata-event
|
||||
import { type FlatCommandMenuItem } from 'src/engine/metadata-modules/flat-command-menu-item/types/flat-command-menu-item.type';
|
||||
import { enrichCommandMenuItemEventWithResolvedNavigation } from 'src/engine/subscriptions/metadata-event/utils/enrich-command-menu-item-event-with-resolved-navigation.util';
|
||||
import { enrichFieldMetadataEventWithRelations } from 'src/engine/subscriptions/metadata-event/utils/enrich-field-metadata-event-with-relations.util';
|
||||
import { sanitizeOverridableEntityEventBatch } from 'src/engine/subscriptions/metadata-event/utils/sanitize-overridable-entity-event-batch.util';
|
||||
import { resolveOverridableEntityEventBatchOverrides } from 'src/engine/subscriptions/metadata-event/utils/sanitize-overridable-entity-event-batch.util';
|
||||
import { WorkspaceEventBroadcaster } from 'src/engine/subscriptions/workspace-event-broadcaster/workspace-event-broadcaster.service';
|
||||
|
||||
@Injectable()
|
||||
@@ -64,7 +64,7 @@ export class MetadataEventPublisher {
|
||||
metadataEventBatch as MetadataEventBatch<'objectMetadata'>,
|
||||
);
|
||||
default:
|
||||
return sanitizeOverridableEntityEventBatch(metadataEventBatch);
|
||||
return resolveOverridableEntityEventBatchOverrides(metadataEventBatch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-150
@@ -1,5 +1,5 @@
|
||||
import { type MetadataEventBatch } from 'src/engine/subscriptions/metadata-event/types/metadata-event-batch.type';
|
||||
import { sanitizeOverridableEntityEventBatch } from 'src/engine/subscriptions/metadata-event/utils/sanitize-overridable-entity-event-batch.util';
|
||||
import { resolveOverridableEntityEventBatchOverrides } from 'src/engine/subscriptions/metadata-event/utils/sanitize-overridable-entity-event-batch.util';
|
||||
|
||||
const makeViewFieldRecord = (
|
||||
overrides?: Partial<Record<string, unknown>>,
|
||||
@@ -35,7 +35,7 @@ const makeBatch = (
|
||||
events,
|
||||
}) as MetadataEventBatch;
|
||||
|
||||
describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
describe('resolveOverridableEntityEventBatchOverrides', () => {
|
||||
describe('non-overridable entity (pass-through)', () => {
|
||||
it('should return the batch unchanged for entities without overrides config', () => {
|
||||
const batch = makeBatch('view', [
|
||||
@@ -52,14 +52,14 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
const result = resolveOverridableEntityEventBatchOverrides(batch);
|
||||
|
||||
expect(result).toBe(batch);
|
||||
});
|
||||
});
|
||||
|
||||
describe('override resolution', () => {
|
||||
it('should resolve overrides into base properties and strip overrides/isActive', () => {
|
||||
it('should resolve overrides into base properties and strip overrides but keep isActive', () => {
|
||||
const after = makeViewFieldRecord({
|
||||
isVisible: true,
|
||||
overrides: { isVisible: false },
|
||||
@@ -74,7 +74,7 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
const result = resolveOverridableEntityEventBatchOverrides(batch);
|
||||
|
||||
const createdRecord = (
|
||||
result.events[0] as { properties: { after: Record<string, unknown> } }
|
||||
@@ -82,10 +82,10 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
|
||||
expect(createdRecord.isVisible).toBe(false);
|
||||
expect(createdRecord).not.toHaveProperty('overrides');
|
||||
expect(createdRecord).not.toHaveProperty('isActive');
|
||||
expect(createdRecord).toHaveProperty('isActive', true);
|
||||
});
|
||||
|
||||
it('should strip overrides and isActive even when overrides is null', () => {
|
||||
it('should strip overrides but keep isActive even when overrides is null', () => {
|
||||
const after = makeViewFieldRecord({ overrides: null });
|
||||
|
||||
const batch = makeBatch('viewField', [
|
||||
@@ -97,7 +97,7 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
const result = resolveOverridableEntityEventBatchOverrides(batch);
|
||||
|
||||
const createdRecord = (
|
||||
result.events[0] as { properties: { after: Record<string, unknown> } }
|
||||
@@ -105,7 +105,7 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
|
||||
expect(createdRecord.isVisible).toBe(true);
|
||||
expect(createdRecord).not.toHaveProperty('overrides');
|
||||
expect(createdRecord).not.toHaveProperty('isActive');
|
||||
expect(createdRecord).toHaveProperty('isActive', true);
|
||||
});
|
||||
|
||||
it('should resolve multiple override properties', () => {
|
||||
@@ -125,7 +125,7 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
const result = resolveOverridableEntityEventBatchOverrides(batch);
|
||||
|
||||
const createdRecord = (
|
||||
result.events[0] as { properties: { after: Record<string, unknown> } }
|
||||
@@ -160,7 +160,7 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
const result = resolveOverridableEntityEventBatchOverrides(batch);
|
||||
|
||||
const event = result.events[0] as {
|
||||
properties: {
|
||||
@@ -188,7 +188,7 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
const result = resolveOverridableEntityEventBatchOverrides(batch);
|
||||
|
||||
const deletedRecord = (
|
||||
result.events[0] as { properties: { before: Record<string, unknown> } }
|
||||
@@ -196,146 +196,12 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
|
||||
expect(deletedRecord.isVisible).toBe(false);
|
||||
expect(deletedRecord).not.toHaveProperty('overrides');
|
||||
expect(deletedRecord).not.toHaveProperty('isActive');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isActive transitions', () => {
|
||||
it('should drop create events when isActive is false', () => {
|
||||
const after = makeViewFieldRecord({ isActive: false });
|
||||
|
||||
const batch = makeBatch('viewField', [
|
||||
{
|
||||
type: 'created',
|
||||
metadataName: 'viewField',
|
||||
recordId: 'vf-1',
|
||||
properties: { after },
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
|
||||
expect(result.events).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should convert update to delete when entity is deactivated', () => {
|
||||
const before = makeViewFieldRecord({ isActive: true });
|
||||
const after = makeViewFieldRecord({ isActive: false });
|
||||
|
||||
const batch = makeBatch('viewField', [
|
||||
{
|
||||
type: 'updated',
|
||||
metadataName: 'viewField',
|
||||
recordId: 'vf-1',
|
||||
properties: {
|
||||
updatedFields: ['isActive'],
|
||||
diff: {},
|
||||
before,
|
||||
after,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
|
||||
expect(result.events).toHaveLength(1);
|
||||
expect(result.events[0].type).toBe('deleted');
|
||||
expect(
|
||||
(
|
||||
result.events[0] as {
|
||||
properties: { before: Record<string, unknown> };
|
||||
}
|
||||
).properties.before,
|
||||
).not.toHaveProperty('isActive');
|
||||
});
|
||||
|
||||
it('should convert update to create when entity is reactivated', () => {
|
||||
const before = makeViewFieldRecord({ isActive: false });
|
||||
const after = makeViewFieldRecord({
|
||||
isActive: true,
|
||||
overrides: { isVisible: false },
|
||||
});
|
||||
|
||||
const batch = makeBatch('viewField', [
|
||||
{
|
||||
type: 'updated',
|
||||
metadataName: 'viewField',
|
||||
recordId: 'vf-1',
|
||||
properties: {
|
||||
updatedFields: ['isActive'],
|
||||
diff: {},
|
||||
before,
|
||||
after,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
|
||||
expect(result.events).toHaveLength(1);
|
||||
expect(result.events[0].type).toBe('created');
|
||||
|
||||
const createdRecord = (
|
||||
result.events[0] as { properties: { after: Record<string, unknown> } }
|
||||
).properties.after;
|
||||
|
||||
expect(createdRecord.isVisible).toBe(false);
|
||||
expect(createdRecord).not.toHaveProperty('overrides');
|
||||
});
|
||||
|
||||
it('should drop update events when both before and after are inactive', () => {
|
||||
const before = makeViewFieldRecord({ isActive: false });
|
||||
const after = makeViewFieldRecord({
|
||||
isActive: false,
|
||||
overrides: { isVisible: false },
|
||||
});
|
||||
|
||||
const batch = makeBatch('viewField', [
|
||||
{
|
||||
type: 'updated',
|
||||
metadataName: 'viewField',
|
||||
recordId: 'vf-1',
|
||||
properties: {
|
||||
updatedFields: ['overrides'],
|
||||
diff: {},
|
||||
before,
|
||||
after,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
|
||||
expect(result.events).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should keep update events when both before and after are active', () => {
|
||||
const before = makeViewFieldRecord({ isActive: true });
|
||||
const after = makeViewFieldRecord({ isActive: true, size: 300 });
|
||||
|
||||
const batch = makeBatch('viewField', [
|
||||
{
|
||||
type: 'updated',
|
||||
metadataName: 'viewField',
|
||||
recordId: 'vf-1',
|
||||
properties: {
|
||||
updatedFields: ['size'],
|
||||
diff: {},
|
||||
before,
|
||||
after,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
|
||||
expect(result.events).toHaveLength(1);
|
||||
expect(result.events[0].type).toBe('updated');
|
||||
expect(deletedRecord).toHaveProperty('isActive', true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pageLayoutWidget (another overridable entity)', () => {
|
||||
it('should resolve overrides for pageLayoutWidget', () => {
|
||||
it('should resolve overrides for pageLayoutWidget and keep isActive', () => {
|
||||
const after = {
|
||||
id: 'plw-1',
|
||||
workspaceId: 'ws-1',
|
||||
@@ -364,7 +230,7 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const result = sanitizeOverridableEntityEventBatch(batch);
|
||||
const result = resolveOverridableEntityEventBatchOverrides(batch);
|
||||
|
||||
const createdRecord = (
|
||||
result.events[0] as { properties: { after: Record<string, unknown> } }
|
||||
@@ -372,7 +238,7 @@ describe('sanitizeOverridableEntityEventBatch', () => {
|
||||
|
||||
expect(createdRecord.title).toBe('Overridden Title');
|
||||
expect(createdRecord).not.toHaveProperty('overrides');
|
||||
expect(createdRecord).not.toHaveProperty('isActive');
|
||||
expect(createdRecord).toHaveProperty('isActive', true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+17
-79
@@ -2,12 +2,7 @@ import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type MetadataEventBatch } from 'src/engine/subscriptions/metadata-event/types/metadata-event-batch.type';
|
||||
import {
|
||||
type CreateMetadataEvent,
|
||||
type DeleteMetadataEvent,
|
||||
type MetadataEvent,
|
||||
type UpdateMetadataEvent,
|
||||
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/metadata-event';
|
||||
import { type MetadataEvent } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/types/metadata-event';
|
||||
|
||||
const OVERRIDABLE_ENTITY_METADATA_NAMES = new Set<AllMetadataName>([
|
||||
'viewField',
|
||||
@@ -19,7 +14,7 @@ const OVERRIDABLE_ENTITY_METADATA_NAMES = new Set<AllMetadataName>([
|
||||
const resolveRecordOverrides = (
|
||||
record: Record<string, unknown>,
|
||||
): Record<string, unknown> => {
|
||||
const { overrides, isActive, ...base } = record;
|
||||
const { overrides, ...base } = record;
|
||||
|
||||
if (!isDefined(overrides)) {
|
||||
return base;
|
||||
@@ -28,89 +23,32 @@ const resolveRecordOverrides = (
|
||||
return { ...base, ...(overrides as Record<string, unknown>) };
|
||||
};
|
||||
|
||||
const sanitizeCreatedEvent = (
|
||||
event: CreateMetadataEvent<AllMetadataName>,
|
||||
): MetadataEvent | null => {
|
||||
const after = event.properties.after as Record<string, unknown>;
|
||||
const resolveEventOverrides = (event: MetadataEvent): MetadataEvent => {
|
||||
const properties = { ...event.properties };
|
||||
|
||||
if (after.isActive === false) {
|
||||
return null;
|
||||
if ('before' in properties && isDefined(properties.before)) {
|
||||
properties.before = resolveRecordOverrides(
|
||||
properties.before as Record<string, unknown>,
|
||||
) as typeof properties.before;
|
||||
}
|
||||
|
||||
return {
|
||||
...event,
|
||||
properties: { after: resolveRecordOverrides(after) },
|
||||
} as typeof event;
|
||||
if ('after' in properties && isDefined(properties.after)) {
|
||||
properties.after = resolveRecordOverrides(
|
||||
properties.after as Record<string, unknown>,
|
||||
) as typeof properties.after;
|
||||
}
|
||||
|
||||
return { ...event, properties } as typeof event;
|
||||
};
|
||||
|
||||
const sanitizeDeletedEvent = (
|
||||
event: DeleteMetadataEvent<AllMetadataName>,
|
||||
): MetadataEvent => {
|
||||
const before = event.properties.before as Record<string, unknown>;
|
||||
|
||||
return {
|
||||
...event,
|
||||
properties: { before: resolveRecordOverrides(before) },
|
||||
} as typeof event;
|
||||
};
|
||||
|
||||
const sanitizeUpdatedEvent = (
|
||||
event: UpdateMetadataEvent<AllMetadataName>,
|
||||
): MetadataEvent | null => {
|
||||
const before = event.properties.before as Record<string, unknown>;
|
||||
const after = event.properties.after as Record<string, unknown>;
|
||||
|
||||
if (before.isActive === false && after.isActive === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (after.isActive === false) {
|
||||
return {
|
||||
type: 'deleted',
|
||||
metadataName: event.metadataName,
|
||||
recordId: event.recordId,
|
||||
properties: { before: resolveRecordOverrides(before) },
|
||||
} as MetadataEvent;
|
||||
}
|
||||
|
||||
if (before.isActive === false) {
|
||||
return {
|
||||
type: 'created',
|
||||
metadataName: event.metadataName,
|
||||
recordId: event.recordId,
|
||||
properties: { after: resolveRecordOverrides(after) },
|
||||
} as MetadataEvent;
|
||||
}
|
||||
|
||||
return {
|
||||
...event,
|
||||
properties: {
|
||||
...event.properties,
|
||||
before: resolveRecordOverrides(before),
|
||||
after: resolveRecordOverrides(after),
|
||||
},
|
||||
} as typeof event;
|
||||
};
|
||||
|
||||
export const sanitizeOverridableEntityEventBatch = (
|
||||
export const resolveOverridableEntityEventBatchOverrides = (
|
||||
metadataEventBatch: MetadataEventBatch,
|
||||
): MetadataEventBatch => {
|
||||
if (!OVERRIDABLE_ENTITY_METADATA_NAMES.has(metadataEventBatch.metadataName)) {
|
||||
return metadataEventBatch;
|
||||
}
|
||||
|
||||
const events = metadataEventBatch.events
|
||||
.map((event) => {
|
||||
switch (event.type) {
|
||||
case 'created':
|
||||
return sanitizeCreatedEvent(event);
|
||||
case 'updated':
|
||||
return sanitizeUpdatedEvent(event);
|
||||
case 'deleted':
|
||||
return sanitizeDeletedEvent(event);
|
||||
}
|
||||
})
|
||||
.filter(isDefined);
|
||||
const events = metadataEventBatch.events.map(resolveEventOverrides);
|
||||
|
||||
return { ...metadataEventBatch, events };
|
||||
};
|
||||
|
||||
+8
-4
@@ -337,14 +337,18 @@ describe('upsertFieldsWidget', () => {
|
||||
},
|
||||
});
|
||||
|
||||
// Verify all groups are soft-deleted
|
||||
const { data: activeGroupsData } = await findViewFieldGroups({
|
||||
// Verify custom group is hard-deleted (not just deactivated)
|
||||
const { data: allGroupsData } = await findViewFieldGroups({
|
||||
viewId: testSetup.viewId,
|
||||
gqlFields: 'id',
|
||||
gqlFields: 'id isActive',
|
||||
expectToFail: false,
|
||||
});
|
||||
|
||||
expect(activeGroupsData.getViewFieldGroups.length).toBe(0);
|
||||
const specificGroup = allGroupsData.getViewFieldGroups.find(
|
||||
(g: { id: string }) => g.id === groupId,
|
||||
);
|
||||
|
||||
expect(specificGroup).toBeUndefined();
|
||||
|
||||
// Verify the field's viewFieldGroupId is null
|
||||
const { data: updatedFieldData } = await findViewFields({
|
||||
|
||||
Reference in New Issue
Block a user