mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-23 20:13:21 +03:00
7499 refactor right drawer to have contextual actions (#7954)
Closes #7499 - Modifies context store states to be component states - Introduces the concept of `mainContextStore` which will dictate the available actions inside the command K - Adds contextual actions inside the right drawer - Creates a new type of modal variant
This commit is contained in:
parent
6c93587efb
commit
6843a642b5
@ -1,6 +1,7 @@
|
||||
import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries';
|
||||
import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
|
||||
import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { ActionMenuType } from '@/action-menu/types/ActionMenuType';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
|
||||
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
@ -9,16 +10,19 @@ import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords
|
||||
import { useFetchAllRecordIds } from '@/object-record/hooks/useFetchAllRecordIds';
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconTrash, isDefined } from 'twenty-ui';
|
||||
|
||||
export const DeleteRecordsActionEffect = ({
|
||||
position,
|
||||
objectMetadataItem,
|
||||
actionMenuType,
|
||||
}: {
|
||||
position: number;
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
actionMenuType: ActionMenuType;
|
||||
}) => {
|
||||
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
|
||||
|
||||
@ -35,12 +39,12 @@ export const DeleteRecordsActionEffect = ({
|
||||
|
||||
const { favorites, deleteFavorite } = useFavorites();
|
||||
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilValue(
|
||||
contextStoreNumberOfSelectedRecordsState,
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
);
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilValue(
|
||||
contextStoreTargetedRecordsRuleState,
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const graphqlFilter = computeContextStoreFilters(
|
||||
@ -53,6 +57,8 @@ export const DeleteRecordsActionEffect = ({
|
||||
filter: graphqlFilter,
|
||||
});
|
||||
|
||||
const { closeRightDrawer } = useRightDrawer();
|
||||
|
||||
const handleDeleteClick = useCallback(async () => {
|
||||
const recordIdsToDelete = await fetchAllRecordIds();
|
||||
|
||||
@ -112,10 +118,19 @@ export const DeleteRecordsActionEffect = ({
|
||||
}? ${
|
||||
contextStoreNumberOfSelectedRecords === 1 ? 'It' : 'They'
|
||||
} can be recovered from the Options menu.`}
|
||||
onConfirmClick={() => handleDeleteClick()}
|
||||
onConfirmClick={() => {
|
||||
handleDeleteClick();
|
||||
|
||||
if (actionMenuType === 'recordShow') {
|
||||
closeRightDrawer();
|
||||
}
|
||||
}}
|
||||
deleteButtonText={`Delete ${
|
||||
contextStoreNumberOfSelectedRecords > 1 ? 'Records' : 'Record'
|
||||
}`}
|
||||
modalVariant={
|
||||
actionMenuType === 'recordShow' ? 'tertiary' : 'primary'
|
||||
}
|
||||
/>
|
||||
),
|
||||
});
|
||||
@ -127,8 +142,10 @@ export const DeleteRecordsActionEffect = ({
|
||||
removeActionMenuEntry('delete');
|
||||
};
|
||||
}, [
|
||||
actionMenuType,
|
||||
addActionMenuEntry,
|
||||
canDelete,
|
||||
closeRightDrawer,
|
||||
contextStoreNumberOfSelectedRecords,
|
||||
handleDeleteClick,
|
||||
isDeleteRecordsModalOpen,
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries';
|
||||
import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconHeart, IconHeartOff, isDefined } from 'twenty-ui';
|
||||
@ -16,8 +17,8 @@ export const ManageFavoritesActionEffect = ({
|
||||
}) => {
|
||||
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilValue(
|
||||
contextStoreTargetedRecordsRuleState,
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const { favorites, createFavorite, deleteFavorite } = useFavorites();
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect';
|
||||
import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect';
|
||||
import { ActionMenuType } from '@/action-menu/types/ActionMenuType';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
|
||||
const actionEffects = [ExportRecordsActionEffect, DeleteRecordsActionEffect];
|
||||
|
||||
export const MultipleRecordsActionMenuEntriesSetter = ({
|
||||
objectMetadataItem,
|
||||
actionMenuType,
|
||||
}: {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
actionMenuType: ActionMenuType;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
@ -16,6 +19,7 @@ export const MultipleRecordsActionMenuEntriesSetter = ({
|
||||
key={index}
|
||||
position={index}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
actionMenuType={actionMenuType}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
|
@ -1,17 +1,22 @@
|
||||
import { MultipleRecordsActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter';
|
||||
import { SingleRecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter';
|
||||
import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState';
|
||||
import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
|
||||
import { ActionMenuType } from '@/action-menu/types/ActionMenuType';
|
||||
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const RecordActionMenuEntriesSetter = () => {
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilValue(
|
||||
contextStoreNumberOfSelectedRecordsState,
|
||||
export const RecordActionMenuEntriesSetter = ({
|
||||
actionMenuType,
|
||||
}: {
|
||||
actionMenuType: ActionMenuType;
|
||||
}) => {
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
);
|
||||
|
||||
const contextStoreCurrentObjectMetadataId = useRecoilValue(
|
||||
contextStoreCurrentObjectMetadataIdState,
|
||||
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentObjectMetadataIdComponentState,
|
||||
);
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItemById({
|
||||
@ -32,6 +37,7 @@ export const RecordActionMenuEntriesSetter = () => {
|
||||
return (
|
||||
<SingleRecordActionMenuEntriesSetter
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
actionMenuType={actionMenuType}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -39,6 +45,7 @@ export const RecordActionMenuEntriesSetter = () => {
|
||||
return (
|
||||
<MultipleRecordsActionMenuEntriesSetter
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
actionMenuType={actionMenuType}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -1,12 +1,15 @@
|
||||
import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect';
|
||||
import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect';
|
||||
import { ManageFavoritesActionEffect } from '@/action-menu/actions/record-actions/components/ManageFavoritesActionEffect';
|
||||
import { ActionMenuType } from '@/action-menu/types/ActionMenuType';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
|
||||
export const SingleRecordActionMenuEntriesSetter = ({
|
||||
objectMetadataItem,
|
||||
actionMenuType,
|
||||
}: {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
actionMenuType: ActionMenuType;
|
||||
}) => {
|
||||
const actionEffects = [
|
||||
ManageFavoritesActionEffect,
|
||||
@ -20,6 +23,7 @@ export const SingleRecordActionMenuEntriesSetter = ({
|
||||
key={index}
|
||||
position={index}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
actionMenuType={actionMenuType}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
|
@ -1,30 +0,0 @@
|
||||
import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
|
||||
import { ActionMenuBar } from '@/action-menu/components/ActionMenuBar';
|
||||
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
|
||||
import { ActionMenuDropdown } from '@/action-menu/components/ActionMenuDropdown';
|
||||
import { ActionMenuEffect } from '@/action-menu/components/ActionMenuEffect';
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
export const ActionMenu = ({ actionMenuId }: { actionMenuId: string }) => {
|
||||
const contextStoreCurrentObjectMetadataId = useRecoilValue(
|
||||
contextStoreCurrentObjectMetadataIdState,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{contextStoreCurrentObjectMetadataId && (
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: actionMenuId }}
|
||||
>
|
||||
<ActionMenuBar />
|
||||
<ActionMenuDropdown />
|
||||
<ActionMenuConfirmationModals />
|
||||
<ActionMenuEffect />
|
||||
<RecordActionMenuEntriesSetter />
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,35 @@
|
||||
import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
|
||||
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
|
||||
import { RecordIndexActionMenuBar } from '@/action-menu/components/RecordIndexActionMenuBar';
|
||||
import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
|
||||
import { RecordIndexActionMenuEffect } from '@/action-menu/components/RecordIndexActionMenuEffect';
|
||||
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const RecordIndexActionMenu = ({
|
||||
actionMenuId,
|
||||
}: {
|
||||
actionMenuId: string;
|
||||
}) => {
|
||||
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentObjectMetadataIdComponentState,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{contextStoreCurrentObjectMetadataId && (
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: actionMenuId }}
|
||||
>
|
||||
<RecordIndexActionMenuBar />
|
||||
<RecordIndexActionMenuDropdown />
|
||||
<ActionMenuConfirmationModals />
|
||||
<RecordIndexActionMenuEffect />
|
||||
<RecordActionMenuEntriesSetter actionMenuType="recordIndex" />
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,14 +1,13 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { ActionMenuBarEntry } from '@/action-menu/components/ActionMenuBarEntry';
|
||||
import { RecordIndexActionMenuBarEntry } from '@/action-menu/components/RecordIndexActionMenuBarEntry';
|
||||
import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector';
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { ActionBarHotkeyScope } from '@/action-menu/types/ActionBarHotKeyScope';
|
||||
import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { BottomBar } from '@/ui/layout/bottom-bar/components/BottomBar';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
const StyledLabel = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
@ -18,9 +17,9 @@ const StyledLabel = styled.div`
|
||||
padding-right: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
export const ActionMenuBar = () => {
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilValue(
|
||||
contextStoreNumberOfSelectedRecordsState,
|
||||
export const RecordIndexActionMenuBar = () => {
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
);
|
||||
|
||||
const actionMenuId = useAvailableComponentInstanceIdOrThrow(
|
||||
@ -44,7 +43,7 @@ export const ActionMenuBar = () => {
|
||||
>
|
||||
<StyledLabel>{contextStoreNumberOfSelectedRecords} selected:</StyledLabel>
|
||||
{actionMenuEntries.map((entry, index) => (
|
||||
<ActionMenuBarEntry key={index} entry={entry} />
|
||||
<RecordIndexActionMenuBarEntry key={index} entry={entry} />
|
||||
))}
|
||||
</BottomBar>
|
||||
);
|
@ -4,7 +4,7 @@ import styled from '@emotion/styled';
|
||||
import { ActionMenuEntry } from '@/action-menu/types/ActionMenuEntry';
|
||||
import { MenuItemAccent } from '@/ui/navigation/menu-item/types/MenuItemAccent';
|
||||
|
||||
type ActionMenuBarEntryProps = {
|
||||
type RecordIndexActionMenuBarEntryProps = {
|
||||
entry: ActionMenuEntry;
|
||||
};
|
||||
|
||||
@ -35,7 +35,9 @@ const StyledButtonLabel = styled.div`
|
||||
margin-left: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
export const ActionMenuBarEntry = ({ entry }: ActionMenuBarEntryProps) => {
|
||||
export const RecordIndexActionMenuBarEntry = ({
|
||||
entry,
|
||||
}: RecordIndexActionMenuBarEntryProps) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<StyledButton
|
@ -3,9 +3,9 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { PositionType } from '../types/PositionType';
|
||||
|
||||
import { actionMenuDropdownPositionComponentState } from '@/action-menu/states/actionMenuDropdownPositionComponentState';
|
||||
import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector';
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
|
||||
import { ActionMenuDropdownHotkeyScope } from '@/action-menu/types/ActionMenuDropdownHotKeyScope';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
@ -34,7 +34,7 @@ const StyledContainerActionMenuDropdown = styled.div<StyledContainerProps>`
|
||||
width: auto;
|
||||
`;
|
||||
|
||||
export const ActionMenuDropdown = () => {
|
||||
export const RecordIndexActionMenuDropdown = () => {
|
||||
const actionMenuEntries = useRecoilComponentValueV2(
|
||||
actionMenuEntriesComponentSelector,
|
||||
);
|
||||
@ -45,7 +45,7 @@ export const ActionMenuDropdown = () => {
|
||||
|
||||
const actionMenuDropdownPosition = useRecoilValue(
|
||||
extractComponentState(
|
||||
actionMenuDropdownPositionComponentState,
|
||||
recordIndexActionMenuDropdownPositionComponentState,
|
||||
`action-menu-dropdown-${actionMenuId}`,
|
||||
),
|
||||
);
|
@ -1,15 +1,16 @@
|
||||
import { useActionMenu } from '@/action-menu/hooks/useActionMenu';
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
export const ActionMenuEffect = () => {
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilValue(
|
||||
contextStoreNumberOfSelectedRecordsState,
|
||||
export const RecordIndexActionMenuEffect = () => {
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
);
|
||||
|
||||
const actionMenuId = useAvailableComponentInstanceIdOrThrow(
|
@ -0,0 +1,31 @@
|
||||
import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
|
||||
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
|
||||
import { RecordShowActionMenuBar } from '@/action-menu/components/RecordShowActionMenuBar';
|
||||
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const RecordShowActionMenu = ({
|
||||
actionMenuId,
|
||||
}: {
|
||||
actionMenuId: string;
|
||||
}) => {
|
||||
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentObjectMetadataIdComponentState,
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{contextStoreCurrentObjectMetadataId && (
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: actionMenuId }}
|
||||
>
|
||||
<RecordShowActionMenuBar />
|
||||
<ActionMenuConfirmationModals />
|
||||
<RecordActionMenuEntriesSetter actionMenuType="recordShow" />
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
import { RecordShowActionMenuBarEntry } from '@/action-menu/components/RecordShowActionMenuBarEntry';
|
||||
import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const RecordShowActionMenuBar = () => {
|
||||
const actionMenuEntries = useRecoilComponentValueV2(
|
||||
actionMenuEntriesComponentSelector,
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{actionMenuEntries.map((actionMenuEntry) => (
|
||||
<RecordShowActionMenuBarEntry entry={actionMenuEntry} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,53 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { ActionMenuEntry } from '@/action-menu/types/ActionMenuEntry';
|
||||
import { MenuItemAccent } from '@/ui/navigation/menu-item/types/MenuItemAccent';
|
||||
|
||||
type RecordShowActionMenuBarEntryProps = {
|
||||
entry: ActionMenuEntry;
|
||||
};
|
||||
|
||||
const StyledButton = styled.div<{ accent: MenuItemAccent }>`
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
color: ${(props) =>
|
||||
props.accent === 'danger'
|
||||
? props.theme.color.red
|
||||
: props.theme.font.color.secondary};
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
transition: background 0.1s ease;
|
||||
user-select: none;
|
||||
|
||||
&:hover {
|
||||
background: ${({ theme, accent }) =>
|
||||
accent === 'danger'
|
||||
? theme.background.danger
|
||||
: theme.background.tertiary};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledButtonLabel = styled.div`
|
||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||
margin-left: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
// For now, this component is the same as RecordIndexActionMenuBarEntry but they
|
||||
// will probably diverge in the future
|
||||
export const RecordShowActionMenuBarEntry = ({
|
||||
entry,
|
||||
}: RecordShowActionMenuBarEntryProps) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<StyledButton
|
||||
accent={entry.accent ?? 'default'}
|
||||
onClick={() => entry.onClick?.()}
|
||||
>
|
||||
{entry.Icon && <entry.Icon size={theme.icon.size.md} />}
|
||||
<StyledButtonLabel>{entry.label}</StyledButtonLabel>
|
||||
</StyledButton>
|
||||
);
|
||||
};
|
@ -1,116 +0,0 @@
|
||||
import { expect, jest } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { ActionMenuBar } from '@/action-menu/components/ActionMenuBar';
|
||||
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
|
||||
import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState';
|
||||
import { userEvent, waitFor, within } from '@storybook/test';
|
||||
import { IconCheckbox, IconTrash } from 'twenty-ui';
|
||||
|
||||
const deleteMock = jest.fn();
|
||||
const markAsDoneMock = jest.fn();
|
||||
|
||||
const meta: Meta<typeof ActionMenuBar> = {
|
||||
title: 'Modules/ActionMenu/ActionMenuBar',
|
||||
component: ActionMenuBar,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(contextStoreTargetedRecordsRuleState, {
|
||||
mode: 'selection',
|
||||
selectedRecordIds: ['1', '2', '3'],
|
||||
});
|
||||
set(contextStoreNumberOfSelectedRecordsState, 3);
|
||||
set(
|
||||
actionMenuEntriesComponentState.atomFamily({
|
||||
instanceId: 'story-action-menu',
|
||||
}),
|
||||
new Map([
|
||||
[
|
||||
'delete',
|
||||
{
|
||||
key: 'delete',
|
||||
label: 'Delete',
|
||||
position: 0,
|
||||
Icon: IconTrash,
|
||||
onClick: deleteMock,
|
||||
},
|
||||
],
|
||||
[
|
||||
'markAsDone',
|
||||
{
|
||||
key: 'markAsDone',
|
||||
label: 'Mark as done',
|
||||
position: 1,
|
||||
Icon: IconCheckbox,
|
||||
onClick: markAsDoneMock,
|
||||
},
|
||||
],
|
||||
]),
|
||||
);
|
||||
set(
|
||||
isBottomBarOpenedComponentState.atomFamily({
|
||||
instanceId: 'action-bar-story-action-menu',
|
||||
}),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'story-action-menu' }}
|
||||
>
|
||||
<Story />
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
),
|
||||
],
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof ActionMenuBar>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
};
|
||||
|
||||
export const WithCustomSelection: Story = {
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
const selectionText = await canvas.findByText('3 selected:');
|
||||
expect(selectionText).toBeInTheDocument();
|
||||
},
|
||||
};
|
||||
|
||||
export const WithButtonClicks: Story = {
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const deleteButton = await canvas.findByText('Delete');
|
||||
await userEvent.click(deleteButton);
|
||||
|
||||
const markAsDoneButton = await canvas.findByText('Mark as done');
|
||||
await userEvent.click(markAsDoneButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(deleteMock).toHaveBeenCalled();
|
||||
expect(markAsDoneMock).toHaveBeenCalled();
|
||||
});
|
||||
},
|
||||
};
|
@ -0,0 +1,131 @@
|
||||
import { expect, jest } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { RecordIndexActionMenuBar } from '@/action-menu/components/RecordIndexActionMenuBar';
|
||||
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState';
|
||||
import { userEvent, waitFor, within } from '@storybook/test';
|
||||
import { IconCheckbox, IconTrash } from 'twenty-ui';
|
||||
|
||||
const deleteMock = jest.fn();
|
||||
const markAsDoneMock = jest.fn();
|
||||
|
||||
const meta: Meta<typeof RecordIndexActionMenuBar> = {
|
||||
title: 'Modules/ActionMenu/RecordIndexActionMenuBar',
|
||||
component: RecordIndexActionMenuBar,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'story-action-menu' }}
|
||||
>
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(
|
||||
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
||||
instanceId: 'story-action-menu',
|
||||
}),
|
||||
{
|
||||
mode: 'selection',
|
||||
selectedRecordIds: ['1', '2', '3'],
|
||||
},
|
||||
);
|
||||
set(
|
||||
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
||||
instanceId: 'story-action-menu',
|
||||
}),
|
||||
3,
|
||||
);
|
||||
set(
|
||||
actionMenuEntriesComponentState.atomFamily({
|
||||
instanceId: 'story-action-menu',
|
||||
}),
|
||||
new Map([
|
||||
[
|
||||
'delete',
|
||||
{
|
||||
key: 'delete',
|
||||
label: 'Delete',
|
||||
position: 0,
|
||||
Icon: IconTrash,
|
||||
onClick: deleteMock,
|
||||
},
|
||||
],
|
||||
[
|
||||
'markAsDone',
|
||||
{
|
||||
key: 'markAsDone',
|
||||
label: 'Mark as done',
|
||||
position: 1,
|
||||
Icon: IconCheckbox,
|
||||
onClick: markAsDoneMock,
|
||||
},
|
||||
],
|
||||
]),
|
||||
);
|
||||
set(
|
||||
isBottomBarOpenedComponentState.atomFamily({
|
||||
instanceId: 'action-bar-story-action-menu',
|
||||
}),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'story-action-menu' }}
|
||||
>
|
||||
<Story />
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
),
|
||||
],
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof RecordIndexActionMenuBar>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
};
|
||||
|
||||
export const WithCustomSelection: Story = {
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
const selectionText = await canvas.findByText('3 selected:');
|
||||
expect(selectionText).toBeInTheDocument();
|
||||
},
|
||||
};
|
||||
|
||||
export const WithButtonClicks: Story = {
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const deleteButton = await canvas.findByText('Delete');
|
||||
await userEvent.click(deleteButton);
|
||||
|
||||
const markAsDoneButton = await canvas.findByText('Mark as done');
|
||||
await userEvent.click(markAsDoneButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(deleteMock).toHaveBeenCalled();
|
||||
expect(markAsDoneMock).toHaveBeenCalled();
|
||||
});
|
||||
},
|
||||
};
|
@ -1,19 +1,19 @@
|
||||
import { RecordIndexActionMenuBarEntry } from '@/action-menu/components/RecordIndexActionMenuBarEntry';
|
||||
import { expect, jest } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, within } from '@storybook/testing-library';
|
||||
|
||||
import { ComponentDecorator, IconCheckbox, IconTrash } from 'twenty-ui';
|
||||
import { ActionMenuBarEntry } from '../ActionMenuBarEntry';
|
||||
|
||||
const meta: Meta<typeof ActionMenuBarEntry> = {
|
||||
title: 'Modules/ActionMenu/ActionMenuBarEntry',
|
||||
component: ActionMenuBarEntry,
|
||||
const meta: Meta<typeof RecordIndexActionMenuBarEntry> = {
|
||||
title: 'Modules/ActionMenu/RecordIndexActionMenuBarEntry',
|
||||
component: RecordIndexActionMenuBarEntry,
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof ActionMenuBarEntry>;
|
||||
type Story = StoryObj<typeof RecordIndexActionMenuBarEntry>;
|
||||
|
||||
const deleteMock = jest.fn();
|
||||
const markAsDoneMock = jest.fn();
|
@ -3,10 +3,10 @@ import { Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, within } from '@storybook/testing-library';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { ActionMenuDropdown } from '@/action-menu/components/ActionMenuDropdown';
|
||||
import { actionMenuDropdownPositionComponentState } from '@/action-menu/states/actionMenuDropdownPositionComponentState';
|
||||
import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
|
||||
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import { IconCheckbox, IconHeart, IconTrash } from 'twenty-ui';
|
||||
@ -15,16 +15,16 @@ const deleteMock = jest.fn();
|
||||
const markAsDoneMock = jest.fn();
|
||||
const addToFavoritesMock = jest.fn();
|
||||
|
||||
const meta: Meta<typeof ActionMenuDropdown> = {
|
||||
title: 'Modules/ActionMenu/ActionMenuDropdown',
|
||||
component: ActionMenuDropdown,
|
||||
const meta: Meta<typeof RecordIndexActionMenuDropdown> = {
|
||||
title: 'Modules/ActionMenu/RecordIndexActionMenuDropdown',
|
||||
component: RecordIndexActionMenuDropdown,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(
|
||||
extractComponentState(
|
||||
actionMenuDropdownPositionComponentState,
|
||||
recordIndexActionMenuDropdownPositionComponentState,
|
||||
'action-menu-dropdown-story',
|
||||
),
|
||||
{ x: 10, y: 10 },
|
||||
@ -87,7 +87,7 @@ const meta: Meta<typeof ActionMenuDropdown> = {
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof ActionMenuDropdown>;
|
||||
type Story = StoryObj<typeof RecordIndexActionMenuDropdown>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
@ -0,0 +1,131 @@
|
||||
import { expect, jest } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { RecordShowActionMenuBar } from '@/action-menu/components/RecordShowActionMenuBar';
|
||||
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { MenuItemAccent } from '@/ui/navigation/menu-item/types/MenuItemAccent';
|
||||
import { userEvent, waitFor, within } from '@storybook/test';
|
||||
import {
|
||||
ComponentDecorator,
|
||||
IconFileExport,
|
||||
IconHeart,
|
||||
IconTrash,
|
||||
} from 'twenty-ui';
|
||||
|
||||
const deleteMock = jest.fn();
|
||||
const addToFavoritesMock = jest.fn();
|
||||
const exportMock = jest.fn();
|
||||
|
||||
const meta: Meta<typeof RecordShowActionMenuBar> = {
|
||||
title: 'Modules/ActionMenu/RecordShowActionMenuBar',
|
||||
component: RecordShowActionMenuBar,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<RecoilRoot
|
||||
initializeState={({ set }) => {
|
||||
set(
|
||||
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
||||
instanceId: 'story-action-menu',
|
||||
}),
|
||||
{
|
||||
mode: 'selection',
|
||||
selectedRecordIds: ['1'],
|
||||
},
|
||||
);
|
||||
set(
|
||||
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
||||
instanceId: 'story-action-menu',
|
||||
}),
|
||||
1,
|
||||
);
|
||||
set(
|
||||
actionMenuEntriesComponentState.atomFamily({
|
||||
instanceId: 'story-action-menu',
|
||||
}),
|
||||
new Map([
|
||||
[
|
||||
'addToFavorites',
|
||||
{
|
||||
key: 'addToFavorites',
|
||||
label: 'Add to favorites',
|
||||
position: 0,
|
||||
Icon: IconHeart,
|
||||
onClick: addToFavoritesMock,
|
||||
},
|
||||
],
|
||||
[
|
||||
'export',
|
||||
{
|
||||
key: 'export',
|
||||
label: 'Export',
|
||||
position: 1,
|
||||
Icon: IconFileExport,
|
||||
onClick: exportMock,
|
||||
},
|
||||
],
|
||||
[
|
||||
'delete',
|
||||
{
|
||||
key: 'delete',
|
||||
label: 'Delete',
|
||||
position: 2,
|
||||
Icon: IconTrash,
|
||||
onClick: deleteMock,
|
||||
accent: 'danger' as MenuItemAccent,
|
||||
},
|
||||
],
|
||||
]),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ActionMenuComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'story-action-menu' }}
|
||||
>
|
||||
<Story />
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
),
|
||||
ComponentDecorator,
|
||||
],
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof RecordShowActionMenuBar>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
};
|
||||
|
||||
export const WithButtonClicks: Story = {
|
||||
args: {
|
||||
actionMenuId: 'story-action-menu',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const deleteButton = await canvas.findByText('Delete');
|
||||
await userEvent.click(deleteButton);
|
||||
|
||||
const addToFavoritesButton = await canvas.findByText('Add to favorites');
|
||||
await userEvent.click(addToFavoritesButton);
|
||||
|
||||
const exportButton = await canvas.findByText('Export');
|
||||
await userEvent.click(exportButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(deleteMock).toHaveBeenCalled();
|
||||
expect(addToFavoritesMock).toHaveBeenCalled();
|
||||
expect(exportMock).toHaveBeenCalled();
|
||||
});
|
||||
},
|
||||
};
|
@ -1,9 +1,9 @@
|
||||
import { PositionType } from '@/action-menu/types/PositionType';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
export const actionMenuDropdownPositionComponentState =
|
||||
export const recordIndexActionMenuDropdownPositionComponentState =
|
||||
createComponentState<PositionType>({
|
||||
key: 'actionMenuDropdownPositionComponentState',
|
||||
key: 'recordIndexActionMenuDropdownPositionComponentState',
|
||||
defaultValue: {
|
||||
x: null,
|
||||
y: null,
|
@ -0,0 +1 @@
|
||||
export type ActionMenuType = 'recordIndex' | 'recordShow';
|
@ -0,0 +1,22 @@
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
export const SetMainContextStoreComponentInstanceIdEffect = () => {
|
||||
const setMainContextStoreComponentInstanceId = useSetRecoilState(
|
||||
mainContextStoreComponentInstanceIdState,
|
||||
);
|
||||
|
||||
const context = useContext(ContextStoreComponentInstanceContext);
|
||||
|
||||
useEffect(() => {
|
||||
setMainContextStoreComponentInstanceId(context?.instanceId ?? null);
|
||||
|
||||
return () => {
|
||||
setMainContextStoreComponentInstanceId(null);
|
||||
};
|
||||
}, [context, setMainContextStoreComponentInstanceId]);
|
||||
|
||||
return null;
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const contextStoreCurrentObjectMetadataIdComponentState =
|
||||
createComponentStateV2<string | null>({
|
||||
key: 'contextStoreCurrentObjectMetadataIdComponentState',
|
||||
defaultValue: null,
|
||||
componentInstanceContext: ContextStoreComponentInstanceContext,
|
||||
});
|
@ -1,8 +0,0 @@
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const contextStoreCurrentObjectMetadataIdState = createState<
|
||||
string | null
|
||||
>({
|
||||
key: 'contextStoreCurrentObjectMetadataIdState',
|
||||
defaultValue: null,
|
||||
});
|
@ -0,0 +1,10 @@
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const contextStoreCurrentViewIdComponentState = createComponentStateV2<
|
||||
string | null
|
||||
>({
|
||||
key: 'contextStoreCurrentViewIdComponentState',
|
||||
defaultValue: null,
|
||||
componentInstanceContext: ContextStoreComponentInstanceContext,
|
||||
});
|
@ -1,6 +0,0 @@
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const contextStoreCurrentViewIdState = createState<string | null>({
|
||||
key: 'contextStoreCurrentViewIdState',
|
||||
defaultValue: null,
|
||||
});
|
@ -0,0 +1,9 @@
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const contextStoreNumberOfSelectedRecordsComponentState =
|
||||
createComponentStateV2<number>({
|
||||
key: 'contextStoreNumberOfSelectedRecordsComponentState',
|
||||
defaultValue: 0,
|
||||
componentInstanceContext: ContextStoreComponentInstanceContext,
|
||||
});
|
@ -1,6 +0,0 @@
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const contextStoreNumberOfSelectedRecordsState = createState<number>({
|
||||
key: 'contextStoreNumberOfSelectedRecordsState',
|
||||
defaultValue: 0,
|
||||
});
|
@ -1,5 +1,6 @@
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||
import { createState } from 'twenty-ui';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
type ContextStoreTargetedRecordsRuleSelectionMode = {
|
||||
mode: 'selection';
|
||||
@ -16,11 +17,12 @@ export type ContextStoreTargetedRecordsRule =
|
||||
| ContextStoreTargetedRecordsRuleSelectionMode
|
||||
| ContextStoreTargetedRecordsRuleExclusionMode;
|
||||
|
||||
export const contextStoreTargetedRecordsRuleState =
|
||||
createState<ContextStoreTargetedRecordsRule>({
|
||||
key: 'contextStoreTargetedRecordsRuleState',
|
||||
export const contextStoreTargetedRecordsRuleComponentState =
|
||||
createComponentStateV2<ContextStoreTargetedRecordsRule>({
|
||||
key: 'contextStoreTargetedRecordsRuleComponentState',
|
||||
defaultValue: {
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [],
|
||||
},
|
||||
componentInstanceContext: ContextStoreComponentInstanceContext,
|
||||
});
|
@ -0,0 +1,4 @@
|
||||
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
|
||||
|
||||
export const ContextStoreComponentInstanceContext =
|
||||
createComponentInstanceContext();
|
@ -0,0 +1,8 @@
|
||||
import { createState } from 'twenty-ui';
|
||||
|
||||
export const mainContextStoreComponentInstanceIdState = createState<
|
||||
string | null
|
||||
>({
|
||||
key: 'mainContextStoreComponentInstanceIdState',
|
||||
defaultValue: null,
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { turnFiltersIntoQueryFilter } from '@/object-record/record-filter/utils/turnFiltersIntoQueryFilter';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useActionMenu } from '@/action-menu/hooks/useActionMenu';
|
||||
import { actionMenuDropdownPositionComponentState } from '@/action-menu/states/actionMenuDropdownPositionComponentState';
|
||||
import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
|
||||
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
|
||||
@ -188,7 +188,7 @@ export const RecordBoardCard = ({
|
||||
|
||||
const setActionMenuDropdownPosition = useSetRecoilState(
|
||||
extractComponentState(
|
||||
actionMenuDropdownPositionComponentState,
|
||||
recordIndexActionMenuDropdownPositionComponentState,
|
||||
`action-menu-dropdown-${recordBoardId}`,
|
||||
),
|
||||
);
|
||||
|
@ -2,7 +2,7 @@ import { useCallback, useEffect } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
|
||||
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
|
||||
@ -11,6 +11,7 @@ import { recordIndexIsCompactModeActiveState } from '@/object-record/record-inde
|
||||
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
|
||||
import { computeRecordBoardColumnDefinitionsFromObjectMetadata } from '@/object-record/utils/computeRecordBoardColumnDefinitionsFromObjectMetadata';
|
||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
@ -120,8 +121,8 @@ export const RecordIndexBoardDataLoaderEffect = ({
|
||||
|
||||
const selectedRecordIds = useRecoilValue(selectedRecordIdsSelector());
|
||||
|
||||
const setContextStoreTargetedRecords = useSetRecoilState(
|
||||
contextStoreTargetedRecordsRuleState,
|
||||
const setContextStoreTargetedRecords = useSetRecoilComponentStateV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -22,8 +22,9 @@ import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
|
||||
|
||||
import { ActionMenu } from '@/action-menu/components/ActionMenu';
|
||||
import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { RecordIndexActionMenu } from '@/action-menu/components/RecordIndexActionMenu';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { ViewBar } from '@/views/components/ViewBar';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { ViewField } from '@/views/types/ViewField';
|
||||
@ -102,8 +103,8 @@ export const RecordIndexContainer = () => {
|
||||
[columnDefinitions, setTableColumns],
|
||||
);
|
||||
|
||||
const setContextStoreTargetedRecordsRule = useSetRecoilState(
|
||||
contextStoreTargetedRecordsRuleState,
|
||||
const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
return (
|
||||
@ -186,7 +187,7 @@ export const RecordIndexContainer = () => {
|
||||
/>
|
||||
</StyledContainerWithPadding>
|
||||
)}
|
||||
<ActionMenu actionMenuId={recordIndexId} />
|
||||
<RecordIndexActionMenu actionMenuId={recordIndexId} />
|
||||
</RecordFieldValueSelectorContextProvider>
|
||||
</ViewComponentInstanceContext.Provider>
|
||||
</StyledContainer>
|
||||
|
@ -1,22 +1,23 @@
|
||||
import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
|
||||
import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
|
||||
import { useFindManyParams } from '@/object-record/record-index/hooks/useLoadRecordIndexTable';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
export const RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect =
|
||||
() => {
|
||||
const setContextStoreNumberOfSelectedRecords = useSetRecoilState(
|
||||
contextStoreNumberOfSelectedRecordsState,
|
||||
const setContextStoreNumberOfSelectedRecords = useSetRecoilComponentStateV2(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
);
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilValue(
|
||||
contextStoreTargetedRecordsRuleState,
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const { objectNamePlural } = useContext(RecordIndexRootPropsContext);
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState';
|
||||
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
|
||||
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
export const RecordIndexContainerContextStoreObjectMetadataEffect = () => {
|
||||
const setContextStoreCurrentObjectMetadataItem = useSetRecoilState(
|
||||
contextStoreCurrentObjectMetadataIdState,
|
||||
const setContextStoreCurrentObjectMetadataItem = useSetRecoilComponentStateV2(
|
||||
contextStoreCurrentObjectMetadataIdComponentState,
|
||||
);
|
||||
const { objectNamePlural } = useContext(RecordIndexRootPropsContext);
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
|
||||
import { useHandleToggleColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleColumnFilter';
|
||||
import { useHandleToggleColumnSort } from '@/object-record/record-index/hooks/useHandleToggleColumnSort';
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useSetRecordCountInCurrentView } from '@/views/hooks/useSetRecordCountInCurrentView';
|
||||
|
||||
export const RecordIndexTableContainerEffect = () => {
|
||||
@ -73,8 +74,8 @@ export const RecordIndexTableContainerEffect = () => {
|
||||
);
|
||||
}, [setRecordCountInCurrentView, setOnEntityCountChange]);
|
||||
|
||||
const setContextStoreTargetedRecords = useSetRecoilState(
|
||||
contextStoreTargetedRecordsRuleState,
|
||||
const setContextStoreTargetedRecords = useSetRecoilComponentStateV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
const hasUserSelectedAllRows = useRecoilValue(hasUserSelectedAllRowsState);
|
||||
const selectedRowIds = useRecoilValue(selectedRowIdsSelector());
|
||||
|
@ -130,6 +130,7 @@ const mocks: MockedResponse[] = [
|
||||
const WrapperWithResponse = getJestMetadataAndApolloMocksAndContextStoreWrapper(
|
||||
{
|
||||
apolloMocks: mocks,
|
||||
componentInstanceId: 'recordIndexId',
|
||||
contextStoreTargetedRecordsRule: {
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [],
|
||||
@ -155,6 +156,7 @@ const graphqlEmptyResponse = [
|
||||
const WrapperWithEmptyResponse =
|
||||
getJestMetadataAndApolloMocksAndContextStoreWrapper({
|
||||
apolloMocks: graphqlEmptyResponse,
|
||||
componentInstanceId: 'recordIndexId',
|
||||
contextStoreTargetedRecordsRule: {
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [],
|
||||
@ -207,7 +209,6 @@ describe('useRecordData', () => {
|
||||
objectMetadataItem,
|
||||
callback,
|
||||
pageSize: 30,
|
||||
|
||||
delayMs: 0,
|
||||
}),
|
||||
{ wrapper: WrapperWithResponse },
|
||||
|
@ -7,7 +7,7 @@ import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefin
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
|
||||
@ -15,6 +15,7 @@ import { useRecordBoardStates } from '@/object-record/record-board/hooks/interna
|
||||
import { useFindManyParams } from '@/object-record/record-index/hooks/useLoadRecordIndexTable';
|
||||
import { EXPORT_TABLE_DATA_DEFAULT_PAGE_SIZE } from '@/object-record/record-index/options/constants/ExportTableDataDefaultPageSize';
|
||||
import { useRecordIndexOptionsForBoard } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
|
||||
export const sleep = (ms: number) =>
|
||||
@ -75,8 +76,8 @@ export const useRecordData = ({
|
||||
);
|
||||
const columns = useRecoilValue(visibleTableColumnsSelector());
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilValue(
|
||||
contextStoreTargetedRecordsRuleState,
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const queryFilter = computeContextStoreFilters(
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { ShowPageContainer } from '@/ui/layout/page/components/ShowPageContainer';
|
||||
|
||||
import { SetMainContextStoreComponentInstanceIdEffect } from '@/context-store/components/SetMainContextStoreComponentInstanceIdEffect';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord';
|
||||
import { RecordShowContainerContextStoreEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreEffect';
|
||||
import { useRecordShowContainerData } from '@/object-record/record-show/hooks/useRecordShowContainerData';
|
||||
import { useRecordShowContainerTabs } from '@/object-record/record-show/hooks/useRecordShowContainerTabs';
|
||||
import { ShowPageSubContainer } from '@/ui/layout/show-page/components/ShowPageSubContainer';
|
||||
@ -38,7 +41,16 @@ export const RecordShowContainer = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: 'record-show',
|
||||
}}
|
||||
>
|
||||
<RecordShowContainerContextStoreEffect
|
||||
recordId={objectRecordId}
|
||||
objectNameSingular={objectNameSingular}
|
||||
/>
|
||||
{!isInRightDrawer && <SetMainContextStoreComponentInstanceIdEffect />}
|
||||
{recordFromStore && recordFromStore.deletedAt && (
|
||||
<InformationBannerDeletedRecord
|
||||
recordId={objectRecordId}
|
||||
@ -57,6 +69,6 @@ export const RecordShowContainer = ({
|
||||
isNewRightDrawerItemLoading={isNewRightDrawerItemLoading}
|
||||
/>
|
||||
</ShowPageContainer>
|
||||
</>
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1,56 @@
|
||||
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export const RecordShowContainerContextStoreEffect = ({
|
||||
recordId,
|
||||
objectNameSingular,
|
||||
}: {
|
||||
recordId: string;
|
||||
objectNameSingular: string;
|
||||
}) => {
|
||||
const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const setContextStoreCurrentObjectMetadataId = useSetRecoilComponentStateV2(
|
||||
contextStoreCurrentObjectMetadataIdComponentState,
|
||||
);
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular: objectNameSingular,
|
||||
});
|
||||
|
||||
const setContextStoreNumberOfSelectedRecords = useSetRecoilComponentStateV2(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setContextStoreTargetedRecordsRule({
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [recordId],
|
||||
});
|
||||
setContextStoreCurrentObjectMetadataId(objectMetadataItem?.id);
|
||||
setContextStoreNumberOfSelectedRecords(1);
|
||||
|
||||
return () => {
|
||||
setContextStoreTargetedRecordsRule({
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [],
|
||||
});
|
||||
setContextStoreCurrentObjectMetadataId(null);
|
||||
setContextStoreNumberOfSelectedRecords(0);
|
||||
};
|
||||
}, [
|
||||
recordId,
|
||||
setContextStoreTargetedRecordsRule,
|
||||
setContextStoreCurrentObjectMetadataId,
|
||||
objectMetadataItem?.id,
|
||||
setContextStoreNumberOfSelectedRecords,
|
||||
]);
|
||||
|
||||
return null;
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { actionMenuDropdownPositionComponentState } from '@/action-menu/states/actionMenuDropdownPositionComponentState';
|
||||
import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
|
||||
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
|
||||
import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
@ -23,7 +23,7 @@ export const useTriggerActionMenuDropdown = ({
|
||||
|
||||
set(
|
||||
extractComponentState(
|
||||
actionMenuDropdownPositionComponentState,
|
||||
recordIndexActionMenuDropdownPositionComponentState,
|
||||
`action-menu-dropdown-${recordTableId}`,
|
||||
),
|
||||
{
|
||||
|
@ -7,7 +7,7 @@ import { useDebouncedCallback } from 'use-debounce';
|
||||
import { Button, ButtonAccent } from '@/ui/input/button/components/Button';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
|
||||
import { Modal } from '@/ui/layout/modal/components/Modal';
|
||||
import { Modal, ModalVariants } from '@/ui/layout/modal/components/Modal';
|
||||
import {
|
||||
Section,
|
||||
SectionAlignment,
|
||||
@ -26,6 +26,7 @@ export type ConfirmationModalProps = {
|
||||
confirmationValue?: string;
|
||||
confirmButtonAccent?: ButtonAccent;
|
||||
AdditionalButtons?: React.ReactNode;
|
||||
modalVariant?: ModalVariants;
|
||||
};
|
||||
|
||||
const StyledConfirmationModal = styled(Modal)`
|
||||
@ -71,6 +72,7 @@ export const ConfirmationModal = ({
|
||||
confirmationPlaceholder,
|
||||
confirmButtonAccent = 'danger',
|
||||
AdditionalButtons,
|
||||
modalVariant = 'primary',
|
||||
}: ConfirmationModalProps) => {
|
||||
const [inputConfirmationValue, setInputConfirmationValue] =
|
||||
useState<string>('');
|
||||
@ -113,6 +115,7 @@ export const ConfirmationModal = ({
|
||||
onEnter={handleEnter}
|
||||
isClosable={true}
|
||||
padding="large"
|
||||
modalVariant={modalVariant}
|
||||
>
|
||||
<StyledCenteredTitle>
|
||||
<H1Title title={title} fontColor={H1TitleFontColor.Primary} />
|
||||
|
@ -94,7 +94,9 @@ const StyledBackDrop = styled(motion.div)<{
|
||||
background: ${({ theme, modalVariant }) =>
|
||||
modalVariant === 'primary'
|
||||
? theme.background.overlayPrimary
|
||||
: theme.background.overlaySecondary};
|
||||
: modalVariant === 'secondary'
|
||||
? theme.background.overlaySecondary
|
||||
: theme.background.overlayTertiary};
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
@ -132,7 +134,7 @@ const ModalFooter = ({ children, className }: ModalFooterProps) => (
|
||||
|
||||
export type ModalSize = 'small' | 'medium' | 'large';
|
||||
export type ModalPadding = 'none' | 'small' | 'medium' | 'large';
|
||||
export type ModalVariants = 'primary' | 'secondary';
|
||||
export type ModalVariants = 'primary' | 'secondary' | 'tertiary';
|
||||
|
||||
export type ModalProps = React.PropsWithChildren & {
|
||||
size?: ModalSize;
|
||||
|
@ -1,52 +0,0 @@
|
||||
import { ReactNode } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { MOBILE_VIEWPORT } from 'twenty-ui';
|
||||
|
||||
import { RightDrawer } from '@/ui/layout/right-drawer/components/RightDrawer';
|
||||
|
||||
import { PagePanel } from './PagePanel';
|
||||
|
||||
type RightDrawerContainerProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
const StyledMainContainer = styled.div`
|
||||
background: ${({ theme }) => theme.background.noisy};
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
flex-direction: row;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
min-height: 0;
|
||||
padding-bottom: ${({ theme }) => theme.spacing(3)};
|
||||
padding-right: ${({ theme }) => theme.spacing(3)};
|
||||
padding-left: 0;
|
||||
width: 100%;
|
||||
|
||||
@media (max-width: ${MOBILE_VIEWPORT}px) {
|
||||
padding-left: ${({ theme }) => theme.spacing(3)};
|
||||
padding-bottom: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
type LeftContainerProps = {
|
||||
isRightDrawerOpen?: boolean;
|
||||
};
|
||||
|
||||
const StyledLeftContainer = styled.div<LeftContainerProps>`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const RightDrawerContainer = ({
|
||||
children,
|
||||
}: RightDrawerContainerProps) => (
|
||||
<StyledMainContainer>
|
||||
<StyledLeftContainer>
|
||||
<PagePanel>{children}</PagePanel>
|
||||
</StyledLeftContainer>
|
||||
<RightDrawer />
|
||||
</StyledMainContainer>
|
||||
);
|
@ -1,3 +1,4 @@
|
||||
import { RecordShowActionMenu } from '@/action-menu/components/RecordShowActionMenu';
|
||||
import { Calendar } from '@/activities/calendar/components/Calendar';
|
||||
import { EmailThreads } from '@/activities/emails/components/EmailThreads';
|
||||
import { Attachments } from '@/activities/files/components/Attachments';
|
||||
@ -6,13 +7,11 @@ import { ObjectTasks } from '@/activities/tasks/components/ObjectTasks';
|
||||
import { TimelineActivities } from '@/activities/timeline-activities/components/TimelineActivities';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { isNewViewableRecordLoadingState } from '@/object-record/record-right-drawer/states/isNewViewableRecordLoading';
|
||||
import { FieldsCard } from '@/object-record/record-show/components/FieldsCard';
|
||||
import { SummaryCard } from '@/object-record/record-show/components/SummaryCard';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { ShowPageActivityContainer } from '@/ui/layout/show-page/components/ShowPageActivityContainer';
|
||||
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
|
||||
import { SingleTabProps, TabList } from '@/ui/layout/tab/components/TabList';
|
||||
@ -25,9 +24,7 @@ import { WorkflowVersionVisualizerEffect } from '@/workflow/components/WorkflowV
|
||||
import { WorkflowVisualizer } from '@/workflow/components/WorkflowVisualizer';
|
||||
import { WorkflowVisualizerEffect } from '@/workflow/components/WorkflowVisualizerEffect';
|
||||
import styled from '@emotion/styled';
|
||||
import { useState } from 'react';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { IconTrash } from 'twenty-ui';
|
||||
|
||||
const StyledShowPageRightContainer = styled.div<{ isMobile: boolean }>`
|
||||
display: flex;
|
||||
@ -198,18 +195,6 @@ export const ShowPageSubContainer = ({
|
||||
}
|
||||
};
|
||||
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
|
||||
const { deleteOneRecord } = useDeleteOneRecord({
|
||||
objectNameSingular: targetableObject.targetObjectNameSingular,
|
||||
});
|
||||
|
||||
const handleDelete = async () => {
|
||||
setIsDeleting(true);
|
||||
await deleteOneRecord(targetableObject.id);
|
||||
setIsDeleting(false);
|
||||
};
|
||||
|
||||
const [recordFromStore] = useRecoilState<ObjectRecord | null>(
|
||||
recordStoreFamilyState(targetableObject.id),
|
||||
);
|
||||
@ -236,12 +221,7 @@ export const ShowPageSubContainer = ({
|
||||
</StyledContentContainer>
|
||||
{isInRightDrawer && recordFromStore && !recordFromStore.deletedAt && (
|
||||
<StyledButtonContainer>
|
||||
<Button
|
||||
Icon={IconTrash}
|
||||
onClick={handleDelete}
|
||||
disabled={isDeleting}
|
||||
title={isDeleting ? 'Deleting...' : 'Delete'}
|
||||
></Button>
|
||||
<RecordShowActionMenu actionMenuId={'right-drawer-action-menu'} />
|
||||
</StyledButtonContainer>
|
||||
)}
|
||||
</StyledShowPageRightContainer>
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { contextStoreCurrentViewIdState } from '@/context-store/states/contextStoreCurrentViewIdState';
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem';
|
||||
import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView';
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { isUndefined } from '@sniptt/guards';
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
@ -39,8 +39,8 @@ export const QueryParamsViewIdEffect = () => {
|
||||
objectMetadataItemId?.id,
|
||||
lastVisitedObjectMetadataItemId,
|
||||
);
|
||||
const setContextStoreCurrentViewId = useSetRecoilState(
|
||||
contextStoreCurrentViewIdState,
|
||||
const setContextStoreCurrentViewId = useSetRecoilComponentStateV2(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
);
|
||||
|
||||
// // TODO: scope view bar per view id if possible
|
||||
|
@ -1,6 +1,8 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { SetMainContextStoreComponentInstanceIdEffect } from '@/context-store/components/SetMainContextStoreComponentInstanceIdEffect';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
|
||||
import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId';
|
||||
@ -73,9 +75,16 @@ export const RecordIndexPage = () => {
|
||||
<RecordIndexPageHeader />
|
||||
<PageBody>
|
||||
<StyledIndexContainer>
|
||||
<RecordIndexContainerContextStoreObjectMetadataEffect />
|
||||
<RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect />
|
||||
<RecordIndexContainer />
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: 'record-index',
|
||||
}}
|
||||
>
|
||||
<RecordIndexContainerContextStoreObjectMetadataEffect />
|
||||
<RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect />
|
||||
<SetMainContextStoreComponentInstanceIdEffect />
|
||||
<RecordIndexContainer />
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
</StyledIndexContainer>
|
||||
</PageBody>
|
||||
</RecordIndexRootPropsContext.Provider>
|
||||
|
@ -12,7 +12,6 @@ import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle';
|
||||
import { RecordShowPageWorkflowHeader } from '@/workflow/components/RecordShowPageWorkflowHeader';
|
||||
import { RecordShowPageWorkflowVersionHeader } from '@/workflow/components/RecordShowPageWorkflowVersionHeader';
|
||||
import { RecordShowPageBaseHeader } from '~/pages/object-record/RecordShowPageBaseHeader';
|
||||
import { RecordShowPageContextStoreEffect } from '~/pages/object-record/RecordShowPageContextStoreEffect';
|
||||
import { RecordShowPageHeader } from '~/pages/object-record/RecordShowPageHeader';
|
||||
|
||||
export const RecordShowPage = () => {
|
||||
@ -40,7 +39,6 @@ export const RecordShowPage = () => {
|
||||
return (
|
||||
<RecordFieldValueSelectorContextProvider>
|
||||
<RecordValueSetterEffect recordId={objectRecordId} />
|
||||
<RecordShowPageContextStoreEffect recordId={objectRecordId} />
|
||||
<PageContainer>
|
||||
<PageTitle title={pageTitle} />
|
||||
<RecordShowPageHeader
|
||||
|
@ -1,57 +0,0 @@
|
||||
import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState';
|
||||
import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
|
||||
import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useEffect } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
export const RecordShowPageContextStoreEffect = ({
|
||||
recordId,
|
||||
}: {
|
||||
recordId: string;
|
||||
}) => {
|
||||
const setContextStoreTargetedRecordsRule = useSetRecoilState(
|
||||
contextStoreTargetedRecordsRuleState,
|
||||
);
|
||||
|
||||
const setContextStoreCurrentObjectMetadataId = useSetRecoilState(
|
||||
contextStoreCurrentObjectMetadataIdState,
|
||||
);
|
||||
|
||||
const { objectNameSingular } = useParams();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular: objectNameSingular ?? '',
|
||||
});
|
||||
|
||||
const setContextStoreNumberOfSelectedRecords = useSetRecoilState(
|
||||
contextStoreNumberOfSelectedRecordsState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setContextStoreTargetedRecordsRule({
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [recordId],
|
||||
});
|
||||
setContextStoreCurrentObjectMetadataId(objectMetadataItem?.id);
|
||||
setContextStoreNumberOfSelectedRecords(1);
|
||||
|
||||
return () => {
|
||||
setContextStoreTargetedRecordsRule({
|
||||
mode: 'selection',
|
||||
selectedRecordIds: [],
|
||||
});
|
||||
setContextStoreCurrentObjectMetadataId(null);
|
||||
setContextStoreNumberOfSelectedRecords(0);
|
||||
};
|
||||
}, [
|
||||
recordId,
|
||||
setContextStoreTargetedRecordsRule,
|
||||
setContextStoreCurrentObjectMetadataId,
|
||||
objectMetadataItem?.id,
|
||||
setContextStoreNumberOfSelectedRecords,
|
||||
]);
|
||||
|
||||
return null;
|
||||
};
|
@ -1,12 +1,12 @@
|
||||
import { ReactNode, useEffect, useState } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState';
|
||||
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||
import {
|
||||
ContextStoreTargetedRecordsRule,
|
||||
contextStoreTargetedRecordsRuleState,
|
||||
} from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
} from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
|
||||
export const JestContextStoreSetter = ({
|
||||
contextStoreTargetedRecordsRule = {
|
||||
@ -20,11 +20,12 @@ export const JestContextStoreSetter = ({
|
||||
contextStoreCurrentObjectMetadataNameSingular?: string;
|
||||
children: ReactNode;
|
||||
}) => {
|
||||
const setContextStoreTargetedRecordsRule = useSetRecoilState(
|
||||
contextStoreTargetedRecordsRuleState,
|
||||
const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
const setContextStoreCurrentObjectMetadataId = useSetRecoilState(
|
||||
contextStoreCurrentObjectMetadataIdState,
|
||||
|
||||
const setContextStoreCurrentObjectMetadataId = useSetRecoilComponentStateV2(
|
||||
contextStoreCurrentObjectMetadataIdComponentState,
|
||||
);
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { MockedResponse } from '@apollo/client/testing';
|
||||
import { ReactNode } from 'react';
|
||||
import { MutableSnapshot } from 'recoil';
|
||||
@ -10,6 +11,7 @@ export const getJestMetadataAndApolloMocksAndContextStoreWrapper = ({
|
||||
onInitializeRecoilSnapshot,
|
||||
contextStoreTargetedRecordsRule,
|
||||
contextStoreCurrentObjectMetadataNameSingular,
|
||||
componentInstanceId,
|
||||
}: {
|
||||
apolloMocks:
|
||||
| readonly MockedResponse<Record<string, any>, Record<string, any>>[]
|
||||
@ -17,6 +19,7 @@ export const getJestMetadataAndApolloMocksAndContextStoreWrapper = ({
|
||||
onInitializeRecoilSnapshot?: (snapshot: MutableSnapshot) => void;
|
||||
contextStoreTargetedRecordsRule?: ContextStoreTargetedRecordsRule;
|
||||
contextStoreCurrentObjectMetadataNameSingular?: string;
|
||||
componentInstanceId: string;
|
||||
}) => {
|
||||
const Wrapper = getJestMetadataAndApolloMocksWrapper({
|
||||
apolloMocks,
|
||||
@ -24,14 +27,20 @@ export const getJestMetadataAndApolloMocksAndContextStoreWrapper = ({
|
||||
});
|
||||
return ({ children }: { children: ReactNode }) => (
|
||||
<Wrapper>
|
||||
<JestContextStoreSetter
|
||||
contextStoreTargetedRecordsRule={contextStoreTargetedRecordsRule}
|
||||
contextStoreCurrentObjectMetadataNameSingular={
|
||||
contextStoreCurrentObjectMetadataNameSingular
|
||||
}
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: componentInstanceId,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</JestContextStoreSetter>
|
||||
<JestContextStoreSetter
|
||||
contextStoreTargetedRecordsRule={contextStoreTargetedRecordsRule}
|
||||
contextStoreCurrentObjectMetadataNameSingular={
|
||||
contextStoreCurrentObjectMetadataNameSingular
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</JestContextStoreSetter>
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
@ -23,8 +23,9 @@ export const BACKGROUND_DARK = {
|
||||
lighter: RGBA(GRAY_SCALE.gray0, 0.03),
|
||||
danger: RGBA(COLOR.red, 0.08),
|
||||
},
|
||||
overlayPrimary: RGBA(GRAY_SCALE.gray80, 0.8),
|
||||
overlaySecondary: RGBA(GRAY_SCALE.gray80, 0.4),
|
||||
overlayPrimary: RGBA(GRAY_SCALE.gray90, 0.8),
|
||||
overlaySecondary: RGBA(GRAY_SCALE.gray90, 0.4),
|
||||
overlayTertiary: RGBA(GRAY_SCALE.gray90, 0.4),
|
||||
radialGradient: `radial-gradient(50% 62.62% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`,
|
||||
radialGradientHover: `radial-gradient(76.32% 95.59% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`,
|
||||
primaryInverted: GRAY_SCALE.gray20,
|
||||
|
@ -23,8 +23,9 @@ export const BACKGROUND_LIGHT = {
|
||||
lighter: RGBA(GRAY_SCALE.gray100, 0.02),
|
||||
danger: RGBA(COLOR.red, 0.08),
|
||||
},
|
||||
overlayPrimary: RGBA(GRAY_SCALE.gray80, 0.8),
|
||||
overlaySecondary: RGBA(GRAY_SCALE.gray80, 0.4),
|
||||
overlayPrimary: RGBA(GRAY_SCALE.gray90, 0.8),
|
||||
overlaySecondary: RGBA(GRAY_SCALE.gray90, 0.4),
|
||||
overlayTertiary: RGBA(GRAY_SCALE.gray90, 0.08),
|
||||
radialGradient: `radial-gradient(50% 62.62% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`,
|
||||
radialGradientHover: `radial-gradient(76.32% 95.59% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`,
|
||||
primaryInverted: GRAY_SCALE.gray60,
|
||||
|
Loading…
Reference in New Issue
Block a user