fix: Refactoring fetching of icon for module instances (#31765)

This commit is contained in:
Ankita Kinger 2024-03-14 14:31:44 +05:30 committed by GitHub
parent 0ac0bd8b77
commit 7b19b3d351
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 82 additions and 45 deletions

View File

@ -1,5 +1,4 @@
import React from "react"; import React from "react";
import type { Plugin } from "api/PluginApi";
import type { LogItemProps } from "components/editorComponents/Debugger/ErrorLogs/ErrorLogItem"; import type { LogItemProps } from "components/editorComponents/Debugger/ErrorLogs/ErrorLogItem";
import { PluginType } from "entities/Action"; import { PluginType } from "entities/Action";
import WidgetIcon from "pages/Editor/Explorer/Widgets/WidgetIcon"; import WidgetIcon from "pages/Editor/Explorer/Widgets/WidgetIcon";
@ -13,7 +12,7 @@ import { ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
export const getIconForEntity: Record< export const getIconForEntity: Record<
string, string,
(props: LogItemProps, pluginGroups: Record<string, Plugin>) => any (props: LogItemProps, pluginImages: Record<string, string>) => any
> = { > = {
[ENTITY_TYPE.WIDGET]: (props) => { [ENTITY_TYPE.WIDGET]: (props) => {
if (props.source?.pluginType) { if (props.source?.pluginType) {
@ -25,19 +24,16 @@ export const getIconForEntity: Record<
[ENTITY_TYPE.JSACTION]: () => { [ENTITY_TYPE.JSACTION]: () => {
return JsFileIconV2(16, 16, true, true); return JsFileIconV2(16, 16, true, true);
}, },
[ENTITY_TYPE.ACTION]: (props, pluginGroups) => { [ENTITY_TYPE.ACTION]: (props, pluginImages) => {
const { iconId, source } = props; const { iconId, source } = props;
if (source?.pluginType === PluginType.API && source.httpMethod) { if (source?.pluginType === PluginType.API && source.httpMethod) {
// If the source is an API action. // If the source is an API action.
return ApiMethodIcon(source.httpMethod, "16px", "32px", 50); return ApiMethodIcon(source.httpMethod, "16px", "32px", 50);
} else if (iconId && pluginGroups[iconId]) { } else if (iconId && pluginImages[iconId]) {
// If the source is a Datasource action. // If the source is a Datasource action.
return ( return (
<EntityIcon height={"16px"} noBackground noBorder width={"16px"}> <EntityIcon height={"16px"} noBackground noBorder width={"16px"}>
<img <img alt="entityIcon" src={getAssetUrl(pluginImages[iconId])} />
alt="entityIcon"
src={getAssetUrl(pluginGroups[iconId].iconLocation)}
/>
</EntityIcon> </EntityIcon>
); );
} }

View File

@ -20,7 +20,6 @@ import type { JSAction, Variable } from "entities/JSCollection";
import keyBy from "lodash/keyBy"; import keyBy from "lodash/keyBy";
import { getActionConfig } from "pages/Editor/Explorer/Actions/helpers"; import { getActionConfig } from "pages/Editor/Explorer/Actions/helpers";
import { JsFileIconV2 } from "pages/Editor/Explorer/ExplorerIcons"; import { JsFileIconV2 } from "pages/Editor/Explorer/ExplorerIcons";
import { useMemo } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import type { import type {
ActionData, ActionData,
@ -69,9 +68,10 @@ import { setShowCreateNewModal } from "actions/propertyPaneActions";
import { setIdeEditorViewMode } from "actions/ideActions"; import { setIdeEditorViewMode } from "actions/ideActions";
import { EditorViewMode } from "@appsmith/entities/IDE/constants"; import { EditorViewMode } from "@appsmith/entities/IDE/constants";
import { getIsSideBySideEnabled } from "selectors/ideSelectors"; import { getIsSideBySideEnabled } from "selectors/ideSelectors";
import { resolveIcon } from "pages/Editor/utils"; import { getModuleIcon, getPluginImagesFromPlugins } from "pages/Editor/utils";
import { getAllModules } from "@appsmith/selectors/modulesSelector"; import { getAllModules } from "@appsmith/selectors/modulesSelector";
import type { Module } from "@appsmith/constants/ModuleConstants"; import type { Module } from "@appsmith/constants/ModuleConstants";
import type { Plugin } from "api/PluginApi";
const actionList: { const actionList: {
label: string; label: string;
@ -396,7 +396,7 @@ export function useModalDropdownList(handleClose: () => void) {
export function getApiQueriesAndJSActionOptionsWithChildren( export function getApiQueriesAndJSActionOptionsWithChildren(
pageId: string, pageId: string,
plugins: any, plugins: Plugin[],
actions: ActionDataState, actions: ActionDataState,
jsActions: Array<JSCollectionData>, jsActions: Array<JSCollectionData>,
dispatch: any, dispatch: any,
@ -422,7 +422,7 @@ export function getApiQueriesAndJSActionOptionsWithChildren(
} }
function getApiAndQueryOptions( function getApiAndQueryOptions(
plugins: any, plugins: Plugin[],
actions: ActionDataState, actions: ActionDataState,
dispatch: any, dispatch: any,
handleClose: () => void, handleClose: () => void,
@ -431,6 +431,8 @@ function getApiAndQueryOptions(
) { ) {
const state = store.getState(); const state = store.getState();
const isSideBySideEnabled = getIsSideBySideEnabled(state); const isSideBySideEnabled = getIsSideBySideEnabled(state);
const pluginImages = getPluginImagesFromPlugins(plugins);
const pluginGroups: any = keyBy(plugins, "id");
const createQueryObject: TreeDropdownOption = { const createQueryObject: TreeDropdownOption = {
label: "New query", label: "New query",
@ -474,7 +476,7 @@ function getApiAndQueryOptions(
type: queryOptions.value, type: queryOptions.value,
icon: getActionConfig(api.config.pluginType)?.getIcon( icon: getActionConfig(api.config.pluginType)?.getIcon(
api.config, api.config,
plugins[(api as any).config.datasource.pluginId], pluginGroups[(api as any).config.datasource.pluginId],
api.config.pluginType === PluginType.API, api.config.pluginType === PluginType.API,
), ),
} as TreeDropdownOption); } as TreeDropdownOption);
@ -488,7 +490,7 @@ function getApiAndQueryOptions(
type: queryOptions.value, type: queryOptions.value,
icon: getActionConfig(query.config.pluginType)?.getIcon( icon: getActionConfig(query.config.pluginType)?.getIcon(
query.config, query.config,
plugins[(query as any).config.datasource.pluginId], pluginGroups[(query as any).config.datasource.pluginId],
), ),
} as TreeDropdownOption); } as TreeDropdownOption);
}); });
@ -499,11 +501,7 @@ function getApiAndQueryOptions(
id: instance.config.id, id: instance.config.id,
value: instance.config.name, value: instance.config.name,
type: queryOptions.value, type: queryOptions.value,
icon: resolveIcon({ icon: getModuleIcon(module, pluginImages),
iconLocation: plugins[module.pluginId]?.iconLocation || "",
pluginType: module.pluginType,
moduleType: module.type,
}),
} as TreeDropdownOption); } as TreeDropdownOption);
}); });
} }
@ -629,7 +627,6 @@ export function useApisQueriesAndJsActionOptions(handleClose: () => void) {
const plugins = useSelector((state: AppState) => { const plugins = useSelector((state: AppState) => {
return state.entities.plugins.list; return state.entities.plugins.list;
}); });
const pluginGroups: any = useMemo(() => keyBy(plugins, "id"), [plugins]);
const actions = useSelector(getCurrentActions); const actions = useSelector(getCurrentActions);
const jsActions = useSelector(getCurrentJSCollections); const jsActions = useSelector(getCurrentJSCollections);
const queryModuleInstances = useSelector( const queryModuleInstances = useSelector(
@ -641,7 +638,7 @@ export function useApisQueriesAndJsActionOptions(handleClose: () => void) {
// this function gets all the Queries/API's/JS Objects and attaches it to actionList // this function gets all the Queries/API's/JS Objects and attaches it to actionList
return getApiQueriesAndJSActionOptionsWithChildren( return getApiQueriesAndJSActionOptionsWithChildren(
pageId, pageId,
pluginGroups, plugins,
actions, actions,
jsActions, jsActions,
dispatch, dispatch,

View File

@ -8,7 +8,7 @@ import { getPlugins } from "@appsmith/selectors/entitiesSelector";
import EntityLink from "../../EntityLink"; import EntityLink from "../../EntityLink";
import { DebuggerLinkUI } from "components/editorComponents/Debugger/DebuggerEntityLink"; import { DebuggerLinkUI } from "components/editorComponents/Debugger/DebuggerEntityLink";
import { getIconForEntity } from "@appsmith/components/editorComponents/Debugger/ErrorLogs/getLogIconForEntity"; import { getIconForEntity } from "@appsmith/components/editorComponents/Debugger/ErrorLogs/getLogIconForEntity";
import type { Plugin } from "api/PluginApi"; import { getPluginImagesFromPlugins } from "pages/Editor/utils";
const EntityLinkWrapper = styled.div` const EntityLinkWrapper = styled.div`
display: flex; display: flex;
@ -30,11 +30,11 @@ const IconWrapper = styled.span`
`; `;
// This function is used to fetch the icon component for the entity link. // This function is used to fetch the icon component for the entity link.
const getIcon = (props: LogItemProps, pluginGroups: Record<string, Plugin>) => { const getIcon = (props: LogItemProps, pluginImages: Record<string, string>) => {
const entityType = props.source?.type; const entityType = props.source?.type;
let icon = null; let icon = null;
if (entityType) { if (entityType) {
icon = getIconForEntity[entityType](props, pluginGroups); icon = getIconForEntity[entityType](props, pluginImages);
} }
return icon || <img alt="icon" src={undefined} />; return icon || <img alt="icon" src={undefined} />;
}; };
@ -43,6 +43,7 @@ const getIcon = (props: LogItemProps, pluginGroups: Record<string, Plugin>) => {
export default function LogEntityLink(props: LogItemProps) { export default function LogEntityLink(props: LogItemProps) {
const plugins = useSelector(getPlugins); const plugins = useSelector(getPlugins);
const pluginGroups = useMemo(() => keyBy(plugins, "id"), [plugins]); const pluginGroups = useMemo(() => keyBy(plugins, "id"), [plugins]);
const pluginImages = getPluginImagesFromPlugins(plugins);
const plugin = props.iconId ? pluginGroups[props.iconId] : undefined; const plugin = props.iconId ? pluginGroups[props.iconId] : undefined;
return ( return (
@ -55,7 +56,7 @@ export default function LogEntityLink(props: LogItemProps) {
lineHeight: "14px", lineHeight: "14px",
}} }}
> >
<IconWrapper>{getIcon(props, pluginGroups)}</IconWrapper> <IconWrapper>{getIcon(props, pluginImages)}</IconWrapper>
<EntityLink <EntityLink
appsmithErrorCode={props.pluginErrorDetails?.appsmithErrorCode} appsmithErrorCode={props.pluginErrorDetails?.appsmithErrorCode}
errorSubType={props.messages && props.messages[0].message.name} errorSubType={props.messages && props.messages[0].message.name}

View File

@ -27,9 +27,7 @@ import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import type { Module } from "@appsmith/constants/ModuleConstants"; import type { Module } from "@appsmith/constants/ModuleConstants";
import { getAllModules } from "@appsmith/selectors/modulesSelector"; import { getAllModules } from "@appsmith/selectors/modulesSelector";
import { resolveIcon } from "pages/Editor/utils"; import { getModuleIcon } from "pages/Editor/utils";
import { Icon } from "design-system";
import { EntityIcon } from "pages/Editor/Explorer/ExplorerIcons";
enum SortingWeights { enum SortingWeights {
alphabetical = 1, alphabetical = 1,
@ -105,19 +103,8 @@ export const getQueryIcon = (
if (query.config.hasOwnProperty("type")) { if (query.config.hasOwnProperty("type")) {
const q = query as ModuleInstanceData; const q = query as ModuleInstanceData;
const module = modules[q.config.sourceModuleId]; const module = modules[q.config.sourceModuleId];
const icon = resolveIcon({
iconLocation: pluginImages[module.pluginId] || "",
pluginType: module.pluginType,
moduleType: module.type,
});
return ( return getModuleIcon(module, pluginImages);
icon || (
<EntityIcon>
<Icon name="module" />
</EntityIcon>
)
);
} else { } else {
const action = query as ActionData; const action = query as ActionData;
return ( return (

View File

@ -22,7 +22,6 @@ import {
getPlugins, getPlugins,
} from "@appsmith/selectors/entitiesSelector"; } from "@appsmith/selectors/entitiesSelector";
import store from "store"; import store from "store";
import keyBy from "lodash/keyBy";
import { getCurrentPageId } from "selectors/editorSelectors"; import { getCurrentPageId } from "selectors/editorSelectors";
import { getApiQueriesAndJSActionOptionsWithChildren } from "components/editorComponents/ActionCreator/helpers"; import { getApiQueriesAndJSActionOptionsWithChildren } from "components/editorComponents/ActionCreator/helpers";
import { selectEvaluationVersion } from "@appsmith/selectors/applicationSelectors"; import { selectEvaluationVersion } from "@appsmith/selectors/applicationSelectors";
@ -152,12 +151,11 @@ class ActionSelectorControl extends BaseControl<ControlProps> {
const pageId = getCurrentPageId(state); const pageId = getCurrentPageId(state);
const plugins = getPlugins(state); const plugins = getPlugins(state);
const pluginGroups: any = keyBy(plugins, "id");
// this function gets all the Queries/API's/JS Objects and attaches it to actionList // this function gets all the Queries/API's/JS Objects and attaches it to actionList
const fieldOptions = getApiQueriesAndJSActionOptionsWithChildren( const fieldOptions = getApiQueriesAndJSActionOptionsWithChildren(
pageId, pageId,
pluginGroups, plugins,
actions, actions,
jsCollections, jsCollections,
() => { () => {

View File

@ -40,6 +40,7 @@ import ConvertEntityNotification from "@appsmith/pages/common/ConvertEntityNotif
import { useIsEditorPaneSegmentsEnabled } from "../IDE/hooks"; import { useIsEditorPaneSegmentsEnabled } from "../IDE/hooks";
import { Icon } from "design-system"; import { Icon } from "design-system";
import { resolveIcon } from "../utils"; import { resolveIcon } from "../utils";
import { ENTITY_ICON_SIZE, EntityIcon } from "../Explorer/ExplorerIcons";
type ApiEditorWrapperProps = RouteComponentProps<APIEditorRouteParams>; type ApiEditorWrapperProps = RouteComponentProps<APIEditorRouteParams>;
@ -72,7 +73,14 @@ function ApiEditorWrapper(props: ApiEditorWrapperProps) {
iconLocation: pluginGroups[pluginId]?.iconLocation || "", iconLocation: pluginGroups[pluginId]?.iconLocation || "",
pluginType: action?.pluginType || "", pluginType: action?.pluginType || "",
moduleType: action?.actionConfiguration?.body?.moduleType, moduleType: action?.actionConfiguration?.body?.moduleType,
}) || <Icon name="module" />; }) || (
<EntityIcon
height={`${ENTITY_ICON_SIZE}px`}
width={`${ENTITY_ICON_SIZE}px`}
>
<Icon name="module" />
</EntityIcon>
);
const isChangePermitted = getHasManageActionPermission( const isChangePermitted = getHasManageActionPermission(
isFeatureEnabled, isFeatureEnabled,

View File

@ -337,3 +337,11 @@ export function AppsmithAIIcon() {
export function ActionUrlIcon(url: string) { export function ActionUrlIcon(url: string) {
return <img src={url} />; return <img src={url} />;
} }
export function DefaultModuleIcon() {
return (
<EntityIcon>
<Icon name="module" size="sm" />
</EntityIcon>
);
}

View File

@ -41,6 +41,7 @@ import { PluginType } from "entities/Action";
import { useIsEditorPaneSegmentsEnabled } from "../IDE/hooks"; import { useIsEditorPaneSegmentsEnabled } from "../IDE/hooks";
import { Icon } from "design-system"; import { Icon } from "design-system";
import { resolveIcon } from "../utils"; import { resolveIcon } from "../utils";
import { ENTITY_ICON_SIZE, EntityIcon } from "../Explorer/ExplorerIcons";
type QueryEditorProps = RouteComponentProps<QueryEditorRouteParams>; type QueryEditorProps = RouteComponentProps<QueryEditorRouteParams>;
@ -66,7 +67,14 @@ function QueryEditor(props: QueryEditorProps) {
iconLocation: pluginImages[pluginId] || "", iconLocation: pluginImages[pluginId] || "",
pluginType: action?.pluginType || "", pluginType: action?.pluginType || "",
moduleType: action?.actionConfiguration?.body?.moduleType, moduleType: action?.actionConfiguration?.body?.moduleType,
}) || <Icon name="module" />; }) || (
<EntityIcon
height={`${ENTITY_ICON_SIZE}px`}
width={`${ENTITY_ICON_SIZE}px`}
>
<Icon name="module" />
</EntityIcon>
);
const isDeletePermitted = getHasDeleteActionPermission( const isDeletePermitted = getHasDeleteActionPermission(
isFeatureEnabled, isFeatureEnabled,

View File

@ -20,6 +20,7 @@ import { useSelector } from "react-redux";
import { getCurrentPageId } from "selectors/editorSelectors"; import { getCurrentPageId } from "selectors/editorSelectors";
import type { WidgetCardProps } from "widgets/BaseWidget"; import type { WidgetCardProps } from "widgets/BaseWidget";
import type { ActionResponse } from "api/ActionAPI"; import type { ActionResponse } from "api/ActionAPI";
import type { Module } from "@appsmith/constants/ModuleConstants";
import { MODULE_TYPE } from "@appsmith/constants/ModuleConstants"; import { MODULE_TYPE } from "@appsmith/constants/ModuleConstants";
import { import {
ENTITY_ICON_SIZE, ENTITY_ICON_SIZE,
@ -29,6 +30,9 @@ import {
} from "pages/Editor/Explorer/ExplorerIcons"; } from "pages/Editor/Explorer/ExplorerIcons";
import { PluginType } from "entities/Action"; import { PluginType } from "entities/Action";
import { getAssetUrl } from "@appsmith/utils/airgapHelpers"; import { getAssetUrl } from "@appsmith/utils/airgapHelpers";
import type { Plugin } from "api/PluginApi";
import ImageAlt from "assets/images/placeholder-image.svg";
import { Icon } from "design-system";
export const draggableElement = ( export const draggableElement = (
id: string, id: string,
@ -381,3 +385,33 @@ export function resolveIcon({
return resolveQueryModuleIcon(iconLocation, pluginType, isLargeIcon); return resolveQueryModuleIcon(iconLocation, pluginType, isLargeIcon);
} }
} }
export function getModuleIcon(
module: Module | undefined,
pluginImages: Record<string, string>,
isLargeIcon = false,
) {
return module ? (
resolveIcon({
iconLocation: pluginImages[module.pluginId] || "",
pluginType: module.pluginType,
moduleType: module.type,
isLargeIcon,
})
) : (
<EntityIcon
height={`${isLargeIcon ? ENTITY_ICON_SIZE * 2 : ENTITY_ICON_SIZE}px`}
width={`${isLargeIcon ? ENTITY_ICON_SIZE * 2 : ENTITY_ICON_SIZE}px`}
>
<Icon name="module" />
</EntityIcon>
);
}
export function getPluginImagesFromPlugins(plugins: Plugin[]) {
const pluginImages: Record<string, string> = {};
plugins.forEach((plugin) => {
pluginImages[plugin.id] = plugin?.iconLocation ?? ImageAlt;
});
return pluginImages;
}