Side Panel Sub Page Framework® (#18579)
Replace hard-coded implementations for sub pages in the side panel with a proper framework
This commit is contained in:
committed by
GitHub
parent
5bfa4c5c39
commit
2a6fcfcfb3
+54
-8
@@ -20,14 +20,8 @@ import {
|
||||
} from '~/testing/mock-data/users';
|
||||
import { sleep } from '~/utils/sleep';
|
||||
|
||||
import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
|
||||
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
|
||||
import { SidePanelRouter } from '@/side-panel/components/SidePanelRouter';
|
||||
import { SIDE_PANEL_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelComponentInstanceId';
|
||||
import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId';
|
||||
import { type SidePanelRootPage } from '@/side-panel/pages/root/components/SidePanelRootPage';
|
||||
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
|
||||
import { isSidePanelOpenedState } from '@/side-panel/states/isSidePanelOpenedState';
|
||||
import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
|
||||
@@ -35,11 +29,19 @@ import { ContextStoreComponentInstanceContext } from '@/context-store/states/con
|
||||
import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper';
|
||||
import { SidePanelRouter } from '@/side-panel/components/SidePanelRouter';
|
||||
import { SIDE_PANEL_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelComponentInstanceId';
|
||||
import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId';
|
||||
import { type SidePanelRootPage } from '@/side-panel/pages/root/components/SidePanelRootPage';
|
||||
import { isSidePanelOpenedState } from '@/side-panel/states/isSidePanelOpenedState';
|
||||
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
|
||||
import { sidePanelPageInfoState } from '@/side-panel/states/sidePanelPageInfoState';
|
||||
import { sidePanelPageState } from '@/side-panel/states/sidePanelPageState';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { HttpResponse, graphql } from 'msw';
|
||||
import { SidePanelPages } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconDotsVertical } from 'twenty-ui/display';
|
||||
import { IconDotsVertical, IconPlus } from 'twenty-ui/display';
|
||||
import { JestContextStoreSetter } from '~/testing/jest/JestContextStoreSetter';
|
||||
|
||||
const openTimeout = 50;
|
||||
@@ -87,6 +89,10 @@ const meta: Meta<typeof SidePanelRootPage> = {
|
||||
mockedUserData.currentUserWorkspace,
|
||||
);
|
||||
jotaiStore.set(isSidePanelOpenedState.atom, true);
|
||||
jotaiStore.set(sidePanelPageInfoState.atom, {
|
||||
title: 'Command Menu',
|
||||
instanceId: SIDE_PANEL_COMPONENT_INSTANCE_ID,
|
||||
});
|
||||
jotaiStore.set(sidePanelNavigationStackState.atom, [
|
||||
{
|
||||
page: SidePanelPages.Root,
|
||||
@@ -244,3 +250,43 @@ export const NoResultsSearchFallback: Story = {
|
||||
// expect(await canvas.findByText('Search records')).toBeVisible();
|
||||
// },
|
||||
// };
|
||||
|
||||
export const SubPageNavigation: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const objectButton = await canvas.findByText('Object');
|
||||
expect(objectButton).toBeVisible();
|
||||
|
||||
await userEvent.click(objectButton);
|
||||
|
||||
expect(await canvas.findByText('Pick an object')).toBeVisible();
|
||||
|
||||
const backButton = await canvas.findByRole('button', { name: 'Go back' });
|
||||
await userEvent.click(backButton);
|
||||
|
||||
expect(await canvas.findByText('Object')).toBeVisible();
|
||||
},
|
||||
decorators: [
|
||||
(Story) => {
|
||||
jotaiStore.set(
|
||||
sidePanelPageState.atom,
|
||||
SidePanelPages.NavigationMenuAddItem,
|
||||
);
|
||||
jotaiStore.set(sidePanelPageInfoState.atom, {
|
||||
title: 'Add item',
|
||||
instanceId: SIDE_PANEL_COMPONENT_INSTANCE_ID,
|
||||
});
|
||||
jotaiStore.set(sidePanelNavigationStackState.atom, [
|
||||
{
|
||||
page: SidePanelPages.NavigationMenuAddItem,
|
||||
pageTitle: 'Add item',
|
||||
pageIcon: IconPlus,
|
||||
pageId: '1',
|
||||
},
|
||||
]);
|
||||
|
||||
return <Story />;
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { SIDE_PANEL_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelComponentInstanceId';
|
||||
import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { useSidePanelHistory } from '@/side-panel/hooks/useSidePanelHistory';
|
||||
import { useOpenAskAIPageInSidePanel } from '@/side-panel/hooks/useOpenAskAIPageInSidePanel';
|
||||
import { useOpenRecordsSearchPageInSidePanel } from '@/side-panel/hooks/useOpenRecordsSearchPageInSidePanel';
|
||||
import { useSetGlobalCommandMenuContext } from '@/command-menu/hooks/useSetGlobalCommandMenuContext';
|
||||
import { sidePanelPageState } from '@/side-panel/states/sidePanelPageState';
|
||||
import { sidePanelSearchState } from '@/side-panel/states/sidePanelSearchState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu';
|
||||
import { SIDE_PANEL_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelComponentInstanceId';
|
||||
import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId';
|
||||
import { useOpenAskAIPageInSidePanel } from '@/side-panel/hooks/useOpenAskAIPageInSidePanel';
|
||||
import { useOpenRecordsSearchPageInSidePanel } from '@/side-panel/hooks/useOpenRecordsSearchPageInSidePanel';
|
||||
import { useSidePanelHistory } from '@/side-panel/hooks/useSidePanelHistory';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { sidePanelPageState } from '@/side-panel/states/sidePanelPageState';
|
||||
import { sidePanelSearchState } from '@/side-panel/states/sidePanelSearchState';
|
||||
import { useGlobalHotkeys } from '@/ui/utilities/hotkey/hooks/useGlobalHotkeys';
|
||||
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { SidePanelPages } from 'twenty-shared/types';
|
||||
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
||||
@@ -26,7 +26,8 @@ export const useCommandMenuHotKeys = () => {
|
||||
|
||||
const { openAskAIPage } = useOpenAskAIPageInSidePanel();
|
||||
|
||||
const { goBackFromSidePanel } = useSidePanelHistory();
|
||||
const { goBackFromSidePanel, goBackOneSubPageOrMainPage } =
|
||||
useSidePanelHistory();
|
||||
|
||||
const { setGlobalCommandMenuContext } = useSetGlobalCommandMenuContext();
|
||||
|
||||
@@ -108,7 +109,7 @@ export const useCommandMenuHotKeys = () => {
|
||||
setGlobalCommandMenuContext();
|
||||
}
|
||||
if (sidePanelPage !== SidePanelPages.Root) {
|
||||
goBackFromSidePanel();
|
||||
goBackOneSubPageOrMainPage();
|
||||
}
|
||||
},
|
||||
focusId: SIDE_PANEL_FOCUS_ID,
|
||||
@@ -116,7 +117,7 @@ export const useCommandMenuHotKeys = () => {
|
||||
sidePanelPage,
|
||||
sidePanelSearch,
|
||||
contextStoreTargetedRecordsRule,
|
||||
goBackFromSidePanel,
|
||||
goBackOneSubPageOrMainPage,
|
||||
setGlobalCommandMenuContext,
|
||||
],
|
||||
options: {
|
||||
|
||||
@@ -5,9 +5,9 @@ import { sidePanelPageState } from '@/side-panel/states/sidePanelPageState';
|
||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
||||
import { SidePanelPages } from 'twenty-shared/types';
|
||||
|
||||
import { useNavigatePageLayoutSidePanel } from '@/side-panel/pages/page-layout/hooks/useNavigatePageLayoutSidePanel';
|
||||
import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
|
||||
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
|
||||
import { useNavigatePageLayoutSidePanel } from '@/side-panel/pages/page-layout/hooks/useNavigatePageLayoutSidePanel';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { t } from '@lingui/core/macro';
|
||||
@@ -36,14 +36,13 @@ export const useEditPageLayoutWidget = (pageLayoutIdFromProps?: string) => {
|
||||
widgetId: string;
|
||||
widgetType: WidgetType;
|
||||
}) => {
|
||||
setPageLayoutEditingWidgetId(widgetId);
|
||||
|
||||
if (widgetType === WidgetType.IFRAME) {
|
||||
navigatePageLayoutSidePanel({
|
||||
sidePanelPage: SidePanelPages.PageLayoutIframeSettings,
|
||||
pageTitle: t`Edit iFrame`,
|
||||
resetNavigationStack: true,
|
||||
});
|
||||
setPageLayoutEditingWidgetId(widgetId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -53,6 +52,7 @@ export const useEditPageLayoutWidget = (pageLayoutIdFromProps?: string) => {
|
||||
pageTitle: t`Edit Graph`,
|
||||
resetNavigationStack: true,
|
||||
});
|
||||
setPageLayoutEditingWidgetId(widgetId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ export const useEditPageLayoutWidget = (pageLayoutIdFromProps?: string) => {
|
||||
pageTitle: t`Edit Fields`,
|
||||
resetNavigationStack: true,
|
||||
});
|
||||
setPageLayoutEditingWidgetId(widgetId);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ import {
|
||||
OverflowingTextWithTooltip,
|
||||
} from 'twenty-ui/display';
|
||||
|
||||
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
|
||||
import { useWorkspaceSectionItems } from '@/navigation-menu-item/hooks/useWorkspaceSectionItems';
|
||||
import { selectedNavigationMenuItemInEditModeState } from '@/navigation-menu-item/states/selectedNavigationMenuItemInEditModeState';
|
||||
import { SidePanelAskAIInfo } from '@/side-panel/components/SidePanelAskAIInfo';
|
||||
import { SidePanelFolderInfo } from '@/side-panel/components/SidePanelFolderInfo';
|
||||
import { SidePanelLinkInfo } from '@/side-panel/components/SidePanelLinkInfo';
|
||||
@@ -14,9 +17,6 @@ import { SidePanelPageInfoLayout } from '@/side-panel/components/SidePanelPageIn
|
||||
import { SidePanelPageLayoutInfo } from '@/side-panel/components/SidePanelPageLayoutInfo';
|
||||
import { SidePanelRecordInfo } from '@/side-panel/components/SidePanelRecordInfo';
|
||||
import { SidePanelWorkflowStepInfo } from '@/side-panel/components/SidePanelWorkflowStepInfo';
|
||||
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
|
||||
import { useWorkspaceSectionItems } from '@/navigation-menu-item/hooks/useWorkspaceSectionItems';
|
||||
import { selectedNavigationMenuItemInEditModeState } from '@/navigation-menu-item/states/selectedNavigationMenuItemInEditModeState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { SidePanelPages } from 'twenty-shared/types';
|
||||
|
||||
@@ -98,11 +98,9 @@ export const SidePanelPageInfo = ({ pageChip }: SidePanelPageInfoProps) => {
|
||||
? [
|
||||
SidePanelPages.PageLayoutWidgetTypeSelect,
|
||||
SidePanelPages.PageLayoutGraphTypeSelect,
|
||||
SidePanelPages.PageLayoutGraphFilter,
|
||||
SidePanelPages.PageLayoutIframeSettings,
|
||||
SidePanelPages.PageLayoutTabSettings,
|
||||
SidePanelPages.PageLayoutFieldsSettings,
|
||||
SidePanelPages.PageLayoutFieldsLayout,
|
||||
].includes(pageChip.page?.page)
|
||||
: false;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CommandMenuContextProvider } from '@/command-menu-item/contexts/CommandMenuContextProvider';
|
||||
import { SidePanelContainer } from '@/side-panel/components/SidePanelContainer';
|
||||
import { SidePanelSubPageRouter } from '@/side-panel/components/SidePanelSubPageRouter';
|
||||
import { SidePanelTopBar } from '@/side-panel/components/SidePanelTopBar';
|
||||
import { SIDE_PANEL_PAGES_CONFIG } from '@/side-panel/constants/SidePanelPagesConfig';
|
||||
import { SidePanelPageComponentInstanceContext } from '@/side-panel/states/contexts/SidePanelPageComponentInstanceContext';
|
||||
@@ -56,7 +57,9 @@ export const SidePanelRouter = () => {
|
||||
displayType="listItem"
|
||||
containerType="command-menu-list"
|
||||
>
|
||||
{sidePanelPageComponent}
|
||||
<SidePanelSubPageRouter>
|
||||
{sidePanelPageComponent}
|
||||
</SidePanelSubPageRouter>
|
||||
</CommandMenuContextProvider>
|
||||
</StyledSidePanelContent>
|
||||
</SidePanelPageComponentInstanceContext.Provider>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { SIDE_PANEL_SUB_PAGES_CONFIG } from '@/side-panel/constants/SidePanelSubPagesConfig';
|
||||
import { useSidePanelSubPageHistory } from '@/side-panel/hooks/useSidePanelSubPageHistory';
|
||||
import { SidePanelSubPageNavigationHeader } from '@/side-panel/pages/common/components/SidePanelSubPageNavigationHeader';
|
||||
import { styled } from '@linaria/react';
|
||||
import React, { type ReactNode } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
const StyledSubPageContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
type SidePanelSubPageRouterProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export const SidePanelSubPageRouter = ({
|
||||
children,
|
||||
}: SidePanelSubPageRouterProps) => {
|
||||
const { currentSidePanelSubPage, goBackFromSidePanelSubPage } =
|
||||
useSidePanelSubPageHistory();
|
||||
|
||||
if (!isDefined(currentSidePanelSubPage)) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
const subPageComponent = SIDE_PANEL_SUB_PAGES_CONFIG.get(
|
||||
currentSidePanelSubPage.subPage,
|
||||
);
|
||||
|
||||
if (!isDefined(subPageComponent)) {
|
||||
throw new Error(
|
||||
`Missing side panel sub-page config for "${currentSidePanelSubPage.subPage}". ` +
|
||||
'Please add it to SIDE_PANEL_SUB_PAGES_CONFIG.',
|
||||
);
|
||||
}
|
||||
|
||||
const keyedSubPageComponent = React.isValidElement(subPageComponent)
|
||||
? React.cloneElement(subPageComponent, {
|
||||
key: currentSidePanelSubPage.id,
|
||||
})
|
||||
: subPageComponent;
|
||||
|
||||
return (
|
||||
<StyledSubPageContainer>
|
||||
<SidePanelSubPageNavigationHeader
|
||||
title={currentSidePanelSubPage.title}
|
||||
onBackClick={goBackFromSidePanelSubPage}
|
||||
/>
|
||||
{keyedSubPageComponent}
|
||||
</StyledSubPageContainer>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
import { styled } from '@linaria/react';
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import { SidePanelSubPageNavigationHeader } from '@/side-panel/pages/common/components/SidePanelSubPageNavigationHeader';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledSubViewContainer = styled.div`
|
||||
@@ -50,8 +49,6 @@ const StyledScrollableListWrapper = styled.div`
|
||||
`;
|
||||
|
||||
type SidePanelSubViewWithSearchProps = {
|
||||
backBarTitle: string;
|
||||
onBack: () => void;
|
||||
searchPlaceholder: string;
|
||||
searchValue: string;
|
||||
onSearchChange: (value: string) => void;
|
||||
@@ -60,8 +57,6 @@ type SidePanelSubViewWithSearchProps = {
|
||||
};
|
||||
|
||||
export const SidePanelSubViewWithSearch = ({
|
||||
backBarTitle,
|
||||
onBack,
|
||||
searchPlaceholder,
|
||||
searchValue,
|
||||
onSearchChange,
|
||||
@@ -69,10 +64,6 @@ export const SidePanelSubViewWithSearch = ({
|
||||
children,
|
||||
}: SidePanelSubViewWithSearchProps) => (
|
||||
<StyledSubViewContainer>
|
||||
<SidePanelSubPageNavigationHeader
|
||||
title={backBarTitle}
|
||||
onBackClick={onBack}
|
||||
/>
|
||||
<StyledSearchContainer>
|
||||
<StyledSearchInput
|
||||
placeholder={searchPlaceholder}
|
||||
|
||||
+7
-15
@@ -1,9 +1,10 @@
|
||||
import { type PageLayoutTab } from '@/page-layout/types/PageLayoutTab';
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { GRAPH_TYPE_INFORMATION } from '@/side-panel/pages/page-layout/constants/GraphTypeInformation';
|
||||
import { getCurrentGraphTypeFromConfig } from '@/side-panel/pages/page-layout/utils/getCurrentGraphTypeFromConfig';
|
||||
import { isWidgetConfigurationOfTypeGraph } from '@/side-panel/pages/page-layout/utils/isWidgetConfigurationOfTypeGraph';
|
||||
import { type PageLayoutTab } from '@/page-layout/types/PageLayoutTab';
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useContext } from 'react';
|
||||
import { SidePanelPages } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
@@ -14,7 +15,6 @@ import {
|
||||
type IconComponent,
|
||||
} from 'twenty-ui/display';
|
||||
import { ThemeContext } from 'twenty-ui/theme-constants';
|
||||
import { useContext } from 'react';
|
||||
|
||||
type PageLayoutHeaderInfo = {
|
||||
headerIcon: IconComponent | undefined;
|
||||
@@ -105,8 +105,7 @@ export const usePageLayoutHeaderInfo = ({
|
||||
};
|
||||
}
|
||||
|
||||
case SidePanelPages.PageLayoutGraphTypeSelect:
|
||||
case SidePanelPages.PageLayoutGraphFilter: {
|
||||
case SidePanelPages.PageLayoutGraphTypeSelect: {
|
||||
if (!isDefined(pageLayoutEditingWidgetId)) {
|
||||
return null;
|
||||
}
|
||||
@@ -127,12 +126,6 @@ export const usePageLayoutHeaderInfo = ({
|
||||
widgetInEditMode.configuration,
|
||||
);
|
||||
const graphTypeInfo = GRAPH_TYPE_INFORMATION[currentGraphType];
|
||||
const graphTypeLabel = t(graphTypeInfo.label);
|
||||
|
||||
const headerType =
|
||||
sidePanelPage === SidePanelPages.PageLayoutGraphFilter
|
||||
? graphTypeLabel
|
||||
: t`Chart`;
|
||||
|
||||
const title = isDefined(editedTitle)
|
||||
? editedTitle
|
||||
@@ -143,16 +136,15 @@ export const usePageLayoutHeaderInfo = ({
|
||||
return {
|
||||
headerIcon: graphTypeInfo.icon,
|
||||
headerIconColor: iconColor,
|
||||
headerType,
|
||||
headerType: t`Chart`,
|
||||
title,
|
||||
isReadonly: sidePanelPage === SidePanelPages.PageLayoutGraphFilter,
|
||||
isReadonly: false,
|
||||
tab: undefined,
|
||||
widgetInEditMode,
|
||||
};
|
||||
}
|
||||
|
||||
case SidePanelPages.PageLayoutFieldsSettings:
|
||||
case SidePanelPages.PageLayoutFieldsLayout: {
|
||||
case SidePanelPages.PageLayoutFieldsSettings: {
|
||||
if (!isDefined(pageLayoutEditingWidgetId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@ import { SidePanelMessageThreadPage } from '@/side-panel/pages/message-thread/co
|
||||
import { SidePanelNavigationMenuItemEditPage } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNavigationMenuItemEditPage';
|
||||
import { SidePanelNewSidebarItemPage } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemPage';
|
||||
import { SidePanelPageLayoutChartSettings } from '@/side-panel/pages/page-layout/components/SidePanelPageLayoutChartSettings';
|
||||
import { SidePanelPageLayoutFieldsLayout } from '@/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsLayout';
|
||||
import { SidePanelPageLayoutFieldsSettings } from '@/side-panel/pages/page-layout/components/SidePanelPageLayoutFieldsSettings';
|
||||
import { SidePanelPageLayoutGraphFilter } from '@/side-panel/pages/page-layout/components/SidePanelPageLayoutGraphFilter';
|
||||
import { SidePanelPageLayoutIframeSettings } from '@/side-panel/pages/page-layout/components/SidePanelPageLayoutIframeSettings';
|
||||
import { SidePanelPageLayoutTabSettings } from '@/side-panel/pages/page-layout/components/SidePanelPageLayoutTabSettings';
|
||||
import { SidePanelPageLayoutWidgetTypeSelect } from '@/side-panel/pages/page-layout/components/SidePanelPageLayoutWidgetTypeSelect';
|
||||
@@ -55,7 +53,6 @@ export const SIDE_PANEL_PAGES_CONFIG = new Map<SidePanelPages, React.ReactNode>(
|
||||
SidePanelPages.PageLayoutGraphTypeSelect,
|
||||
<SidePanelPageLayoutChartSettings />,
|
||||
],
|
||||
[SidePanelPages.PageLayoutGraphFilter, <SidePanelPageLayoutGraphFilter />],
|
||||
[
|
||||
SidePanelPages.PageLayoutIframeSettings,
|
||||
<SidePanelPageLayoutIframeSettings />,
|
||||
@@ -65,10 +62,6 @@ export const SIDE_PANEL_PAGES_CONFIG = new Map<SidePanelPages, React.ReactNode>(
|
||||
SidePanelPages.PageLayoutFieldsSettings,
|
||||
<SidePanelPageLayoutFieldsSettings />,
|
||||
],
|
||||
[
|
||||
SidePanelPages.PageLayoutFieldsLayout,
|
||||
<SidePanelPageLayoutFieldsLayout />,
|
||||
],
|
||||
[SidePanelPages.ViewFrontComponent, <SidePanelFrontComponentPage />],
|
||||
[
|
||||
SidePanelPages.NavigationMenuItemEdit,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { SidePanelEditFolderPickerSubPage } from '@/side-panel/pages/navigation-menu-item/components/SidePanelEditFolderPickerSubPage';
|
||||
import { SidePanelNewSidebarItemObjectSubPage } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemObjectSubPage';
|
||||
import { SidePanelNewSidebarItemObjectSystemPickerSubPage } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemObjectSystemPickerSubPage';
|
||||
import { SidePanelNewSidebarItemRecordSubPage } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemRecordSubPage';
|
||||
import { SidePanelNewSidebarItemViewObjectPickerSubPage } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemViewObjectPickerSubPage';
|
||||
import { SidePanelNewSidebarItemViewPickerSubPage } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemViewPickerSubPage';
|
||||
import { SidePanelNewSidebarItemViewSystemPickerSubPage } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemViewSystemPickerSubPage';
|
||||
import { SidePanelChartFilterSubPage } from '@/side-panel/pages/page-layout/components/SidePanelChartFilterSubPage';
|
||||
import { SidePanelFieldsLayoutSubPage } from '@/side-panel/pages/page-layout/components/SidePanelFieldsLayoutSubPage';
|
||||
import { SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
import React from 'react';
|
||||
|
||||
export const SIDE_PANEL_SUB_PAGES_CONFIG = new Map<
|
||||
SidePanelSubPages,
|
||||
React.ReactNode
|
||||
>([
|
||||
[SidePanelSubPages.PageLayoutGraphFilter, <SidePanelChartFilterSubPage />],
|
||||
[SidePanelSubPages.PageLayoutFieldsLayout, <SidePanelFieldsLayoutSubPage />],
|
||||
[
|
||||
SidePanelSubPages.NewSidebarItemViewObjectPicker,
|
||||
<SidePanelNewSidebarItemViewObjectPickerSubPage />,
|
||||
],
|
||||
[
|
||||
SidePanelSubPages.NewSidebarItemViewPicker,
|
||||
<SidePanelNewSidebarItemViewPickerSubPage />,
|
||||
],
|
||||
[
|
||||
SidePanelSubPages.NewSidebarItemViewSystemPicker,
|
||||
<SidePanelNewSidebarItemViewSystemPickerSubPage />,
|
||||
],
|
||||
[
|
||||
SidePanelSubPages.NewSidebarItemObjectPicker,
|
||||
<SidePanelNewSidebarItemObjectSubPage />,
|
||||
],
|
||||
[
|
||||
SidePanelSubPages.NewSidebarItemObjectSystemPicker,
|
||||
<SidePanelNewSidebarItemObjectSystemPickerSubPage />,
|
||||
],
|
||||
[
|
||||
SidePanelSubPages.NewSidebarItemRecord,
|
||||
<SidePanelNewSidebarItemRecordSubPage />,
|
||||
],
|
||||
[SidePanelSubPages.EditFolderPicker, <SidePanelEditFolderPickerSubPage />],
|
||||
]);
|
||||
@@ -1,22 +1,65 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { hasUserSelectedSidePanelListItemState } from '@/side-panel/states/hasUserSelectedSidePanelListItemState';
|
||||
import { sidePanelNavigationMorphItemsByPageState } from '@/side-panel/states/sidePanelNavigationMorphItemsByPageState';
|
||||
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
|
||||
import { sidePanelPageInfoState } from '@/side-panel/states/sidePanelPageInfoState';
|
||||
import { sidePanelPageState } from '@/side-panel/states/sidePanelPageState';
|
||||
import { hasUserSelectedSidePanelListItemState } from '@/side-panel/states/hasUserSelectedSidePanelListItemState';
|
||||
import { sidePanelSubPageStackComponentState } from '@/side-panel/states/sidePanelSubPageStackComponentState';
|
||||
import { getShowPageTabListComponentId } from '@/ui/layout/show-page/utils/getShowPageTabListComponentId';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { isNonEmptyArray } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useStore } from 'jotai';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useSidePanelHistory = () => {
|
||||
const store = useStore();
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
|
||||
const cleanupCurrentPage = useCallback(() => {
|
||||
const currentNavigationStack = store.get(
|
||||
sidePanelNavigationStackState.atom,
|
||||
);
|
||||
|
||||
const currentMorphItems = store.get(
|
||||
sidePanelNavigationMorphItemsByPageState.atom,
|
||||
);
|
||||
|
||||
if (currentNavigationStack.length > 0) {
|
||||
const removedItem = currentNavigationStack.at(-1);
|
||||
|
||||
if (isDefined(removedItem)) {
|
||||
const newMorphItems = new Map(currentMorphItems);
|
||||
newMorphItems.delete(removedItem.pageId);
|
||||
store.set(sidePanelNavigationMorphItemsByPageState.atom, newMorphItems);
|
||||
|
||||
store.set(
|
||||
sidePanelSubPageStackComponentState.atomFamily({
|
||||
instanceId: removedItem.pageId,
|
||||
}),
|
||||
[],
|
||||
);
|
||||
|
||||
const morphItems = currentMorphItems.get(removedItem.pageId);
|
||||
if (isNonEmptyArray(morphItems)) {
|
||||
store.set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: getShowPageTabListComponentId({
|
||||
pageId: removedItem.pageId,
|
||||
targetObjectId: morphItems[0].recordId,
|
||||
}),
|
||||
}),
|
||||
null,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [store]);
|
||||
|
||||
const goBackFromSidePanel = useCallback(() => {
|
||||
cleanupCurrentPage();
|
||||
|
||||
const currentNavigationStack = store.get(
|
||||
sidePanelNavigationStackState.atom,
|
||||
);
|
||||
@@ -39,35 +82,30 @@ export const useSidePanelHistory = () => {
|
||||
|
||||
store.set(sidePanelNavigationStackState.atom, newNavigationStack);
|
||||
|
||||
const currentMorphItems = store.get(
|
||||
sidePanelNavigationMorphItemsByPageState.atom,
|
||||
store.set(hasUserSelectedSidePanelListItemState.atom, false);
|
||||
}, [cleanupCurrentPage, closeSidePanelMenu, store]);
|
||||
|
||||
const goBackOneSubPageOrMainPage = useCallback(() => {
|
||||
const currentPageInfo = store.get(sidePanelPageInfoState.atom);
|
||||
|
||||
const subPageStack = store.get(
|
||||
sidePanelSubPageStackComponentState.atomFamily({
|
||||
instanceId: currentPageInfo.instanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
if (currentNavigationStack.length > 0) {
|
||||
const removedItem = currentNavigationStack.at(-1);
|
||||
|
||||
if (isDefined(removedItem)) {
|
||||
const newMorphItems = new Map(currentMorphItems);
|
||||
newMorphItems.delete(removedItem.pageId);
|
||||
store.set(sidePanelNavigationMorphItemsByPageState.atom, newMorphItems);
|
||||
|
||||
const morphItems = currentMorphItems.get(removedItem.pageId);
|
||||
if (isNonEmptyArray(morphItems)) {
|
||||
store.set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: getShowPageTabListComponentId({
|
||||
pageId: removedItem.pageId,
|
||||
targetObjectId: morphItems[0].recordId,
|
||||
}),
|
||||
}),
|
||||
null,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (isNonEmptyArray(subPageStack)) {
|
||||
store.set(
|
||||
sidePanelSubPageStackComponentState.atomFamily({
|
||||
instanceId: currentPageInfo.instanceId,
|
||||
}),
|
||||
subPageStack.slice(0, -1),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
store.set(hasUserSelectedSidePanelListItemState.atom, false);
|
||||
}, [closeSidePanelMenu, store]);
|
||||
goBackFromSidePanel();
|
||||
}, [goBackFromSidePanel, store]);
|
||||
|
||||
const navigateSidePanelHistory = useCallback(
|
||||
(pageIndex: number) => {
|
||||
@@ -99,6 +137,13 @@ export const useSidePanelHistory = () => {
|
||||
|
||||
for (const [pageId, morphItems] of currentMorphItems.entries()) {
|
||||
if (!newNavigationStack.some((item) => item.pageId === pageId)) {
|
||||
store.set(
|
||||
sidePanelSubPageStackComponentState.atomFamily({
|
||||
instanceId: pageId,
|
||||
}),
|
||||
[],
|
||||
);
|
||||
|
||||
store.set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: getShowPageTabListComponentId({
|
||||
@@ -126,6 +171,7 @@ export const useSidePanelHistory = () => {
|
||||
|
||||
return {
|
||||
goBackFromSidePanel,
|
||||
goBackOneSubPageOrMainPage,
|
||||
navigateSidePanelHistory,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { useCallback } from 'react';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { sidePanelSubPageStackComponentState } from '@/side-panel/states/sidePanelSubPageStackComponentState';
|
||||
import { type SidePanelSubPageEntry } from '@/side-panel/types/SidePanelSubPageEntry';
|
||||
import { type SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
import { getSidePanelSubPageTitle } from '@/side-panel/utils/getSidePanelSubPageTitle';
|
||||
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useSidePanelSubPageHistory = () => {
|
||||
const [sidePanelSubPageStack, setSidePanelSubPageStack] =
|
||||
useAtomComponentState(sidePanelSubPageStackComponentState);
|
||||
|
||||
const currentSidePanelSubPage: SidePanelSubPageEntry | undefined =
|
||||
sidePanelSubPageStack.at(-1);
|
||||
|
||||
const hasSidePanelSubPages = isDefined(currentSidePanelSubPage);
|
||||
|
||||
const navigateToSidePanelSubPage = useCallback(
|
||||
(subPage: SidePanelSubPages, titleOverride?: string) => {
|
||||
const title = isDefined(titleOverride)
|
||||
? titleOverride
|
||||
: getSidePanelSubPageTitle(subPage);
|
||||
|
||||
setSidePanelSubPageStack((currentStack) => [
|
||||
...currentStack,
|
||||
{ id: v4(), subPage, title },
|
||||
]);
|
||||
},
|
||||
[setSidePanelSubPageStack],
|
||||
);
|
||||
|
||||
const goBackFromSidePanelSubPage = useCallback(() => {
|
||||
setSidePanelSubPageStack((currentStack) => currentStack.slice(0, -1));
|
||||
}, [setSidePanelSubPageStack]);
|
||||
|
||||
const resetSidePanelSubPages = useCallback(() => {
|
||||
setSidePanelSubPageStack([]);
|
||||
}, [setSidePanelSubPageStack]);
|
||||
|
||||
return {
|
||||
navigateToSidePanelSubPage,
|
||||
goBackFromSidePanelSubPage,
|
||||
resetSidePanelSubPages,
|
||||
currentSidePanelSubPage,
|
||||
sidePanelSubPageStack,
|
||||
hasSidePanelSubPages,
|
||||
};
|
||||
};
|
||||
+1
@@ -34,6 +34,7 @@ export const SidePanelSubPageNavigationHeader = ({
|
||||
Icon={IconChevronLeft}
|
||||
variant="tertiary"
|
||||
size="small"
|
||||
ariaLabel="Go back"
|
||||
/>
|
||||
<StyledText>{title}</StyledText>
|
||||
</StyledContainer>
|
||||
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useState } from 'react';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
|
||||
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
|
||||
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
|
||||
import { FOLDER_ICON_DEFAULT } from '@/navigation-menu-item/constants/FolderIconDefault';
|
||||
import { DEFAULT_NAVIGATION_MENU_ITEM_COLOR_FOLDER } from '@/navigation-menu-item/constants/NavigationMenuItemDefaultColorFolder';
|
||||
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
||||
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
||||
import { SidePanelSubViewWithSearch } from '@/side-panel/components/SidePanelSubViewWithSearch';
|
||||
import { useFolderPickerSelectionData } from '@/side-panel/pages/navigation-menu-item/hooks/useFolderPickerSelectionData';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { filterBySearchQuery } from '~/utils/filterBySearchQuery';
|
||||
|
||||
export const SidePanelEditFolderPickerSubPage = () => {
|
||||
const { t } = useLingui();
|
||||
const { getIcon } = useIcons();
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const { foldersToShow, includeNoFolderOption, handleSelectFolder } =
|
||||
useFolderPickerSelectionData();
|
||||
|
||||
const filteredFolders = filterBySearchQuery({
|
||||
items: foldersToShow,
|
||||
searchQuery: searchValue,
|
||||
getSearchableValues: (folder) => [folder.name],
|
||||
});
|
||||
const isEmpty = filteredFolders.length === 0 && !includeNoFolderOption;
|
||||
const selectableItemIds = [
|
||||
...(includeNoFolderOption ? ['no-folder'] : []),
|
||||
...(filteredFolders.length > 0 ? filteredFolders.map((f) => f.id) : []),
|
||||
];
|
||||
const noResultsText =
|
||||
searchValue.trim().length > 0
|
||||
? t`No results found`
|
||||
: t`No folders available`;
|
||||
|
||||
return (
|
||||
<SidePanelSubViewWithSearch
|
||||
searchPlaceholder={t`Search a folder...`}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={setSearchValue}
|
||||
>
|
||||
<SidePanelList
|
||||
commandGroups={[]}
|
||||
selectableItemIds={selectableItemIds}
|
||||
noResults={isEmpty}
|
||||
noResultsText={noResultsText}
|
||||
>
|
||||
<SidePanelGroup heading={t`Folders`}>
|
||||
{includeNoFolderOption && (
|
||||
<SelectableListItem
|
||||
itemId="no-folder"
|
||||
onEnter={() => handleSelectFolder(null)}
|
||||
>
|
||||
<CommandMenuItem
|
||||
label={t`No folder`}
|
||||
id="no-folder"
|
||||
onClick={() => handleSelectFolder(null)}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
)}
|
||||
{filteredFolders.map((folder) => {
|
||||
const FolderIcon = getIcon(folder.icon ?? FOLDER_ICON_DEFAULT);
|
||||
const folderColor =
|
||||
folder.color ?? DEFAULT_NAVIGATION_MENU_ITEM_COLOR_FOLDER;
|
||||
return (
|
||||
<SelectableListItem
|
||||
key={folder.id}
|
||||
itemId={folder.id}
|
||||
onEnter={() => handleSelectFolder(folder.id)}
|
||||
>
|
||||
<CommandMenuItem
|
||||
LeftComponent={
|
||||
<NavigationMenuItemStyleIcon
|
||||
Icon={FolderIcon}
|
||||
color={folderColor}
|
||||
/>
|
||||
}
|
||||
label={folder.name}
|
||||
id={folder.id}
|
||||
onClick={() => handleSelectFolder(folder.id)}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
);
|
||||
})}
|
||||
</SidePanelGroup>
|
||||
</SidePanelList>
|
||||
</SidePanelSubViewWithSearch>
|
||||
);
|
||||
};
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useState } from 'react';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
|
||||
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
||||
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
|
||||
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
||||
import { SidePanelSubViewWithSearch } from '@/side-panel/components/SidePanelSubViewWithSearch';
|
||||
import { useFolderPickerSelectionData } from '@/side-panel/pages/navigation-menu-item/hooks/useFolderPickerSelectionData';
|
||||
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
|
||||
import { FOLDER_ICON_DEFAULT } from '@/navigation-menu-item/constants/FolderIconDefault';
|
||||
import { DEFAULT_NAVIGATION_MENU_ITEM_COLOR_FOLDER } from '@/navigation-menu-item/constants/NavigationMenuItemDefaultColorFolder';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { filterBySearchQuery } from '~/utils/filterBySearchQuery';
|
||||
|
||||
type SidePanelEditFolderPickerSubViewProps = {
|
||||
onBack: () => void;
|
||||
};
|
||||
|
||||
export const SidePanelEditFolderPickerSubView = ({
|
||||
onBack,
|
||||
}: SidePanelEditFolderPickerSubViewProps) => {
|
||||
const { t } = useLingui();
|
||||
const { getIcon } = useIcons();
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const { foldersToShow, includeNoFolderOption, handleSelectFolder } =
|
||||
useFolderPickerSelectionData({ onCloseSubView: onBack });
|
||||
|
||||
const filteredFolders = filterBySearchQuery({
|
||||
items: foldersToShow,
|
||||
searchQuery: searchValue,
|
||||
getSearchableValues: (folder) => [folder.name],
|
||||
});
|
||||
const isEmpty = filteredFolders.length === 0 && !includeNoFolderOption;
|
||||
const selectableItemIds = [
|
||||
...(includeNoFolderOption ? ['no-folder'] : []),
|
||||
...(filteredFolders.length > 0 ? filteredFolders.map((f) => f.id) : []),
|
||||
];
|
||||
const noResultsText =
|
||||
searchValue.trim().length > 0
|
||||
? t`No results found`
|
||||
: t`No folders available`;
|
||||
|
||||
return (
|
||||
<SidePanelSubViewWithSearch
|
||||
backBarTitle={t`Move to a folder`}
|
||||
onBack={onBack}
|
||||
searchPlaceholder={t`Search a folder...`}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={setSearchValue}
|
||||
>
|
||||
<SidePanelList
|
||||
commandGroups={[]}
|
||||
selectableItemIds={selectableItemIds}
|
||||
noResults={isEmpty}
|
||||
noResultsText={noResultsText}
|
||||
>
|
||||
<SidePanelGroup heading={t`Folders`}>
|
||||
{includeNoFolderOption && (
|
||||
<SelectableListItem
|
||||
itemId="no-folder"
|
||||
onEnter={() => handleSelectFolder(null)}
|
||||
>
|
||||
<CommandMenuItem
|
||||
label={t`No folder`}
|
||||
id="no-folder"
|
||||
onClick={() => handleSelectFolder(null)}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
)}
|
||||
{filteredFolders.map((folder) => {
|
||||
const FolderIcon = getIcon(folder.icon ?? FOLDER_ICON_DEFAULT);
|
||||
const folderColor =
|
||||
folder.color ?? DEFAULT_NAVIGATION_MENU_ITEM_COLOR_FOLDER;
|
||||
return (
|
||||
<SelectableListItem
|
||||
key={folder.id}
|
||||
itemId={folder.id}
|
||||
onEnter={() => handleSelectFolder(folder.id)}
|
||||
>
|
||||
<CommandMenuItem
|
||||
LeftComponent={
|
||||
<NavigationMenuItemStyleIcon
|
||||
Icon={FolderIcon}
|
||||
color={folderColor}
|
||||
/>
|
||||
}
|
||||
label={folder.name}
|
||||
id={folder.id}
|
||||
onClick={() => handleSelectFolder(folder.id)}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
);
|
||||
})}
|
||||
</SidePanelGroup>
|
||||
</SidePanelList>
|
||||
</SidePanelSubViewWithSearch>
|
||||
);
|
||||
};
|
||||
|
||||
+5
-12
@@ -10,20 +10,20 @@ import { selectedNavigationMenuItemInEditModeState } from '@/navigation-menu-ite
|
||||
import { parseThemeColor } from '@/navigation-menu-item/utils/parseThemeColor';
|
||||
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
||||
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
||||
import { useSidePanelSubPageHistory } from '@/side-panel/hooks/useSidePanelSubPageHistory';
|
||||
import { SidePanelEditColorOption } from '@/side-panel/pages/navigation-menu-item/components/SidePanelEditColorOption';
|
||||
import { SidePanelEditFolderPickerSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelEditFolderPickerSubView';
|
||||
import { SidePanelEditLinkItemView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelEditLinkItemView';
|
||||
import { SidePanelEditObjectViewBase } from '@/side-panel/pages/navigation-menu-item/components/SidePanelEditObjectViewBase';
|
||||
import { SidePanelEditOrganizeActions } from '@/side-panel/pages/navigation-menu-item/components/SidePanelEditOrganizeActions';
|
||||
import { SidePanelEditOwnerSection } from '@/side-panel/pages/navigation-menu-item/components/SidePanelEditOwnerSection';
|
||||
import { useNavigationMenuItemEditOrganizeActions } from '@/side-panel/pages/navigation-menu-item/hooks/useNavigationMenuItemEditOrganizeActions';
|
||||
import { getOrganizeActionsSelectableItemIds } from '@/side-panel/pages/navigation-menu-item/utils/getOrganizeActionsSelectableItemIds';
|
||||
import { SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconPlus } from 'twenty-ui/display';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
@@ -51,8 +51,9 @@ export const SidePanelNavigationMenuItemEditPage = () => {
|
||||
useSelectedNavigationMenuItemEditItemObjectMetadata();
|
||||
const selectedItemType = selectedItem?.itemType ?? null;
|
||||
|
||||
const [isFolderPickerOpen, setIsFolderPickerOpen] = useState(false);
|
||||
const openFolderPicker = () => setIsFolderPickerOpen(true);
|
||||
const { navigateToSidePanelSubPage } = useSidePanelSubPageHistory();
|
||||
const openFolderPicker = () =>
|
||||
navigateToSidePanelSubPage(SidePanelSubPages.EditFolderPicker);
|
||||
|
||||
const {
|
||||
canMoveUp,
|
||||
@@ -95,14 +96,6 @@ export const SidePanelNavigationMenuItemEditPage = () => {
|
||||
);
|
||||
}
|
||||
|
||||
if (isFolderPickerOpen) {
|
||||
return (
|
||||
<SidePanelEditFolderPickerSubView
|
||||
onBack={() => setIsFolderPickerOpen(false)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
switch (selectedItemType) {
|
||||
case NavigationMenuItemType.VIEW:
|
||||
if (!selectedItemObjectMetadata) return null;
|
||||
|
||||
+10
-36
@@ -1,4 +1,3 @@
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { useAddObjectToNavigationMenuDraft } from '@/navigation-menu-item/hooks/useAddObjectToNavigationMenuDraft';
|
||||
@@ -10,26 +9,19 @@ import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStan
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useSidePanelSubPageHistory } from '@/side-panel/hooks/useSidePanelSubPageHistory';
|
||||
import { SidePanelObjectPickerSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelObjectPickerSubView';
|
||||
import { SidePanelSystemObjectPickerSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelSystemObjectPickerSubView';
|
||||
import { getAvailableObjectMetadataForNewSidebarItem } from '@/side-panel/pages/navigation-menu-item/utils/getAvailableObjectMetadataForNewSidebarItem';
|
||||
import { SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
|
||||
type SidePanelNewSidebarItemObjectFlowProps = {
|
||||
onBack: () => void;
|
||||
};
|
||||
|
||||
export const SidePanelNewSidebarItemObjectFlow = ({
|
||||
onBack,
|
||||
}: SidePanelNewSidebarItemObjectFlowProps) => {
|
||||
const { t } = useLingui();
|
||||
export const SidePanelNewSidebarItemObjectSubPage = () => {
|
||||
const { navigateToSidePanelSubPage } = useSidePanelSubPageHistory();
|
||||
const { getIcon } = useIcons();
|
||||
const [objectSearchInput, setObjectSearchInput] = useState('');
|
||||
const [systemObjectSearchInput, setSystemObjectSearchInput] = useState('');
|
||||
const [isInSystemPicker, setIsInSystemPicker] = useState(false);
|
||||
|
||||
const { currentDraft } = useDraftNavigationMenuItems();
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
@@ -56,7 +48,7 @@ export const SidePanelNewSidebarItemObjectFlow = ({
|
||||
.map((view) => view.objectMetadataId),
|
||||
);
|
||||
|
||||
const { availableObjectMetadataItems, availableSystemObjectMetadataItems } =
|
||||
const { availableObjectMetadataItems } =
|
||||
getAvailableObjectMetadataForNewSidebarItem({
|
||||
objectMetadataItems,
|
||||
activeNonSystemObjectMetadataItems,
|
||||
@@ -87,36 +79,18 @@ export const SidePanelNewSidebarItemObjectFlow = ({
|
||||
});
|
||||
};
|
||||
|
||||
const handleBackToObjectList = () => {
|
||||
setIsInSystemPicker(false);
|
||||
setSystemObjectSearchInput('');
|
||||
};
|
||||
|
||||
const disableDrag = addMenuItemInsertionContext?.disableDrag === true;
|
||||
|
||||
if (isInSystemPicker) {
|
||||
return (
|
||||
<SidePanelSystemObjectPickerSubView
|
||||
systemObjects={availableSystemObjectMetadataItems}
|
||||
searchValue={systemObjectSearchInput}
|
||||
onSearchChange={setSystemObjectSearchInput}
|
||||
onBack={handleBackToObjectList}
|
||||
isViewItem={false}
|
||||
onChangeObject={handleSelectObject}
|
||||
objectMenuItemVariant="add"
|
||||
emptyNoResultsText={t`All system objects are already in the sidebar`}
|
||||
disableDrag={disableDrag}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SidePanelObjectPickerSubView
|
||||
objects={availableObjectMetadataItems}
|
||||
searchValue={objectSearchInput}
|
||||
onSearchChange={setObjectSearchInput}
|
||||
onBack={onBack}
|
||||
onOpenSystemPicker={() => setIsInSystemPicker(true)}
|
||||
onOpenSystemPicker={() =>
|
||||
navigateToSidePanelSubPage(
|
||||
SidePanelSubPages.NewSidebarItemObjectSystemPicker,
|
||||
)
|
||||
}
|
||||
isViewItem={false}
|
||||
onChangeObject={handleSelectObject}
|
||||
objectMenuItemVariant="add"
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
import { useAddObjectToNavigationMenuDraft } from '@/navigation-menu-item/hooks/useAddObjectToNavigationMenuDraft';
|
||||
import { useDraftNavigationMenuItems } from '@/navigation-menu-item/hooks/useDraftNavigationMenuItems';
|
||||
import { useNavigationMenuObjectMetadataFromDraft } from '@/navigation-menu-item/hooks/useNavigationMenuObjectMetadataFromDraft';
|
||||
import { useOpenNavigationMenuItemInSidePanel } from '@/navigation-menu-item/hooks/useOpenNavigationMenuItemInSidePanel';
|
||||
import { addMenuItemInsertionContextState } from '@/navigation-menu-item/states/addMenuItemInsertionContextState';
|
||||
import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStandardObjectIconColor';
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { SidePanelSystemObjectPickerSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelSystemObjectPickerSubView';
|
||||
import { getAvailableObjectMetadataForNewSidebarItem } from '@/side-panel/pages/navigation-menu-item/utils/getAvailableObjectMetadataForNewSidebarItem';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { useState } from 'react';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
|
||||
export const SidePanelNewSidebarItemObjectSystemPickerSubPage = () => {
|
||||
const { t } = useLingui();
|
||||
const { getIcon } = useIcons();
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
|
||||
const { currentDraft } = useDraftNavigationMenuItems();
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
const { addObjectToDraft } = useAddObjectToNavigationMenuDraft();
|
||||
const { openNavigationMenuItemInSidePanel } =
|
||||
useOpenNavigationMenuItemInSidePanel();
|
||||
const { activeNonSystemObjectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
const addMenuItemInsertionContext = useAtomStateValue(
|
||||
addMenuItemInsertionContextState,
|
||||
);
|
||||
const setAddMenuItemInsertionContext = useSetAtomState(
|
||||
addMenuItemInsertionContextState,
|
||||
);
|
||||
const {
|
||||
views,
|
||||
objectMetadataIdsWithIndexView,
|
||||
objectMetadataIdsInWorkspace,
|
||||
} = useNavigationMenuObjectMetadataFromDraft(currentDraft);
|
||||
|
||||
const objectMetadataIdsWithDisplayableViews = new Set(
|
||||
views
|
||||
.filter((view) => view.key !== ViewKey.Index)
|
||||
.map((view) => view.objectMetadataId),
|
||||
);
|
||||
|
||||
const { availableSystemObjectMetadataItems } =
|
||||
getAvailableObjectMetadataForNewSidebarItem({
|
||||
objectMetadataItems,
|
||||
activeNonSystemObjectMetadataItems,
|
||||
objectMetadataIdsWithIndexView,
|
||||
objectMetadataIdsWithDisplayableViews,
|
||||
});
|
||||
|
||||
const handleSelectObject = (
|
||||
objectMetadataItem: ObjectMetadataItem,
|
||||
defaultViewId: string,
|
||||
) => {
|
||||
if (objectMetadataIdsInWorkspace.has(objectMetadataItem.id)) {
|
||||
return;
|
||||
}
|
||||
const itemId = addObjectToDraft(
|
||||
objectMetadataItem.id,
|
||||
defaultViewId,
|
||||
currentDraft,
|
||||
addMenuItemInsertionContext?.targetFolderId,
|
||||
addMenuItemInsertionContext?.targetIndex,
|
||||
getStandardObjectIconColor(objectMetadataItem.nameSingular),
|
||||
);
|
||||
setAddMenuItemInsertionContext(null);
|
||||
openNavigationMenuItemInSidePanel({
|
||||
itemId,
|
||||
pageTitle: objectMetadataItem.labelSingular,
|
||||
pageIcon: getIcon(objectMetadataItem.icon),
|
||||
});
|
||||
};
|
||||
|
||||
const disableDrag = addMenuItemInsertionContext?.disableDrag === true;
|
||||
|
||||
return (
|
||||
<SidePanelSystemObjectPickerSubView
|
||||
systemObjects={availableSystemObjectMetadataItems}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={setSearchValue}
|
||||
isViewItem={false}
|
||||
onChangeObject={handleSelectObject}
|
||||
objectMenuItemVariant="add"
|
||||
emptyNoResultsText={t`All system objects are already in the sidebar`}
|
||||
disableDrag={disableDrag}
|
||||
/>
|
||||
);
|
||||
};
|
||||
+18
-40
@@ -1,45 +1,23 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import { addMenuItemInsertionContextState } from '@/navigation-menu-item/states/addMenuItemInsertionContextState';
|
||||
import { useSidePanelSubPageHistory } from '@/side-panel/hooks/useSidePanelSubPageHistory';
|
||||
import { SidePanelNewSidebarItemMainMenu } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemMainMenu';
|
||||
import { SidePanelNewSidebarItemObjectFlow } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemObjectFlow';
|
||||
import { SidePanelNewSidebarItemRecordSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemRecordSubView';
|
||||
import { SidePanelNewSidebarItemViewFlow } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemViewFlow';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type SelectedOption = 'object' | 'record' | 'view' | null;
|
||||
import { SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
|
||||
export const SidePanelNewSidebarItemPage = () => {
|
||||
const [selectedOption, setSelectedOption] = useState<SelectedOption>(null);
|
||||
const addMenuItemInsertionContext = useAtomStateValue(
|
||||
addMenuItemInsertionContextState,
|
||||
const { navigateToSidePanelSubPage } = useSidePanelSubPageHistory();
|
||||
|
||||
return (
|
||||
<SidePanelNewSidebarItemMainMenu
|
||||
onSelectRecord={() =>
|
||||
navigateToSidePanelSubPage(SidePanelSubPages.NewSidebarItemRecord)
|
||||
}
|
||||
onSelectObject={() =>
|
||||
navigateToSidePanelSubPage(SidePanelSubPages.NewSidebarItemObjectPicker)
|
||||
}
|
||||
onSelectView={() =>
|
||||
navigateToSidePanelSubPage(
|
||||
SidePanelSubPages.NewSidebarItemViewObjectPicker,
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
const disableDrag = isDefined(addMenuItemInsertionContext);
|
||||
|
||||
const handleBackToMain = () => {
|
||||
setSelectedOption(null);
|
||||
};
|
||||
|
||||
switch (selectedOption) {
|
||||
case 'view':
|
||||
return <SidePanelNewSidebarItemViewFlow onBack={handleBackToMain} />;
|
||||
case 'object':
|
||||
return <SidePanelNewSidebarItemObjectFlow onBack={handleBackToMain} />;
|
||||
case 'record':
|
||||
return (
|
||||
<SidePanelNewSidebarItemRecordSubView
|
||||
onBack={handleBackToMain}
|
||||
disableDrag={disableDrag}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<SidePanelNewSidebarItemMainMenu
|
||||
onSelectRecord={() => setSelectedOption('record')}
|
||||
onSelectObject={() => setSelectedOption('object')}
|
||||
onSelectView={() => setSelectedOption('view')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
+2
-13
@@ -25,21 +25,12 @@ type SearchRecordBase = {
|
||||
imageUrl?: string | null;
|
||||
};
|
||||
|
||||
type SidePanelNewSidebarItemRecordSubViewProps = {
|
||||
onBack: () => void;
|
||||
disableDrag?: boolean;
|
||||
};
|
||||
|
||||
export const SidePanelNewSidebarItemRecordSubView = ({
|
||||
onBack,
|
||||
disableDrag: disableDragProp,
|
||||
}: SidePanelNewSidebarItemRecordSubViewProps) => {
|
||||
export const SidePanelNewSidebarItemRecordSubPage = () => {
|
||||
const { t } = useLingui();
|
||||
const addMenuItemInsertionContext = useAtomStateValue(
|
||||
addMenuItemInsertionContextState,
|
||||
);
|
||||
const disableDrag =
|
||||
disableDragProp ?? addMenuItemInsertionContext?.disableDrag === true;
|
||||
const disableDrag = addMenuItemInsertionContext?.disableDrag === true;
|
||||
const { currentDraft } = useDraftNavigationMenuItems();
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
const [recordSearchInput, setRecordSearchInput] = useState('');
|
||||
@@ -92,8 +83,6 @@ export const SidePanelNewSidebarItemRecordSubView = ({
|
||||
|
||||
return (
|
||||
<SidePanelSubViewWithSearch
|
||||
backBarTitle={t`Add a record`}
|
||||
onBack={onBack}
|
||||
searchPlaceholder={t`Search records...`}
|
||||
searchValue={recordSearchInput}
|
||||
onSearchChange={setRecordSearchInput}
|
||||
-115
@@ -1,115 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { useDraftNavigationMenuItems } from '@/navigation-menu-item/hooks/useDraftNavigationMenuItems';
|
||||
import { useNavigationMenuObjectMetadataFromDraft } from '@/navigation-menu-item/hooks/useNavigationMenuObjectMetadataFromDraft';
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { SidePanelNewSidebarItemViewObjectPickerSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemViewObjectPickerSubView';
|
||||
import { SidePanelNewSidebarItemViewPickerSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemViewPickerSubView';
|
||||
import { SidePanelNewSidebarItemViewSystemSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemViewSystemSubView';
|
||||
import { getAvailableObjectMetadataForNewSidebarItem } from '@/side-panel/pages/navigation-menu-item/utils/getAvailableObjectMetadataForNewSidebarItem';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
|
||||
type SidePanelNewSidebarItemViewFlowProps = {
|
||||
onBack: () => void;
|
||||
};
|
||||
|
||||
export const SidePanelNewSidebarItemViewFlow = ({
|
||||
onBack,
|
||||
}: SidePanelNewSidebarItemViewFlowProps) => {
|
||||
const [selectedObjectMetadataIdForView, setSelectedObjectMetadataIdForView] =
|
||||
useState<string | null>(null);
|
||||
const [objectSearchInput, setObjectSearchInput] = useState('');
|
||||
const [systemObjectSearchInput, setSystemObjectSearchInput] = useState('');
|
||||
const [isInSystemPicker, setIsInSystemPicker] = useState(false);
|
||||
|
||||
const { currentDraft } = useDraftNavigationMenuItems();
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
const { activeNonSystemObjectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
const { views, objectMetadataIdsWithIndexView } =
|
||||
useNavigationMenuObjectMetadataFromDraft(currentDraft);
|
||||
|
||||
const objectMetadataIdsWithDisplayableViews = new Set(
|
||||
views
|
||||
.filter(
|
||||
(view) =>
|
||||
view.key !== ViewKey.Index && view.type !== ViewType.FieldsWidget,
|
||||
)
|
||||
.map((view) => view.objectMetadataId),
|
||||
);
|
||||
|
||||
const {
|
||||
objectMetadataItemsWithViews,
|
||||
availableSystemObjectMetadataItemsForView,
|
||||
} = getAvailableObjectMetadataForNewSidebarItem({
|
||||
objectMetadataItems,
|
||||
activeNonSystemObjectMetadataItems,
|
||||
objectMetadataIdsWithIndexView,
|
||||
objectMetadataIdsWithDisplayableViews,
|
||||
});
|
||||
|
||||
const handleBackFromViewPicker = () => {
|
||||
const selectedObjectMetadataItem = isDefined(
|
||||
selectedObjectMetadataIdForView,
|
||||
)
|
||||
? objectMetadataItems.find(
|
||||
(item) => item.id === selectedObjectMetadataIdForView,
|
||||
)
|
||||
: undefined;
|
||||
const cameFromSystemObjects = selectedObjectMetadataItem?.isSystem ?? false;
|
||||
|
||||
setSelectedObjectMetadataIdForView(null);
|
||||
setIsInSystemPicker(cameFromSystemObjects);
|
||||
};
|
||||
|
||||
const handleBackFromSystemPicker = () => {
|
||||
setIsInSystemPicker(false);
|
||||
};
|
||||
|
||||
const handleSelectObject = (objectId: string) => {
|
||||
setSelectedObjectMetadataIdForView(objectId);
|
||||
};
|
||||
|
||||
const handleSelectObjectFromSystem = (objectId: string) => {
|
||||
setSelectedObjectMetadataIdForView(objectId);
|
||||
setIsInSystemPicker(false);
|
||||
};
|
||||
|
||||
if (isDefined(selectedObjectMetadataIdForView) && !isInSystemPicker) {
|
||||
return (
|
||||
<SidePanelNewSidebarItemViewPickerSubView
|
||||
selectedObjectMetadataIdForView={selectedObjectMetadataIdForView}
|
||||
onBack={handleBackFromViewPicker}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (isInSystemPicker) {
|
||||
return (
|
||||
<SidePanelNewSidebarItemViewSystemSubView
|
||||
systemObjects={availableSystemObjectMetadataItemsForView}
|
||||
searchValue={systemObjectSearchInput}
|
||||
onSearchChange={setSystemObjectSearchInput}
|
||||
onBack={handleBackFromSystemPicker}
|
||||
onSelectObject={(item) => handleSelectObjectFromSystem(item.id)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SidePanelNewSidebarItemViewObjectPickerSubView
|
||||
objects={objectMetadataItemsWithViews}
|
||||
searchValue={objectSearchInput}
|
||||
onSearchChange={setObjectSearchInput}
|
||||
onBack={onBack}
|
||||
onOpenSystemPicker={() => setIsInSystemPicker(true)}
|
||||
onSelectObject={(item) => handleSelectObject(item.id)}
|
||||
showSystemObjectsOption={
|
||||
availableSystemObjectMetadataItemsForView.length > 0
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
import { useDraftNavigationMenuItems } from '@/navigation-menu-item/hooks/useDraftNavigationMenuItems';
|
||||
import { useNavigationMenuObjectMetadataFromDraft } from '@/navigation-menu-item/hooks/useNavigationMenuObjectMetadataFromDraft';
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useSidePanelSubPageHistory } from '@/side-panel/hooks/useSidePanelSubPageHistory';
|
||||
import { SidePanelNewSidebarItemViewObjectPickerSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemViewObjectPickerSubView';
|
||||
import { getAvailableObjectMetadataForNewSidebarItem } from '@/side-panel/pages/navigation-menu-item/utils/getAvailableObjectMetadataForNewSidebarItem';
|
||||
import { selectedObjectMetadataIdForViewFlowState } from '@/side-panel/states/selectedObjectMetadataIdForViewFlowState';
|
||||
import { SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { useState } from 'react';
|
||||
|
||||
export const SidePanelNewSidebarItemViewObjectPickerSubPage = () => {
|
||||
const { navigateToSidePanelSubPage } = useSidePanelSubPageHistory();
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const setSelectedObjectMetadataIdForViewFlow = useSetAtomComponentState(
|
||||
selectedObjectMetadataIdForViewFlowState,
|
||||
);
|
||||
|
||||
const { currentDraft } = useDraftNavigationMenuItems();
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
const { activeNonSystemObjectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
const { views, objectMetadataIdsWithIndexView } =
|
||||
useNavigationMenuObjectMetadataFromDraft(currentDraft);
|
||||
|
||||
const objectMetadataIdsWithDisplayableViews = new Set(
|
||||
views
|
||||
.filter(
|
||||
(view) =>
|
||||
view.key !== ViewKey.Index && view.type !== ViewType.FieldsWidget,
|
||||
)
|
||||
.map((view) => view.objectMetadataId),
|
||||
);
|
||||
|
||||
const {
|
||||
objectMetadataItemsWithViews,
|
||||
availableSystemObjectMetadataItemsForView,
|
||||
} = getAvailableObjectMetadataForNewSidebarItem({
|
||||
objectMetadataItems,
|
||||
activeNonSystemObjectMetadataItems,
|
||||
objectMetadataIdsWithIndexView,
|
||||
objectMetadataIdsWithDisplayableViews,
|
||||
});
|
||||
|
||||
const handleSelectObject = (objectMetadataItem: ObjectMetadataItem) => {
|
||||
setSelectedObjectMetadataIdForViewFlow(objectMetadataItem.id);
|
||||
navigateToSidePanelSubPage(
|
||||
SidePanelSubPages.NewSidebarItemViewPicker,
|
||||
objectMetadataItem.labelPlural,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<SidePanelNewSidebarItemViewObjectPickerSubView
|
||||
objects={objectMetadataItemsWithViews}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={setSearchValue}
|
||||
onOpenSystemPicker={() =>
|
||||
navigateToSidePanelSubPage(
|
||||
SidePanelSubPages.NewSidebarItemViewSystemPicker,
|
||||
)
|
||||
}
|
||||
onSelectObject={handleSelectObject}
|
||||
showSystemObjectsOption={
|
||||
availableSystemObjectMetadataItemsForView.length > 0
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
+4
-8
@@ -1,21 +1,20 @@
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { IconSettings, useIcons } from 'twenty-ui/display';
|
||||
|
||||
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
||||
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
|
||||
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
||||
import { SidePanelSubViewWithSearch } from '@/side-panel/components/SidePanelSubViewWithSearch';
|
||||
import { useSidePanelFilteredPickerItems } from '@/side-panel/hooks/useSidePanelFilteredPickerItems';
|
||||
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
|
||||
import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStandardObjectIconColor';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
||||
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
||||
import { SidePanelSubViewWithSearch } from '@/side-panel/components/SidePanelSubViewWithSearch';
|
||||
import { useSidePanelFilteredPickerItems } from '@/side-panel/hooks/useSidePanelFilteredPickerItems';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
|
||||
type SidePanelNewSidebarItemViewObjectPickerSubViewProps = {
|
||||
objects: ObjectMetadataItem[];
|
||||
searchValue: string;
|
||||
onSearchChange: (value: string) => void;
|
||||
onBack: () => void;
|
||||
onOpenSystemPicker: () => void;
|
||||
onSelectObject: (objectMetadataItem: ObjectMetadataItem) => void;
|
||||
showSystemObjectsOption?: boolean;
|
||||
@@ -25,7 +24,6 @@ export const SidePanelNewSidebarItemViewObjectPickerSubView = ({
|
||||
objects,
|
||||
searchValue,
|
||||
onSearchChange,
|
||||
onBack,
|
||||
onOpenSystemPicker,
|
||||
onSelectObject,
|
||||
showSystemObjectsOption = true,
|
||||
@@ -45,8 +43,6 @@ export const SidePanelNewSidebarItemViewObjectPickerSubView = ({
|
||||
|
||||
return (
|
||||
<SidePanelSubViewWithSearch
|
||||
backBarTitle={t`Pick an object`}
|
||||
onBack={onBack}
|
||||
searchPlaceholder={t`Search an object...`}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={onSearchChange}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import { SidePanelNewSidebarItemViewPickerSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemViewPickerSubView';
|
||||
import { selectedObjectMetadataIdForViewFlowState } from '@/side-panel/states/selectedObjectMetadataIdForViewFlowState';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SidePanelNewSidebarItemViewPickerSubPage = () => {
|
||||
const selectedObjectMetadataIdForViewFlow = useAtomComponentStateValue(
|
||||
selectedObjectMetadataIdForViewFlowState,
|
||||
);
|
||||
|
||||
if (!isDefined(selectedObjectMetadataIdForViewFlow)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<SidePanelNewSidebarItemViewPickerSubView
|
||||
selectedObjectMetadataIdForView={selectedObjectMetadataIdForViewFlow}
|
||||
/>
|
||||
);
|
||||
};
|
||||
-6
@@ -27,12 +27,10 @@ import { ViewVisibility } from '~/generated-metadata/graphql';
|
||||
|
||||
type SidePanelNewSidebarItemViewPickerSubViewProps = {
|
||||
selectedObjectMetadataIdForView: string;
|
||||
onBack: () => void;
|
||||
};
|
||||
|
||||
export const SidePanelNewSidebarItemViewPickerSubView = ({
|
||||
selectedObjectMetadataIdForView,
|
||||
onBack,
|
||||
}: SidePanelNewSidebarItemViewPickerSubViewProps) => {
|
||||
const { t } = useLingui();
|
||||
const { getIcon } = useIcons();
|
||||
@@ -63,8 +61,6 @@ export const SidePanelNewSidebarItemViewPickerSubView = ({
|
||||
const selectedObjectMetadataItem = objectMetadataItems.find(
|
||||
(item) => item.id === selectedObjectMetadataIdForView,
|
||||
);
|
||||
const backBarTitle =
|
||||
selectedObjectMetadataItem?.labelPlural ?? t`Pick a view`;
|
||||
|
||||
const {
|
||||
filteredItems: filteredViews,
|
||||
@@ -102,8 +98,6 @@ export const SidePanelNewSidebarItemViewPickerSubView = ({
|
||||
|
||||
return (
|
||||
<SidePanelSubViewWithSearch
|
||||
backBarTitle={backBarTitle}
|
||||
onBack={onBack}
|
||||
searchPlaceholder={t`Search a view...`}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={setSearchValue}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
import { useDraftNavigationMenuItems } from '@/navigation-menu-item/hooks/useDraftNavigationMenuItems';
|
||||
import { useNavigationMenuObjectMetadataFromDraft } from '@/navigation-menu-item/hooks/useNavigationMenuObjectMetadataFromDraft';
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useSidePanelSubPageHistory } from '@/side-panel/hooks/useSidePanelSubPageHistory';
|
||||
import { SidePanelNewSidebarItemViewSystemSubView } from '@/side-panel/pages/navigation-menu-item/components/SidePanelNewSidebarItemViewSystemSubView';
|
||||
import { getAvailableObjectMetadataForNewSidebarItem } from '@/side-panel/pages/navigation-menu-item/utils/getAvailableObjectMetadataForNewSidebarItem';
|
||||
import { selectedObjectMetadataIdForViewFlowState } from '@/side-panel/states/selectedObjectMetadataIdForViewFlowState';
|
||||
import { SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { useState } from 'react';
|
||||
|
||||
export const SidePanelNewSidebarItemViewSystemPickerSubPage = () => {
|
||||
const { navigateToSidePanelSubPage } = useSidePanelSubPageHistory();
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const setSelectedObjectMetadataIdForViewFlow = useSetAtomComponentState(
|
||||
selectedObjectMetadataIdForViewFlowState,
|
||||
);
|
||||
|
||||
const { currentDraft } = useDraftNavigationMenuItems();
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
const { activeNonSystemObjectMetadataItems } =
|
||||
useFilteredObjectMetadataItems();
|
||||
const { views, objectMetadataIdsWithIndexView } =
|
||||
useNavigationMenuObjectMetadataFromDraft(currentDraft);
|
||||
|
||||
const objectMetadataIdsWithDisplayableViews = new Set(
|
||||
views
|
||||
.filter(
|
||||
(view) =>
|
||||
view.key !== ViewKey.Index && view.type !== ViewType.FieldsWidget,
|
||||
)
|
||||
.map((view) => view.objectMetadataId),
|
||||
);
|
||||
|
||||
const { availableSystemObjectMetadataItemsForView } =
|
||||
getAvailableObjectMetadataForNewSidebarItem({
|
||||
objectMetadataItems,
|
||||
activeNonSystemObjectMetadataItems,
|
||||
objectMetadataIdsWithIndexView,
|
||||
objectMetadataIdsWithDisplayableViews,
|
||||
});
|
||||
|
||||
const handleSelectObject = (objectMetadataItem: ObjectMetadataItem) => {
|
||||
setSelectedObjectMetadataIdForViewFlow(objectMetadataItem.id);
|
||||
navigateToSidePanelSubPage(
|
||||
SidePanelSubPages.NewSidebarItemViewPicker,
|
||||
objectMetadataItem.labelPlural,
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<SidePanelNewSidebarItemViewSystemSubView
|
||||
systemObjects={availableSystemObjectMetadataItemsForView}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={setSearchValue}
|
||||
onSelectObject={handleSelectObject}
|
||||
/>
|
||||
);
|
||||
};
|
||||
+4
-8
@@ -1,21 +1,20 @@
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
|
||||
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
||||
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
|
||||
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
||||
import { SidePanelSubViewWithSearch } from '@/side-panel/components/SidePanelSubViewWithSearch';
|
||||
import { useSidePanelFilteredPickerItems } from '@/side-panel/hooks/useSidePanelFilteredPickerItems';
|
||||
import { NavigationMenuItemStyleIcon } from '@/navigation-menu-item/components/NavigationMenuItemStyleIcon';
|
||||
import { getStandardObjectIconColor } from '@/navigation-menu-item/utils/getStandardObjectIconColor';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
||||
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
||||
import { SidePanelSubViewWithSearch } from '@/side-panel/components/SidePanelSubViewWithSearch';
|
||||
import { useSidePanelFilteredPickerItems } from '@/side-panel/hooks/useSidePanelFilteredPickerItems';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
|
||||
type SidePanelNewSidebarItemViewSystemSubViewProps = {
|
||||
systemObjects: ObjectMetadataItem[];
|
||||
searchValue: string;
|
||||
onSearchChange: (value: string) => void;
|
||||
onBack: () => void;
|
||||
onSelectObject: (objectMetadataItem: ObjectMetadataItem) => void;
|
||||
};
|
||||
|
||||
@@ -23,7 +22,6 @@ export const SidePanelNewSidebarItemViewSystemSubView = ({
|
||||
systemObjects,
|
||||
searchValue,
|
||||
onSearchChange,
|
||||
onBack,
|
||||
onSelectObject,
|
||||
}: SidePanelNewSidebarItemViewSystemSubViewProps) => {
|
||||
const { t } = useLingui();
|
||||
@@ -44,8 +42,6 @@ export const SidePanelNewSidebarItemViewSystemSubView = ({
|
||||
|
||||
return (
|
||||
<SidePanelSubViewWithSearch
|
||||
backBarTitle={t`System objects`}
|
||||
onBack={onBack}
|
||||
searchPlaceholder={t`Search a system object...`}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={onSearchChange}
|
||||
|
||||
-4
@@ -16,7 +16,6 @@ type SidePanelObjectPickerSubViewProps = {
|
||||
objects: ObjectMetadataItem[];
|
||||
searchValue: string;
|
||||
onSearchChange: (value: string) => void;
|
||||
onBack: () => void;
|
||||
onOpenSystemPicker: () => void;
|
||||
isViewItem: boolean;
|
||||
onSelectObjectForViewEdit?: (objectMetadataItem: ObjectMetadataItem) => void;
|
||||
@@ -33,7 +32,6 @@ export const SidePanelObjectPickerSubView = ({
|
||||
objects,
|
||||
searchValue,
|
||||
onSearchChange,
|
||||
onBack,
|
||||
onOpenSystemPicker,
|
||||
isViewItem,
|
||||
onSelectObjectForViewEdit,
|
||||
@@ -85,8 +83,6 @@ export const SidePanelObjectPickerSubView = ({
|
||||
|
||||
return (
|
||||
<SidePanelSubViewWithSearch
|
||||
backBarTitle={t`Pick an object`}
|
||||
onBack={onBack}
|
||||
searchPlaceholder={t`Search an object...`}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={onSearchChange}
|
||||
|
||||
-4
@@ -12,7 +12,6 @@ type SidePanelSystemObjectPickerSubViewProps = {
|
||||
systemObjects: ObjectMetadataItem[];
|
||||
searchValue: string;
|
||||
onSearchChange: (value: string) => void;
|
||||
onBack: () => void;
|
||||
isViewItem: boolean;
|
||||
onSelectObjectForViewEdit?: (objectMetadataItem: ObjectMetadataItem) => void;
|
||||
onChangeObject: (
|
||||
@@ -28,7 +27,6 @@ export const SidePanelSystemObjectPickerSubView = ({
|
||||
systemObjects,
|
||||
searchValue,
|
||||
onSearchChange,
|
||||
onBack,
|
||||
isViewItem,
|
||||
onSelectObjectForViewEdit,
|
||||
onChangeObject,
|
||||
@@ -69,8 +67,6 @@ export const SidePanelSystemObjectPickerSubView = ({
|
||||
|
||||
return (
|
||||
<SidePanelSubViewWithSearch
|
||||
backBarTitle={t`System objects`}
|
||||
onBack={onBack}
|
||||
searchPlaceholder={t`Search a system object...`}
|
||||
searchValue={searchValue}
|
||||
onSearchChange={onSearchChange}
|
||||
|
||||
+4
-11
@@ -1,13 +1,13 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
|
||||
import { useDraftNavigationMenuItemsAllFolders } from '@/navigation-menu-item/hooks/useDraftNavigationMenuItemsAllFolders';
|
||||
import { useDraftNavigationMenuItemsWorkspaceFolders } from '@/navigation-menu-item/hooks/useDraftNavigationMenuItemsWorkspaceFolders';
|
||||
import { useSelectedNavigationMenuItemEditItem } from '@/navigation-menu-item/hooks/useSelectedNavigationMenuItemEditItem';
|
||||
import { useNavigationMenuItemMoveRemove } from '@/navigation-menu-item/hooks/useNavigationMenuItemMoveRemove';
|
||||
import { useSelectedNavigationMenuItemEditItem } from '@/navigation-menu-item/hooks/useSelectedNavigationMenuItemEditItem';
|
||||
import { selectedNavigationMenuItemInEditModeState } from '@/navigation-menu-item/states/selectedNavigationMenuItemInEditModeState';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { NavigationMenuItemType } from '@/navigation-menu-item/constants/NavigationMenuItemType';
|
||||
|
||||
type FolderOption = {
|
||||
id: string;
|
||||
@@ -38,13 +38,7 @@ const excludeCurrentFolder = <T extends { id: string }>(
|
||||
? folders
|
||||
: folders.filter((folder) => folder.id !== currentFolderId);
|
||||
|
||||
type UseFolderPickerSelectionDataParams = {
|
||||
onCloseSubView: () => void;
|
||||
};
|
||||
|
||||
export const useFolderPickerSelectionData = ({
|
||||
onCloseSubView,
|
||||
}: UseFolderPickerSelectionDataParams) => {
|
||||
export const useFolderPickerSelectionData = () => {
|
||||
const { closeSidePanelMenu } = useSidePanelMenu();
|
||||
const { moveToFolder } = useNavigationMenuItemMoveRemove();
|
||||
const selectedNavigationMenuItemInEditMode = useAtomStateValue(
|
||||
@@ -94,7 +88,6 @@ export const useFolderPickerSelectionData = ({
|
||||
const handleSelectFolder = (folderId: string | null) => {
|
||||
if (isDefined(selectedNavigationMenuItemInEditMode)) {
|
||||
moveToFolder(selectedNavigationMenuItemInEditMode, folderId);
|
||||
onCloseSubView();
|
||||
closeSidePanelMenu();
|
||||
}
|
||||
};
|
||||
|
||||
+20
-30
@@ -1,5 +1,3 @@
|
||||
import { useSidePanelHistory } from '@/side-panel/hooks/useSidePanelHistory';
|
||||
import { SidePanelSubPageNavigationHeader } from '@/side-panel/pages/common/components/SidePanelSubPageNavigationHeader';
|
||||
import { ChartFiltersSettingsInitializeStateEffect } from '@/side-panel/pages/page-layout/components/ChartFiltersSettingsInitializeStateEffect';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/side-panel/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useUpdateCurrentWidgetConfig } from '@/side-panel/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||
@@ -15,9 +13,9 @@ import { RecordFiltersComponentInstanceContext } from '@/object-record/record-fi
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { InputLabel } from '@/ui/input/components/InputLabel';
|
||||
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
||||
import { useStore } from 'jotai';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useStore } from 'jotai';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledChartFiltersPageContainer = styled.div`
|
||||
@@ -38,8 +36,6 @@ export const ChartFiltersSettings = ({
|
||||
objectMetadataItem,
|
||||
widget,
|
||||
}: ChartFiltersSettingsProps) => {
|
||||
const { goBackFromSidePanel } = useSidePanelHistory();
|
||||
|
||||
const { instanceId } = getChartFiltersSettingsInstanceId({
|
||||
widgetId: widget.id,
|
||||
objectMetadataItemId: objectMetadataItem.id,
|
||||
@@ -79,32 +75,26 @@ export const ChartFiltersSettings = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SidePanelSubPageNavigationHeader
|
||||
title={t`Filter`}
|
||||
onBackClick={goBackFromSidePanel}
|
||||
/>
|
||||
<StyledChartFiltersPageContainer>
|
||||
<div>
|
||||
<InputLabel>{t`Conditions`}</InputLabel>
|
||||
<RecordFilterGroupsComponentInstanceContext.Provider
|
||||
<StyledChartFiltersPageContainer>
|
||||
<div>
|
||||
<InputLabel>{t`Conditions`}</InputLabel>
|
||||
<RecordFilterGroupsComponentInstanceContext.Provider
|
||||
value={{ instanceId }}
|
||||
>
|
||||
<RecordFiltersComponentInstanceContext.Provider
|
||||
value={{ instanceId }}
|
||||
>
|
||||
<RecordFiltersComponentInstanceContext.Provider
|
||||
value={{ instanceId }}
|
||||
>
|
||||
<AdvancedFilterSidePanelContainer
|
||||
onUpdate={handleFiltersUpdate}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
isWorkflowFindRecords={false}
|
||||
/>
|
||||
<ChartFiltersSettingsInitializeStateEffect
|
||||
initialChartFilters={chartWidgetConfiguration.filter}
|
||||
/>
|
||||
</RecordFiltersComponentInstanceContext.Provider>
|
||||
</RecordFilterGroupsComponentInstanceContext.Provider>
|
||||
</div>
|
||||
</StyledChartFiltersPageContainer>
|
||||
</>
|
||||
<AdvancedFilterSidePanelContainer
|
||||
onUpdate={handleFiltersUpdate}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
isWorkflowFindRecords={false}
|
||||
/>
|
||||
<ChartFiltersSettingsInitializeStateEffect
|
||||
initialChartFilters={chartWidgetConfiguration.filter}
|
||||
/>
|
||||
</RecordFiltersComponentInstanceContext.Provider>
|
||||
</RecordFilterGroupsComponentInstanceContext.Provider>
|
||||
</div>
|
||||
</StyledChartFiltersPageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
+12
-15
@@ -1,14 +1,14 @@
|
||||
import { ChartFiltersSettings } from '@/side-panel/pages/page-layout/components/ChartFiltersSettings';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/side-panel/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { isChartWidget } from '@/side-panel/pages/page-layout/utils/isChartWidget';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
|
||||
import { ChartFiltersSettings } from '@/side-panel/pages/page-layout/components/ChartFiltersSettings';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/side-panel/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { isChartWidget } from '@/side-panel/pages/page-layout/utils/isChartWidget';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SidePanelPageLayoutGraphFilter = () => {
|
||||
export const SidePanelChartFilterSubPage = () => {
|
||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
||||
|
||||
const pageLayoutDraft = useAtomComponentStateValue(
|
||||
@@ -29,29 +29,26 @@ export const SidePanelPageLayoutGraphFilter = () => {
|
||||
|
||||
if (
|
||||
!isDefined(widgetInEditMode) ||
|
||||
!isDefined(widgetInEditMode.objectMetadataId) ||
|
||||
!isChartWidget(widgetInEditMode)
|
||||
!isChartWidget(widgetInEditMode) ||
|
||||
!isDefined(widgetInEditMode.objectMetadataId)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.id === widgetInEditMode?.objectMetadataId,
|
||||
(item) => item.id === widgetInEditMode.objectMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(objectMetadataItem)) {
|
||||
throw new Error(
|
||||
`Object metadata item not found for id ${widgetInEditMode?.objectMetadataId}`,
|
||||
`Object metadata item not found for id ${widgetInEditMode.objectMetadataId}`,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ChartFiltersSettings
|
||||
widget={widgetInEditMode}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
/>
|
||||
</>
|
||||
<ChartFiltersSettings
|
||||
widget={widgetInEditMode}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
/>
|
||||
);
|
||||
};
|
||||
+16
-33
@@ -1,26 +1,17 @@
|
||||
import { useSidePanelHistory } from '@/side-panel/hooks/useSidePanelHistory';
|
||||
import { SidePanelSubPageNavigationHeader } from '@/side-panel/pages/common/components/SidePanelSubPageNavigationHeader';
|
||||
import { usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord } from '@/side-panel/pages/page-layout/hooks/usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord';
|
||||
import { useWidgetInEditMode } from '@/side-panel/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { useTemporaryFieldsConfiguration } from '@/page-layout/hooks/useTemporaryFieldsConfiguration';
|
||||
import { FieldsConfigurationEditor } from '@/page-layout/widgets/fields/components/FieldsConfigurationEditor';
|
||||
import { FieldsWidgetGroupsDraftInitializationEffect } from '@/page-layout/widgets/fields/components/FieldsWidgetGroupsDraftInitializationEffect';
|
||||
import { usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord } from '@/side-panel/pages/page-layout/hooks/usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord';
|
||||
import { useWidgetInEditMode } from '@/side-panel/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import {
|
||||
type FieldsConfiguration,
|
||||
WidgetConfigurationType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledOuterContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
const StyledFieldsLayoutContainer = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
@@ -29,9 +20,7 @@ const StyledContainer = styled.div`
|
||||
padding: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
export const SidePanelPageLayoutFieldsLayout = () => {
|
||||
const { goBackFromSidePanel } = useSidePanelHistory();
|
||||
|
||||
export const SidePanelFieldsLayoutSubPage = () => {
|
||||
const { pageLayoutId } =
|
||||
usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord();
|
||||
|
||||
@@ -44,29 +33,23 @@ export const SidePanelPageLayoutFieldsLayout = () => {
|
||||
|
||||
const widgetConfiguration = widgetInEditMode.configuration;
|
||||
|
||||
const fieldsConfiguration: FieldsConfiguration =
|
||||
const resolvedFieldsConfiguration: FieldsConfiguration =
|
||||
isDefined(widgetConfiguration) &&
|
||||
widgetConfiguration.configurationType === WidgetConfigurationType.FIELDS
|
||||
? (widgetConfiguration as FieldsConfiguration)
|
||||
: temporaryFieldsConfiguration;
|
||||
|
||||
return (
|
||||
<StyledOuterContainer>
|
||||
<SidePanelSubPageNavigationHeader
|
||||
title={t`Layout`}
|
||||
onBackClick={goBackFromSidePanel}
|
||||
<StyledFieldsLayoutContainer>
|
||||
<FieldsWidgetGroupsDraftInitializationEffect
|
||||
viewId={resolvedFieldsConfiguration.viewId ?? null}
|
||||
pageLayoutId={pageLayoutId}
|
||||
widgetId={widgetInEditMode.id}
|
||||
/>
|
||||
<StyledContainer>
|
||||
<FieldsWidgetGroupsDraftInitializationEffect
|
||||
viewId={fieldsConfiguration.viewId ?? null}
|
||||
pageLayoutId={pageLayoutId}
|
||||
widgetId={widgetInEditMode.id}
|
||||
/>
|
||||
<FieldsConfigurationEditor
|
||||
pageLayoutId={pageLayoutId}
|
||||
widgetId={widgetInEditMode.id}
|
||||
/>
|
||||
</StyledContainer>
|
||||
</StyledOuterContainer>
|
||||
<FieldsConfigurationEditor
|
||||
pageLayoutId={pageLayoutId}
|
||||
widgetId={widgetInEditMode.id}
|
||||
/>
|
||||
</StyledFieldsLayoutContainer>
|
||||
);
|
||||
};
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
|
||||
import { WidgetComponentInstanceContext } from '@/page-layout/widgets/states/contexts/WidgetComponentInstanceContext';
|
||||
import { ChartSettings } from '@/side-panel/pages/page-layout/components/ChartSettings';
|
||||
import { WidgetSettingsFooter } from '@/side-panel/pages/page-layout/components/WidgetSettingsFooter';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/side-panel/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { isChartWidget } from '@/side-panel/pages/page-layout/utils/isChartWidget';
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
|
||||
import { WidgetComponentInstanceContext } from '@/page-layout/widgets/states/contexts/WidgetComponentInstanceContext';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { styled } from '@linaria/react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
+4
-6
@@ -3,16 +3,16 @@ import { CommandMenuItemToggle } from '@/command-menu/components/CommandMenuItem
|
||||
import { useFieldsWidgetGroups } from '@/page-layout/widgets/fields/hooks/useFieldsWidgetGroups';
|
||||
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
|
||||
import { SidePanelList } from '@/side-panel/components/SidePanelList';
|
||||
import { useSidePanelSubPageHistory } from '@/side-panel/hooks/useSidePanelSubPageHistory';
|
||||
import { NewFieldDefaultVisibilityToggle } from '@/side-panel/pages/page-layout/components/NewFieldDefaultVisibilityToggle';
|
||||
import { WidgetSettingsFooter } from '@/side-panel/pages/page-layout/components/WidgetSettingsFooter';
|
||||
import { useNavigatePageLayoutSidePanel } from '@/side-panel/pages/page-layout/hooks/useNavigatePageLayoutSidePanel';
|
||||
import { usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord } from '@/side-panel/pages/page-layout/hooks/usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord';
|
||||
import { useUpdateCurrentWidgetConfig } from '@/side-panel/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||
import { useWidgetInEditMode } from '@/side-panel/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { SidePanelPages } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IconChevronDown, IconLayoutSidebarRight } from 'twenty-ui/display';
|
||||
import { type FieldsConfiguration } from '~/generated-metadata/graphql';
|
||||
@@ -32,7 +32,7 @@ const StyledSidePanelContainer = styled.div`
|
||||
|
||||
export const SidePanelPageLayoutFieldsSettings = () => {
|
||||
const { t } = useLingui();
|
||||
const { navigatePageLayoutSidePanel } = useNavigatePageLayoutSidePanel();
|
||||
const { navigateToSidePanelSubPage } = useSidePanelSubPageHistory();
|
||||
const { pageLayoutId, objectNameSingular } =
|
||||
usePageLayoutIdForRecordPageLayoutFromContextStoreTargetedRecord();
|
||||
|
||||
@@ -60,9 +60,7 @@ export const SidePanelPageLayoutFieldsSettings = () => {
|
||||
);
|
||||
|
||||
const handleNavigateToLayout = () => {
|
||||
navigatePageLayoutSidePanel({
|
||||
sidePanelPage: SidePanelPages.PageLayoutFieldsLayout,
|
||||
});
|
||||
navigateToSidePanelSubPage(SidePanelSubPages.PageLayoutFieldsLayout);
|
||||
};
|
||||
|
||||
const isShouldAllowUserToSeeHiddenFieldsToggled =
|
||||
|
||||
+4
-6
@@ -4,8 +4,8 @@ import { CommandMenuItemNumberInput } from '@/command-menu/components/CommandMen
|
||||
import { CommandMenuItemTextInput } from '@/command-menu/components/CommandMenuItemTextInput';
|
||||
import { CommandMenuItemToggle } from '@/command-menu/components/CommandMenuItemToggle';
|
||||
import { SIDE_PANEL_SELECTABLE_LIST_ID } from '@/side-panel/constants/SidePanelSelectableListId';
|
||||
import { useSidePanelSubPageHistory } from '@/side-panel/hooks/useSidePanelSubPageHistory';
|
||||
import { useChartSettingsValues } from '@/side-panel/pages/page-layout/hooks/useChartSettingsValues';
|
||||
import { useNavigatePageLayoutSidePanel } from '@/side-panel/pages/page-layout/hooks/useNavigatePageLayoutSidePanel';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/side-panel/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useUpdateChartSettingInput } from '@/side-panel/pages/page-layout/hooks/useUpdateChartSettingInput';
|
||||
import { useUpdateChartSettingTextInput } from '@/side-panel/pages/page-layout/hooks/useUpdateChartSettingTextInput';
|
||||
@@ -14,6 +14,7 @@ import { type ChartConfiguration } from '@/side-panel/pages/page-layout/types/Ch
|
||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/side-panel/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { type ChartSettingsItem } from '@/side-panel/pages/page-layout/types/ChartSettingsGroup';
|
||||
import { isMinMaxRangeValid } from '@/side-panel/pages/page-layout/utils/isMinMaxRangeValid';
|
||||
import { SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { useCloseAnyOpenDropdown } from '@/ui/layout/dropdown/hooks/useCloseAnyOpenDropdown';
|
||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
@@ -21,7 +22,6 @@ import { SelectableListItem } from '@/ui/layout/selectable-list/components/Selec
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isString } from '@sniptt/guards';
|
||||
import { SidePanelPages } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type ChartSettingItemProps = {
|
||||
@@ -41,7 +41,7 @@ export const ChartSettingItem = ({
|
||||
const { setSelectedItemId } = useSelectableList(
|
||||
SIDE_PANEL_SELECTABLE_LIST_ID,
|
||||
);
|
||||
const { navigatePageLayoutSidePanel } = useNavigatePageLayoutSidePanel();
|
||||
const { navigateToSidePanelSubPage } = useSidePanelSubPageHistory();
|
||||
|
||||
const { getChartSettingsValues } = useChartSettingsValues({
|
||||
objectMetadataId,
|
||||
@@ -80,9 +80,7 @@ export const ChartSettingItem = ({
|
||||
};
|
||||
|
||||
const handleFilterClick = () => {
|
||||
navigatePageLayoutSidePanel({
|
||||
sidePanelPage: SidePanelPages.PageLayoutGraphFilter,
|
||||
});
|
||||
navigateToSidePanelSubPage(SidePanelSubPages.PageLayoutGraphFilter);
|
||||
};
|
||||
if (item.id === CHART_CONFIGURATION_SETTING_IDS.FILTER) {
|
||||
const filterValue = getChartSettingsValues(item.id);
|
||||
|
||||
+1
-3
@@ -4,7 +4,5 @@ export type PageLayoutSidePanelPage =
|
||||
| SidePanelPages.PageLayoutWidgetTypeSelect
|
||||
| SidePanelPages.PageLayoutGraphTypeSelect
|
||||
| SidePanelPages.PageLayoutIframeSettings
|
||||
| SidePanelPages.PageLayoutGraphFilter
|
||||
| SidePanelPages.PageLayoutTabSettings
|
||||
| SidePanelPages.PageLayoutFieldsSettings
|
||||
| SidePanelPages.PageLayoutFieldsLayout;
|
||||
| SidePanelPages.PageLayoutFieldsSettings;
|
||||
|
||||
-6
@@ -4,9 +4,7 @@ import { assertUnreachable } from 'twenty-shared/utils';
|
||||
import {
|
||||
IconAppWindow,
|
||||
IconChartPie,
|
||||
IconFilter,
|
||||
IconFrame,
|
||||
IconLayoutSidebarRight,
|
||||
IconList,
|
||||
} from 'twenty-ui/display';
|
||||
|
||||
@@ -18,14 +16,10 @@ export const getPageLayoutIcon = (page: PageLayoutSidePanelPage) => {
|
||||
return IconChartPie;
|
||||
case SidePanelPages.PageLayoutIframeSettings:
|
||||
return IconFrame;
|
||||
case SidePanelPages.PageLayoutGraphFilter:
|
||||
return IconFilter;
|
||||
case SidePanelPages.PageLayoutTabSettings:
|
||||
return IconAppWindow;
|
||||
case SidePanelPages.PageLayoutFieldsSettings:
|
||||
return IconList;
|
||||
case SidePanelPages.PageLayoutFieldsLayout:
|
||||
return IconLayoutSidebarRight;
|
||||
default:
|
||||
assertUnreachable(page);
|
||||
}
|
||||
|
||||
-4
@@ -11,14 +11,10 @@ export const getPageLayoutPageTitle = (page: PageLayoutSidePanelPage) => {
|
||||
return t`Select Graph Type`;
|
||||
case SidePanelPages.PageLayoutIframeSettings:
|
||||
return t`iFrame Settings`;
|
||||
case SidePanelPages.PageLayoutGraphFilter:
|
||||
return t`Configure filters`;
|
||||
case SidePanelPages.PageLayoutTabSettings:
|
||||
return t`Tab Settings`;
|
||||
case SidePanelPages.PageLayoutFieldsSettings:
|
||||
return t`Fields Settings`;
|
||||
case SidePanelPages.PageLayoutFieldsLayout:
|
||||
return t`Layout`;
|
||||
default:
|
||||
assertUnreachable(page);
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { SidePanelPageComponentInstanceContext } from '@/side-panel/states/contexts/SidePanelPageComponentInstanceContext';
|
||||
import { createAtomComponentState } from '@/ui/utilities/state/jotai/utils/createAtomComponentState';
|
||||
|
||||
export const selectedObjectMetadataIdForViewFlowState =
|
||||
createAtomComponentState<string | null>({
|
||||
key: 'side-panel/selected-object-metadata-id-for-view-flow',
|
||||
defaultValue: null,
|
||||
componentInstanceContext: SidePanelPageComponentInstanceContext,
|
||||
});
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { SidePanelPageComponentInstanceContext } from '@/side-panel/states/contexts/SidePanelPageComponentInstanceContext';
|
||||
import { type SidePanelSubPageEntry } from '@/side-panel/types/SidePanelSubPageEntry';
|
||||
import { createAtomComponentState } from '@/ui/utilities/state/jotai/utils/createAtomComponentState';
|
||||
|
||||
export const sidePanelSubPageStackComponentState = createAtomComponentState<
|
||||
SidePanelSubPageEntry[]
|
||||
>({
|
||||
key: 'side-panel/sub-page-stack',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: SidePanelPageComponentInstanceContext,
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
import { type SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
|
||||
export type SidePanelSubPageEntry = {
|
||||
id: string;
|
||||
subPage: SidePanelSubPages;
|
||||
title: string;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
export enum SidePanelSubPages {
|
||||
PageLayoutGraphFilter = 'page-layout-graph-filter',
|
||||
PageLayoutFieldsLayout = 'page-layout-fields-layout',
|
||||
NewSidebarItemViewObjectPicker = 'new-sidebar-item-view-object-picker',
|
||||
NewSidebarItemViewPicker = 'new-sidebar-item-view-picker',
|
||||
NewSidebarItemViewSystemPicker = 'new-sidebar-item-view-system-picker',
|
||||
NewSidebarItemObjectPicker = 'new-sidebar-item-object-picker',
|
||||
NewSidebarItemObjectSystemPicker = 'new-sidebar-item-object-system-picker',
|
||||
NewSidebarItemRecord = 'new-sidebar-item-record',
|
||||
EditFolderPicker = 'edit-folder-picker',
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { SidePanelSubPages } from '@/side-panel/types/SidePanelSubPages';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { assertUnreachable } from 'twenty-shared/utils';
|
||||
|
||||
export const getSidePanelSubPageTitle = (
|
||||
subPage: SidePanelSubPages,
|
||||
): string => {
|
||||
switch (subPage) {
|
||||
case SidePanelSubPages.PageLayoutGraphFilter:
|
||||
return t`Filters`;
|
||||
case SidePanelSubPages.PageLayoutFieldsLayout:
|
||||
return t`Layout`;
|
||||
case SidePanelSubPages.NewSidebarItemViewObjectPicker:
|
||||
return t`Pick an object`;
|
||||
case SidePanelSubPages.NewSidebarItemViewPicker:
|
||||
return t`Pick a view`;
|
||||
case SidePanelSubPages.NewSidebarItemViewSystemPicker:
|
||||
return t`System objects`;
|
||||
case SidePanelSubPages.NewSidebarItemObjectPicker:
|
||||
return t`Pick an object`;
|
||||
case SidePanelSubPages.NewSidebarItemObjectSystemPicker:
|
||||
return t`System objects`;
|
||||
case SidePanelSubPages.NewSidebarItemRecord:
|
||||
return t`Add a record`;
|
||||
case SidePanelSubPages.EditFolderPicker:
|
||||
return t`Move to a folder`;
|
||||
default:
|
||||
assertUnreachable(subPage);
|
||||
}
|
||||
};
|
||||
@@ -18,11 +18,9 @@ export enum SidePanelPages {
|
||||
ViewPreviousAIChats = 'view-previous-ai-chats',
|
||||
PageLayoutWidgetTypeSelect = 'page-layout-widget-type-select',
|
||||
PageLayoutGraphTypeSelect = 'page-layout-graph-type-select',
|
||||
PageLayoutGraphFilter = 'page-layout-graph-filter',
|
||||
PageLayoutIframeSettings = 'page-layout-iframe-settings',
|
||||
PageLayoutTabSettings = 'page-layout-tab-settings',
|
||||
PageLayoutFieldsSettings = 'page-layout-fields-settings',
|
||||
PageLayoutFieldsLayout = 'page-layout-fields-layout',
|
||||
ViewFrontComponent = 'view-front-component',
|
||||
NavigationMenuItemEdit = 'navigation-menu-item-edit',
|
||||
NavigationMenuAddItem = 'navigation-menu-add-item',
|
||||
|
||||
Reference in New Issue
Block a user