2439 improve command menu item display in right panel (#21020)
## Before <img width="1512" height="389" alt="image" src="https://github.com/user-attachments/assets/33274356-fb99-4a02-baa7-c324e6d151c6" /> ## After <img width="1512" height="357" alt="image" src="https://github.com/user-attachments/assets/c0affb71-e920-4d64-b2f0-1bed53209ea5" />
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -0,0 +1,37 @@
|
||||
import { AppChip } from '@/applications/components/AppChip';
|
||||
import { useApplicationChipData } from '@/applications/hooks/useApplicationChipData';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
|
||||
type AppMenuItemProps = {
|
||||
applicationId?: string | null;
|
||||
text: string;
|
||||
onClick?: () => void;
|
||||
focused?: boolean;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export const AppMenuItem = ({
|
||||
applicationId,
|
||||
text,
|
||||
onClick,
|
||||
focused,
|
||||
disabled,
|
||||
}: AppMenuItemProps) => {
|
||||
const { applicationChipData } = useApplicationChipData({
|
||||
applicationId,
|
||||
});
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
withIconContainer={true}
|
||||
LeftIcon={() => (
|
||||
<AppChip applicationId={applicationId} size={'md'} chipOnly />
|
||||
)}
|
||||
text={text}
|
||||
contextualText={applicationChipData.name}
|
||||
onClick={onClick}
|
||||
focused={focused}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import { isTwentyStandardApplication } from '@/applications/utils/isTwentyStandardApplication';
|
||||
import { isWorkspaceCustomApplication } from '@/applications/utils/isWorkspaceCustomApplication';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useIsThirdPartyApplication = (
|
||||
applicationId?: string | null,
|
||||
): boolean => {
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
|
||||
if (!isDefined(applicationId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const application = currentWorkspace?.installedApplications.find(
|
||||
(app) => app.id === applicationId,
|
||||
);
|
||||
|
||||
return (
|
||||
isDefined(application) &&
|
||||
!isTwentyStandardApplication(application) &&
|
||||
!isWorkspaceCustomApplication(application, currentWorkspace)
|
||||
);
|
||||
};
|
||||
+18
@@ -1,3 +1,5 @@
|
||||
import { AppMenuItem } from '@/applications/components/AppMenuItem';
|
||||
import { useIsThirdPartyApplication } from '@/applications/hooks/useIsThirdPartyApplication';
|
||||
import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
|
||||
import { CommandListItemLoader } from '@/command-menu-item/display/components/CommandListItemLoader';
|
||||
import { interpolateCommandMenuItemFields } from '@/command-menu-item/display/utils/interpolateCommandMenuItemFields';
|
||||
@@ -101,6 +103,8 @@ const CommandMenuItemSelectableRenderer = ({
|
||||
selectableListInstanceId,
|
||||
);
|
||||
|
||||
const isThirdPartyApp = useIsThirdPartyApplication(item.applicationId);
|
||||
|
||||
const onItemClick = () => {
|
||||
if (disabled) {
|
||||
return;
|
||||
@@ -108,6 +112,20 @@ const CommandMenuItemSelectableRenderer = ({
|
||||
handleClick();
|
||||
};
|
||||
|
||||
if (isThirdPartyApp) {
|
||||
return (
|
||||
<SelectableListItem itemId={item.id} onEnter={onItemClick}>
|
||||
<AppMenuItem
|
||||
applicationId={item.applicationId}
|
||||
text={getCommandMenuItemLabel(label)}
|
||||
onClick={disabled ? undefined : handleClick}
|
||||
focused={!disabled && isSelectedItemId}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
);
|
||||
}
|
||||
|
||||
if (displayType === 'listItem') {
|
||||
const loaderComponent =
|
||||
disabled && showDisabledLoader ? (
|
||||
|
||||
+1
@@ -3,6 +3,7 @@ import { gql } from '@apollo/client';
|
||||
export const COMMAND_MENU_ITEM_FRAGMENT = gql`
|
||||
fragment CommandMenuItemFields on CommandMenuItem {
|
||||
id
|
||||
applicationId
|
||||
workflowVersionId
|
||||
frontComponentId
|
||||
frontComponent {
|
||||
|
||||
+3
-17
@@ -1,7 +1,5 @@
|
||||
import { AppChip } from '@/applications/components/AppChip';
|
||||
import { useApplicationChipData } from '@/applications/hooks/useApplicationChipData';
|
||||
import { AppMenuItem } from '@/applications/components/AppMenuItem';
|
||||
import { type LogicFunction } from '@/logic-functions/types/LogicFunction';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
|
||||
type ToolMenuItemProps = {
|
||||
logicFunction: LogicFunction;
|
||||
@@ -9,24 +7,12 @@ type ToolMenuItemProps = {
|
||||
};
|
||||
|
||||
export const ToolMenuItem = ({ logicFunction, onClick }: ToolMenuItemProps) => {
|
||||
const { applicationChipData } = useApplicationChipData({
|
||||
applicationId: logicFunction.applicationId,
|
||||
});
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
withIconContainer={true}
|
||||
LeftIcon={() => (
|
||||
<AppChip
|
||||
applicationId={logicFunction.applicationId}
|
||||
size={'md'}
|
||||
chipOnly
|
||||
/>
|
||||
)}
|
||||
<AppMenuItem
|
||||
applicationId={logicFunction.applicationId}
|
||||
text={
|
||||
logicFunction.workflowActionTriggerSettings?.label ?? logicFunction.name
|
||||
}
|
||||
contextualText={applicationChipData.name}
|
||||
onClick={onClick}
|
||||
/>
|
||||
);
|
||||
|
||||
+3
@@ -64,5 +64,8 @@ describe('defineCommandMenuItem', () => {
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.config.icon).toBe('IconRocket');
|
||||
expect(result.config.isPinned).toBe(true);
|
||||
expect(result.warnings).toContain(
|
||||
'CommandMenuItem icon will be ignored in favor of application icon, you should remove it',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ export const defineCommandMenuItem: DefineEntity<CommandMenuItemConfig> = (
|
||||
config,
|
||||
) => {
|
||||
const errors: string[] = [];
|
||||
const warnings: string[] = [];
|
||||
|
||||
if (!config.universalIdentifier) {
|
||||
errors.push('CommandMenuItem must have a universalIdentifier');
|
||||
@@ -21,5 +22,11 @@ export const defineCommandMenuItem: DefineEntity<CommandMenuItemConfig> = (
|
||||
);
|
||||
}
|
||||
|
||||
return createValidationResult({ config, errors });
|
||||
if (config.icon) {
|
||||
warnings.push(
|
||||
'CommandMenuItem icon will be ignored in favor of application icon, you should remove it',
|
||||
);
|
||||
}
|
||||
|
||||
return createValidationResult({ config, errors, warnings });
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import { type SyncableEntityOptions } from '@/application/syncableEntityOptionsT
|
||||
export type CommandMenuItemManifest = SyncableEntityOptions & {
|
||||
label: string;
|
||||
shortLabel?: string;
|
||||
/** @deprecated icon will be ignored in favor of application icon */
|
||||
icon?: string;
|
||||
isPinned?: boolean;
|
||||
availabilityType?:
|
||||
|
||||
Reference in New Issue
Block a user