b11f77df2a
## PR Description - Uses `expr-eval` to enable front components (SDK plugins) to define conditional availability as declarative expressions. - Moves shared types and constants to `twenty-shared` - Introduces a `conditionalAvailabilityExpression` field on `CommandMenuItemEntity`, allowing command menu items to store an `expr-eval` compatible expression string that is evaluated against a CommandMenuContext to determine if the item should be shown. - Creates an esbuild transform plugin `conditional-availability-transform-plugin` in `twenty-sdk` that converts TypeScript conditional availability expressions into `expr-eval` compatible syntax at build time, so SDK developers can write natural TS expressions that get transformed to evaluable strings. - Removes deprecated `forceRegisteredActionsByKey` state and its usage. - Creates `useCommandMenuContext` hook that builds the full `CommandMenuContext` object from React state, which is then passed to `useCommandMenuItemFrontComponentActions` for evaluating conditional availability expressions.
92 lines
2.7 KiB
TypeScript
92 lines
2.7 KiB
TypeScript
import { useEffect } from 'react';
|
|
|
|
import { CoreObjectNameSingular } from 'twenty-shared/types';
|
|
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
|
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
|
|
import { useSetAtomFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomFamilyState';
|
|
import { shouldWorkflowRefetchRequestFamilyState } from '@/workflow/states/shouldWorkflowRefetchRequestFamilyState';
|
|
import {
|
|
type Workflow,
|
|
type WorkflowVersion,
|
|
type WorkflowWithCurrentVersion,
|
|
} from '@/workflow/types/Workflow';
|
|
import { isDefined } from 'twenty-shared/utils';
|
|
|
|
type WorkflowWithAllVersions = Omit<Workflow, 'versions'> & {
|
|
versions: Array<
|
|
Pick<WorkflowVersion, 'id' | 'status' | 'name' | 'createdAt'>
|
|
>;
|
|
};
|
|
|
|
export const useWorkflowWithCurrentVersion = (
|
|
workflowId: string | undefined,
|
|
): WorkflowWithCurrentVersion | undefined => {
|
|
const shouldWorkflowRefetchRequest = useAtomFamilyStateValue(
|
|
shouldWorkflowRefetchRequestFamilyState,
|
|
workflowId ?? '',
|
|
);
|
|
const setShouldWorkflowRefetchRequest = useSetAtomFamilyState(
|
|
shouldWorkflowRefetchRequestFamilyState,
|
|
workflowId ?? '',
|
|
);
|
|
|
|
const { record: workflow, refetch: refetchWorkflow } =
|
|
useFindOneRecord<WorkflowWithAllVersions>({
|
|
objectNameSingular: CoreObjectNameSingular.Workflow,
|
|
objectRecordId: workflowId,
|
|
recordGqlFields: {
|
|
id: true,
|
|
name: true,
|
|
statuses: true,
|
|
lastPublishedVersionId: true,
|
|
versions: {
|
|
id: true,
|
|
status: true,
|
|
name: true,
|
|
createdAt: true,
|
|
},
|
|
},
|
|
skip: !isDefined(workflowId),
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (shouldWorkflowRefetchRequest) {
|
|
setShouldWorkflowRefetchRequest(false);
|
|
refetchWorkflow();
|
|
}
|
|
}, [
|
|
shouldWorkflowRefetchRequest,
|
|
setShouldWorkflowRefetchRequest,
|
|
refetchWorkflow,
|
|
]);
|
|
|
|
const draftVersion = workflow?.versions.find(
|
|
(workflowVersion) => workflowVersion.status === 'DRAFT',
|
|
);
|
|
|
|
const workflowVersions = [...(workflow?.versions ?? [])];
|
|
|
|
workflowVersions.sort((a, b) => (a.createdAt > b.createdAt ? -1 : 1));
|
|
|
|
const latestVersion = workflowVersions[0];
|
|
|
|
const currentVersionWithoutSteps = draftVersion ?? latestVersion;
|
|
|
|
const { record: currentVersionWithSteps } = useFindOneRecord<WorkflowVersion>(
|
|
{
|
|
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
|
objectRecordId: currentVersionWithoutSteps?.id,
|
|
skip: !isDefined(currentVersionWithoutSteps?.id),
|
|
},
|
|
);
|
|
|
|
if (!isDefined(workflow) || !isDefined(currentVersionWithSteps)) {
|
|
return undefined;
|
|
}
|
|
|
|
return {
|
|
...workflow,
|
|
currentVersion: currentVersionWithSteps,
|
|
};
|
|
};
|