Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dae999ca8d | |||
| 83162b1b80 | |||
| 5485343c05 | |||
| e8994eb0bb | |||
| c9b118baaa | |||
| 284d4124ff | |||
| 21deebad34 | |||
| b2957d9a29 |
@@ -1,14 +1,29 @@
|
||||
import { PageContentSkeletonLoader } from '~/loading/components/PageContentSkeletonLoader';
|
||||
import { RecordIndexSkeletonLoader } from '@/object-record/record-index/components/RecordIndexSkeletonLoader';
|
||||
import { SettingsSkeletonLoader } from '@/settings/components/SettingsSkeletonLoader';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { AppPath } from 'twenty-shared/types';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { isMatchingLocation } from '~/utils/isMatchingLocation';
|
||||
|
||||
const StyledRightPanelContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: ${themeCssVariables.spacing[2]};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const RightPanelSkeletonLoader = () => (
|
||||
<StyledRightPanelContainer>
|
||||
<PageContentSkeletonLoader />
|
||||
</StyledRightPanelContainer>
|
||||
);
|
||||
export const RightPanelSkeletonLoader = () => {
|
||||
const location = useLocation();
|
||||
const isSettingsPage = isMatchingLocation(location, AppPath.SettingsCatchAll);
|
||||
|
||||
return (
|
||||
<StyledRightPanelContainer>
|
||||
{isSettingsPage ? (
|
||||
<SettingsSkeletonLoader />
|
||||
) : (
|
||||
<RecordIndexSkeletonLoader />
|
||||
)}
|
||||
</StyledRightPanelContainer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ import { VerifyEmailEffect } from '@/auth/components/VerifyEmailEffect';
|
||||
import indexAppPath from '@/navigation/utils/indexAppPath';
|
||||
import { BlankLayout } from '@/ui/layout/page/components/BlankLayout';
|
||||
import { DefaultLayout } from '@/ui/layout/page/components/DefaultLayout';
|
||||
import { MainAppLayoutWithSidePanel } from '@/ui/layout/page/components/MainAppLayoutWithSidePanel';
|
||||
import { AppPath } from 'twenty-shared/types';
|
||||
|
||||
import { lazy } from 'react';
|
||||
@@ -209,48 +210,50 @@ export const useCreateAppRouter = (
|
||||
</LazyRoute>
|
||||
}
|
||||
/>
|
||||
<Route path={indexAppPath.getIndexAppPath()} element={<></>} />
|
||||
<Route
|
||||
path={AppPath.RecordIndexPage}
|
||||
element={
|
||||
<LazyRoute>
|
||||
<RecordIndexPage />
|
||||
</LazyRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={AppPath.RecordShowPage}
|
||||
element={
|
||||
<LazyRoute>
|
||||
<RecordShowPage />
|
||||
</LazyRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={AppPath.PageLayoutPage}
|
||||
element={
|
||||
<LazyRoute>
|
||||
<StandalonePageLayoutPage />
|
||||
</LazyRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={AppPath.SettingsCatchAll}
|
||||
element={
|
||||
<SettingsRoutes
|
||||
isFunctionSettingsEnabled={isFunctionSettingsEnabled}
|
||||
isAdminPageEnabled={isAdminPageEnabled}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={AppPath.NotFoundWildcard}
|
||||
element={
|
||||
<LazyRoute>
|
||||
<NotFound />
|
||||
</LazyRoute>
|
||||
}
|
||||
/>
|
||||
<Route element={<MainAppLayoutWithSidePanel />}>
|
||||
<Route path={indexAppPath.getIndexAppPath()} element={<></>} />
|
||||
<Route
|
||||
path={AppPath.RecordIndexPage}
|
||||
element={
|
||||
<LazyRoute>
|
||||
<RecordIndexPage />
|
||||
</LazyRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={AppPath.RecordShowPage}
|
||||
element={
|
||||
<LazyRoute>
|
||||
<RecordShowPage />
|
||||
</LazyRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={AppPath.PageLayoutPage}
|
||||
element={
|
||||
<LazyRoute>
|
||||
<StandalonePageLayoutPage />
|
||||
</LazyRoute>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={AppPath.SettingsCatchAll}
|
||||
element={
|
||||
<SettingsRoutes
|
||||
isFunctionSettingsEnabled={isFunctionSettingsEnabled}
|
||||
isAdminPageEnabled={isAdminPageEnabled}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path={AppPath.NotFoundWildcard}
|
||||
element={
|
||||
<LazyRoute>
|
||||
<NotFound />
|
||||
</LazyRoute>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
<Route element={<BlankLayout />}>
|
||||
<Route
|
||||
|
||||
+14
-2
@@ -31,12 +31,14 @@ const StyledPreviewWrapper = styled.div`
|
||||
|
||||
type CommandMenuItemRendererProps = {
|
||||
item: CommandMenuItemFieldsFragment;
|
||||
isPrimaryAction?: boolean;
|
||||
};
|
||||
|
||||
type CommandMenuItemButtonRendererProps = CommandMenuItemRendererProps;
|
||||
|
||||
const CommandMenuItemButtonRenderer = ({
|
||||
item,
|
||||
isPrimaryAction = false,
|
||||
}: CommandMenuItemButtonRendererProps) => {
|
||||
const { commandMenuContextApi, isInPreviewMode } =
|
||||
useContext(CommandMenuContext);
|
||||
@@ -60,7 +62,10 @@ const CommandMenuItemButtonRenderer = ({
|
||||
if (isInPreviewMode) {
|
||||
return (
|
||||
<StyledPreviewWrapper>
|
||||
<CommandMenuButton command={command} />
|
||||
<CommandMenuButton
|
||||
command={command}
|
||||
isPrimaryAction={isPrimaryAction}
|
||||
/>
|
||||
</StyledPreviewWrapper>
|
||||
);
|
||||
}
|
||||
@@ -70,6 +75,7 @@ const CommandMenuItemButtonRenderer = ({
|
||||
command={command}
|
||||
onClick={disabled ? undefined : handleClick}
|
||||
disabled={disabled}
|
||||
isPrimaryAction={isPrimaryAction}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -167,11 +173,17 @@ const CommandMenuItemSelectableRenderer = ({
|
||||
// oxlint-disable-next-line twenty/effect-components
|
||||
export const CommandMenuItemRenderer = ({
|
||||
item,
|
||||
isPrimaryAction,
|
||||
}: CommandMenuItemRendererProps) => {
|
||||
const { displayType } = useContext(CommandMenuContext);
|
||||
|
||||
if (displayType === 'button') {
|
||||
return <CommandMenuItemButtonRenderer item={item} />;
|
||||
return (
|
||||
<CommandMenuItemButtonRenderer
|
||||
item={item}
|
||||
isPrimaryAction={isPrimaryAction}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (displayType === 'listItem' || displayType === 'dropdownItem') {
|
||||
|
||||
+5
-2
@@ -68,7 +68,7 @@ export const PinnedCommandMenuItemButtons = () => {
|
||||
<NodeDimension onDimensionChange={onContainerDimensionChange}>
|
||||
<StyledContainer>
|
||||
<StyledItemsContainer>
|
||||
{pinnedInlineCommandMenuItems.map((item) => (
|
||||
{pinnedInlineCommandMenuItems.map((item, index) => (
|
||||
<StyledCommandMenuItemContainer
|
||||
key={item.id}
|
||||
layout
|
||||
@@ -80,7 +80,10 @@ export const PinnedCommandMenuItemButtons = () => {
|
||||
ease: 'easeInOut',
|
||||
}}
|
||||
>
|
||||
<CommandMenuItemRenderer item={item} />
|
||||
<CommandMenuItemRenderer
|
||||
item={item}
|
||||
isPrimaryAction={index === 0}
|
||||
/>
|
||||
</StyledCommandMenuItemContainer>
|
||||
))}
|
||||
</StyledItemsContainer>
|
||||
|
||||
@@ -28,6 +28,7 @@ export type CommandMenuButtonProps = {
|
||||
onClick?: (event?: MouseEvent<HTMLElement>) => void;
|
||||
to?: string;
|
||||
disabled?: boolean;
|
||||
isPrimaryAction?: boolean;
|
||||
};
|
||||
|
||||
export const CommandMenuButton = ({
|
||||
@@ -35,6 +36,7 @@ export const CommandMenuButton = ({
|
||||
onClick,
|
||||
to,
|
||||
disabled = false,
|
||||
isPrimaryAction = false,
|
||||
}: CommandMenuButtonProps) => {
|
||||
const resolvedLabel = getCommandMenuItemLabel(command.label);
|
||||
|
||||
@@ -50,8 +52,8 @@ export const CommandMenuButton = ({
|
||||
<Button
|
||||
Icon={command.Icon}
|
||||
size="small"
|
||||
variant="secondary"
|
||||
accent={buttonAccent}
|
||||
variant={isPrimaryAction ? 'primary' : 'secondary'}
|
||||
accent={isPrimaryAction ? 'blue' : buttonAccent}
|
||||
to={to}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
@@ -63,8 +65,8 @@ export const CommandMenuButton = ({
|
||||
<IconButton
|
||||
Icon={command.Icon}
|
||||
size="small"
|
||||
variant="secondary"
|
||||
accent={buttonAccent}
|
||||
variant={isPrimaryAction ? 'primary' : 'secondary'}
|
||||
accent={isPrimaryAction ? 'blue' : buttonAccent}
|
||||
to={to}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
|
||||
+2
-11
@@ -1,13 +1,10 @@
|
||||
import { CommandMenuForMobile } from '@/command-menu/components/CommandMenuForMobile';
|
||||
import { SidePanelForDesktop } from '@/side-panel/components/SidePanelForDesktop';
|
||||
import { useCommandMenuHotKeys } from '@/command-menu/hooks/useCommandMenuHotKeys';
|
||||
import { PageBody } from '@/ui/layout/page/components/PageBody';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type ReactNode } from 'react';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type MainContainerLayoutWithSidePanelProps = {
|
||||
type MainContainerLayoutProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
@@ -54,20 +51,15 @@ const StyledPageBodyForMobileContainer = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export const MainContainerLayoutWithSidePanel = ({
|
||||
children,
|
||||
}: MainContainerLayoutWithSidePanelProps) => {
|
||||
export const MainContainerLayout = ({ children }: MainContainerLayoutProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
useCommandMenuHotKeys();
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<StyledMainContainerLayoutForMobile>
|
||||
<StyledPageBodyForMobileContainer>
|
||||
<PageBody>{children}</PageBody>
|
||||
</StyledPageBodyForMobileContainer>
|
||||
<CommandMenuForMobile />
|
||||
</StyledMainContainerLayoutForMobile>
|
||||
);
|
||||
}
|
||||
@@ -77,7 +69,6 @@ export const MainContainerLayoutWithSidePanel = ({
|
||||
<StyledPageBodyForDesktopContainer>
|
||||
<PageBody>{children}</PageBody>
|
||||
</StyledPageBodyForDesktopContainer>
|
||||
<SidePanelForDesktop />
|
||||
</StyledMainContainerLayoutForDesktop>
|
||||
);
|
||||
};
|
||||
+32
-62
@@ -1,21 +1,16 @@
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { ObjectOptionsDropdown } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdown';
|
||||
import { RecordBoardContainer } from '@/object-record/record-board/components/RecordBoardContainer';
|
||||
import { RecordIndexTableContainer } from '@/object-record/record-index/components/RecordIndexTableContainer';
|
||||
import { RecordIndexViewBarEffect } from '@/object-record/record-index/components/RecordIndexViewBarEffect';
|
||||
import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
|
||||
import { InformationBannerWrapper } from '@/information-banner/components/InformationBannerWrapper';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
|
||||
|
||||
import { RecordIndexCalendarContainer } from '@/object-record/record-index/components/RecordIndexCalendarContainer';
|
||||
import { RecordIndexEmptyStateNotShared } from '@/object-record/record-index/components/RecordIndexEmptyStateNotShared';
|
||||
import { RecordIndexFiltersToContextStoreEffect } from '@/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect';
|
||||
import { useHasCurrentViewNonReadableFields } from '@/object-record/record-index/hooks/useHasCurrentViewNonReadableFields';
|
||||
import { ViewBar } from '@/views/components/ViewBar';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
@@ -24,7 +19,6 @@ const StyledContainer = styled.div`
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
@@ -38,67 +32,43 @@ const StyledContainerWithPadding = styled.div`
|
||||
export const RecordIndexContainer = () => {
|
||||
const recordIndexViewType = useAtomStateValue(recordIndexViewTypeState);
|
||||
|
||||
const {
|
||||
objectNamePlural,
|
||||
recordIndexId,
|
||||
objectMetadataItem,
|
||||
objectNameSingular,
|
||||
} = useRecordIndexContextOrThrow();
|
||||
const { recordIndexId, objectMetadataItem, objectNameSingular } =
|
||||
useRecordIndexContextOrThrow();
|
||||
|
||||
const { hasCurrentViewNonReadableFields, nonReadableViewFieldInfo } =
|
||||
useHasCurrentViewNonReadableFields(objectMetadataItem);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledContainer>
|
||||
<InformationBannerWrapper />
|
||||
<SpreadsheetImportProvider>
|
||||
<ViewBar
|
||||
isReadOnly={hasCurrentViewNonReadableFields}
|
||||
viewBarId={recordIndexId}
|
||||
optionsDropdownButton={
|
||||
<ObjectOptionsDropdown
|
||||
recordIndexId={recordIndexId}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
viewType={recordIndexViewType ?? ViewType.TABLE}
|
||||
<StyledContainer>
|
||||
{hasCurrentViewNonReadableFields ? (
|
||||
<RecordIndexEmptyStateNotShared
|
||||
nonReadableViewFieldInfo={nonReadableViewFieldInfo}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<RecordIndexFiltersToContextStoreEffect />
|
||||
{recordIndexViewType === ViewType.TABLE && (
|
||||
<RecordIndexTableContainer recordTableId={recordIndexId} />
|
||||
)}
|
||||
{recordIndexViewType === ViewType.KANBAN && (
|
||||
<StyledContainerWithPadding>
|
||||
<RecordBoardContainer
|
||||
recordBoardId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<RecordIndexViewBarEffect
|
||||
objectNamePlural={objectNamePlural}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
</SpreadsheetImportProvider>
|
||||
{hasCurrentViewNonReadableFields ? (
|
||||
<RecordIndexEmptyStateNotShared
|
||||
nonReadableViewFieldInfo={nonReadableViewFieldInfo}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<RecordIndexFiltersToContextStoreEffect />
|
||||
{recordIndexViewType === ViewType.TABLE && (
|
||||
<RecordIndexTableContainer recordTableId={recordIndexId} />
|
||||
)}
|
||||
{recordIndexViewType === ViewType.KANBAN && (
|
||||
<StyledContainerWithPadding>
|
||||
<RecordBoardContainer
|
||||
recordBoardId={recordIndexId}
|
||||
viewBarId={recordIndexId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
/>
|
||||
</StyledContainerWithPadding>
|
||||
)}
|
||||
{recordIndexViewType === ViewType.CALENDAR && (
|
||||
<StyledContainerWithPadding>
|
||||
<RecordIndexCalendarContainer
|
||||
recordCalendarInstanceId={recordIndexId}
|
||||
viewBarInstanceId={recordIndexId}
|
||||
/>
|
||||
</StyledContainerWithPadding>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</StyledContainer>
|
||||
</>
|
||||
</StyledContainerWithPadding>
|
||||
)}
|
||||
{recordIndexViewType === ViewType.CALENDAR && (
|
||||
<StyledContainerWithPadding>
|
||||
<RecordIndexCalendarContainer
|
||||
recordCalendarInstanceId={recordIndexId}
|
||||
viewBarInstanceId={recordIndexId}
|
||||
/>
|
||||
</StyledContainerWithPadding>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
+9
-4
@@ -3,7 +3,7 @@ import { RecordIndexContextProvider } from '@/object-record/record-index/context
|
||||
import { getCommandMenuIdFromRecordIndexId } from '@/command-menu-item/utils/getCommandMenuIdFromRecordIndexId';
|
||||
import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
|
||||
import { getObjectPermissionsForObject } from '@/object-metadata/utils/getObjectPermissionsForObject';
|
||||
import { MainContainerLayoutWithSidePanel } from '@/object-record/components/MainContainerLayoutWithSidePanel';
|
||||
import { RecordIndexViewBar } from '@/object-record/record-index/components/RecordIndexViewBar';
|
||||
import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { lastShowPageRecordIdState } from '@/object-record/record-field/ui/states/lastShowPageRecordId';
|
||||
@@ -16,6 +16,7 @@ import { useHandleIndexIdentifierClick } from '@/object-record/record-index/hook
|
||||
import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates';
|
||||
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
|
||||
import { RECORD_INDEX_DRAG_SELECT_BOUNDARY_CLASS } from '@/ui/utilities/drag-select/constants/RecordIndecDragSelectBoundaryClass';
|
||||
import { PageCardLayout } from '@/ui/layout/page/components/PageCardLayout';
|
||||
import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { styled } from '@linaria/react';
|
||||
@@ -91,8 +92,12 @@ export const RecordIndexContainerGater = () => {
|
||||
}}
|
||||
>
|
||||
<PageTitle title={objectMetadataItem.labelPlural} />
|
||||
<RecordIndexPageHeader />
|
||||
<MainContainerLayoutWithSidePanel>
|
||||
<PageCardLayout
|
||||
header={<RecordIndexPageHeader />}
|
||||
secondaryBar={
|
||||
hasObjectReadPermissions ? <RecordIndexViewBar /> : undefined
|
||||
}
|
||||
>
|
||||
<StyledIndexContainer
|
||||
className={RECORD_INDEX_DRAG_SELECT_BOUNDARY_CLASS}
|
||||
>
|
||||
@@ -105,7 +110,7 @@ export const RecordIndexContainerGater = () => {
|
||||
<RecordIndexEmptyStateNotShared />
|
||||
)}
|
||||
</StyledIndexContainer>
|
||||
</MainContainerLayoutWithSidePanel>
|
||||
</PageCardLayout>
|
||||
</CommandMenuComponentInstanceContext.Provider>
|
||||
</RecordComponentInstanceContextsWrapper>
|
||||
<RecordIndexLoadBaseOnContextStoreEffect />
|
||||
|
||||
+15
-14
@@ -1,5 +1,4 @@
|
||||
import { RecordIndexCommandMenu } from '@/command-menu-item/components/RecordIndexCommandMenu';
|
||||
import { SidePanelToggleButton } from '@/side-panel/components/SidePanelToggleButton';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
@@ -7,7 +6,8 @@ import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/st
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { RecordIndexPageHeaderIcon } from '@/object-record/record-index/components/RecordIndexPageHeaderIcon';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { PageHeader } from '@/ui/layout/page/components/PageHeader';
|
||||
import { SidePanelToggleButton } from '@/side-panel/components/SidePanelToggleButton';
|
||||
import { PageCardHeader } from '@/ui/layout/page/components/PageCardHeader';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { styled } from '@linaria/react';
|
||||
@@ -68,18 +68,19 @@ export const RecordIndexPageHeader = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<PageHeader
|
||||
title={pageHeaderTitle}
|
||||
Icon={() => (
|
||||
<PageCardHeader
|
||||
icon={
|
||||
<RecordIndexPageHeaderIcon objectMetadataItem={objectMetadataItem} />
|
||||
)}
|
||||
>
|
||||
{isDefined(contextStoreCurrentViewId) && (
|
||||
<>
|
||||
<RecordIndexCommandMenu />
|
||||
{!isLayoutCustomizationModeEnabled && <SidePanelToggleButton />}
|
||||
</>
|
||||
)}
|
||||
</PageHeader>
|
||||
}
|
||||
title={pageHeaderTitle}
|
||||
actionButton={
|
||||
isDefined(contextStoreCurrentViewId) ? (
|
||||
<>
|
||||
<RecordIndexCommandMenu />
|
||||
{!isLayoutCustomizationModeEnabled && <SidePanelToggleButton />}
|
||||
</>
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
+76
-7
@@ -1,8 +1,77 @@
|
||||
import { PageContainer } from '@/ui/layout/page/components/PageContainer';
|
||||
import { PageContentSkeletonLoader } from '~/loading/components/PageContentSkeletonLoader';
|
||||
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
|
||||
import { PageCardHeader } from '@/ui/layout/page/components/PageCardHeader';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useContext } from 'react';
|
||||
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
export const RecordIndexSkeletonLoader = () => (
|
||||
<PageContainer>
|
||||
<PageContentSkeletonLoader />
|
||||
</PageContainer>
|
||||
);
|
||||
const StyledCard = styled.div`
|
||||
background: ${themeCssVariables.background.primary};
|
||||
border: 1px solid ${themeCssVariables.border.color.medium};
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledSecondaryBar = styled.div`
|
||||
align-items: center;
|
||||
border-bottom: 1px solid ${themeCssVariables.border.color.light};
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: space-between;
|
||||
min-height: ${themeCssVariables.spacing[10]};
|
||||
padding: 0 ${themeCssVariables.spacing[3]};
|
||||
`;
|
||||
|
||||
const StyledBody = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
padding: ${themeCssVariables.spacing[3]};
|
||||
`;
|
||||
|
||||
export const RecordIndexSkeletonLoader = () => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
<StyledCard>
|
||||
<SkeletonTheme
|
||||
baseColor={theme.background.tertiary}
|
||||
highlightColor={theme.background.transparent.lighter}
|
||||
borderRadius={4}
|
||||
>
|
||||
<PageCardHeader
|
||||
icon={<Skeleton width={20} height={20} />}
|
||||
title={
|
||||
<Skeleton
|
||||
width={120}
|
||||
height={SKELETON_LOADER_HEIGHT_SIZES.standard.s}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<StyledSecondaryBar>
|
||||
<Skeleton
|
||||
width={120}
|
||||
height={SKELETON_LOADER_HEIGHT_SIZES.standard.s}
|
||||
/>
|
||||
<Skeleton
|
||||
width={180}
|
||||
height={SKELETON_LOADER_HEIGHT_SIZES.standard.s}
|
||||
/>
|
||||
</StyledSecondaryBar>
|
||||
<StyledBody>
|
||||
<Skeleton
|
||||
count={8}
|
||||
height={SKELETON_LOADER_HEIGHT_SIZES.standard.l}
|
||||
/>
|
||||
</StyledBody>
|
||||
</SkeletonTheme>
|
||||
</StyledCard>
|
||||
);
|
||||
};
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
import { ObjectOptionsDropdown } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdown';
|
||||
import { RecordIndexViewBarEffect } from '@/object-record/record-index/components/RecordIndexViewBarEffect';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { useHasCurrentViewNonReadableFields } from '@/object-record/record-index/hooks/useHasCurrentViewNonReadableFields';
|
||||
import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState';
|
||||
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { ViewBar } from '@/views/components/ViewBar';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
|
||||
export const RecordIndexViewBar = () => {
|
||||
const recordIndexViewType = useAtomStateValue(recordIndexViewTypeState);
|
||||
|
||||
const { objectNamePlural, recordIndexId, objectMetadataItem } =
|
||||
useRecordIndexContextOrThrow();
|
||||
|
||||
const { hasCurrentViewNonReadableFields } =
|
||||
useHasCurrentViewNonReadableFields(objectMetadataItem);
|
||||
|
||||
return (
|
||||
<SpreadsheetImportProvider>
|
||||
<ViewBar
|
||||
isReadOnly={hasCurrentViewNonReadableFields}
|
||||
viewBarId={recordIndexId}
|
||||
optionsDropdownButton={
|
||||
<ObjectOptionsDropdown
|
||||
recordIndexId={recordIndexId}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
viewType={recordIndexViewType ?? ViewType.TABLE}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<RecordIndexViewBarEffect
|
||||
objectNamePlural={objectNamePlural}
|
||||
viewBarId={recordIndexId}
|
||||
/>
|
||||
</SpreadsheetImportProvider>
|
||||
);
|
||||
};
|
||||
@@ -1,20 +1,17 @@
|
||||
import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SettingsSectionSkeletonLoader } from '@/settings/components/SettingsSectionSkeletonLoader';
|
||||
import { SettingsPageHeader } from '@/settings/components/layout/SettingsPageHeader';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { PageCardHeader } from '@/ui/layout/page/components/PageCardHeader';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useContext } from 'react';
|
||||
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledRoot = styled.div<{ isMobile: boolean }>`
|
||||
const StyledRoot = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
padding: ${({ isMobile }) =>
|
||||
isMobile ? themeCssVariables.spacing[1] : themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledCard = styled.div`
|
||||
@@ -31,18 +28,17 @@ const StyledCard = styled.div`
|
||||
`;
|
||||
|
||||
export const SettingsSkeletonLoader = () => {
|
||||
const isMobile = useIsMobile();
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
return (
|
||||
<StyledRoot isMobile={isMobile}>
|
||||
<StyledRoot>
|
||||
<StyledCard>
|
||||
<SkeletonTheme
|
||||
baseColor={theme.background.tertiary}
|
||||
highlightColor={theme.background.transparent.lighter}
|
||||
borderRadius={4}
|
||||
>
|
||||
<SettingsPageHeader
|
||||
<PageCardHeader
|
||||
links={[
|
||||
{
|
||||
children: (
|
||||
|
||||
+21
-74
@@ -1,15 +1,9 @@
|
||||
import { CommandMenuForMobile } from '@/command-menu/components/CommandMenuForMobile';
|
||||
import { useCommandMenuHotKeys } from '@/command-menu/hooks/useCommandMenuHotKeys';
|
||||
import { InformationBannerWrapper } from '@/information-banner/components/InformationBannerWrapper';
|
||||
import { SettingsPageHeader } from '@/settings/components/layout/SettingsPageHeader';
|
||||
import { SettingsSecondaryBar } from '@/settings/components/layout/SettingsSecondaryBar';
|
||||
import { SidePanelForDesktop } from '@/side-panel/components/SidePanelForDesktop';
|
||||
import { PageCardHeader } from '@/ui/layout/page/components/PageCardHeader';
|
||||
import { PageCardLayout } from '@/ui/layout/page/components/PageCardLayout';
|
||||
import { type BreadcrumbProps } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type JSX, type ReactNode } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type SettingsPageLayoutProps = {
|
||||
links: BreadcrumbProps['links'];
|
||||
@@ -20,44 +14,6 @@ type SettingsPageLayoutProps = {
|
||||
tag?: JSX.Element;
|
||||
};
|
||||
|
||||
const StyledRoot = styled.div<{ isMobile: boolean }>`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
padding: ${({ isMobile }) =>
|
||||
isMobile ? themeCssVariables.spacing[1] : themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledMainCardWrapper = styled.div`
|
||||
display: flex;
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
width: 0;
|
||||
`;
|
||||
|
||||
const StyledCard = styled.div`
|
||||
background: ${themeCssVariables.background.primary};
|
||||
border: 1px solid ${themeCssVariables.border.color.medium};
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledBodyContent = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const SettingsPageLayout = ({
|
||||
links,
|
||||
title,
|
||||
@@ -65,31 +21,22 @@ export const SettingsPageLayout = ({
|
||||
secondaryBar,
|
||||
children,
|
||||
tag,
|
||||
}: SettingsPageLayoutProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
useCommandMenuHotKeys();
|
||||
|
||||
return (
|
||||
<StyledRoot isMobile={isMobile}>
|
||||
<StyledMainCardWrapper>
|
||||
<StyledCard>
|
||||
<SettingsPageHeader
|
||||
links={links}
|
||||
title={title}
|
||||
tag={tag}
|
||||
actionButton={actionButton}
|
||||
/>
|
||||
{isDefined(secondaryBar) && (
|
||||
<SettingsSecondaryBar>{secondaryBar}</SettingsSecondaryBar>
|
||||
)}
|
||||
<StyledBodyContent>
|
||||
<InformationBannerWrapper />
|
||||
{children}
|
||||
</StyledBodyContent>
|
||||
</StyledCard>
|
||||
</StyledMainCardWrapper>
|
||||
{isMobile ? <CommandMenuForMobile /> : <SidePanelForDesktop />}
|
||||
</StyledRoot>
|
||||
);
|
||||
};
|
||||
}: SettingsPageLayoutProps) => (
|
||||
<PageCardLayout
|
||||
header={
|
||||
<PageCardHeader
|
||||
links={links}
|
||||
title={title}
|
||||
tag={tag}
|
||||
actionButton={actionButton}
|
||||
/>
|
||||
}
|
||||
secondaryBar={
|
||||
isDefined(secondaryBar) ? (
|
||||
<SettingsSecondaryBar>{secondaryBar}</SettingsSecondaryBar>
|
||||
) : undefined
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</PageCardLayout>
|
||||
);
|
||||
|
||||
@@ -145,7 +145,7 @@ export const SidePanelToggleButton = () => {
|
||||
dataClickOutsideId={PAGE_HEADER_SIDE_PANEL_BUTTON_CLICK_OUTSIDE_ID}
|
||||
dataTestId="page-header-side-panel-button"
|
||||
size={isMobile ? 'medium' : 'small'}
|
||||
variant="secondary"
|
||||
variant="tertiary"
|
||||
accent="default"
|
||||
hotkeys={[getOsControlSymbol(), 'K']}
|
||||
ariaLabel={ariaLabel}
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
import { CommandMenuForMobile } from '@/command-menu/components/CommandMenuForMobile';
|
||||
import { useCommandMenuHotKeys } from '@/command-menu/hooks/useCommandMenuHotKeys';
|
||||
import { SidePanelForDesktop } from '@/side-panel/components/SidePanelForDesktop';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { styled } from '@linaria/react';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledRow = styled.div<{ isMobile: boolean }>`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
padding: ${({ isMobile }) =>
|
||||
isMobile ? themeCssVariables.spacing[1] : themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
const StyledContent = styled.div`
|
||||
display: flex;
|
||||
flex: 1 1 0;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
export const MainAppLayoutWithSidePanel = () => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
useCommandMenuHotKeys();
|
||||
|
||||
return (
|
||||
<StyledRow isMobile={isMobile}>
|
||||
<StyledContent>
|
||||
<Outlet />
|
||||
</StyledContent>
|
||||
{isMobile ? <CommandMenuForMobile /> : <SidePanelForDesktop />}
|
||||
</StyledRow>
|
||||
);
|
||||
};
|
||||
+22
-15
@@ -11,23 +11,22 @@ import { type ReactNode } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type SettingsPageHeaderProps = {
|
||||
links: BreadcrumbProps['links'];
|
||||
type PageCardHeaderProps = {
|
||||
links?: BreadcrumbProps['links'];
|
||||
breadcrumb?: ReactNode;
|
||||
icon?: ReactNode;
|
||||
title?: ReactNode;
|
||||
tag?: ReactNode;
|
||||
actionButton?: ReactNode;
|
||||
};
|
||||
|
||||
// minmax(0, 1fr) side tracks (not 1fr) let a long breadcrumb truncate instead of
|
||||
// pushing the centered title off its shared axis with the tabs and body.
|
||||
const StyledHeader = styled.div`
|
||||
align-items: center;
|
||||
background-color: ${themeCssVariables.background.secondary};
|
||||
border-bottom: 1px solid ${themeCssVariables.border.color.medium};
|
||||
box-sizing: border-box;
|
||||
display: grid;
|
||||
display: flex;
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
||||
min-height: ${SIDE_PANEL_TOP_BAR_HEIGHT}px;
|
||||
padding: 0 ${themeCssVariables.spacing[3]};
|
||||
width: 100%;
|
||||
@@ -36,7 +35,7 @@ const StyledHeader = styled.div`
|
||||
const StyledLeft = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
`;
|
||||
@@ -49,23 +48,25 @@ const StyledTitle = styled.div`
|
||||
font-weight: ${themeCssVariables.font.weight.semiBold};
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
min-width: 0;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const StyledRight = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
gap: ${themeCssVariables.spacing[2]};
|
||||
justify-content: flex-end;
|
||||
min-width: 0;
|
||||
`;
|
||||
|
||||
export const SettingsPageHeader = ({
|
||||
export const PageCardHeader = ({
|
||||
links,
|
||||
breadcrumb,
|
||||
icon,
|
||||
title,
|
||||
tag,
|
||||
actionButton,
|
||||
}: SettingsPageHeaderProps) => {
|
||||
}: PageCardHeaderProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
const isNavigationDrawerExpanded = useNavigationDrawerExpanded();
|
||||
|
||||
@@ -75,12 +76,18 @@ export const SettingsPageHeader = ({
|
||||
{!isNavigationDrawerExpanded && (
|
||||
<NavigationDrawerCollapseButton direction="right" />
|
||||
)}
|
||||
<Breadcrumb links={links} />
|
||||
{isDefined(breadcrumb)
|
||||
? breadcrumb
|
||||
: isDefined(links) && <Breadcrumb links={links} />}
|
||||
{!isMobile &&
|
||||
(isDefined(icon) || isDefined(title) || isDefined(tag)) && (
|
||||
<StyledTitle>
|
||||
{icon}
|
||||
{isDefined(title) && title}
|
||||
{tag}
|
||||
</StyledTitle>
|
||||
)}
|
||||
</StyledLeft>
|
||||
<StyledTitle>
|
||||
{!isMobile && isDefined(title) && title}
|
||||
{!isMobile && tag}
|
||||
</StyledTitle>
|
||||
<StyledRight>{actionButton}</StyledRight>
|
||||
</StyledHeader>
|
||||
);
|
||||
@@ -0,0 +1,68 @@
|
||||
import { InformationBannerWrapper } from '@/information-banner/components/InformationBannerWrapper';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type ReactNode } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
type PageCardLayoutProps = {
|
||||
header: ReactNode;
|
||||
secondaryBar?: ReactNode;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
const StyledRoot = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
`;
|
||||
|
||||
const StyledMainCardWrapper = styled.div`
|
||||
display: flex;
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
width: 0;
|
||||
`;
|
||||
|
||||
const StyledCard = styled.div`
|
||||
background: ${themeCssVariables.background.primary};
|
||||
border: 1px solid ${themeCssVariables.border.color.medium};
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledBodyContent = styled.div`
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const PageCardLayout = ({
|
||||
header,
|
||||
secondaryBar,
|
||||
children,
|
||||
}: PageCardLayoutProps) => {
|
||||
return (
|
||||
<StyledRoot>
|
||||
<StyledMainCardWrapper>
|
||||
<StyledCard>
|
||||
{header}
|
||||
{isDefined(secondaryBar) && secondaryBar}
|
||||
<StyledBodyContent>
|
||||
<InformationBannerWrapper />
|
||||
{children}
|
||||
</StyledBodyContent>
|
||||
</StyledCard>
|
||||
</StyledMainCardWrapper>
|
||||
</StyledRoot>
|
||||
);
|
||||
};
|
||||
@@ -7,13 +7,12 @@ import { TimelineActivityContext } from '@/activities/timeline-activities/contex
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/states/isLayoutCustomizationModeEnabledState';
|
||||
import { MainContainerLayoutWithSidePanel } from '@/object-record/components/MainContainerLayoutWithSidePanel';
|
||||
import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper';
|
||||
import { PageLayoutRecordPageRenderer } from '@/object-record/record-show/components/PageLayoutRecordPageRenderer';
|
||||
import { RecordShowPageSSESubscribeEffect } from '@/object-record/record-show/components/RecordShowPageSSESubscribeEffect';
|
||||
import { useRecordShowPage } from '@/object-record/record-show/hooks/useRecordShowPage';
|
||||
import { computeRecordShowComponentInstanceId } from '@/object-record/record-show/utils/computeRecordShowComponentInstanceId';
|
||||
import { PageContainer } from '@/ui/layout/page/components/PageContainer';
|
||||
import { PageCardLayout } from '@/ui/layout/page/components/PageCardLayout';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { RecordShowPageHeader } from '~/pages/object-record/RecordShowPageHeader';
|
||||
import { RecordShowPageTitle } from '~/pages/object-record/RecordShowPageTitle';
|
||||
@@ -46,38 +45,39 @@ export const RecordShowPage = () => {
|
||||
<CommandMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: recordShowComponentInstanceId }}
|
||||
>
|
||||
<PageContainer>
|
||||
<RecordShowPageTitle
|
||||
objectNameSingular={objectNameSingular}
|
||||
objectRecordId={objectRecordId}
|
||||
/>
|
||||
<RecordShowPageHeader
|
||||
objectNameSingular={objectNameSingular}
|
||||
objectRecordId={objectRecordId}
|
||||
>
|
||||
<RecordShowCommandMenu />
|
||||
{!isLayoutCustomizationModeEnabled && <SidePanelToggleButton />}
|
||||
</RecordShowPageHeader>
|
||||
<MainContainerLayoutWithSidePanel>
|
||||
<TimelineActivityContext.Provider
|
||||
value={{
|
||||
recordId: objectRecordId,
|
||||
}}
|
||||
<RecordShowPageTitle
|
||||
objectNameSingular={objectNameSingular}
|
||||
objectRecordId={objectRecordId}
|
||||
/>
|
||||
<PageCardLayout
|
||||
header={
|
||||
<RecordShowPageHeader
|
||||
objectNameSingular={objectNameSingular}
|
||||
objectRecordId={objectRecordId}
|
||||
>
|
||||
<PageLayoutRecordPageRenderer
|
||||
targetRecordIdentifier={{
|
||||
id: objectRecordId,
|
||||
targetObjectNameSingular: objectNameSingular,
|
||||
}}
|
||||
isInSidePanel={false}
|
||||
/>
|
||||
<RecordShowPageSSESubscribeEffect
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordId={objectRecordId}
|
||||
/>
|
||||
</TimelineActivityContext.Provider>
|
||||
</MainContainerLayoutWithSidePanel>
|
||||
</PageContainer>
|
||||
<RecordShowCommandMenu />
|
||||
{!isLayoutCustomizationModeEnabled && <SidePanelToggleButton />}
|
||||
</RecordShowPageHeader>
|
||||
}
|
||||
>
|
||||
<TimelineActivityContext.Provider
|
||||
value={{
|
||||
recordId: objectRecordId,
|
||||
}}
|
||||
>
|
||||
<PageLayoutRecordPageRenderer
|
||||
targetRecordIdentifier={{
|
||||
id: objectRecordId,
|
||||
targetObjectNameSingular: objectNameSingular,
|
||||
}}
|
||||
isInSidePanel={false}
|
||||
/>
|
||||
<RecordShowPageSSESubscribeEffect
|
||||
objectNameSingular={objectNameSingular}
|
||||
recordId={objectRecordId}
|
||||
/>
|
||||
</TimelineActivityContext.Provider>
|
||||
</PageCardLayout>
|
||||
</CommandMenuComponentInstanceContext.Provider>
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
</RecordComponentInstanceContextsWrapper>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { getObjectMetadataIdentifierFields } from '@/object-metadata/utils/getObjectMetadataIdentifierFields';
|
||||
import { ObjectRecordShowPageBreadcrumb } from '@/object-record/record-show/components/ObjectRecordShowPageBreadcrumb';
|
||||
import { useRecordShowPagePagination } from '@/object-record/record-show/hooks/useRecordShowPagePagination';
|
||||
import { PageHeader } from '@/ui/layout/page/components/PageHeader';
|
||||
import { PageCardHeader } from '@/ui/layout/page/components/PageCardHeader';
|
||||
|
||||
export const RecordShowPageHeader = ({
|
||||
objectNameSingular,
|
||||
@@ -21,8 +21,8 @@ export const RecordShowPageHeader = ({
|
||||
getObjectMetadataIdentifierFields({ objectMetadataItem });
|
||||
|
||||
return (
|
||||
<PageHeader
|
||||
title={
|
||||
<PageCardHeader
|
||||
breadcrumb={
|
||||
<ObjectRecordShowPageBreadcrumb
|
||||
objectNameSingular={objectNameSingular}
|
||||
objectRecordId={objectRecordId}
|
||||
@@ -30,8 +30,7 @@ export const RecordShowPageHeader = ({
|
||||
labelIdentifierFieldMetadataItem={labelIdentifierFieldMetadataItem}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</PageHeader>
|
||||
actionButton={children}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom';
|
||||
import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { MainContainerLayoutWithSidePanel } from '@/object-record/components/MainContainerLayoutWithSidePanel';
|
||||
import { MainContainerLayout } from '@/object-record/components/MainContainerLayout';
|
||||
import { PageLayoutRenderer } from '@/page-layout/components/PageLayoutRenderer';
|
||||
import { LayoutRenderingProvider } from '@/ui/layout/contexts/LayoutRenderingContext';
|
||||
import { PageContainer } from '@/ui/layout/page/components/PageContainer';
|
||||
@@ -34,9 +34,9 @@ export const StandalonePageLayoutPage = () => {
|
||||
isInSidePanel: false,
|
||||
}}
|
||||
>
|
||||
<MainContainerLayoutWithSidePanel>
|
||||
<MainContainerLayout>
|
||||
<PageLayoutRenderer pageLayoutId={pageLayoutId} />
|
||||
</MainContainerLayoutWithSidePanel>
|
||||
</MainContainerLayout>
|
||||
</LayoutRenderingProvider>
|
||||
</CommandMenuComponentInstanceContext.Provider>
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
|
||||
Reference in New Issue
Block a user