Wire fields widget to backend + basic edition (#17965)
Closes https://github.com/twentyhq/core-team-issues/issues/2215 Closes https://github.com/twentyhq/core-team-issues/issues/2216 Closes https://github.com/twentyhq/core-team-issues/issues/2218 ## Fields widget edition demo https://github.com/user-attachments/assets/08626d70-8fcb-4ae2-9222-10ef57e75f90 ## Dashboards still work https://github.com/user-attachments/assets/aa9a9c45-a0a2-481e-b132-bc52254778da
This commit is contained in:
committed by
GitHub
parent
b107020ad3
commit
00209f7e2c
+21
-15
@@ -3,12 +3,15 @@ import { SidePanelSubPageNavigationHeader } from '@/command-menu/pages/common/co
|
||||
import { usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { useTemporaryFieldsConfiguration } from '@/page-layout/hooks/useTemporaryFieldsConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import { FieldsConfigurationEditor } from '@/page-layout/widgets/fields/components/FieldsConfigurationEditor';
|
||||
import { FieldsWidgetGroupsDraftInitializationEffect } from '@/page-layout/widgets/fields/components/FieldsWidgetGroupsDraftInitializationEffect';
|
||||
import styled from '@emotion/styled';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type FieldsConfiguration,
|
||||
WidgetConfigurationType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
const StyledOuterContainer = styled.div`
|
||||
display: flex;
|
||||
@@ -28,25 +31,23 @@ const StyledContainer = styled.div`
|
||||
export const CommandMenuPageLayoutFieldsLayout = () => {
|
||||
const { goBackFromCommandMenu } = useCommandMenuHistory();
|
||||
|
||||
const { pageLayoutId, objectNameSingular } =
|
||||
const { pageLayoutId } =
|
||||
usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord();
|
||||
|
||||
const { widgetInEditMode } = useWidgetInEditMode(pageLayoutId);
|
||||
const defaultFieldsConfiguration =
|
||||
useTemporaryFieldsConfiguration(objectNameSingular);
|
||||
const [fieldsConfiguration, setFieldsConfiguration] =
|
||||
useState<FieldsConfiguration>(defaultFieldsConfiguration);
|
||||
const temporaryFieldsConfiguration = useTemporaryFieldsConfiguration();
|
||||
|
||||
if (!isDefined(widgetInEditMode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handleConfigurationChange = (
|
||||
updatedConfiguration: FieldsConfiguration,
|
||||
) => {
|
||||
// TODO: replace with a call to updatePageLayoutWidget
|
||||
setFieldsConfiguration(updatedConfiguration);
|
||||
};
|
||||
const widgetConfiguration = widgetInEditMode.configuration;
|
||||
|
||||
const fieldsConfiguration: FieldsConfiguration =
|
||||
isDefined(widgetConfiguration) &&
|
||||
widgetConfiguration.configurationType === WidgetConfigurationType.FIELDS
|
||||
? (widgetConfiguration as FieldsConfiguration)
|
||||
: temporaryFieldsConfiguration;
|
||||
|
||||
return (
|
||||
<StyledOuterContainer>
|
||||
@@ -55,9 +56,14 @@ export const CommandMenuPageLayoutFieldsLayout = () => {
|
||||
onBackClick={goBackFromCommandMenu}
|
||||
/>
|
||||
<StyledContainer>
|
||||
<FieldsWidgetGroupsDraftInitializationEffect
|
||||
viewId={fieldsConfiguration.viewId ?? null}
|
||||
pageLayoutId={pageLayoutId}
|
||||
widgetId={widgetInEditMode.id}
|
||||
/>
|
||||
<FieldsConfigurationEditor
|
||||
configuration={fieldsConfiguration}
|
||||
onChange={handleConfigurationChange}
|
||||
pageLayoutId={pageLayoutId}
|
||||
widgetId={widgetInEditMode.id}
|
||||
/>
|
||||
</StyledContainer>
|
||||
</StyledOuterContainer>
|
||||
|
||||
+13
-5
@@ -6,12 +6,13 @@ import { useNavigatePageLayoutCommandMenu } from '@/command-menu/pages/page-layo
|
||||
import { usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { useTemporaryFieldsConfiguration } from '@/page-layout/hooks/useTemporaryFieldsConfiguration';
|
||||
import { useFieldsWidgetGroups } from '@/page-layout/widgets/fields/hooks/useFieldsWidgetGroups';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconLayoutSidebarRight } from 'twenty-ui/display';
|
||||
import { type FieldsConfiguration } from '~/generated-metadata/graphql';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
@@ -33,15 +34,22 @@ export const CommandMenuPageLayoutFieldsSettings = () => {
|
||||
usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord();
|
||||
|
||||
const { widgetInEditMode } = useWidgetInEditMode(pageLayoutId);
|
||||
const fieldsConfiguration =
|
||||
useTemporaryFieldsConfiguration(objectNameSingular);
|
||||
|
||||
const fieldsConfiguration = widgetInEditMode?.configuration as
|
||||
| FieldsConfiguration
|
||||
| undefined;
|
||||
|
||||
const { groups } = useFieldsWidgetGroups({
|
||||
viewId: fieldsConfiguration?.viewId ?? null,
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
if (!isDefined(widgetInEditMode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const totalFieldsCount = fieldsConfiguration.sections.reduce(
|
||||
(count, section) => count + section.fields.length,
|
||||
const totalFieldsCount = groups.reduce(
|
||||
(count, group) => count + group.fields.length,
|
||||
0,
|
||||
);
|
||||
|
||||
|
||||
+4
-2
@@ -5,7 +5,6 @@ import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/
|
||||
import { getDateGranularityLabel } from '@/command-menu/pages/page-layout/utils/getDateGranularityLabel';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
@@ -17,7 +16,10 @@ import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useR
|
||||
import { ObjectRecordGroupByDateGranularity } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { MenuItemSelect } from 'twenty-ui/navigation';
|
||||
import { type WidgetConfiguration } from '~/generated-metadata/graphql';
|
||||
import {
|
||||
type FieldsConfiguration,
|
||||
type WidgetConfiguration,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
type ChartDateGranularitySelectionDropdownContentProps = {
|
||||
axis?: 'primary' | 'secondary';
|
||||
|
||||
-3
@@ -32,10 +32,7 @@ export const usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord =
|
||||
throw new Error('Only one record should be selected');
|
||||
}
|
||||
|
||||
const recordId: string = targetedRecordsRule.selectedRecordIds[0];
|
||||
|
||||
const { pageLayoutId } = useRecordPageLayoutIdFromRecordStoreOrThrow({
|
||||
id: recordId,
|
||||
targetObjectNameSingular: objectMetadataItem.nameSingular,
|
||||
});
|
||||
|
||||
|
||||
+1
-5
@@ -1,13 +1,9 @@
|
||||
import { type ChartWidget } from '@/command-menu/pages/page-layout/types/ChartWidget';
|
||||
import { isWidgetConfigurationOfTypeGraph } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfTypeGraph';
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { type WidgetConfiguration } from '~/generated-metadata/graphql';
|
||||
|
||||
export const isChartWidget = (
|
||||
pageLayoutWidget: PageLayoutWidget,
|
||||
): pageLayoutWidget is ChartWidget => {
|
||||
return isWidgetConfigurationOfTypeGraph(
|
||||
// TODO: Remove this cast when we FieldsConfiguration and FieldConfiguration are in the backend
|
||||
pageLayoutWidget.configuration as WidgetConfiguration,
|
||||
);
|
||||
return isWidgetConfigurationOfTypeGraph(pageLayoutWidget.configuration);
|
||||
};
|
||||
|
||||
+1
-1
@@ -1,11 +1,11 @@
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import {
|
||||
type AggregateChartConfiguration,
|
||||
type BarChartConfiguration,
|
||||
type CalendarConfiguration,
|
||||
type EmailsConfiguration,
|
||||
type FieldRichTextConfiguration,
|
||||
type FieldsConfiguration,
|
||||
type FilesConfiguration,
|
||||
type FrontComponentConfiguration,
|
||||
type GaugeChartConfiguration,
|
||||
|
||||
+4
-2
@@ -1,8 +1,10 @@
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import { type WidgetConfiguration } from '~/generated-metadata/graphql';
|
||||
import {
|
||||
type FieldsConfiguration,
|
||||
type WidgetConfiguration,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const isWidgetConfigurationOfTypeGraph = (
|
||||
configuration:
|
||||
|
||||
Reference in New Issue
Block a user