8191 command k workflow trigger for selected record (#8315)
Closes #8191 https://github.com/user-attachments/assets/694da229-cc91-4df2-97a0-49cd5dabcf12
This commit is contained in:
@ -97,6 +97,7 @@ export const DeleteRecordsActionEffect = ({
|
||||
useEffect(() => {
|
||||
if (canDelete) {
|
||||
addActionMenuEntry({
|
||||
type: 'standard',
|
||||
key: 'delete',
|
||||
label: 'Delete',
|
||||
position,
|
||||
|
||||
@ -3,10 +3,12 @@ import {
|
||||
displayedExportProgress,
|
||||
useExportRecordData,
|
||||
} from '@/action-menu/hooks/useExportRecordData';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { IconDatabaseExport } from 'twenty-ui';
|
||||
|
||||
import { useEffect } from 'react';
|
||||
import { IconFileExport } from 'twenty-ui';
|
||||
|
||||
export const ExportRecordsActionEffect = ({
|
||||
position,
|
||||
@ -16,6 +18,9 @@ export const ExportRecordsActionEffect = ({
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
}) => {
|
||||
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
|
||||
contextStoreNumberOfSelectedRecordsComponentState,
|
||||
);
|
||||
|
||||
const { progress, download } = useExportRecordData({
|
||||
delayMs: 100,
|
||||
@ -26,10 +31,14 @@ export const ExportRecordsActionEffect = ({
|
||||
|
||||
useEffect(() => {
|
||||
addActionMenuEntry({
|
||||
type: 'standard',
|
||||
key: 'export',
|
||||
position,
|
||||
label: displayedExportProgress(progress),
|
||||
Icon: IconFileExport,
|
||||
label: displayedExportProgress(
|
||||
contextStoreNumberOfSelectedRecords > 0 ? 'selection' : 'all',
|
||||
progress,
|
||||
),
|
||||
Icon: IconDatabaseExport,
|
||||
accent: 'default',
|
||||
onClick: () => download(),
|
||||
});
|
||||
@ -37,6 +46,14 @@ export const ExportRecordsActionEffect = ({
|
||||
return () => {
|
||||
removeActionMenuEntry('export');
|
||||
};
|
||||
}, [download, progress, addActionMenuEntry, removeActionMenuEntry, position]);
|
||||
}, [
|
||||
contextStoreNumberOfSelectedRecords,
|
||||
download,
|
||||
progress,
|
||||
addActionMenuEntry,
|
||||
removeActionMenuEntry,
|
||||
position,
|
||||
]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -44,6 +44,7 @@ export const ManageFavoritesActionEffect = ({
|
||||
}
|
||||
|
||||
addActionMenuEntry({
|
||||
type: 'standard',
|
||||
key: 'manage-favorites',
|
||||
label: isFavorite ? 'Remove from favorites' : 'Add to favorites',
|
||||
position,
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect';
|
||||
import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect';
|
||||
import { ManageFavoritesActionEffect } from '@/action-menu/actions/record-actions/components/ManageFavoritesActionEffect';
|
||||
import { WorkflowRunRecordActionEffect } from '@/action-menu/actions/record-actions/workflow-run-record-actions/components/WorkflowRunRecordActionEffect';
|
||||
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
|
||||
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
|
||||
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
const globalRecordActionEffects = [ExportRecordsActionEffect];
|
||||
|
||||
const singleRecordActionEffects = [
|
||||
ManageFavoritesActionEffect,
|
||||
ExportRecordsActionEffect,
|
||||
DeleteRecordsActionEffect,
|
||||
];
|
||||
|
||||
const multipleRecordActionEffects = [
|
||||
ExportRecordsActionEffect,
|
||||
DeleteRecordsActionEffect,
|
||||
];
|
||||
const multipleRecordActionEffects = [DeleteRecordsActionEffect];
|
||||
|
||||
export const RecordActionMenuEntriesSetter = () => {
|
||||
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
|
||||
@ -36,10 +35,6 @@ export const RecordActionMenuEntriesSetter = () => {
|
||||
);
|
||||
}
|
||||
|
||||
if (!contextStoreNumberOfSelectedRecords) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const actions =
|
||||
contextStoreNumberOfSelectedRecords === 1
|
||||
? singleRecordActionEffects
|
||||
@ -47,13 +42,25 @@ export const RecordActionMenuEntriesSetter = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{actions.map((ActionEffect, index) => (
|
||||
{globalRecordActionEffects.map((ActionEffect, index) => (
|
||||
<ActionEffect
|
||||
key={index}
|
||||
position={index}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
/>
|
||||
))}
|
||||
{actions.map((ActionEffect, index) => (
|
||||
<ActionEffect
|
||||
key={index}
|
||||
position={globalRecordActionEffects.length + index}
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
/>
|
||||
))}
|
||||
{contextStoreNumberOfSelectedRecords === 1 && (
|
||||
<WorkflowRunRecordActionEffect
|
||||
objectMetadataItem={objectMetadataItem}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useAllActiveWorkflowVersionsForObject } from '@/workflow/hooks/useAllActiveWorkflowVersionsForObject';
|
||||
import { useRunWorkflowVersion } from '@/workflow/hooks/useRunWorkflowVersion';
|
||||
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { IconSettingsAutomation, isDefined } from 'twenty-ui';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const WorkflowRunRecordActionEffect = ({
|
||||
objectMetadataItem,
|
||||
}: {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
}) => {
|
||||
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
|
||||
|
||||
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
|
||||
contextStoreTargetedRecordsRuleComponentState,
|
||||
);
|
||||
|
||||
const selectedRecordId =
|
||||
contextStoreTargetedRecordsRule.mode === 'selection'
|
||||
? contextStoreTargetedRecordsRule.selectedRecordIds[0]
|
||||
: undefined;
|
||||
|
||||
const selectedRecord = useRecoilValue(
|
||||
recordStoreFamilyState(selectedRecordId ?? ''),
|
||||
);
|
||||
|
||||
const { records: activeWorkflowVersions } =
|
||||
useAllActiveWorkflowVersionsForObject({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
triggerType: 'MANUAL',
|
||||
});
|
||||
|
||||
const { runWorkflowVersion } = useRunWorkflowVersion();
|
||||
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDefined(objectMetadataItem) || objectMetadataItem.isRemote) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const [
|
||||
index,
|
||||
activeWorkflowVersion,
|
||||
] of activeWorkflowVersions.entries()) {
|
||||
addActionMenuEntry({
|
||||
type: 'workflow-run',
|
||||
key: `workflow-run-${activeWorkflowVersion.workflow.name}`,
|
||||
label: capitalize(activeWorkflowVersion.workflow.name),
|
||||
position: index,
|
||||
Icon: IconSettingsAutomation,
|
||||
onClick: async () => {
|
||||
if (!isDefined(selectedRecord)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await runWorkflowVersion(activeWorkflowVersion.id, selectedRecord);
|
||||
|
||||
enqueueSnackBar('', {
|
||||
variant: SnackBarVariant.Success,
|
||||
title: `${capitalize(activeWorkflowVersion.workflow.name)} starting...`,
|
||||
icon: (
|
||||
<IconSettingsAutomation
|
||||
size={16}
|
||||
color={theme.snackBar.success.color}
|
||||
/>
|
||||
),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return () => {
|
||||
for (const activeWorkflowVersion of activeWorkflowVersions) {
|
||||
removeActionMenuEntry(
|
||||
`workflow-run-${activeWorkflowVersion.workflow.name}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
}, [
|
||||
activeWorkflowVersions,
|
||||
addActionMenuEntry,
|
||||
enqueueSnackBar,
|
||||
objectMetadataItem,
|
||||
removeActionMenuEntry,
|
||||
runWorkflowVersion,
|
||||
selectedRecord,
|
||||
theme.snackBar.success.color,
|
||||
]);
|
||||
|
||||
return null;
|
||||
};
|
||||
Reference in New Issue
Block a user