refactor(command-menu-item): rename Actions to CommandMenuItem (#18489)
actions are being renamed to command menu item, they will be migrated to server and will be served as headless front components --------- Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import {
|
||||
enqueueSnackbar,
|
||||
getFrontComponentCommandErrorDedupeKey,
|
||||
unmountFrontComponent,
|
||||
useFrontComponentId,
|
||||
} from '../front-component-api';
|
||||
|
||||
export type CommandProps = {
|
||||
execute: () => void | Promise<void>;
|
||||
};
|
||||
|
||||
export const Command = ({ execute }: CommandProps) => {
|
||||
const [hasExecuted, setHasExecuted] = useState(false);
|
||||
|
||||
const frontComponentId = useFrontComponentId();
|
||||
|
||||
useEffect(() => {
|
||||
if (hasExecuted) {
|
||||
return;
|
||||
}
|
||||
|
||||
setHasExecuted(true);
|
||||
|
||||
const run = async () => {
|
||||
try {
|
||||
await execute();
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
await enqueueSnackbar({
|
||||
message: 'Command failed',
|
||||
detailedMessage: error.message,
|
||||
variant: 'error',
|
||||
dedupeKey: getFrontComponentCommandErrorDedupeKey(frontComponentId),
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
await unmountFrontComponent();
|
||||
}
|
||||
};
|
||||
|
||||
run();
|
||||
}, [execute, hasExecuted, frontComponentId]);
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { type NavigateOptions } from 'react-router-dom';
|
||||
import { type AppPath } from 'twenty-shared/types';
|
||||
import { type getAppPath } from 'twenty-shared/utils';
|
||||
import {
|
||||
enqueueSnackbar,
|
||||
getFrontComponentCommandErrorDedupeKey,
|
||||
navigate,
|
||||
unmountFrontComponent,
|
||||
useFrontComponentId,
|
||||
} from '../front-component-api';
|
||||
|
||||
export type CommandLinkProps<T extends AppPath> = {
|
||||
to: T;
|
||||
params?: Parameters<typeof getAppPath<T>>[1];
|
||||
queryParams?: Record<string, any>;
|
||||
options?: NavigateOptions;
|
||||
};
|
||||
|
||||
export const CommandLink = <T extends AppPath>({
|
||||
to,
|
||||
params,
|
||||
queryParams,
|
||||
options,
|
||||
}: CommandLinkProps<T>) => {
|
||||
const [hasExecuted, setHasExecuted] = useState(false);
|
||||
|
||||
const frontComponentId = useFrontComponentId();
|
||||
|
||||
useEffect(() => {
|
||||
if (hasExecuted) {
|
||||
return;
|
||||
}
|
||||
|
||||
setHasExecuted(true);
|
||||
|
||||
const run = async () => {
|
||||
try {
|
||||
await navigate(to, params, queryParams, options);
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
await enqueueSnackbar({
|
||||
message: 'Command failed',
|
||||
detailedMessage: error.message,
|
||||
variant: 'error',
|
||||
dedupeKey: getFrontComponentCommandErrorDedupeKey(frontComponentId),
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
await unmountFrontComponent();
|
||||
}
|
||||
};
|
||||
|
||||
run();
|
||||
}, [to, params, queryParams, options, hasExecuted, frontComponentId]);
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -0,0 +1,77 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import {
|
||||
enqueueSnackbar,
|
||||
getFrontComponentCommandErrorDedupeKey,
|
||||
openCommandConfirmationModal,
|
||||
unmountFrontComponent,
|
||||
useFrontComponentId,
|
||||
type CommandConfirmationModalAccent,
|
||||
} from '../front-component-api';
|
||||
|
||||
export type CommandModalProps = {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
execute: () => void | Promise<void>;
|
||||
confirmButtonText?: string;
|
||||
confirmButtonAccent?: CommandConfirmationModalAccent;
|
||||
};
|
||||
|
||||
export const CommandModal = ({
|
||||
title,
|
||||
subtitle,
|
||||
execute,
|
||||
confirmButtonText,
|
||||
confirmButtonAccent,
|
||||
}: CommandModalProps) => {
|
||||
const [hasExecuted, setHasExecuted] = useState(false);
|
||||
|
||||
const frontComponentId = useFrontComponentId();
|
||||
|
||||
useEffect(() => {
|
||||
if (hasExecuted) {
|
||||
return;
|
||||
}
|
||||
|
||||
setHasExecuted(true);
|
||||
|
||||
const run = async () => {
|
||||
try {
|
||||
const commandConfirmationModalResult =
|
||||
await openCommandConfirmationModal({
|
||||
title,
|
||||
subtitle,
|
||||
confirmButtonText,
|
||||
confirmButtonAccent,
|
||||
});
|
||||
|
||||
if (commandConfirmationModalResult === 'confirm') {
|
||||
await execute();
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
|
||||
await enqueueSnackbar({
|
||||
message: 'Command failed',
|
||||
detailedMessage: message,
|
||||
variant: 'error',
|
||||
dedupeKey: getFrontComponentCommandErrorDedupeKey(frontComponentId),
|
||||
});
|
||||
} finally {
|
||||
await unmountFrontComponent();
|
||||
}
|
||||
};
|
||||
|
||||
run();
|
||||
}, [
|
||||
title,
|
||||
subtitle,
|
||||
execute,
|
||||
confirmButtonText,
|
||||
confirmButtonAccent,
|
||||
hasExecuted,
|
||||
frontComponentId,
|
||||
]);
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
import {
|
||||
enqueueSnackbar,
|
||||
getFrontComponentCommandErrorDedupeKey,
|
||||
openSidePanelPage,
|
||||
unmountFrontComponent,
|
||||
useFrontComponentId,
|
||||
} from '@/sdk/front-component-api';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { type SidePanelPages } from 'twenty-shared/types';
|
||||
|
||||
export type CommandOpenSidePanelPageProps = {
|
||||
page: SidePanelPages;
|
||||
pageTitle: string;
|
||||
pageIcon: string;
|
||||
onClick?: () => void;
|
||||
shouldResetSearchState?: boolean;
|
||||
};
|
||||
|
||||
export const CommandOpenSidePanelPage = ({
|
||||
page,
|
||||
pageTitle,
|
||||
pageIcon,
|
||||
onClick,
|
||||
shouldResetSearchState = false,
|
||||
}: CommandOpenSidePanelPageProps) => {
|
||||
const [hasExecuted, setHasExecuted] = useState(false);
|
||||
|
||||
const frontComponentId = useFrontComponentId();
|
||||
|
||||
useEffect(() => {
|
||||
if (hasExecuted) {
|
||||
return;
|
||||
}
|
||||
|
||||
setHasExecuted(true);
|
||||
|
||||
const run = async () => {
|
||||
onClick?.();
|
||||
|
||||
try {
|
||||
await openSidePanelPage({
|
||||
page,
|
||||
pageTitle,
|
||||
pageIcon,
|
||||
shouldResetSearchState,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
await enqueueSnackbar({
|
||||
message: 'Command failed',
|
||||
detailedMessage: error.message,
|
||||
variant: 'error',
|
||||
dedupeKey: getFrontComponentCommandErrorDedupeKey(frontComponentId),
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
await unmountFrontComponent();
|
||||
}
|
||||
};
|
||||
|
||||
run();
|
||||
}, [
|
||||
page,
|
||||
pageTitle,
|
||||
pageIcon,
|
||||
shouldResetSearchState,
|
||||
onClick,
|
||||
hasExecuted,
|
||||
frontComponentId,
|
||||
]);
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
export { Command } from './Command';
|
||||
export type { CommandProps } from './Command';
|
||||
export { CommandLink } from './CommandLink';
|
||||
export type { CommandLinkProps } from './CommandLink';
|
||||
export { CommandOpenSidePanelPage } from './CommandOpenSidePanelPage';
|
||||
export type { CommandOpenSidePanelPageProps } from './CommandOpenSidePanelPage';
|
||||
export { CommandModal } from './CommandModal';
|
||||
export type { CommandModalProps } from './CommandModal';
|
||||
Reference in New Issue
Block a user