fix: icon ds missing when plugin not present (#40327)

This commit is contained in:
Aman Agarwal 2025-04-23 15:23:10 +05:30 committed by GitHub
parent ea214c254f
commit 68354422eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 42 additions and 47 deletions

View File

@ -12,7 +12,7 @@ import { Flex } from "@appsmith/ads";
import styled from "styled-components"; import styled from "styled-components";
import { noop } from "lodash"; import { noop } from "lodash";
import { EditableName, useIsRenaming } from "IDE"; import { EditableName, useIsRenaming } from "IDE";
import ImageAlt from "assets/images/placeholder-image.svg";
export interface SaveActionNameParams { export interface SaveActionNameParams {
id: string; id: string;
name: string; name: string;
@ -64,7 +64,7 @@ const PluginActionNameEditor = ({
isFeatureEnabled, isFeatureEnabled,
action?.userPermissions, action?.userPermissions,
); );
const iconUrl = getAssetUrl(plugin?.iconLocation) || ""; const iconUrl = getAssetUrl(plugin?.iconLocation ?? ImageAlt);
const icon = ActionUrlIcon(iconUrl); const icon = ActionUrlIcon(iconUrl);
const handleDoubleClick = isChangePermitted ? enterEditMode : noop; const handleDoubleClick = isChangePermitted ? enterEditMode : noop;

View File

@ -598,15 +598,25 @@ export const getDatasourcePlugins = createSelector(getPlugins, (plugins) => {
return plugins.filter((plugin) => plugin?.allowUserDatasources ?? true); return plugins.filter((plugin) => plugin?.allowUserDatasources ?? true);
}); });
export const getPluginImages = createSelector(getPlugins, (plugins) => { export const getPluginImages = createSelector(
const pluginImages: Record<string, string> = {}; getPlugins,
getDatasources,
(plugins, datasources) => {
const pluginImages: Record<string, string> = {};
plugins.forEach((plugin) => { plugins.forEach((plugin) => {
pluginImages[plugin.id] = plugin?.iconLocation ?? ImageAlt; pluginImages[plugin.id] = plugin?.iconLocation ?? ImageAlt;
}); });
return pluginImages; datasources.forEach((datasource) => {
}); if (!pluginImages[datasource.pluginId]) {
pluginImages[datasource.pluginId] = ImageAlt;
}
});
return pluginImages;
},
);
export const getPluginNames = createSelector(getPlugins, (plugins) => { export const getPluginNames = createSelector(getPlugins, (plugins) => {
const pluginNames: Record<string, string> = {}; const pluginNames: Record<string, string> = {};
@ -1676,7 +1686,7 @@ export const getQuerySegmentItems = createSelector(
const items: EntityItem[] = actions.map((action) => { const items: EntityItem[] = actions.map((action) => {
let group; let group;
const iconUrl = getAssetUrl( const iconUrl = getAssetUrl(
pluginGroups[action.config.pluginId]?.iconLocation, pluginGroups[action.config.pluginId]?.iconLocation ?? ImageAlt,
); );
if (action.config.pluginType === PluginType.API) { if (action.config.pluginType === PluginType.API) {

View File

@ -32,6 +32,7 @@ import {
getCurrentJSCollections, getCurrentJSCollections,
getQueryModuleInstances, getQueryModuleInstances,
getJSModuleInstancesData, getJSModuleInstancesData,
getPluginImages,
} from "ee/selectors/entitiesSelector"; } from "ee/selectors/entitiesSelector";
import { import {
getModalDropdownList, getModalDropdownList,
@ -64,7 +65,7 @@ import { selectEvaluationVersion } from "ee/selectors/applicationSelectors";
import { isJSAction } from "ee/workers/Evaluation/evaluationUtils"; import { isJSAction } from "ee/workers/Evaluation/evaluationUtils";
import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes";
import type { ModuleInstanceDataState } from "ee/constants/ModuleInstanceConstants"; import type { ModuleInstanceDataState } from "ee/constants/ModuleInstanceConstants";
import { getModuleIcon, getPluginImagesFromPlugins } from "pages/Editor/utils"; import { getModuleIcon } from "pages/Editor/utils";
import { getAllModules } from "ee/selectors/modulesSelector"; import { getAllModules } from "ee/selectors/modulesSelector";
import type { Module } from "ee/constants/ModuleConstants"; import type { Module } from "ee/constants/ModuleConstants";
import { import {
@ -420,6 +421,7 @@ export function getApiQueriesAndJSActionOptionsWithChildren(
queryModuleInstances: ModuleInstanceDataState, queryModuleInstances: ModuleInstanceDataState,
jsModuleInstances: ReturnType<typeof getJSModuleInstancesData>, jsModuleInstances: ReturnType<typeof getJSModuleInstancesData>,
modules: Record<string, Module>, modules: Record<string, Module>,
pluginImages: Record<string, string>,
) { ) {
// this function gets a list of all the queries/apis and attaches it to actionList // this function gets a list of all the queries/apis and attaches it to actionList
getApiAndQueryOptions( getApiAndQueryOptions(
@ -429,6 +431,7 @@ export function getApiQueriesAndJSActionOptionsWithChildren(
handleClose, handleClose,
queryModuleInstances, queryModuleInstances,
modules, modules,
pluginImages,
); );
// this function gets a list of all the JS Objects and attaches it to actionList // this function gets a list of all the JS Objects and attaches it to actionList
@ -446,8 +449,8 @@ function getApiAndQueryOptions(
handleClose: () => void, handleClose: () => void,
queryModuleInstances: ModuleInstanceDataState, queryModuleInstances: ModuleInstanceDataState,
modules: Record<string, Module>, modules: Record<string, Module>,
pluginImages: Record<string, string>,
) { ) {
const pluginImages = getPluginImagesFromPlugins(plugins);
// TODO: Fix this the next time the file is edited // TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const pluginGroups: any = keyBy(plugins, "id"); const pluginGroups: any = keyBy(plugins, "id");
@ -686,6 +689,7 @@ export function useApisQueriesAndJsActionOptions(handleClose: () => void) {
) as unknown as ModuleInstanceDataState; ) as unknown as ModuleInstanceDataState;
const jsModuleInstancesData = useSelector(getJSModuleInstancesData); const jsModuleInstancesData = useSelector(getJSModuleInstancesData);
const modules = useSelector(getAllModules); const modules = useSelector(getAllModules);
const pluginImages = useSelector(getPluginImages);
// 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(
@ -698,5 +702,6 @@ export function useApisQueriesAndJsActionOptions(handleClose: () => void) {
queryModuleInstances, queryModuleInstances,
jsModuleInstancesData, jsModuleInstancesData,
modules, modules,
pluginImages,
); );
} }

View File

@ -4,11 +4,10 @@ import { useSelector } from "react-redux";
import { keyBy } from "lodash"; import { keyBy } from "lodash";
import type { LogItemProps } from "../ErrorLogItem"; import type { LogItemProps } from "../ErrorLogItem";
import { Colors } from "constants/Colors"; import { Colors } from "constants/Colors";
import { getPlugins } from "ee/selectors/entitiesSelector"; import { getPluginImages, getPlugins } from "ee/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 "ee/components/editorComponents/Debugger/ErrorLogs/getLogIconForEntity"; import { getIconForEntity } from "ee/components/editorComponents/Debugger/ErrorLogs/getLogIconForEntity";
import { getPluginImagesFromPlugins } from "pages/Editor/utils";
const EntityLinkWrapper = styled.div` const EntityLinkWrapper = styled.div`
display: flex; display: flex;
@ -50,7 +49,7 @@ const getIcon = (props: LogItemProps, pluginImages: Record<string, string>) => {
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 pluginImages = useSelector(getPluginImages);
const plugin = props.iconId ? pluginGroups[props.iconId] : undefined; const plugin = props.iconId ? pluginGroups[props.iconId] : undefined;

View File

@ -19,6 +19,7 @@ import {
getAllJSCollections, getAllJSCollections,
getJSModuleInstancesData, getJSModuleInstancesData,
getModuleInstances, getModuleInstances,
getPluginImages,
getPlugins, getPlugins,
} from "ee/selectors/entitiesSelector"; } from "ee/selectors/entitiesSelector";
import store from "store"; import store from "store";
@ -115,6 +116,7 @@ class ActionSelectorControl extends BaseControl<ControlProps> {
const queryModuleInstances = [] as ModuleInstanceDataState; const queryModuleInstances = [] as ModuleInstanceDataState;
const jsModuleInstances = getJSModuleInstancesData(state); const jsModuleInstances = getJSModuleInstancesData(state);
const modules = getAllModules(state); const modules = getAllModules(state);
const pluginImages = getPluginImages(state);
if (!!moduleInstances) { if (!!moduleInstances) {
for (const moduleInstance of Object.values(moduleInstances)) { for (const moduleInstance of Object.values(moduleInstances)) {
@ -174,6 +176,7 @@ class ActionSelectorControl extends BaseControl<ControlProps> {
queryModuleInstances, queryModuleInstances,
jsModuleInstances, jsModuleInstances,
modules, modules,
pluginImages,
); );
try { try {

View File

@ -5,12 +5,12 @@ import { useSelector } from "react-redux";
import { import {
getDatasources, getDatasources,
getDatasourcesGroupedByPluginCategory, getDatasourcesGroupedByPluginCategory,
getPlugins, getPluginImages,
} from "ee/selectors/entitiesSelector"; } from "ee/selectors/entitiesSelector";
import history from "utils/history"; import history from "utils/history";
import { datasourcesEditorIdURL, integrationEditorURL } from "ee/RouteBuilder"; import { datasourcesEditorIdURL, integrationEditorURL } from "ee/RouteBuilder";
import { getSelectedDatasourceId } from "ee/navigation/FocusSelectors"; import { getSelectedDatasourceId } from "ee/navigation/FocusSelectors";
import { get, keyBy } from "lodash"; import { get } from "lodash";
import CreateDatasourceButton from "./CreateDatasourceButton"; import CreateDatasourceButton from "./CreateDatasourceButton";
import { useLocation } from "react-router"; import { useLocation } from "react-router";
import { import {
@ -53,8 +53,7 @@ export const DataSidePane = (props: DataSidePaneProps) => {
>(""); >("");
const datasources = useSelector(getDatasources); const datasources = useSelector(getDatasources);
const groupedDatasources = useSelector(getDatasourcesGroupedByPluginCategory); const groupedDatasources = useSelector(getDatasourcesGroupedByPluginCategory);
const plugins = useSelector(getPlugins); const pluginImages = useSelector(getPluginImages);
const groupedPlugins = keyBy(plugins, "id");
const location = useLocation(); const location = useLocation();
const goToDatasource = useCallback((id: string) => { const goToDatasource = useCallback((id: string) => {
history.push(datasourcesEditorIdURL({ datasourceId: id })); history.push(datasourcesEditorIdURL({ datasourceId: id }));
@ -123,9 +122,7 @@ export const DataSidePane = (props: DataSidePaneProps) => {
title: data.name, title: data.name,
startIcon: ( startIcon: (
<DatasourceIcon <DatasourceIcon
src={getAssetUrl( src={getAssetUrl(pluginImages[data.pluginId])}
groupedPlugins[data.pluginId]?.iconLocation || "",
)}
/> />
), ),
description: get(dsUsageMap, data.id, ""), description: get(dsUsageMap, data.id, ""),

View File

@ -6,6 +6,7 @@ import styled from "styled-components";
import { getAssetUrl } from "ee/utils/airgapHelpers"; import { getAssetUrl } from "ee/utils/airgapHelpers";
import { PluginImage } from "pages/Editor/DataSourceEditor/DSFormHeader"; import { PluginImage } from "pages/Editor/DataSourceEditor/DSFormHeader";
import { isEnvironmentConfigured } from "ee/utils/Environments"; import { isEnvironmentConfigured } from "ee/utils/Environments";
import ImageAlt from "assets/images/placeholder-image.svg";
import type { Plugin } from "entities/Plugin"; import type { Plugin } from "entities/Plugin";
import { import {
isDatasourceAuthorizedForQueryCreation, isDatasourceAuthorizedForQueryCreation,
@ -76,7 +77,10 @@ function ListItemWrapper(props: {
className={`t--ds-list ${selected ? "active" : ""}`} className={`t--ds-list ${selected ? "active" : ""}`}
onClick={() => onClick(ds)} onClick={() => onClick(ds)}
> >
<PluginImage alt="Datasource" src={getAssetUrl(plugin?.iconLocation)} /> <PluginImage
alt="Datasource"
src={getAssetUrl(plugin?.iconLocation || ImageAlt)}
/>
<ListLabels> <ListLabels>
<Tooltip content={ds.name} placement="left"> <Tooltip content={ds.name} placement="left">
<DsTitle> <DsTitle>

View File

@ -28,8 +28,7 @@ import {
JsFileIconV2, JsFileIconV2,
} from "pages/Editor/Explorer/ExplorerIcons"; } from "pages/Editor/Explorer/ExplorerIcons";
import { getAssetUrl } from "ee/utils/airgapHelpers"; import { getAssetUrl } from "ee/utils/airgapHelpers";
import { type Plugin, PluginType } from "entities/Plugin"; import { PluginType } from "entities/Plugin";
import ImageAlt from "assets/images/placeholder-image.svg";
import { Icon } from "@appsmith/ads"; import { Icon } from "@appsmith/ads";
import { objectKeys } from "@appsmith/utils"; import { objectKeys } from "@appsmith/utils";
@ -438,13 +437,3 @@ export function getModuleIcon(
</EntityIcon> </EntityIcon>
); );
} }
export function getPluginImagesFromPlugins(plugins: Plugin[]) {
const pluginImages: Record<string, string> = {};
plugins.forEach((plugin) => {
pluginImages[plugin.id] = plugin?.iconLocation ?? ImageAlt;
});
return pluginImages;
}

View File

@ -169,18 +169,6 @@ export const getExistingActionNames = createSelector(
}, },
); );
export const getPluginIdToImageLocation = createSelector(
getPlugins,
(plugins) =>
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
plugins.reduce((acc: any, p: Plugin) => {
acc[p.id] = p.iconLocation;
return acc;
}, {}),
);
/** /**
* returns a objects of existing page name in data tree * returns a objects of existing page name in data tree
* *