Refactor: Unify command menu item execution (#18908)
- Makes engineComponentKey non-nullable on CommandMenuItem. Adds two new engine component keys: TRIGGER_WORKFLOW_VERSION and FRONT_COMPONENT_RENDERER to cover the former standalone cases. - Unifies the previously separated engine, front component and workflow runners into a single `CommandRunner` component with a unified `useMountCommand` hook that handles all command types.
This commit is contained in:
+38
@@ -0,0 +1,38 @@
|
||||
import { CommandMenuItemErrorBoundary } from '@/command-menu-item/display/components/CommandMenuItemErrorBoundary';
|
||||
import { ENGINE_COMPONENT_KEY_COMPONENT_MAP } from '@/command-menu-item/engine-command/constants/EngineComponentKeyHeadlessComponentMap';
|
||||
import { useUnmountCommand } from '@/command-menu-item/engine-command/hooks/useUnmountEngineCommand';
|
||||
import { CommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/CommandComponentInstanceContext';
|
||||
import { headlessCommandContextApisState } from '@/command-menu-item/engine-command/states/headlessCommandContextApisState';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
|
||||
export const CommandRunner = () => {
|
||||
const headlessCommandContextApis = useAtomStateValue(
|
||||
headlessCommandContextApisState,
|
||||
);
|
||||
const unmountCommand = useUnmountCommand();
|
||||
|
||||
return (
|
||||
<>
|
||||
{[...headlessCommandContextApis.entries()].map(
|
||||
([commandMenuItemId, context]) => (
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
key={commandMenuItemId}
|
||||
value={{ instanceId: context.contextStoreInstanceId }}
|
||||
>
|
||||
<CommandComponentInstanceContext.Provider
|
||||
value={{ instanceId: commandMenuItemId }}
|
||||
>
|
||||
<CommandMenuItemErrorBoundary
|
||||
shouldReportToSentry
|
||||
onError={() => unmountCommand(commandMenuItemId)}
|
||||
>
|
||||
{ENGINE_COMPONENT_KEY_COMPONENT_MAP[context.engineComponentKey]}
|
||||
</CommandMenuItemErrorBoundary>
|
||||
</CommandComponentInstanceContext.Provider>
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
),
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
+12
-11
@@ -4,8 +4,8 @@ import { type ReactNode, useEffect } from 'react';
|
||||
import { COMMAND_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME } from '@/command-menu-item/confirmation-modal/constants/CommandMenuItemConfirmationModalResultBrowserEventName';
|
||||
import { useCommandMenuConfirmationModal } from '@/command-menu-item/confirmation-modal/hooks/useCommandMenuConfirmationModal';
|
||||
import { type CommandMenuConfirmationModalResultBrowserEventDetail } from '@/command-menu-item/confirmation-modal/types/CommandMenuConfirmationModalResultBrowserEventDetail';
|
||||
import { useUnmountEngineCommand } from '@/command-menu-item/engine-command/hooks/useUnmountEngineCommand';
|
||||
import { EngineCommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/EngineCommandComponentInstanceContext';
|
||||
import { useUnmountCommand } from '@/command-menu-item/engine-command/hooks/useUnmountEngineCommand';
|
||||
import { CommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/CommandComponentInstanceContext';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { type ButtonAccent } from 'twenty-ui/input';
|
||||
|
||||
@@ -26,10 +26,11 @@ export const HeadlessConfirmationModalEngineCommandEffect = ({
|
||||
}: HeadlessConfirmationModalEngineCommandEffectProps) => {
|
||||
const { isInitializedRef, setIsInitialized } =
|
||||
useIsHeadlessEngineCommandEffectInitialized();
|
||||
const engineCommandId = useAvailableComponentInstanceIdOrThrow(
|
||||
EngineCommandComponentInstanceContext,
|
||||
|
||||
const commandMenuItemId = useAvailableComponentInstanceIdOrThrow(
|
||||
CommandComponentInstanceContext,
|
||||
);
|
||||
const unmountEngineCommand = useUnmountEngineCommand();
|
||||
const unmountCommand = useUnmountCommand();
|
||||
const { openConfirmationModal } = useCommandMenuConfirmationModal();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -40,7 +41,7 @@ export const HeadlessConfirmationModalEngineCommandEffect = ({
|
||||
setIsInitialized(true);
|
||||
|
||||
openConfirmationModal({
|
||||
caller: { type: 'engineCommand', engineCommandId },
|
||||
caller: { type: 'commandMenuItem', commandMenuItemId },
|
||||
title,
|
||||
subtitle,
|
||||
confirmButtonText,
|
||||
@@ -49,7 +50,7 @@ export const HeadlessConfirmationModalEngineCommandEffect = ({
|
||||
}, [
|
||||
isInitializedRef,
|
||||
setIsInitialized,
|
||||
engineCommandId,
|
||||
commandMenuItemId,
|
||||
openConfirmationModal,
|
||||
title,
|
||||
subtitle,
|
||||
@@ -65,8 +66,8 @@ export const HeadlessConfirmationModalEngineCommandEffect = ({
|
||||
const caller = customEvent.detail.caller;
|
||||
|
||||
if (
|
||||
caller.type !== 'engineCommand' ||
|
||||
caller.engineCommandId !== engineCommandId
|
||||
caller.type !== 'commandMenuItem' ||
|
||||
caller.commandMenuItemId !== commandMenuItemId
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -75,7 +76,7 @@ export const HeadlessConfirmationModalEngineCommandEffect = ({
|
||||
await execute();
|
||||
}
|
||||
|
||||
unmountEngineCommand(engineCommandId);
|
||||
unmountCommand(commandMenuItemId);
|
||||
};
|
||||
|
||||
window.addEventListener(
|
||||
@@ -89,7 +90,7 @@ export const HeadlessConfirmationModalEngineCommandEffect = ({
|
||||
handleConfirmationResult,
|
||||
);
|
||||
};
|
||||
}, [engineCommandId, execute, unmountEngineCommand]);
|
||||
}, [execute, commandMenuItemId, unmountCommand]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
import { CommandMenuItemErrorBoundary } from '@/command-menu-item/display/components/CommandMenuItemErrorBoundary';
|
||||
import { ENGINE_COMPONENT_KEY_HEADLESS_COMPONENT_MAP } from '@/command-menu-item/engine-command/constants/EngineComponentKeyHeadlessComponentMap';
|
||||
import { useUnmountEngineCommand } from '@/command-menu-item/engine-command/hooks/useUnmountEngineCommand';
|
||||
import { EngineCommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/EngineCommandComponentInstanceContext';
|
||||
import { mountedEngineCommandsState } from '@/command-menu-item/engine-command/states/mountedEngineCommandsState';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
|
||||
export const HeadlessEngineCommandMountRoot = () => {
|
||||
const mountedEngineCommands = useAtomStateValue(mountedEngineCommandsState);
|
||||
const unmountEngineCommand = useUnmountEngineCommand();
|
||||
|
||||
return (
|
||||
<>
|
||||
{[...mountedEngineCommands.entries()].map(
|
||||
([engineCommandId, mountContext]) => (
|
||||
<CommandMenuItemErrorBoundary
|
||||
key={engineCommandId}
|
||||
engineCommandId={engineCommandId}
|
||||
shouldReportToSentry
|
||||
onError={() => unmountEngineCommand(engineCommandId)}
|
||||
>
|
||||
<ContextStoreComponentInstanceContext.Provider
|
||||
value={{ instanceId: mountContext.contextStoreInstanceId }}
|
||||
>
|
||||
<EngineCommandComponentInstanceContext.Provider
|
||||
value={{ instanceId: engineCommandId }}
|
||||
>
|
||||
{
|
||||
ENGINE_COMPONENT_KEY_HEADLESS_COMPONENT_MAP[
|
||||
mountContext.engineComponentKey
|
||||
]
|
||||
}
|
||||
</EngineCommandComponentInstanceContext.Provider>
|
||||
</ContextStoreComponentInstanceContext.Provider>
|
||||
</CommandMenuItemErrorBoundary>
|
||||
),
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
+8
-8
@@ -1,6 +1,6 @@
|
||||
import { useIsHeadlessEngineCommandEffectInitialized } from '@/command-menu-item/engine-command/hooks/useIsHeadlessEngineCommandEffectInitialized';
|
||||
import { useUnmountEngineCommand } from '@/command-menu-item/engine-command/hooks/useUnmountEngineCommand';
|
||||
import { EngineCommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/EngineCommandComponentInstanceContext';
|
||||
import { useUnmountCommand } from '@/command-menu-item/engine-command/hooks/useUnmountEngineCommand';
|
||||
import { CommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/CommandComponentInstanceContext';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useEffect } from 'react';
|
||||
@@ -17,11 +17,11 @@ export const HeadlessEngineCommandWrapperEffect = ({
|
||||
const { isInitializedRef, setIsInitialized } =
|
||||
useIsHeadlessEngineCommandEffectInitialized();
|
||||
|
||||
const engineCommandId = useAvailableComponentInstanceIdOrThrow(
|
||||
EngineCommandComponentInstanceContext,
|
||||
const commandMenuItemId = useAvailableComponentInstanceIdOrThrow(
|
||||
CommandComponentInstanceContext,
|
||||
);
|
||||
|
||||
const unmountEngineCommand = useUnmountEngineCommand();
|
||||
const unmountCommand = useUnmountCommand();
|
||||
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
@@ -35,7 +35,7 @@ export const HeadlessEngineCommandWrapperEffect = ({
|
||||
const run = async () => {
|
||||
await execute();
|
||||
|
||||
unmountEngineCommand(engineCommandId);
|
||||
unmountCommand(commandMenuItemId);
|
||||
};
|
||||
|
||||
run();
|
||||
@@ -44,8 +44,8 @@ export const HeadlessEngineCommandWrapperEffect = ({
|
||||
ready,
|
||||
isInitializedRef,
|
||||
setIsInitialized,
|
||||
engineCommandId,
|
||||
unmountEngineCommand,
|
||||
commandMenuItemId,
|
||||
unmountCommand,
|
||||
enqueueErrorSnackBar,
|
||||
]);
|
||||
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
import { Suspense, lazy } from 'react';
|
||||
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { CommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/CommandComponentInstanceContext';
|
||||
import { isHeadlessFrontComponentCommandContextApi } from '@/command-menu-item/engine-command/utils/isHeadlessFrontComponentCommandContextApi';
|
||||
import { LayoutRenderingProvider } from '@/ui/layout/contexts/LayoutRenderingContext';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { PageLayoutType } from '~/generated-metadata/graphql';
|
||||
|
||||
const FrontComponentRenderer = lazy(() =>
|
||||
import('@/front-components/components/FrontComponentRenderer').then(
|
||||
(module) => ({ default: module.FrontComponentRenderer }),
|
||||
),
|
||||
);
|
||||
|
||||
export const HeadlessFrontComponentRendererEngineCommand = () => {
|
||||
const commandMenuItemId = useAvailableComponentInstanceIdOrThrow(
|
||||
CommandComponentInstanceContext,
|
||||
);
|
||||
|
||||
const context = useHeadlessCommandContextApi();
|
||||
|
||||
if (!isHeadlessFrontComponentCommandContextApi(context)) {
|
||||
throw new Error(
|
||||
'Context is not a headless front component command context API',
|
||||
);
|
||||
}
|
||||
|
||||
const objectNameSingular = context.objectMetadataItem?.nameSingular;
|
||||
|
||||
const recordId =
|
||||
context.selectedRecords.length === 1
|
||||
? context.selectedRecords[0].id
|
||||
: undefined;
|
||||
|
||||
// TODO: Remove layout rendering provider once we have refactored FrontComponentRenderer to have one headless renderer and a standard renderer
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<LayoutRenderingProvider
|
||||
value={{
|
||||
targetRecordIdentifier:
|
||||
isDefined(objectNameSingular) && isDefined(recordId)
|
||||
? {
|
||||
id: recordId,
|
||||
targetObjectNameSingular: objectNameSingular,
|
||||
}
|
||||
: undefined,
|
||||
layoutType: PageLayoutType.DASHBOARD,
|
||||
isInSidePanel: false,
|
||||
}}
|
||||
>
|
||||
<FrontComponentRenderer
|
||||
frontComponentId={context.frontComponentId}
|
||||
commandMenuItemId={commandMenuItemId}
|
||||
/>
|
||||
</LayoutRenderingProvider>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
+9
-1
@@ -42,13 +42,15 @@ import { SeeRunsWorkflowSingleRecordCommand } from '@/command-menu-item/engine-c
|
||||
import { SeeVersionsWorkflowSingleRecordCommand } from '@/command-menu-item/engine-command/record/single-record/workflow/components/SeeVersionsWorkflowSingleRecordCommand';
|
||||
import { TestWorkflowSingleRecordCommand } from '@/command-menu-item/engine-command/record/single-record/workflow/components/TestWorkflowSingleRecordCommand';
|
||||
import { TidyUpWorkflowSingleRecordCommand } from '@/command-menu-item/engine-command/record/single-record/workflow/components/TidyUpWorkflowSingleRecordCommand';
|
||||
import { HeadlessFrontComponentRendererEngineCommand } from '@/command-menu-item/engine-command/components/HeadlessFrontComponentRendererEngineCommand';
|
||||
import { TriggerWorkflowVersionEngineCommand } from '@/command-menu-item/engine-command/record/components/TriggerWorkflowVersionEngineCommand';
|
||||
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { AppPath, SettingsPath, SidePanelPages } from 'twenty-shared/types';
|
||||
import { IconHistory, IconSearch, IconSparkles } from 'twenty-ui/display';
|
||||
import { EngineComponentKey } from '~/generated-metadata/graphql';
|
||||
|
||||
export const ENGINE_COMPONENT_KEY_HEADLESS_COMPONENT_MAP: Record<
|
||||
export const ENGINE_COMPONENT_KEY_COMPONENT_MAP: Record<
|
||||
EngineComponentKey,
|
||||
React.ReactNode
|
||||
> = {
|
||||
@@ -251,4 +253,10 @@ export const ENGINE_COMPONENT_KEY_HEADLESS_COMPONENT_MAP: Record<
|
||||
[EngineComponentKey.SEE_VERSIONS_WORKFLOW_VERSION]: (
|
||||
<SeeVersionsWorkflowVersionSingleRecordCommand />
|
||||
),
|
||||
[EngineComponentKey.TRIGGER_WORKFLOW_VERSION]: (
|
||||
<TriggerWorkflowVersionEngineCommand />
|
||||
),
|
||||
[EngineComponentKey.FRONT_COMPONENT_RENDERER]: (
|
||||
<HeadlessFrontComponentRendererEngineCommand />
|
||||
),
|
||||
};
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import {
|
||||
type HeadlessCommandContextApi,
|
||||
type HeadlessEngineCommandContextApi,
|
||||
} from '@/command-menu-item/engine-command/types/HeadlessCommandContextApi';
|
||||
import { buildTriggerWorkflowVersionPayloads } from '@/command-menu-item/engine-command/utils/buildTriggerWorkflowVersionPayloads';
|
||||
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
|
||||
import { useLazyFindOneRecord } from '@/object-record/hooks/useLazyFindOneRecord';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { type WorkflowVersion } from '@/workflow/types/Workflow';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useStore } from 'jotai';
|
||||
import { QUERY_MAX_RECORDS } from 'twenty-shared/constants';
|
||||
import { CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
import { isDefined, isNonEmptyArray } from 'twenty-shared/utils';
|
||||
import {
|
||||
CommandMenuItemAvailabilityType as CommandMenuItemAvailabilityTypeEnum,
|
||||
type CommandMenuItemAvailabilityType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
type WorkflowVersionRecord = Pick<
|
||||
WorkflowVersion,
|
||||
'id' | 'workflowId' | 'trigger' | '__typename'
|
||||
>;
|
||||
|
||||
type BuildTriggerWorkflowVersionCommandStateParams = {
|
||||
headlessEngineCommandContextApi: HeadlessEngineCommandContextApi;
|
||||
workflowVersionId: string;
|
||||
availabilityType: CommandMenuItemAvailabilityType;
|
||||
availabilityObjectMetadataId?: string | null;
|
||||
};
|
||||
|
||||
export const useEnrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation =
|
||||
() => {
|
||||
const store = useStore();
|
||||
const { enqueueWarningSnackBar } = useSnackBar();
|
||||
|
||||
const { findOneRecord: findOneWorkflowVersion } =
|
||||
useLazyFindOneRecord<WorkflowVersionRecord>({
|
||||
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
||||
recordGqlFields: { id: true, workflowId: true, trigger: true },
|
||||
});
|
||||
|
||||
const fetchWorkflowVersion = useCallback(
|
||||
async (versionId: string): Promise<WorkflowVersionRecord | undefined> => {
|
||||
let record: WorkflowVersionRecord | undefined;
|
||||
|
||||
await findOneWorkflowVersion({
|
||||
objectRecordId: versionId,
|
||||
onCompleted: (data) => {
|
||||
record = data;
|
||||
},
|
||||
});
|
||||
|
||||
return record;
|
||||
},
|
||||
[findOneWorkflowVersion],
|
||||
);
|
||||
|
||||
const enrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation =
|
||||
useCallback(
|
||||
async ({
|
||||
headlessEngineCommandContextApi,
|
||||
workflowVersionId,
|
||||
availabilityType,
|
||||
availabilityObjectMetadataId,
|
||||
}: BuildTriggerWorkflowVersionCommandStateParams): Promise<
|
||||
HeadlessCommandContextApi | undefined
|
||||
> => {
|
||||
const workflowVersion = await fetchWorkflowVersion(workflowVersionId);
|
||||
|
||||
if (!isDefined(workflowVersion)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const selectedRecordIds =
|
||||
headlessEngineCommandContextApi.targetedRecordsRule.mode ===
|
||||
'selection'
|
||||
? headlessEngineCommandContextApi.targetedRecordsRule
|
||||
.selectedRecordIds
|
||||
: [];
|
||||
|
||||
if (selectedRecordIds.length > QUERY_MAX_RECORDS) {
|
||||
const selectedCountFormatted =
|
||||
selectedRecordIds.length.toLocaleString();
|
||||
|
||||
const limitFormatted = QUERY_MAX_RECORDS.toLocaleString();
|
||||
|
||||
enqueueWarningSnackBar({
|
||||
message: t`You selected ${selectedCountFormatted} records but manual triggers can run on at most ${limitFormatted} records at once. Only the first ${limitFormatted} records will be processed.`,
|
||||
options: {
|
||||
dedupeKey: 'workflow-manual-trigger-selection-limit',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const objectMetadataItems = store.get(
|
||||
objectMetadataItemsSelector.atom,
|
||||
);
|
||||
|
||||
const payloads = buildTriggerWorkflowVersionPayloads({
|
||||
store,
|
||||
trigger: workflowVersion.trigger,
|
||||
availabilityType,
|
||||
availabilityObjectMetadataId,
|
||||
objectMetadataItems,
|
||||
selectedRecordIds,
|
||||
});
|
||||
|
||||
if (
|
||||
availabilityType ===
|
||||
CommandMenuItemAvailabilityTypeEnum.RECORD_SELECTION &&
|
||||
!isNonEmptyArray(payloads)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
...headlessEngineCommandContextApi,
|
||||
workflowId: workflowVersion.workflowId,
|
||||
workflowVersionId: workflowVersion.id,
|
||||
payloads,
|
||||
};
|
||||
},
|
||||
[store, fetchWorkflowVersion, enqueueWarningSnackBar],
|
||||
);
|
||||
|
||||
return {
|
||||
enrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation,
|
||||
};
|
||||
};
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import { CommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/CommandComponentInstanceContext';
|
||||
import { headlessCommandContextApisState } from '@/command-menu-item/engine-command/states/headlessCommandContextApisState';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useHeadlessCommandContextApi = () => {
|
||||
const engineCommandId = useAvailableComponentInstanceIdOrThrow(
|
||||
CommandComponentInstanceContext,
|
||||
);
|
||||
|
||||
const headlessCommandContextApis = useAtomStateValue(
|
||||
headlessCommandContextApisState,
|
||||
);
|
||||
const headlessCommandContextApi =
|
||||
headlessCommandContextApis.get(engineCommandId);
|
||||
|
||||
if (!isDefined(headlessCommandContextApi)) {
|
||||
throw new Error(
|
||||
'Headless command context API not found. Make sure the command was mounted via the command mount flow.',
|
||||
);
|
||||
}
|
||||
|
||||
return headlessCommandContextApi;
|
||||
};
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useEnrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation } from '@/command-menu-item/engine-command/hooks/useEnrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation';
|
||||
import { headlessCommandContextApisState } from '@/command-menu-item/engine-command/states/headlessCommandContextApisState';
|
||||
import { buildHeadlessCommandContextApi } from '@/command-menu-item/engine-command/utils/buildHeadlessCommandContextApi';
|
||||
import { useStore } from 'jotai';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type CommandMenuItemAvailabilityType,
|
||||
type EngineComponentKey,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
type MountCommandParams = {
|
||||
engineCommandId: string;
|
||||
contextStoreInstanceId: string;
|
||||
engineComponentKey: EngineComponentKey;
|
||||
frontComponentId?: string;
|
||||
workflowVersionId?: string;
|
||||
availabilityType?: CommandMenuItemAvailabilityType;
|
||||
availabilityObjectMetadataId?: string | null;
|
||||
};
|
||||
|
||||
export const useMountCommand = () => {
|
||||
const store = useStore();
|
||||
|
||||
const {
|
||||
enrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation,
|
||||
} = useEnrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation();
|
||||
|
||||
const mountCommand = useCallback(
|
||||
async ({
|
||||
engineCommandId,
|
||||
contextStoreInstanceId,
|
||||
engineComponentKey,
|
||||
frontComponentId,
|
||||
workflowVersionId,
|
||||
availabilityType,
|
||||
availabilityObjectMetadataId,
|
||||
}: MountCommandParams) => {
|
||||
const headlessEngineCommandContextApi = buildHeadlessCommandContextApi({
|
||||
store,
|
||||
contextStoreInstanceId,
|
||||
engineComponentKey,
|
||||
});
|
||||
|
||||
const commandState = isDefined(frontComponentId)
|
||||
? { ...headlessEngineCommandContextApi, frontComponentId }
|
||||
: isDefined(workflowVersionId) && isDefined(availabilityType)
|
||||
? await enrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation(
|
||||
{
|
||||
headlessEngineCommandContextApi,
|
||||
workflowVersionId,
|
||||
availabilityType,
|
||||
availabilityObjectMetadataId,
|
||||
},
|
||||
)
|
||||
: headlessEngineCommandContextApi;
|
||||
|
||||
if (!isDefined(commandState)) {
|
||||
return;
|
||||
}
|
||||
|
||||
store.set(headlessCommandContextApisState.atom, (previousMap) => {
|
||||
const newMap = new Map(previousMap);
|
||||
|
||||
newMap.set(engineCommandId, commandState);
|
||||
|
||||
return newMap;
|
||||
});
|
||||
},
|
||||
[
|
||||
store,
|
||||
enrichHeadlessCommandContextApiWithWorkflowVersionTriggerInformation,
|
||||
],
|
||||
);
|
||||
|
||||
return mountCommand;
|
||||
};
|
||||
-129
@@ -1,129 +0,0 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { mountedEngineCommandsState } from '@/command-menu-item/engine-command/states/mountedEngineCommandsState';
|
||||
import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState';
|
||||
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
|
||||
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
||||
import { useStore } from 'jotai';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type EngineComponentKey } from '~/generated-metadata/graphql';
|
||||
|
||||
export const useMountEngineCommand = () => {
|
||||
const store = useStore();
|
||||
|
||||
const mountEngineCommand = useCallback(
|
||||
(
|
||||
engineCommandId: string,
|
||||
contextStoreInstanceId: string,
|
||||
engineComponentKey: EngineComponentKey,
|
||||
) => {
|
||||
const objectMetadataItemId = store.get(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const objectMetadataItems = store.get(objectMetadataItemsSelector.atom);
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(item) => item.id === objectMetadataItemId,
|
||||
);
|
||||
|
||||
const currentViewId = store.get(
|
||||
contextStoreCurrentViewIdComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const targetedRecordsRule = store.get(
|
||||
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const selectedRecords = (
|
||||
targetedRecordsRule.mode === 'selection'
|
||||
? targetedRecordsRule.selectedRecordIds
|
||||
: []
|
||||
)
|
||||
.map((id) => store.get(recordStoreFamilyState.atomFamily(id)))
|
||||
.filter(isDefined);
|
||||
|
||||
const filters = store.get(
|
||||
contextStoreFiltersComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const filterGroups = store.get(
|
||||
contextStoreFilterGroupsComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const anyFieldFilterValue = store.get(
|
||||
contextStoreAnyFieldFilterValueComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const currentWorkspaceMember = store.get(
|
||||
currentWorkspaceMemberState.atom,
|
||||
);
|
||||
const systemTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
const userTimezone =
|
||||
currentWorkspaceMember?.timeZone !== 'system'
|
||||
? (currentWorkspaceMember?.timeZone ?? systemTimeZone)
|
||||
: systemTimeZone;
|
||||
|
||||
const graphqlFilter = isDefined(objectMetadataItem)
|
||||
? computeContextStoreFilters({
|
||||
contextStoreTargetedRecordsRule: targetedRecordsRule,
|
||||
contextStoreFilters: filters,
|
||||
contextStoreFilterGroups: filterGroups,
|
||||
objectMetadataItem,
|
||||
filterValueDependencies: {
|
||||
currentWorkspaceMemberId: currentWorkspaceMember?.id,
|
||||
timeZone: userTimezone,
|
||||
},
|
||||
contextStoreAnyFieldFilterValue: anyFieldFilterValue,
|
||||
})
|
||||
: null;
|
||||
|
||||
const recordIndexId =
|
||||
objectMetadataItem && currentViewId
|
||||
? getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
currentViewId,
|
||||
)
|
||||
: null;
|
||||
|
||||
store.set(mountedEngineCommandsState.atom, (previousMap) => {
|
||||
const newMap = new Map(previousMap);
|
||||
|
||||
newMap.set(engineCommandId, {
|
||||
engineComponentKey,
|
||||
contextStoreInstanceId,
|
||||
objectMetadataItem: objectMetadataItem ?? null,
|
||||
currentViewId,
|
||||
recordIndexId,
|
||||
targetedRecordsRule,
|
||||
selectedRecords,
|
||||
graphqlFilter,
|
||||
});
|
||||
|
||||
return newMap;
|
||||
});
|
||||
},
|
||||
[store],
|
||||
);
|
||||
|
||||
return mountEngineCommand;
|
||||
};
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
import { EngineCommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/EngineCommandComponentInstanceContext';
|
||||
import { mountedEngineCommandsState } from '@/command-menu-item/engine-command/states/mountedEngineCommandsState';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useMountedEngineCommandContext = () => {
|
||||
const engineCommandId = useAvailableComponentInstanceIdOrThrow(
|
||||
EngineCommandComponentInstanceContext,
|
||||
);
|
||||
|
||||
const mountedEngineCommands = useAtomStateValue(mountedEngineCommandsState);
|
||||
const context = mountedEngineCommands.get(engineCommandId);
|
||||
|
||||
if (!isDefined(context)) {
|
||||
throw new Error(
|
||||
'Engine command mount context not found. Make sure the command was mounted via the engine command mount flow.',
|
||||
);
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
+5
-5
@@ -1,15 +1,15 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { mountedEngineCommandsState } from '@/command-menu-item/engine-command/states/mountedEngineCommandsState';
|
||||
import { headlessCommandContextApisState } from '@/command-menu-item/engine-command/states/headlessCommandContextApisState';
|
||||
import { commandMenuItemProgressFamilyState } from '@/command-menu-item/states/commandMenuItemProgressFamilyState';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
export const useUnmountEngineCommand = () => {
|
||||
export const useUnmountCommand = () => {
|
||||
const store = useStore();
|
||||
|
||||
const unmountEngineCommand = useCallback(
|
||||
const unmountCommand = useCallback(
|
||||
(engineCommandId: string) => {
|
||||
store.set(mountedEngineCommandsState.atom, (previousMap) => {
|
||||
store.set(headlessCommandContextApisState.atom, (previousMap) => {
|
||||
const newMap = new Map(previousMap);
|
||||
|
||||
newMap.delete(engineCommandId);
|
||||
@@ -25,5 +25,5 @@ export const useUnmountEngineCommand = () => {
|
||||
[store],
|
||||
);
|
||||
|
||||
return unmountEngineCommand;
|
||||
return unmountCommand;
|
||||
};
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { isHeadlessTriggerWorkflowVersionCommandContextApi } from '@/command-menu-item/engine-command/utils/isHeadlessTriggerWorkflowVersionCommandContextApi';
|
||||
import { useRunWorkflowVersion } from '@/workflow/hooks/useRunWorkflowVersion';
|
||||
import { useCallback } from 'react';
|
||||
import { isNonEmptyArray } from 'twenty-shared/utils';
|
||||
|
||||
export const TriggerWorkflowVersionEngineCommand = () => {
|
||||
const mountedCommandState = useHeadlessCommandContextApi();
|
||||
|
||||
const { runWorkflowVersion } = useRunWorkflowVersion();
|
||||
|
||||
const execute = useCallback(async () => {
|
||||
if (
|
||||
!isHeadlessTriggerWorkflowVersionCommandContextApi(mountedCommandState)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isNonEmptyArray(mountedCommandState.payloads)) {
|
||||
await runWorkflowVersion({
|
||||
workflowId: mountedCommandState.workflowId,
|
||||
workflowVersionId: mountedCommandState.workflowVersionId,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (const payload of mountedCommandState.payloads) {
|
||||
await runWorkflowVersion({
|
||||
workflowId: mountedCommandState.workflowId,
|
||||
workflowVersionId: mountedCommandState.workflowVersionId,
|
||||
payload,
|
||||
});
|
||||
}
|
||||
}, [runWorkflowVersion, mountedCommandState]);
|
||||
|
||||
return <HeadlessEngineCommandWrapperEffect execute={execute} />;
|
||||
};
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize';
|
||||
import { useIncrementalDeleteManyRecords } from '@/object-record/hooks/useIncrementalDeleteManyRecords';
|
||||
import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-board/hooks/useRemoveSelectedRecordsFromRecordBoard';
|
||||
@@ -8,7 +8,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const DeleteMultipleRecordsCommand = () => {
|
||||
const { recordIndexId, objectMetadataItem, graphqlFilter } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
if (
|
||||
!isDefined(recordIndexId) ||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessConfirmationModalEngineCommandEffect } from '@/command-menu-item/engine-command/components/HeadlessConfirmationModalEngineCommandEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize';
|
||||
import { useIncrementalDestroyManyRecords } from '@/object-record/hooks/useIncrementalDestroyManyRecords';
|
||||
import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-board/hooks/useRemoveSelectedRecordsFromRecordBoard';
|
||||
@@ -10,7 +10,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const DestroyMultipleRecordsCommand = () => {
|
||||
const { recordIndexId, objectMetadataItem, graphqlFilter } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
if (
|
||||
!isDefined(recordIndexId) ||
|
||||
|
||||
+4
-5
@@ -1,6 +1,6 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { EngineCommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/EngineCommandComponentInstanceContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { CommandComponentInstanceContext } from '@/command-menu-item/engine-command/states/contexts/CommandComponentInstanceContext';
|
||||
import { commandMenuItemProgressFamilyState } from '@/command-menu-item/states/commandMenuItemProgressFamilyState';
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { useRecordIndexExportRecords } from '@/object-record/record-index/export/hooks/useRecordIndexExportRecords';
|
||||
@@ -43,11 +43,10 @@ const ExportMultipleRecordsCommandContent = ({
|
||||
};
|
||||
|
||||
export const ExportMultipleRecordsCommand = () => {
|
||||
const { objectMetadataItem, recordIndexId } =
|
||||
useMountedEngineCommandContext();
|
||||
const { objectMetadataItem, recordIndexId } = useHeadlessCommandContextApi();
|
||||
|
||||
const engineCommandId = useAvailableComponentInstanceIdOrThrow(
|
||||
EngineCommandComponentInstanceContext,
|
||||
CommandComponentInstanceContext,
|
||||
);
|
||||
|
||||
const setCommandMenuItemProgress = useSetAtomFamilyState(
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useOpenMergeRecordsPageInSidePanel } from '@/side-panel/hooks/useOpenMergeRecordsPageInSidePanel';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const MergeMultipleRecordsCommand = () => {
|
||||
const { objectMetadataItem, selectedRecords } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
const selectedRecordIds = selectedRecords.map((record) => record.id);
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessConfirmationModalEngineCommandEffect } from '@/command-menu-item/engine-command/components/HeadlessConfirmationModalEngineCommandEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize';
|
||||
import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords';
|
||||
import { useRestoreManyRecords } from '@/object-record/hooks/useRestoreManyRecords';
|
||||
@@ -11,7 +11,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const RestoreMultipleRecordsCommand = () => {
|
||||
const { recordIndexId, objectMetadataItem, graphqlFilter } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
if (
|
||||
!isDefined(recordIndexId) ||
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useOpenUpdateMultipleRecordsPageInSidePanel } from '@/side-panel/hooks/useOpenUpdateMultipleRecordsPageInSidePanel';
|
||||
|
||||
export const UpdateMultipleRecordsCommand = () => {
|
||||
const { contextStoreInstanceId } = useMountedEngineCommandContext();
|
||||
const { contextStoreInstanceId } = useHeadlessCommandContextApi();
|
||||
|
||||
const { openUpdateMultipleRecordsPageInSidePanel } =
|
||||
useOpenUpdateMultipleRecordsPageInSidePanel({
|
||||
|
||||
+2
-3
@@ -1,11 +1,10 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useCreateNewIndexRecord } from '@/object-record/record-table/hooks/useCreateNewIndexRecord';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const CreateNewIndexRecordNoSelectionRecordCommand = () => {
|
||||
const { objectMetadataItem, recordIndexId } =
|
||||
useMountedEngineCommandContext();
|
||||
const { objectMetadataItem, recordIndexId } = useHeadlessCommandContextApi();
|
||||
|
||||
if (!isDefined(objectMetadataItem) || !isDefined(recordIndexId)) {
|
||||
throw new Error(
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||
@@ -8,7 +8,7 @@ import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/sta
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const CreateNewViewNoSelectionRecordCommand = () => {
|
||||
const { currentViewId, recordIndexId } = useMountedEngineCommandContext();
|
||||
const { currentViewId, recordIndexId } = useHeadlessCommandContextApi();
|
||||
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useCheckIsSoftDeleteFilter } from '@/object-record/record-filter/hooks/useCheckIsSoftDeleteFilter';
|
||||
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
@@ -8,8 +8,7 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const HideDeletedRecordsNoSelectionRecordCommand = () => {
|
||||
const { objectMetadataItem, recordIndexId } =
|
||||
useMountedEngineCommandContext();
|
||||
const { objectMetadataItem, recordIndexId } = useHeadlessCommandContextApi();
|
||||
|
||||
if (!isDefined(objectMetadataItem) || !isDefined(recordIndexId)) {
|
||||
throw new Error(
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useOpenObjectRecordsSpreadsheetImportDialog } from '@/object-record/spreadsheet-import/hooks/useOpenObjectRecordsSpreadsheetImportDialog';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const ImportRecordsNoSelectionRecordCommand = () => {
|
||||
const { objectMetadataItem } = useMountedEngineCommandContext();
|
||||
const { objectMetadataItem } = useHeadlessCommandContextApi();
|
||||
|
||||
if (!isDefined(objectMetadataItem)) {
|
||||
throw new Error('Object metadata item is required to import records');
|
||||
|
||||
+2
-3
@@ -1,11 +1,10 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeDeletedRecordsNoSelectionRecordCommand = () => {
|
||||
const { objectMetadataItem, recordIndexId } =
|
||||
useMountedEngineCommandContext();
|
||||
const { objectMetadataItem, recordIndexId } = useHeadlessCommandContextApi();
|
||||
|
||||
if (!isDefined(objectMetadataItem) || !isDefined(recordIndexId)) {
|
||||
throw new Error(
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useCreateNavigationMenuItem } from '@/navigation-menu-item/common/hooks/useCreateNavigationMenuItem';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const AddToFavoritesSingleRecordCommand = () => {
|
||||
const { objectMetadataItem, selectedRecords } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
const selectedRecord = selectedRecords[0];
|
||||
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useNavigationMenuItemsData } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemsData';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useRemoveNavigationMenuItemByTargetRecordId } from '@/navigation-menu-item/common/hooks/useRemoveNavigationMenuItemByTargetRecordId';
|
||||
import { useNavigationMenuItemsData } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemsData';
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-board/hooks/useRemoveSelectedRecordsFromRecordBoard';
|
||||
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
|
||||
@@ -9,7 +9,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const DeleteSingleRecordCommand = () => {
|
||||
const { recordIndexId, objectMetadataItem, selectedRecords } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessConfirmationModalEngineCommandEffect } from '@/command-menu-item/engine-command/components/HeadlessConfirmationModalEngineCommandEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useDestroyOneRecord } from '@/object-record/hooks/useDestroyOneRecord';
|
||||
import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-board/hooks/useRemoveSelectedRecordsFromRecordBoard';
|
||||
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
|
||||
@@ -10,7 +10,7 @@ import { useNavigateApp } from '~/hooks/useNavigateApp';
|
||||
|
||||
export const DestroySingleRecordCommand = () => {
|
||||
const { recordIndexId, objectMetadataItem, selectedRecords } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const ExportNoteSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
const selectedRecord = selectedRecords[0];
|
||||
|
||||
const recordId = selectedRecord?.id;
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useExportSingleRecord } from '@/object-record/record-show/hooks/useExportSingleRecord';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const ExportSingleRecordCommand = () => {
|
||||
const { objectMetadataItem, currentViewId, selectedRecords } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useRecordShowPagePagination } from '@/object-record/record-show/hooks/useRecordShowPagePagination';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const NavigateToNextRecordSingleRecordCommand = () => {
|
||||
const { objectMetadataItem, selectedRecords } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useRecordShowPagePagination } from '@/object-record/record-show/hooks/useRecordShowPagePagination';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const NavigateToPreviousRecordSingleRecordCommand = () => {
|
||||
const { objectMetadataItem, selectedRecords } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useDeleteNavigationMenuItem } from '@/navigation-menu-item/common/hooks/useDeleteNavigationMenuItem';
|
||||
import { useNavigationMenuItemsData } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemsData';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const RemoveFromFavoritesSingleRecordCommand = () => {
|
||||
const { selectedRecords, objectMetadataItem } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessConfirmationModalEngineCommandEffect } from '@/command-menu-item/engine-command/components/HeadlessConfirmationModalEngineCommandEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useRestoreManyRecords } from '@/object-record/hooks/useRestoreManyRecords';
|
||||
import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-board/hooks/useRemoveSelectedRecordsFromRecordBoard';
|
||||
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
|
||||
@@ -8,7 +8,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const RestoreSingleRecordCommand = () => {
|
||||
const { recordIndexId, objectMetadataItem, selectedRecords } =
|
||||
useMountedEngineCommandContext();
|
||||
useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useResetDraftPageLayoutToPersistedPageLayout } from '@/page-layout/hooks/useResetDraftPageLayoutToPersistedPageLayout';
|
||||
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
|
||||
import { getTabListInstanceIdFromPageLayoutAndRecord } from '@/page-layout/utils/getTabListInstanceIdFromPageLayoutAndRecord';
|
||||
@@ -8,7 +8,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { PageLayoutType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const CancelDashboardSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
const selectedRecord = selectedRecords[0];
|
||||
|
||||
if (!isDefined(selectedRecord)) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useDuplicateDashboard } from '@/dashboards/hooks/useDuplicateDashboard';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
@@ -9,7 +9,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { useNavigateApp } from '~/hooks/useNavigateApp';
|
||||
|
||||
export const DuplicateDashboardSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const { duplicateDashboard } = useDuplicateDashboard();
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useResetLocationHash } from 'twenty-ui/utilities';
|
||||
|
||||
export const EditDashboardSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
const selectedRecord = selectedRecords[0];
|
||||
|
||||
if (!isDefined(selectedRecord)) {
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useSavePageLayout } from '@/page-layout/hooks/useSavePageLayout';
|
||||
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
|
||||
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SaveDashboardSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
const selectedRecord = selectedRecords[0];
|
||||
|
||||
if (!isDefined(selectedRecord)) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
|
||||
import { useRecordPageLayoutIdFromRecordStoreOrThrow } from '@/page-layout/hooks/useRecordPageLayoutIdFromRecordStoreOrThrow';
|
||||
import { useResetDraftPageLayoutToPersistedPageLayout } from '@/page-layout/hooks/useResetDraftPageLayoutToPersistedPageLayout';
|
||||
@@ -10,7 +10,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { PageLayoutType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const CancelRecordPageLayoutSingleRecordCommand = () => {
|
||||
const { objectMetadataItem } = useMountedEngineCommandContext();
|
||||
const { objectMetadataItem } = useHeadlessCommandContextApi();
|
||||
|
||||
if (!isDefined(objectMetadataItem)) {
|
||||
throw new Error(
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useRecordPageLayoutIdFromRecordStoreOrThrow } from '@/page-layout/hooks/useRecordPageLayoutIdFromRecordStoreOrThrow';
|
||||
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useResetLocationHash } from 'twenty-ui/utilities';
|
||||
|
||||
export const EditRecordPageLayoutSingleRecordCommand = () => {
|
||||
const { objectMetadataItem } = useMountedEngineCommandContext();
|
||||
const { objectMetadataItem } = useHeadlessCommandContextApi();
|
||||
|
||||
if (!isDefined(objectMetadataItem)) {
|
||||
throw new Error(
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useRecordPageLayoutIdFromRecordStoreOrThrow } from '@/page-layout/hooks/useRecordPageLayoutIdFromRecordStoreOrThrow';
|
||||
import { useSaveFieldsWidgetGroups } from '@/page-layout/hooks/useSaveFieldsWidgetGroups';
|
||||
import { useSavePageLayout } from '@/page-layout/hooks/useSavePageLayout';
|
||||
@@ -8,7 +8,7 @@ import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SaveRecordPageLayoutSingleRecordCommand = () => {
|
||||
const { objectMetadataItem } = useMountedEngineCommandContext();
|
||||
const { objectMetadataItem } = useHeadlessCommandContextApi();
|
||||
|
||||
if (!isDefined(objectMetadataItem)) {
|
||||
throw new Error(
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import { HeadlessNavigateEngineCommand } from '@/command-menu-item/engine-command/components/HeadlessNavigateEngineCommand';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { AppPath, CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeVersionWorkflowRunSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
const selectedRecord = selectedRecords[0];
|
||||
|
||||
if (
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
import { HeadlessNavigateEngineCommand } from '@/command-menu-item/engine-command/components/HeadlessNavigateEngineCommand';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { CoreObjectNameSingular, AppPath } from 'twenty-shared/types';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { AppPath, CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeWorkflowWorkflowRunSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
const selectedRecord = selectedRecords[0];
|
||||
|
||||
if (!isDefined(selectedRecord) || !isDefined(selectedRecord?.workflow?.id)) {
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize';
|
||||
import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords';
|
||||
import { useStopWorkflowRun } from '@/workflow/hooks/useStopWorkflowRun';
|
||||
@@ -7,8 +7,7 @@ import { CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const StopWorkflowRunSingleRecordCommand = () => {
|
||||
const { targetedRecordsRule, graphqlFilter } =
|
||||
useMountedEngineCommandContext();
|
||||
const { targetedRecordsRule, graphqlFilter } = useHeadlessCommandContextApi();
|
||||
|
||||
const { fetchAllRecords: fetchAllRecordIds } = useLazyFetchAllRecords({
|
||||
objectNameSingular: CoreObjectNameSingular.WorkflowRun,
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessNavigateEngineCommand } from '@/command-menu-item/engine-command/components/HeadlessNavigateEngineCommand';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { AppPath, ViewFilterOperand } from 'twenty-shared/types';
|
||||
@@ -37,7 +37,7 @@ const SeeRunsWorkflowVersionSingleRecordCommandContent = ({
|
||||
};
|
||||
|
||||
export const SeeRunsWorkflowVersionSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const selectedRecord = selectedRecords[0];
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessNavigateEngineCommand } from '@/command-menu-item/engine-command/components/HeadlessNavigateEngineCommand';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { AppPath, ViewFilterOperand } from 'twenty-shared/types';
|
||||
@@ -30,7 +30,7 @@ const SeeVersionsWorkflowVersionSingleRecordCommandContent = ({
|
||||
};
|
||||
|
||||
export const SeeVersionsWorkflowVersionSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
const selectedRecord = selectedRecords[0];
|
||||
|
||||
if (!isDefined(selectedRecord) || !isDefined(selectedRecord.workflowId)) {
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import { HeadlessNavigateEngineCommand } from '@/command-menu-item/engine-command/components/HeadlessNavigateEngineCommand';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { AppPath, CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeWorkflowWorkflowVersionSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
const selectedRecord = selectedRecords[0];
|
||||
|
||||
if (!isDefined(selectedRecord) || !isDefined(selectedRecord?.workflow?.id)) {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { OverrideWorkflowDraftConfirmationModal } from '@/workflow/components/OverrideWorkflowDraftConfirmationModal';
|
||||
import { OVERRIDE_WORKFLOW_DRAFT_CONFIRMATION_MODAL_ID } from '@/workflow/constants/OverrideWorkflowDraftConfirmationModalId';
|
||||
@@ -66,7 +66,7 @@ const UseAsDraftWorkflowVersionSingleRecordCommandContent = ({
|
||||
};
|
||||
|
||||
export const UseAsDraftWorkflowVersionSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const workflowVersion = useWorkflowVersion(recordId ?? '');
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useActivateWorkflowVersion } from '@/workflow/hooks/useActivateWorkflowVersion';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const ActivateWorkflowSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
|
||||
const { activateWorkflowVersion } = useActivateWorkflowVersion();
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useSidePanelWorkflowNavigation } from '@/side-panel/pages/workflow/hooks/useSidePanelWorkflowNavigation';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const AddNodeWorkflowSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useDeactivateWorkflowVersion } from '@/workflow/hooks/useDeactivateWorkflowVersion';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const DeactivateWorkflowSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const { deactivateWorkflowVersion } = useDeactivateWorkflowVersion();
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useDeleteOneWorkflowVersion } from '@/workflow/hooks/useDeleteOneWorkflowVersion';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const DiscardDraftWorkflowSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const { deleteOneWorkflowVersion } = useDeleteOneWorkflowVersion();
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useDuplicateWorkflow } from '@/workflow/hooks/useDuplicateWorkflow';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
@@ -10,7 +10,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { useNavigateApp } from '~/hooks/useNavigateApp';
|
||||
|
||||
export const DuplicateWorkflowSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const workflow = useWorkflowWithCurrentVersion(recordId ?? '');
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessNavigateEngineCommand } from '@/command-menu-item/engine-command/components/HeadlessNavigateEngineCommand';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useActiveWorkflowVersion } from '@/workflow/hooks/useActiveWorkflowVersion';
|
||||
import { AppPath, CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeActiveVersionWorkflowSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
import { HeadlessNavigateEngineCommand } from '@/command-menu-item/engine-command/components/HeadlessNavigateEngineCommand';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { AppPath, ViewFilterOperand } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeRunsWorkflowSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(
|
||||
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
import { HeadlessNavigateEngineCommand } from '@/command-menu-item/engine-command/components/HeadlessNavigateEngineCommand';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { AppPath, ViewFilterOperand } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const SeeVersionsWorkflowSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useRunWorkflowVersion } from '@/workflow/hooks/useRunWorkflowVersion';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const TestWorkflowSingleRecordCommand = () => {
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const { runWorkflowVersion } = useRunWorkflowVersion();
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { HeadlessEngineCommandWrapperEffect } from '@/command-menu-item/engine-command/components/HeadlessEngineCommandWrapperEffect';
|
||||
import { useMountedEngineCommandContext } from '@/command-menu-item/engine-command/hooks/useMountedEngineCommandContext';
|
||||
import { useHeadlessCommandContextApi } from '@/command-menu-item/engine-command/hooks/useHeadlessCommandContextApi';
|
||||
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
|
||||
import { getWorkflowVisualizerComponentInstanceId } from '@/workflow/utils/getWorkflowVisualizerComponentInstanceId';
|
||||
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
|
||||
@@ -9,7 +9,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const TidyUpWorkflowSingleRecordCommand = () => {
|
||||
const store = useStore();
|
||||
const { selectedRecords } = useMountedEngineCommandContext();
|
||||
const { selectedRecords } = useHeadlessCommandContextApi();
|
||||
|
||||
const recordId = selectedRecords[0]?.id;
|
||||
const { tidyUpWorkflowVersion } = useTidyUpWorkflowVersion();
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { mountedEngineCommandsState } from '@/command-menu-item/engine-command/states/mountedEngineCommandsState';
|
||||
import { headlessCommandContextApisState } from '@/command-menu-item/engine-command/states/headlessCommandContextApisState';
|
||||
import { createAtomFamilySelector } from '@/ui/utilities/state/jotai/utils/createAtomFamilySelector';
|
||||
|
||||
export const isEngineCommandMountedFamilySelector = createAtomFamilySelector<
|
||||
@@ -9,8 +9,8 @@ export const isEngineCommandMountedFamilySelector = createAtomFamilySelector<
|
||||
get:
|
||||
(engineCommandId: string) =>
|
||||
({ get }) => {
|
||||
const mountedMap = get(mountedEngineCommandsState);
|
||||
const headlessCommandContextApis = get(headlessCommandContextApisState);
|
||||
|
||||
return mountedMap.has(engineCommandId);
|
||||
return headlessCommandContextApis.has(engineCommandId);
|
||||
},
|
||||
});
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
|
||||
|
||||
export const EngineCommandComponentInstanceContext =
|
||||
createComponentInstanceContext();
|
||||
export const CommandComponentInstanceContext = createComponentInstanceContext();
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { type HeadlessCommandContextApi } from '@/command-menu-item/engine-command/types/HeadlessCommandContextApi';
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const headlessCommandContextApisState = createAtomState<
|
||||
Map<string, HeadlessCommandContextApi>
|
||||
>({
|
||||
key: 'headlessCommandContextApisState',
|
||||
defaultValue: new Map(),
|
||||
});
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
import { type MountedEngineCommandState } from '@/command-menu-item/engine-command/types/MountedEngineCommandContext';
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
|
||||
export const mountedEngineCommandsState = createAtomState<
|
||||
Map<string, MountedEngineCommandState>
|
||||
>({
|
||||
key: 'mountedEngineCommandsState',
|
||||
defaultValue: new Map(),
|
||||
});
|
||||
+18
-1
@@ -7,7 +7,7 @@ import {
|
||||
} from 'twenty-shared/types';
|
||||
import { type EngineComponentKey } from '~/generated-metadata/graphql';
|
||||
|
||||
export type MountedEngineCommandState = {
|
||||
export type HeadlessEngineCommandContextApi = {
|
||||
engineComponentKey: EngineComponentKey;
|
||||
contextStoreInstanceId: string;
|
||||
objectMetadataItem: Nullable<EnrichedObjectMetadataItem>;
|
||||
@@ -17,3 +17,20 @@ export type MountedEngineCommandState = {
|
||||
selectedRecords: ObjectRecord[];
|
||||
graphqlFilter: Nullable<RecordGqlOperationFilter>;
|
||||
};
|
||||
|
||||
export type HeadlessFrontComponentCommandContextApi =
|
||||
HeadlessEngineCommandContextApi & {
|
||||
frontComponentId: string;
|
||||
};
|
||||
|
||||
export type HeadlessTriggerWorkflowVersionCommandContextApi =
|
||||
HeadlessEngineCommandContextApi & {
|
||||
workflowId: string;
|
||||
workflowVersionId: string;
|
||||
payloads: Record<string, any>[];
|
||||
};
|
||||
|
||||
export type HeadlessCommandContextApi =
|
||||
| HeadlessEngineCommandContextApi
|
||||
| HeadlessFrontComponentCommandContextApi
|
||||
| HeadlessTriggerWorkflowVersionCommandContextApi;
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
import type { Store } from 'jotai/vanilla/store';
|
||||
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { type HeadlessEngineCommandContextApi } from '@/command-menu-item/engine-command/types/HeadlessCommandContextApi';
|
||||
import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState';
|
||||
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
|
||||
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type EngineComponentKey } from '~/generated-metadata/graphql';
|
||||
|
||||
export const buildHeadlessCommandContextApi = ({
|
||||
store,
|
||||
contextStoreInstanceId,
|
||||
engineComponentKey,
|
||||
}: {
|
||||
store: Store;
|
||||
contextStoreInstanceId: string;
|
||||
engineComponentKey: EngineComponentKey;
|
||||
}): HeadlessEngineCommandContextApi => {
|
||||
const objectMetadataItemId = store.get(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const objectMetadataItems = store.get(objectMetadataItemsSelector.atom);
|
||||
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(item: EnrichedObjectMetadataItem) => item.id === objectMetadataItemId,
|
||||
);
|
||||
|
||||
const currentViewId = store.get(
|
||||
contextStoreCurrentViewIdComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const targetedRecordsRule = store.get(
|
||||
contextStoreTargetedRecordsRuleComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const selectedRecords = (
|
||||
targetedRecordsRule.mode === 'selection'
|
||||
? targetedRecordsRule.selectedRecordIds
|
||||
: []
|
||||
)
|
||||
.map((id: string) => store.get(recordStoreFamilyState.atomFamily(id)))
|
||||
.filter(isDefined);
|
||||
|
||||
const filters = store.get(
|
||||
contextStoreFiltersComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const filterGroups = store.get(
|
||||
contextStoreFilterGroupsComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const anyFieldFilterValue = store.get(
|
||||
contextStoreAnyFieldFilterValueComponentState.atomFamily({
|
||||
instanceId: contextStoreInstanceId,
|
||||
}),
|
||||
);
|
||||
|
||||
const currentWorkspaceMember = store.get(currentWorkspaceMemberState.atom);
|
||||
|
||||
const systemTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
|
||||
const userTimezone =
|
||||
currentWorkspaceMember?.timeZone !== 'system'
|
||||
? (currentWorkspaceMember?.timeZone ?? systemTimeZone)
|
||||
: systemTimeZone;
|
||||
|
||||
const graphqlFilter = isDefined(objectMetadataItem)
|
||||
? computeContextStoreFilters({
|
||||
contextStoreTargetedRecordsRule: targetedRecordsRule,
|
||||
contextStoreFilters: filters,
|
||||
contextStoreFilterGroups: filterGroups,
|
||||
objectMetadataItem,
|
||||
filterValueDependencies: {
|
||||
currentWorkspaceMemberId: currentWorkspaceMember?.id,
|
||||
timeZone: userTimezone,
|
||||
},
|
||||
contextStoreAnyFieldFilterValue: anyFieldFilterValue,
|
||||
})
|
||||
: null;
|
||||
|
||||
const recordIndexId =
|
||||
objectMetadataItem && currentViewId
|
||||
? getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
currentViewId,
|
||||
)
|
||||
: null;
|
||||
|
||||
return {
|
||||
engineComponentKey,
|
||||
contextStoreInstanceId,
|
||||
objectMetadataItem: objectMetadataItem ?? null,
|
||||
currentViewId,
|
||||
recordIndexId,
|
||||
targetedRecordsRule,
|
||||
selectedRecords,
|
||||
graphqlFilter,
|
||||
};
|
||||
};
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
import type { Store } from 'jotai/vanilla/store';
|
||||
|
||||
import { isBulkRecordsManualTrigger } from '@/command-menu-item/record/utils/isBulkRecordsManualTrigger';
|
||||
import { type EnrichedObjectMetadataItem } from '@/object-metadata/types/EnrichedObjectMetadataItem';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { type WorkflowTrigger } from '@/workflow/types/Workflow';
|
||||
import { QUERY_MAX_RECORDS } from 'twenty-shared/constants';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type CommandMenuItemAvailabilityType,
|
||||
CommandMenuItemAvailabilityType as CommandMenuItemAvailabilityTypeEnum,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const buildTriggerWorkflowVersionPayloads = ({
|
||||
store,
|
||||
trigger,
|
||||
availabilityType,
|
||||
availabilityObjectMetadataId,
|
||||
objectMetadataItems,
|
||||
selectedRecordIds,
|
||||
}: {
|
||||
store: Store;
|
||||
trigger: WorkflowTrigger | null;
|
||||
availabilityType: CommandMenuItemAvailabilityType;
|
||||
availabilityObjectMetadataId?: string | null;
|
||||
objectMetadataItems: EnrichedObjectMetadataItem[];
|
||||
selectedRecordIds: string[];
|
||||
}): Record<string, any>[] => {
|
||||
const payloads: Record<string, any>[] = [];
|
||||
|
||||
switch (availabilityType) {
|
||||
case CommandMenuItemAvailabilityTypeEnum.RECORD_SELECTION: {
|
||||
if (selectedRecordIds.length === 0) {
|
||||
return payloads;
|
||||
}
|
||||
|
||||
const limitedSelectedRecordIds = selectedRecordIds.slice(
|
||||
0,
|
||||
QUERY_MAX_RECORDS,
|
||||
);
|
||||
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(metadata) => metadata.id === availabilityObjectMetadataId,
|
||||
);
|
||||
|
||||
if (isDefined(trigger) && isBulkRecordsManualTrigger(trigger)) {
|
||||
const selectedRecords = limitedSelectedRecordIds
|
||||
.map((recordId) =>
|
||||
store.get(recordStoreFamilyState.atomFamily(recordId)),
|
||||
)
|
||||
.filter(isDefined);
|
||||
|
||||
if (isDefined(objectMetadataItem)) {
|
||||
payloads.push({
|
||||
[objectMetadataItem.namePlural]: selectedRecords,
|
||||
});
|
||||
}
|
||||
|
||||
return payloads;
|
||||
}
|
||||
|
||||
for (const selectedRecordId of limitedSelectedRecordIds) {
|
||||
const selectedRecord = store.get(
|
||||
recordStoreFamilyState.atomFamily(selectedRecordId),
|
||||
);
|
||||
|
||||
if (!isDefined(selectedRecord)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
payloads.push(selectedRecord);
|
||||
}
|
||||
|
||||
return payloads;
|
||||
}
|
||||
case CommandMenuItemAvailabilityTypeEnum.GLOBAL:
|
||||
case CommandMenuItemAvailabilityTypeEnum.FALLBACK: {
|
||||
return payloads;
|
||||
}
|
||||
default: {
|
||||
return payloads;
|
||||
}
|
||||
}
|
||||
};
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import {
|
||||
type HeadlessCommandContextApi,
|
||||
type HeadlessFrontComponentCommandContextApi,
|
||||
} from '@/command-menu-item/engine-command/types/HeadlessCommandContextApi';
|
||||
|
||||
export const isHeadlessFrontComponentCommandContextApi = (
|
||||
state: HeadlessCommandContextApi,
|
||||
): state is HeadlessFrontComponentCommandContextApi =>
|
||||
'frontComponentId' in state;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import {
|
||||
type HeadlessCommandContextApi,
|
||||
type HeadlessTriggerWorkflowVersionCommandContextApi,
|
||||
} from '@/command-menu-item/engine-command/types/HeadlessCommandContextApi';
|
||||
|
||||
export const isHeadlessTriggerWorkflowVersionCommandContextApi = (
|
||||
state: HeadlessCommandContextApi,
|
||||
): state is HeadlessTriggerWorkflowVersionCommandContextApi =>
|
||||
'workflowId' in state;
|
||||
Reference in New Issue
Block a user