Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement contextual actions for the workflows #8814

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
85941d1
create activate workflow action effect
bosiraphael Oct 29, 2024
d1740cd
add ActivateWorkflowActionEffect to setter
bosiraphael Oct 29, 2024
d9eb528
Add see executions action
bosiraphael Oct 29, 2024
1702bad
add deactivate option
bosiraphael Oct 29, 2024
9c33f73
update dependency array
bosiraphael Oct 30, 2024
7770145
Merge branch 'main' into implement-contextual-actions-for-the-workflows
bosiraphael Nov 27, 2024
09b2c3d
use hooks
bosiraphael Nov 27, 2024
a218ea1
fix see workflow executions
bosiraphael Nov 27, 2024
7f690ae
modify icon
bosiraphael Nov 27, 2024
c490e9b
refactor action hooks
bosiraphael Nov 27, 2024
18f2380
create useSeeWorkflowActiveVersionSingleRecordAction
bosiraphael Nov 27, 2024
8e68e19
add useSeeWorkflowActiveVersionSingleRecordAction
bosiraphael Nov 28, 2024
8eb2e7f
show see workflow active version conditionnally if it's a draft
bosiraphael Nov 28, 2024
0f2a0b9
add useActivateWorkflowDraftSingleRecordAction
bosiraphael Nov 28, 2024
ad2f580
add useDiscardWorkflowDraftSingleRecordAction
bosiraphael Nov 28, 2024
8e7c5c7
refactor single record actions
bosiraphael Nov 28, 2024
27d5d7e
create test workflow action
bosiraphael Nov 28, 2024
53f1f83
Merge branch 'main' of github.com:twentyhq/twenty into implement-cont…
bosiraphael Nov 28, 2024
2c0c7e3
Refactor single record actions
bosiraphael Nov 28, 2024
5b91b32
add action for workflow versions
bosiraphael Nov 29, 2024
e898a9e
remove console log
bosiraphael Nov 29, 2024
742ae30
Merge branch 'main' into implement-contextual-actions-for-the-workflows
bosiraphael Nov 29, 2024
2f899f5
fix after merge
bosiraphael Nov 29, 2024
98b912a
renaming
bosiraphael Nov 29, 2024
08b05a9
create use as draft action
bosiraphael Nov 29, 2024
2157cd8
do not show use as draft if draft
bosiraphael Nov 29, 2024
4fc0ddd
add discard draft workflow version action
bosiraphael Nov 29, 2024
0c9bcd6
fix
bosiraphael Nov 29, 2024
b4dc811
add see executions action
bosiraphael Nov 29, 2024
adcab24
test should be fixed
bosiraphael Nov 29, 2024
b1a9a88
Merge branch 'main' of github.com:twentyhq/twenty into implement-cont…
bosiraphael Dec 2, 2024
5aa2579
fix incorrect condition
bosiraphael Dec 2, 2024
dda2da5
remove redundant check
bosiraphael Dec 2, 2024
cede6a8
Fix chek
bosiraphael Dec 2, 2024
07b8efb
Fix tests
charlesBochet Dec 2, 2024
202f216
remove unnecessary code
bosiraphael Dec 2, 2024
3b260b2
Merge branch 'implement-contextual-actions-for-the-workflows' of gith…
bosiraphael Dec 2, 2024
ff748ec
fix check
bosiraphael Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { MultipleRecordsActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/multiple-records/components/MultipleRecordsActionMenuEntrySetterEffect';
import { NoSelectionActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/no-selection/components/NoSelectionActionMenuEntrySetterEffect';
import { SingleRecordActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/single-record/components/SingleRecordActionMenuEntrySetterEffect';
import { SingleRecordActionMenuEntrySetter } from '@/action-menu/actions/record-actions/single-record/components/SingleRecordActionMenuEntrySetter';
import { WorkflowRunRecordActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/workflow-run-record-actions/components/WorkflowRunRecordActionMenuEntrySetter';
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
Expand Down Expand Up @@ -32,34 +32,40 @@ const ActionEffects = ({
objectId: objectMetadataItemId,
});

const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
contextStoreNumberOfSelectedRecordsComponentState,
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
contextStoreTargetedRecordsRuleComponentState,
);

const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED');

return (
<>
{contextStoreNumberOfSelectedRecords === 0 && (
<NoSelectionActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
)}
{contextStoreNumberOfSelectedRecords === 1 && (
<SingleRecordActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
)}
{contextStoreNumberOfSelectedRecords === 1 && isWorkflowEnabled && (
<WorkflowRunRecordActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
)}
{contextStoreNumberOfSelectedRecords > 1 && (
<MultipleRecordsActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
)}
{contextStoreTargetedRecordsRule.mode === 'selection' &&
contextStoreTargetedRecordsRule.selectedRecordIds.length === 0 && (
<NoSelectionActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
)}
{contextStoreTargetedRecordsRule.mode === 'selection' &&
contextStoreTargetedRecordsRule.selectedRecordIds.length === 1 && (
<SingleRecordActionMenuEntrySetter
objectMetadataItem={objectMetadataItem}
/>
)}
{contextStoreTargetedRecordsRule.mode === 'selection' &&
contextStoreTargetedRecordsRule.selectedRecordIds.length === 1 &&
isWorkflowEnabled && (
<WorkflowRunRecordActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
)}
{contextStoreTargetedRecordsRule.mode === 'exclusion' ||
(contextStoreTargetedRecordsRule.mode === 'selection' &&
contextStoreTargetedRecordsRule.selectedRecordIds.length > 1 && (
<MultipleRecordsActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
))}
bosiraphael marked this conversation as resolved.
Show resolved Hide resolved
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ import { useCallback, useContext, useState } from 'react';
import { IconTrash, isDefined } from 'twenty-ui';

export const useDeleteMultipleRecordsAction = ({
position,
objectMetadataItem,
}: {
position: number;
objectMetadataItem: ObjectMetadataItem;
}) => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
Expand Down Expand Up @@ -106,7 +104,11 @@ export const useDeleteMultipleRecordsAction = ({
const { isInRightDrawer, onActionExecutedCallback } =
useContext(ActionMenuContext);

const registerDeleteMultipleRecordsAction = () => {
const registerDeleteMultipleRecordsAction = ({
position,
}: {
position: number;
}) => {
if (canDelete) {
addActionMenuEntry({
type: ActionMenuEntryType.Standard,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ import {
} from '@/object-record/record-index/export/hooks/useExportRecords';

export const useExportMultipleRecordsAction = ({
position,
objectMetadataItem,
}: {
position: number;
objectMetadataItem: ObjectMetadataItem;
}) => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
Expand All @@ -27,7 +25,11 @@ export const useExportMultipleRecordsAction = ({
filename: `${objectMetadataItem.nameSingular}.csv`,
});

const registerExportMultipleRecordsAction = () => {
const registerExportMultipleRecordsAction = ({
position,
}: {
position: number;
}) => {
addActionMenuEntry({
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.RecordSelection,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useDeleteMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction';
import { useExportViewNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useExportMultipleRecordsAction';
import { useExportMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';

export const useMultipleRecordsActions = ({
Expand All @@ -11,26 +11,24 @@ export const useMultipleRecordsActions = ({
registerDeleteMultipleRecordsAction,
unregisterDeleteMultipleRecordsAction,
} = useDeleteMultipleRecordsAction({
position: 0,
objectMetadataItem,
});

const {
registerExportViewNoSelectionRecordsAction,
unregisterExportViewNoSelectionRecordsAction,
} = useExportViewNoSelectionRecordAction({
position: 1,
registerExportMultipleRecordsAction,
unregisterExportMultipleRecordsAction,
} = useExportMultipleRecordsAction({
objectMetadataItem,
});

const registerMultipleRecordsActions = () => {
registerDeleteMultipleRecordsAction();
registerExportViewNoSelectionRecordsAction();
registerDeleteMultipleRecordsAction({ position: 0 });
registerExportMultipleRecordsAction({ position: 1 });
bosiraphael marked this conversation as resolved.
Show resolved Hide resolved
};

const unregisterMultipleRecordsActions = () => {
unregisterDeleteMultipleRecordsAction();
unregisterExportViewNoSelectionRecordsAction();
unregisterExportMultipleRecordsAction();
bosiraphael marked this conversation as resolved.
Show resolved Hide resolved
};

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ import {
} from '@/object-record/record-index/export/hooks/useExportRecords';

export const useExportViewNoSelectionRecordAction = ({
position,
objectMetadataItem,
}: {
position: number;
objectMetadataItem: ObjectMetadataItem;
}) => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
Expand All @@ -27,7 +25,11 @@ export const useExportViewNoSelectionRecordAction = ({
filename: `${objectMetadataItem.nameSingular}.csv`,
});

const registerExportViewNoSelectionRecordsAction = () => {
const registerExportViewNoSelectionRecordsAction = ({
position,
}: {
position: number;
}) => {
addActionMenuEntry({
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.Global,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useExportViewNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useExportMultipleRecordsAction';
import { useExportViewNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useExportViewNoSelectionRecordAction';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';

export const useNoSelectionRecordActions = ({
Expand All @@ -10,12 +10,11 @@ export const useNoSelectionRecordActions = ({
registerExportViewNoSelectionRecordsAction,
unregisterExportViewNoSelectionRecordsAction,
} = useExportViewNoSelectionRecordAction({
position: 0,
objectMetadataItem,
});

const registerNoSelectionRecordActions = () => {
registerExportViewNoSelectionRecordsAction();
registerExportViewNoSelectionRecordsAction({ position: 0 });
};

const unregisterNoSelectionRecordActions = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { SingleRecordActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/single-record/components/SingleRecordActionMenuEntrySetterEffect';
import { WorkflowSingleRecordActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/WorkflowSingleRecordActionMenuEntrySetterEffect';
import { WorkflowVersionsSingleRecordActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/components/WorkflowVersionsSingleRecordActionMenuEntrySetterEffect';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';

export const SingleRecordActionMenuEntrySetter = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem;
}) => {
return (
<>
<SingleRecordActionMenuEntrySetterEffect
objectMetadataItem={objectMetadataItem}
/>
{objectMetadataItem.nameSingular === CoreObjectNameSingular.Workflow && (
<WorkflowSingleRecordActionMenuEntrySetterEffect startPosition={3} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: startPosition={3} is hardcoded in multiple places. Consider making this configurable or using a constant to avoid magic numbers

)}
{objectMetadataItem.nameSingular ===
CoreObjectNameSingular.WorkflowVersion && (
<WorkflowVersionsSingleRecordActionMenuEntrySetterEffect
startPosition={3}
/>
)}
bosiraphael marked this conversation as resolved.
Show resolved Hide resolved
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,21 @@ import {
ActionMenuEntryScope,
ActionMenuEntryType,
} from '@/action-menu/types/ActionMenuEntry';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useCallback, useContext, useState } from 'react';
import { IconTrash, isDefined } from 'twenty-ui';

export const useDeleteSingleRecordAction = ({
position,
recordId,
objectMetadataItem,
}: {
position: number;
recordId: string;
objectMetadataItem: ObjectMetadataItem;
}) => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
Expand All @@ -39,48 +37,43 @@ export const useDeleteSingleRecordAction = ({
const { sortedFavorites: favorites } = useFavorites();
const { deleteFavorite } = useDeleteFavorite();

const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
contextStoreTargetedRecordsRuleComponentState,
);

const { closeRightDrawer } = useRightDrawer();

const recordIdToDelete =
contextStoreTargetedRecordsRule.mode === 'selection'
? contextStoreTargetedRecordsRule.selectedRecordIds?.[0]
: undefined;

const handleDeleteClick = useCallback(async () => {
if (!isDefined(recordIdToDelete)) {
if (!isDefined(recordId)) {
return;
}
bosiraphael marked this conversation as resolved.
Show resolved Hide resolved

resetTableRowSelection();

const foundFavorite = favorites?.find(
(favorite) => favorite.recordId === recordIdToDelete,
(favorite) => favorite.recordId === recordId,
);

if (isDefined(foundFavorite)) {
deleteFavorite(foundFavorite.id);
}

await deleteOneRecord(recordIdToDelete);
await deleteOneRecord(recordId);
}, [
deleteFavorite,
deleteOneRecord,
favorites,
recordIdToDelete,
resetTableRowSelection,
recordId,
]);

const isRemoteObject = objectMetadataItem.isRemote;

const { isInRightDrawer, onActionExecutedCallback } =
useContext(ActionMenuContext);

const registerDeleteSingleRecordAction = () => {
if (isRemoteObject || !isDefined(recordIdToDelete)) {
const registerDeleteSingleRecordAction = ({
position,
}: {
position: number;
}) => {
if (isRemoteObject) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,42 @@ import {
ActionMenuEntryScope,
ActionMenuEntryType,
} from '@/action-menu/types/ActionMenuEntry';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useCreateFavorite } from '@/favorites/hooks/useCreateFavorite';
import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useRecoilValue } from 'recoil';
import { IconHeart, IconHeartOff, isDefined } from 'twenty-ui';

export const useManageFavoritesSingleRecordAction = ({
position,
recordId,
objectMetadataItem,
}: {
position: number;
recordId: string;
objectMetadataItem: ObjectMetadataItem;
}) => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();

const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
contextStoreTargetedRecordsRuleComponentState,
);

const { sortedFavorites: favorites } = useFavorites();

const { createFavorite } = useCreateFavorite();

const { deleteFavorite } = useDeleteFavorite();

const selectedRecordId =
contextStoreTargetedRecordsRule.mode === 'selection'
? contextStoreTargetedRecordsRule.selectedRecordIds[0]
: undefined;

const selectedRecord = useRecoilValue(
recordStoreFamilyState(selectedRecordId ?? ''),
);
const selectedRecord = useRecoilValue(recordStoreFamilyState(recordId));

const foundFavorite = favorites?.find(
(favorite) => favorite.recordId === selectedRecordId,
(favorite) => favorite.recordId === recordId,
);

const isFavorite = !!selectedRecordId && !!foundFavorite;
const isFavorite = !!foundFavorite;

const registerManageFavoritesSingleRecordAction = () => {
const registerManageFavoritesSingleRecordAction = ({
position,
}: {
position: number;
}) => {
if (!isDefined(objectMetadataItem) || objectMetadataItem.isRemote) {
return;
}
Expand Down
Loading
Loading