250 implement restore context button on command menu (#9836)
Closes https://github.com/twentyhq/core-team-issues/issues/250 https://github.com/user-attachments/assets/9c120188-497d-4273-9137-f8d0de3bd884
This commit is contained in:
@ -1,19 +1,24 @@
|
|||||||
import { CommandGroup } from '@/command-menu/components/CommandGroup';
|
import { CommandGroup } from '@/command-menu/components/CommandGroup';
|
||||||
import { CommandMenuDefaultSelectionEffect } from '@/command-menu/components/CommandMenuDefaultSelectionEffect';
|
import { CommandMenuDefaultSelectionEffect } from '@/command-menu/components/CommandMenuDefaultSelectionEffect';
|
||||||
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
|
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
|
||||||
|
import { ResetContextToSelectionCommandButton } from '@/command-menu/components/ResetContextToSelectionCommandButton';
|
||||||
import { COMMAND_MENU_SEARCH_BAR_HEIGHT } from '@/command-menu/constants/CommandMenuSearchBarHeight';
|
import { COMMAND_MENU_SEARCH_BAR_HEIGHT } from '@/command-menu/constants/CommandMenuSearchBarHeight';
|
||||||
import { COMMAND_MENU_SEARCH_BAR_PADDING } from '@/command-menu/constants/CommandMenuSearchBarPadding';
|
import { COMMAND_MENU_SEARCH_BAR_PADDING } from '@/command-menu/constants/CommandMenuSearchBarPadding';
|
||||||
import { useCommandMenuOnItemClick } from '@/command-menu/hooks/useCommandMenuOnItemClick';
|
import { useCommandMenuOnItemClick } from '@/command-menu/hooks/useCommandMenuOnItemClick';
|
||||||
import { useMatchingCommandMenuCommands } from '@/command-menu/hooks/useMatchingCommandMenuCommands';
|
import { useMatchingCommandMenuCommands } from '@/command-menu/hooks/useMatchingCommandMenuCommands';
|
||||||
|
import { useResetPreviousCommandMenuContext } from '@/command-menu/hooks/useResetPreviousCommandMenuContext';
|
||||||
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
|
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
|
||||||
import { Command } from '@/command-menu/types/Command';
|
import { Command } from '@/command-menu/types/Command';
|
||||||
|
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||||
import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
|
import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
|
||||||
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
||||||
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
|
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
|
||||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||||
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useLingui } from '@lingui/react/macro';
|
import { useLingui } from '@lingui/react/macro';
|
||||||
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { isDefined } from 'twenty-ui';
|
import { isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
@ -60,6 +65,8 @@ export const CommandMenu = () => {
|
|||||||
const { t } = useLingui();
|
const { t } = useLingui();
|
||||||
|
|
||||||
const { onItemClick } = useCommandMenuOnItemClick();
|
const { onItemClick } = useCommandMenuOnItemClick();
|
||||||
|
const { resetPreviousCommandMenuContext } =
|
||||||
|
useResetPreviousCommandMenuContext();
|
||||||
|
|
||||||
const commandMenuSearch = useRecoilValue(commandMenuSearchState);
|
const commandMenuSearch = useRecoilValue(commandMenuSearchState);
|
||||||
|
|
||||||
@ -84,22 +91,33 @@ export const CommandMenu = () => {
|
|||||||
commandMenuSearch,
|
commandMenuSearch,
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectableItems = copilotCommands
|
const selectableItems: Command[] = copilotCommands
|
||||||
.concat(matchingStandardActionRecordSelectionCommands)
|
.concat(
|
||||||
.concat(matchingWorkflowRunRecordSelectionCommands)
|
matchingStandardActionRecordSelectionCommands,
|
||||||
.concat(matchingStandardActionGlobalCommands)
|
matchingWorkflowRunRecordSelectionCommands,
|
||||||
.concat(matchingWorkflowRunGlobalCommands)
|
matchingStandardActionGlobalCommands,
|
||||||
.concat(matchingNavigateCommand)
|
matchingWorkflowRunGlobalCommands,
|
||||||
.concat(peopleCommands)
|
matchingNavigateCommand,
|
||||||
.concat(companyCommands)
|
peopleCommands,
|
||||||
.concat(opportunityCommands)
|
companyCommands,
|
||||||
.concat(noteCommands)
|
opportunityCommands,
|
||||||
.concat(tasksCommands)
|
noteCommands,
|
||||||
.concat(customObjectCommands)
|
tasksCommands,
|
||||||
|
customObjectCommands,
|
||||||
|
)
|
||||||
.filter(isDefined);
|
.filter(isDefined);
|
||||||
|
|
||||||
|
const previousContextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
|
||||||
|
contextStoreCurrentObjectMetadataIdComponentState,
|
||||||
|
'command-menu-previous',
|
||||||
|
);
|
||||||
|
|
||||||
const selectableItemIds = selectableItems.map((item) => item.id);
|
const selectableItemIds = selectableItems.map((item) => item.id);
|
||||||
|
|
||||||
|
if (isNonEmptyString(previousContextStoreCurrentObjectMetadataId)) {
|
||||||
|
selectableItemIds.unshift('reset-context-to-selection');
|
||||||
|
}
|
||||||
|
|
||||||
const commandGroups: CommandGroupConfig[] = [
|
const commandGroups: CommandGroupConfig[] = [
|
||||||
{
|
{
|
||||||
heading: t`Copilot`,
|
heading: t`Copilot`,
|
||||||
@ -168,6 +186,11 @@ export const CommandMenu = () => {
|
|||||||
selectableItemIdArray={selectableItemIds}
|
selectableItemIdArray={selectableItemIds}
|
||||||
hotkeyScope={AppHotkeyScope.CommandMenu}
|
hotkeyScope={AppHotkeyScope.CommandMenu}
|
||||||
onEnter={(itemId) => {
|
onEnter={(itemId) => {
|
||||||
|
if (itemId === 'reset-context-to-selection') {
|
||||||
|
resetPreviousCommandMenuContext();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const command = selectableItems.find(
|
const command = selectableItems.find(
|
||||||
(item) => item.id === itemId,
|
(item) => item.id === itemId,
|
||||||
);
|
);
|
||||||
@ -184,6 +207,16 @@ export const CommandMenu = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{isNonEmptyString(
|
||||||
|
previousContextStoreCurrentObjectMetadataId,
|
||||||
|
) && (
|
||||||
|
<CommandGroup heading={t`Context`} key={t`Context`}>
|
||||||
|
<SelectableItem itemId="reset-context-to-selection">
|
||||||
|
<ResetContextToSelectionCommandButton />
|
||||||
|
</SelectableItem>
|
||||||
|
</CommandGroup>
|
||||||
|
)}
|
||||||
|
|
||||||
{isNoResults && !isLoading && (
|
{isNoResults && !isLoading && (
|
||||||
<StyledEmpty>No results found</StyledEmpty>
|
<StyledEmpty>No results found</StyledEmpty>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
const StyledChip = styled.div`
|
const StyledChip = styled.div<{ variant?: 'default' | 'small' }>`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: ${({ theme }) => theme.background.transparent.light};
|
background: ${({ theme }) => theme.background.transparent.light};
|
||||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||||
@ -8,7 +8,8 @@ const StyledChip = styled.div`
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: ${({ theme }) => theme.spacing(1)};
|
gap: ${({ theme }) => theme.spacing(1)};
|
||||||
height: ${({ theme }) => theme.spacing(8)};
|
height: ${({ theme, variant }) =>
|
||||||
|
variant === 'small' ? theme.spacing(6) : theme.spacing(8)};
|
||||||
padding: 0 ${({ theme }) => theme.spacing(2)};
|
padding: 0 ${({ theme }) => theme.spacing(2)};
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
@ -40,13 +41,15 @@ export const CommandMenuContextChip = ({
|
|||||||
Icons,
|
Icons,
|
||||||
text,
|
text,
|
||||||
withIconBackground,
|
withIconBackground,
|
||||||
|
variant = 'default',
|
||||||
}: {
|
}: {
|
||||||
Icons: React.ReactNode[];
|
Icons: React.ReactNode[];
|
||||||
text?: string;
|
text?: string;
|
||||||
withIconBackground?: boolean;
|
withIconBackground?: boolean;
|
||||||
|
variant?: 'default' | 'small';
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<StyledChip>
|
<StyledChip variant={variant}>
|
||||||
<StyledIconsContainer>
|
<StyledIconsContainer>
|
||||||
{Icons.map((Icon, index) => (
|
{Icons.map((Icon, index) => (
|
||||||
<StyledIconWrapper
|
<StyledIconWrapper
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
import { CommandMenuContextChip } from '@/command-menu/components/CommandMenuContextChip';
|
import { CommandMenuContextChip } from '@/command-menu/components/CommandMenuContextChip';
|
||||||
import { CommandMenuContextRecordChipAvatars } from '@/command-menu/components/CommandMenuContextRecordChipAvatars';
|
import { CommandMenuContextRecordChipAvatars } from '@/command-menu/components/CommandMenuContextRecordChipAvatars';
|
||||||
|
import { getSelectedRecordsContextText } from '@/command-menu/utils/getRecordContextText';
|
||||||
import { useFindManyRecordsSelectedInContextStore } from '@/context-store/hooks/useFindManyRecordsSelectedInContextStore';
|
import { useFindManyRecordsSelectedInContextStore } from '@/context-store/hooks/useFindManyRecordsSelectedInContextStore';
|
||||||
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
||||||
import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier';
|
|
||||||
import { capitalize } from 'twenty-shared';
|
|
||||||
|
|
||||||
export const CommandMenuContextRecordChip = ({
|
export const CommandMenuContextRecordChip = ({
|
||||||
objectMetadataItemId,
|
objectMetadataItemId,
|
||||||
|
instanceId,
|
||||||
|
variant = 'default',
|
||||||
}: {
|
}: {
|
||||||
objectMetadataItemId: string;
|
objectMetadataItemId: string;
|
||||||
|
instanceId?: string;
|
||||||
|
variant?: 'default' | 'small';
|
||||||
}) => {
|
}) => {
|
||||||
const { objectMetadataItem } = useObjectMetadataItemById({
|
const { objectMetadataItem } = useObjectMetadataItemById({
|
||||||
objectId: objectMetadataItemId,
|
objectId: objectMetadataItemId,
|
||||||
@ -17,6 +20,7 @@ export const CommandMenuContextRecordChip = ({
|
|||||||
const { records, loading, totalCount } =
|
const { records, loading, totalCount } =
|
||||||
useFindManyRecordsSelectedInContextStore({
|
useFindManyRecordsSelectedInContextStore({
|
||||||
limit: 3,
|
limit: 3,
|
||||||
|
instanceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (loading || !totalCount) {
|
if (loading || !totalCount) {
|
||||||
@ -31,17 +35,16 @@ export const CommandMenuContextRecordChip = ({
|
|||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
const text =
|
|
||||||
totalCount === 1
|
|
||||||
? getObjectRecordIdentifier({ objectMetadataItem, record: records[0] })
|
|
||||||
.name
|
|
||||||
: `${totalCount} ${capitalize(objectMetadataItem.namePlural)}`;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandMenuContextChip
|
<CommandMenuContextChip
|
||||||
text={text}
|
text={getSelectedRecordsContextText(
|
||||||
|
objectMetadataItem,
|
||||||
|
records,
|
||||||
|
totalCount,
|
||||||
|
)}
|
||||||
Icons={Avatars}
|
Icons={Avatars}
|
||||||
withIconBackground={true}
|
withIconBackground={true}
|
||||||
|
variant={variant}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,7 +14,10 @@ export const CommandMenuDefaultSelectionEffect = ({
|
|||||||
const selectedItemId = useRecoilValue(selectedItemIdState);
|
const selectedItemId = useRecoilValue(selectedItemIdState);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDefined(selectedItemId)) {
|
if (
|
||||||
|
isDefined(selectedItemId) &&
|
||||||
|
selectableItemIds.includes(selectedItemId)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { IconArrowUpRight, IconComponent, MenuItemCommand } from 'twenty-ui';
|
|||||||
|
|
||||||
import { useCommandMenuOnItemClick } from '@/command-menu/hooks/useCommandMenuOnItemClick';
|
import { useCommandMenuOnItemClick } from '@/command-menu/hooks/useCommandMenuOnItemClick';
|
||||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
export type CommandMenuItemProps = {
|
export type CommandMenuItemProps = {
|
||||||
label: string;
|
label: string;
|
||||||
@ -14,6 +15,7 @@ export type CommandMenuItemProps = {
|
|||||||
firstHotKey?: string;
|
firstHotKey?: string;
|
||||||
secondHotKey?: string;
|
secondHotKey?: string;
|
||||||
shouldCloseCommandMenuOnClick?: boolean;
|
shouldCloseCommandMenuOnClick?: boolean;
|
||||||
|
RightComponent?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CommandMenuItem = ({
|
export const CommandMenuItem = ({
|
||||||
@ -25,6 +27,7 @@ export const CommandMenuItem = ({
|
|||||||
firstHotKey,
|
firstHotKey,
|
||||||
secondHotKey,
|
secondHotKey,
|
||||||
shouldCloseCommandMenuOnClick,
|
shouldCloseCommandMenuOnClick,
|
||||||
|
RightComponent,
|
||||||
}: CommandMenuItemProps) => {
|
}: CommandMenuItemProps) => {
|
||||||
const { onItemClick } = useCommandMenuOnItemClick();
|
const { onItemClick } = useCommandMenuOnItemClick();
|
||||||
|
|
||||||
@ -49,6 +52,7 @@ export const CommandMenuItem = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
isSelected={isSelectedItemId}
|
isSelected={isSelectedItemId}
|
||||||
|
RightComponent={RightComponent}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,56 @@
|
|||||||
|
import { CommandMenuContextRecordChip } from '@/command-menu/components/CommandMenuContextRecordChip';
|
||||||
|
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
|
||||||
|
import { useResetPreviousCommandMenuContext } from '@/command-menu/hooks/useResetPreviousCommandMenuContext';
|
||||||
|
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||||
|
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||||
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
|
import { t } from '@lingui/core/macro';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import { IconArrowBackUp, isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
|
export const ResetContextToSelectionCommandButton = () => {
|
||||||
|
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||||
|
contextStoreTargetedRecordsRuleComponentState,
|
||||||
|
'command-menu-previous',
|
||||||
|
);
|
||||||
|
|
||||||
|
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
|
||||||
|
contextStoreCurrentObjectMetadataIdComponentState,
|
||||||
|
'command-menu-previous',
|
||||||
|
);
|
||||||
|
|
||||||
|
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||||
|
|
||||||
|
const objectMetadataItem = objectMetadataItems.find(
|
||||||
|
(objectMetadataItem) =>
|
||||||
|
objectMetadataItem.id === contextStoreCurrentObjectMetadataId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { resetPreviousCommandMenuContext } =
|
||||||
|
useResetPreviousCommandMenuContext();
|
||||||
|
|
||||||
|
if (
|
||||||
|
!isDefined(objectMetadataItem) ||
|
||||||
|
(contextStoreTargetedRecordsRule.mode === 'selection' &&
|
||||||
|
contextStoreTargetedRecordsRule.selectedRecordIds.length === 0)
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CommandMenuItem
|
||||||
|
id="reset-context-to-selection"
|
||||||
|
Icon={IconArrowBackUp}
|
||||||
|
label={t`Reset to`}
|
||||||
|
RightComponent={
|
||||||
|
<CommandMenuContextRecordChip
|
||||||
|
objectMetadataItemId={objectMetadataItem.id}
|
||||||
|
instanceId="command-menu-previous"
|
||||||
|
variant="small"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
onClick={resetPreviousCommandMenuContext}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -4,19 +4,18 @@ import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchS
|
|||||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||||
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
|
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
|
||||||
|
|
||||||
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
|
|
||||||
import { CommandMenuPages } from '@/command-menu/components/CommandMenuPages';
|
import { CommandMenuPages } from '@/command-menu/components/CommandMenuPages';
|
||||||
|
import { useCopyContextStoreStates } from '@/command-menu/hooks/useCopyContextStoreAndActionMenuStates';
|
||||||
|
import { useResetContextStoreStates } from '@/command-menu/hooks/useResetContextStoreStates';
|
||||||
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
|
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
|
||||||
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageTitle';
|
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageTitle';
|
||||||
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
|
||||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
|
||||||
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
|
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
|
||||||
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
|
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
|
||||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||||
import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
|
import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
|
||||||
|
import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
|
||||||
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
|
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
|
||||||
import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState';
|
import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState';
|
||||||
import { emitRightDrawerCloseEvent } from '@/ui/layout/right-drawer/utils/emitRightDrawerCloseEvent';
|
import { emitRightDrawerCloseEvent } from '@/ui/layout/right-drawer/utils/emitRightDrawerCloseEvent';
|
||||||
@ -33,120 +32,22 @@ export const useCommandMenu = () => {
|
|||||||
mainContextStoreComponentInstanceIdState,
|
mainContextStoreComponentInstanceIdState,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { copyContextStoreStates } = useCopyContextStoreStates();
|
||||||
|
const { resetContextStoreStates } = useResetContextStoreStates();
|
||||||
|
|
||||||
const openCommandMenu = useRecoilCallback(
|
const openCommandMenu = useRecoilCallback(
|
||||||
({ snapshot, set }) =>
|
({ set }) =>
|
||||||
() => {
|
() => {
|
||||||
if (isDefined(mainContextStoreComponentInstanceId)) {
|
copyContextStoreStates({
|
||||||
const contextStoreCurrentObjectMetadataId = snapshot
|
instanceIdToCopyFrom: mainContextStoreComponentInstanceId,
|
||||||
.getLoadable(
|
instanceIdToCopyTo: 'command-menu',
|
||||||
contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
|
});
|
||||||
instanceId: mainContextStoreComponentInstanceId,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
contextStoreCurrentObjectMetadataId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const contextStoreTargetedRecordsRule = snapshot
|
|
||||||
.getLoadable(
|
|
||||||
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
|
||||||
instanceId: mainContextStoreComponentInstanceId,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
contextStoreTargetedRecordsRule,
|
|
||||||
);
|
|
||||||
|
|
||||||
const contextStoreNumberOfSelectedRecords = snapshot
|
|
||||||
.getLoadable(
|
|
||||||
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
|
||||||
instanceId: mainContextStoreComponentInstanceId,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
contextStoreNumberOfSelectedRecords,
|
|
||||||
);
|
|
||||||
|
|
||||||
const contextStoreFilters = snapshot
|
|
||||||
.getLoadable(
|
|
||||||
contextStoreFiltersComponentState.atomFamily({
|
|
||||||
instanceId: mainContextStoreComponentInstanceId,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreFiltersComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
contextStoreFilters,
|
|
||||||
);
|
|
||||||
|
|
||||||
const contextStoreCurrentViewId = snapshot
|
|
||||||
.getLoadable(
|
|
||||||
contextStoreCurrentViewIdComponentState.atomFamily({
|
|
||||||
instanceId: mainContextStoreComponentInstanceId,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreCurrentViewIdComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
contextStoreCurrentViewId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const contextStoreCurrentViewType = snapshot
|
|
||||||
.getLoadable(
|
|
||||||
contextStoreCurrentViewTypeComponentState.atomFamily({
|
|
||||||
instanceId: mainContextStoreComponentInstanceId,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreCurrentViewTypeComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
contextStoreCurrentViewType,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const actionMenuEntries = snapshot
|
|
||||||
.getLoadable(
|
|
||||||
actionMenuEntriesComponentState.atomFamily({
|
|
||||||
instanceId: mainContextStoreComponentInstanceId,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
set(
|
|
||||||
actionMenuEntriesComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
actionMenuEntries,
|
|
||||||
);
|
|
||||||
|
|
||||||
set(isCommandMenuOpenedState, true);
|
set(isCommandMenuOpenedState, true);
|
||||||
setHotkeyScopeAndMemorizePreviousScope(AppHotkeyScope.CommandMenuOpen);
|
setHotkeyScopeAndMemorizePreviousScope(AppHotkeyScope.CommandMenuOpen);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
|
copyContextStoreStates,
|
||||||
mainContextStoreComponentInstanceId,
|
mainContextStoreComponentInstanceId,
|
||||||
setHotkeyScopeAndMemorizePreviousScope,
|
setHotkeyScopeAndMemorizePreviousScope,
|
||||||
],
|
],
|
||||||
@ -160,57 +61,8 @@ export const useCommandMenu = () => {
|
|||||||
.getValue();
|
.getValue();
|
||||||
|
|
||||||
if (isCommandMenuOpened) {
|
if (isCommandMenuOpened) {
|
||||||
set(
|
resetContextStoreStates('command-menu');
|
||||||
contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
|
resetContextStoreStates('command-menu-previous');
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
mode: 'selection',
|
|
||||||
selectedRecordIds: [],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreFiltersComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreCurrentViewIdComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
|
|
||||||
set(
|
|
||||||
contextStoreCurrentViewTypeComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
|
|
||||||
set(
|
|
||||||
actionMenuEntriesComponentState.atomFamily({
|
|
||||||
instanceId: 'command-menu',
|
|
||||||
}),
|
|
||||||
new Map(),
|
|
||||||
);
|
|
||||||
|
|
||||||
set(viewableRecordIdState, null);
|
set(viewableRecordIdState, null);
|
||||||
set(commandMenuPageState, CommandMenuPages.Root);
|
set(commandMenuPageState, CommandMenuPages.Root);
|
||||||
@ -225,7 +77,7 @@ export const useCommandMenu = () => {
|
|||||||
emitRightDrawerCloseEvent();
|
emitRightDrawerCloseEvent();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[goBackToPreviousHotkeyScope, resetSelectedItem],
|
[goBackToPreviousHotkeyScope, resetContextStoreStates, resetSelectedItem],
|
||||||
);
|
);
|
||||||
|
|
||||||
const toggleCommandMenu = useRecoilCallback(
|
const toggleCommandMenu = useRecoilCallback(
|
||||||
@ -258,44 +110,59 @@ export const useCommandMenu = () => {
|
|||||||
[openCommandMenu],
|
[openCommandMenu],
|
||||||
);
|
);
|
||||||
|
|
||||||
const setGlobalCommandMenuContext = useRecoilCallback(({ set }) => {
|
const setGlobalCommandMenuContext = useRecoilCallback(
|
||||||
return () => {
|
({ set }) => {
|
||||||
set(
|
return () => {
|
||||||
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
copyContextStoreStates({
|
||||||
instanceId: 'command-menu',
|
instanceIdToCopyFrom: 'command-menu',
|
||||||
}),
|
instanceIdToCopyTo: 'command-menu-previous',
|
||||||
{
|
});
|
||||||
mode: 'selection',
|
|
||||||
selectedRecordIds: [],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
set(
|
set(
|
||||||
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
||||||
instanceId: 'command-menu',
|
instanceId: 'command-menu',
|
||||||
}),
|
}),
|
||||||
0,
|
{
|
||||||
);
|
mode: 'selection',
|
||||||
|
selectedRecordIds: [],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
set(
|
set(
|
||||||
contextStoreCurrentViewTypeComponentState.atomFamily({
|
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
||||||
instanceId: 'command-menu',
|
instanceId: 'command-menu',
|
||||||
}),
|
}),
|
||||||
null,
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
set(commandMenuPageInfoState, {
|
set(
|
||||||
title: undefined,
|
contextStoreFiltersComponentState.atomFamily({
|
||||||
Icon: undefined,
|
instanceId: 'command-menu',
|
||||||
});
|
}),
|
||||||
};
|
[],
|
||||||
}, []);
|
);
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreCurrentViewTypeComponentState.atomFamily({
|
||||||
|
instanceId: 'command-menu',
|
||||||
|
}),
|
||||||
|
ContextStoreViewType.Table,
|
||||||
|
);
|
||||||
|
|
||||||
|
set(commandMenuPageInfoState, {
|
||||||
|
title: undefined,
|
||||||
|
Icon: undefined,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[copyContextStoreStates],
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
openCommandMenu,
|
openCommandMenu,
|
||||||
closeCommandMenu,
|
closeCommandMenu,
|
||||||
openRecordInCommandMenu,
|
openRecordInCommandMenu,
|
||||||
toggleCommandMenu,
|
toggleCommandMenu,
|
||||||
resetCommandMenuContext: setGlobalCommandMenuContext,
|
setGlobalCommandMenuContext,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,15 +2,17 @@ import { CommandMenuPages } from '@/command-menu/components/CommandMenuPages';
|
|||||||
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||||
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
|
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
|
||||||
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
|
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
|
||||||
|
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||||
import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu';
|
import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
|
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
|
||||||
|
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
|
|
||||||
export const useCommandMenuHotKeys = () => {
|
export const useCommandMenuHotKeys = () => {
|
||||||
const { closeCommandMenu, toggleCommandMenu, resetCommandMenuContext } =
|
const { closeCommandMenu, toggleCommandMenu, setGlobalCommandMenuContext } =
|
||||||
useCommandMenu();
|
useCommandMenu();
|
||||||
|
|
||||||
const commandMenuSearch = useRecoilValue(commandMenuSearchState);
|
const commandMenuSearch = useRecoilValue(commandMenuSearchState);
|
||||||
@ -19,6 +21,11 @@ export const useCommandMenuHotKeys = () => {
|
|||||||
|
|
||||||
const commandMenuPage = useRecoilValue(commandMenuPageState);
|
const commandMenuPage = useRecoilValue(commandMenuPageState);
|
||||||
|
|
||||||
|
const contextStoreTargetedRecordsRuleComponent = useRecoilComponentValueV2(
|
||||||
|
contextStoreTargetedRecordsRuleComponentState,
|
||||||
|
'command-menu',
|
||||||
|
);
|
||||||
|
|
||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
'ctrl+k,meta+k',
|
'ctrl+k,meta+k',
|
||||||
() => {
|
() => {
|
||||||
@ -43,9 +50,14 @@ export const useCommandMenuHotKeys = () => {
|
|||||||
() => {
|
() => {
|
||||||
if (
|
if (
|
||||||
commandMenuPage === CommandMenuPages.Root &&
|
commandMenuPage === CommandMenuPages.Root &&
|
||||||
!isNonEmptyString(commandMenuSearch)
|
!isNonEmptyString(commandMenuSearch) &&
|
||||||
|
!(
|
||||||
|
contextStoreTargetedRecordsRuleComponent.mode === 'selection' &&
|
||||||
|
contextStoreTargetedRecordsRuleComponent.selectedRecordIds.length ===
|
||||||
|
0
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
resetCommandMenuContext();
|
setGlobalCommandMenuContext();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AppHotkeyScope.CommandMenuOpen,
|
AppHotkeyScope.CommandMenuOpen,
|
||||||
|
|||||||
@ -0,0 +1,129 @@
|
|||||||
|
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
|
||||||
|
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||||
|
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||||
|
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
|
||||||
|
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
|
||||||
|
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||||
|
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||||
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
|
export const useCopyContextStoreStates = () => {
|
||||||
|
const copyContextStoreStates = useRecoilCallback(
|
||||||
|
({ snapshot, set }) =>
|
||||||
|
({
|
||||||
|
instanceIdToCopyFrom,
|
||||||
|
instanceIdToCopyTo,
|
||||||
|
}: {
|
||||||
|
instanceIdToCopyFrom: string;
|
||||||
|
instanceIdToCopyTo: string;
|
||||||
|
}) => {
|
||||||
|
const contextStoreCurrentObjectMetadataId = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyFrom,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyTo,
|
||||||
|
}),
|
||||||
|
contextStoreCurrentObjectMetadataId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const contextStoreTargetedRecordsRule = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyFrom,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyTo,
|
||||||
|
}),
|
||||||
|
contextStoreTargetedRecordsRule,
|
||||||
|
);
|
||||||
|
|
||||||
|
const contextStoreNumberOfSelectedRecords = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyFrom,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyTo,
|
||||||
|
}),
|
||||||
|
contextStoreNumberOfSelectedRecords,
|
||||||
|
);
|
||||||
|
|
||||||
|
const contextStoreFilters = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
contextStoreFiltersComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyFrom,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreFiltersComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyTo,
|
||||||
|
}),
|
||||||
|
contextStoreFilters,
|
||||||
|
);
|
||||||
|
|
||||||
|
const contextStoreCurrentViewId = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
contextStoreCurrentViewIdComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyFrom,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreCurrentViewIdComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyTo,
|
||||||
|
}),
|
||||||
|
contextStoreCurrentViewId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const contextStoreCurrentViewType = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
contextStoreCurrentViewTypeComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyFrom,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreCurrentViewTypeComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyTo,
|
||||||
|
}),
|
||||||
|
contextStoreCurrentViewType,
|
||||||
|
);
|
||||||
|
|
||||||
|
const actionMenuEntries = snapshot
|
||||||
|
.getLoadable(
|
||||||
|
actionMenuEntriesComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyFrom,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.getValue();
|
||||||
|
|
||||||
|
set(
|
||||||
|
actionMenuEntriesComponentState.atomFamily({
|
||||||
|
instanceId: instanceIdToCopyTo,
|
||||||
|
}),
|
||||||
|
actionMenuEntries,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { copyContextStoreStates };
|
||||||
|
};
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
|
||||||
|
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||||
|
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||||
|
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
|
||||||
|
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
|
||||||
|
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||||
|
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||||
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
|
export const useResetContextStoreStates = () => {
|
||||||
|
const resetContextStoreStates = useRecoilCallback(({ set }) => {
|
||||||
|
return (instanceId: string) => {
|
||||||
|
set(
|
||||||
|
contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
|
||||||
|
instanceId,
|
||||||
|
}),
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
||||||
|
instanceId,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
mode: 'selection',
|
||||||
|
selectedRecordIds: [],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
|
||||||
|
instanceId,
|
||||||
|
}),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreFiltersComponentState.atomFamily({
|
||||||
|
instanceId,
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreCurrentViewIdComponentState.atomFamily({
|
||||||
|
instanceId,
|
||||||
|
}),
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
|
set(
|
||||||
|
contextStoreCurrentViewTypeComponentState.atomFamily({
|
||||||
|
instanceId,
|
||||||
|
}),
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
|
set(
|
||||||
|
actionMenuEntriesComponentState.atomFamily({
|
||||||
|
instanceId,
|
||||||
|
}),
|
||||||
|
new Map(),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return { resetContextStoreStates };
|
||||||
|
};
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { useCopyContextStoreStates } from '@/command-menu/hooks/useCopyContextStoreAndActionMenuStates';
|
||||||
|
import { useResetContextStoreStates } from '@/command-menu/hooks/useResetContextStoreStates';
|
||||||
|
|
||||||
|
export const useResetPreviousCommandMenuContext = () => {
|
||||||
|
const { copyContextStoreStates } = useCopyContextStoreStates();
|
||||||
|
const { resetContextStoreStates } = useResetContextStoreStates();
|
||||||
|
|
||||||
|
const resetPreviousCommandMenuContext = () => {
|
||||||
|
copyContextStoreStates({
|
||||||
|
instanceIdToCopyFrom: 'command-menu-previous',
|
||||||
|
instanceIdToCopyTo: 'command-menu',
|
||||||
|
});
|
||||||
|
resetContextStoreStates('command-menu-previous');
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
resetPreviousCommandMenuContext,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
|
import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier';
|
||||||
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
|
import { capitalize } from 'twenty-shared';
|
||||||
|
|
||||||
|
export const getSelectedRecordsContextText = (
|
||||||
|
objectMetadataItem: ObjectMetadataItem,
|
||||||
|
records: ObjectRecord[],
|
||||||
|
totalCount: number,
|
||||||
|
) => {
|
||||||
|
return totalCount === 1
|
||||||
|
? getObjectRecordIdentifier({ objectMetadataItem, record: records[0] }).name
|
||||||
|
: `${totalCount} ${capitalize(objectMetadataItem.namePlural)}`;
|
||||||
|
};
|
||||||
@ -53,6 +53,7 @@ export const useFindManyRecordsSelectedInContextStore = ({
|
|||||||
contextStoreTargetedRecordsRule.mode === 'selection' &&
|
contextStoreTargetedRecordsRule.mode === 'selection' &&
|
||||||
contextStoreTargetedRecordsRule.selectedRecordIds.length === 0,
|
contextStoreTargetedRecordsRule.selectedRecordIds.length === 0,
|
||||||
limit,
|
limit,
|
||||||
|
fetchPolicy: 'cache-and-network',
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -39,6 +39,7 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
const { objectMetadataItem } = useObjectMetadataItem({
|
const { objectMetadataItem } = useObjectMetadataItem({
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { findManyRecordsQuery } = useFindManyRecordsQuery({
|
const { findManyRecordsQuery } = useFindManyRecordsQuery({
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
recordGqlFields,
|
recordGqlFields,
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import {
|
|||||||
|
|
||||||
import { IconComponent } from '@ui/display';
|
import { IconComponent } from '@ui/display';
|
||||||
import { useIsMobile } from '@ui/utilities/responsive/hooks/useIsMobile';
|
import { useIsMobile } from '@ui/utilities/responsive/hooks/useIsMobile';
|
||||||
|
import { ReactNode } from 'react';
|
||||||
import { MenuItemCommandHotKeys } from './MenuItemCommandHotKeys';
|
import { MenuItemCommandHotKeys } from './MenuItemCommandHotKeys';
|
||||||
|
|
||||||
const StyledMenuItemLabelText = styled(StyledMenuItemLabel)`
|
const StyledMenuItemLabelText = styled(StyledMenuItemLabel)`
|
||||||
@ -72,6 +73,7 @@ export type MenuItemCommandProps = {
|
|||||||
className?: string;
|
className?: string;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
|
RightComponent?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MenuItemCommand = ({
|
export const MenuItemCommand = ({
|
||||||
@ -82,6 +84,7 @@ export const MenuItemCommand = ({
|
|||||||
className,
|
className,
|
||||||
isSelected,
|
isSelected,
|
||||||
onClick,
|
onClick,
|
||||||
|
RightComponent,
|
||||||
}: MenuItemCommandProps) => {
|
}: MenuItemCommandProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
@ -99,6 +102,7 @@ export const MenuItemCommand = ({
|
|||||||
</StyledBigIconContainer>
|
</StyledBigIconContainer>
|
||||||
)}
|
)}
|
||||||
<StyledMenuItemLabelText>{text}</StyledMenuItemLabelText>
|
<StyledMenuItemLabelText>{text}</StyledMenuItemLabelText>
|
||||||
|
{RightComponent}
|
||||||
</StyledMenuItemLeftContent>
|
</StyledMenuItemLeftContent>
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<MenuItemCommandHotKeys
|
<MenuItemCommandHotKeys
|
||||||
|
|||||||
Reference in New Issue
Block a user