Skip to content

Commit cf90a8e

Browse files
author
Aman Agarwal
authored
fix: Updated the copy text if plugin not installed, disabled new query and edit for unavailable plugin ds (#40360)
1 parent d1f55d2 commit cf90a8e

File tree

7 files changed

+75
-39
lines changed

7 files changed

+75
-39
lines changed

app/client/src/PluginActionEditor/PluginActionEditor.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import CenteredWrapper from "components/designSystems/appsmith/CenteredWrapper";
1515
import { Text } from "@appsmith/ads";
1616
import { useIsEditorInitialised } from "IDE/hooks";
1717
import { useActionSettingsConfig } from "./hooks";
18+
import { createMessage, PLUGIN_NOT_INSTALLED } from "ee/constants/messages";
19+
import { ShowUpgradeMenuItem } from "ee/utils/licenseHelpers";
1820

1921
interface ChildrenProps {
2022
children: React.ReactNode | React.ReactNode[];
@@ -54,10 +56,11 @@ const PluginActionEditor = (props: ChildrenProps) => {
5456

5557
if (!plugin) {
5658
return (
57-
<CenteredWrapper>
59+
<CenteredWrapper className="flex-col">
5860
<Text color="var(--ads-v2-color-fg-error)" kind="heading-m">
59-
Plugin not installed!
61+
{createMessage(PLUGIN_NOT_INSTALLED)}
6062
</Text>
63+
<ShowUpgradeMenuItem />
6164
</CenteredWrapper>
6265
);
6366
}

app/client/src/ce/constants/messages.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2693,3 +2693,6 @@ export const GOOGLE_RECAPTCHA_FAILED = () =>
26932693
"Google reCAPTCHA verification failed";
26942694
export const PASSWORD_INSUFFICIENT_STRENGTH = () =>
26952695
"Insufficient password strength";
2696+
2697+
export const PLUGIN_NOT_INSTALLED = () =>
2698+
"Upgrade your plan to unlock access to these integrations.";

app/client/src/ce/pages/AppIDE/components/QueryAdd/useGroupedAddQueryOperations.tsx

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -45,34 +45,40 @@ export const useAddQueryListItems = () => {
4545
);
4646

4747
const getListItems = (data: ActionOperation[]) => {
48-
return data.map((fileOperation) => {
49-
let title =
50-
fileOperation.entityExplorerTitle ||
51-
fileOperation.dsName ||
52-
fileOperation.title;
53-
54-
title =
55-
fileOperation.focusEntityType === FocusEntity.QUERY_MODULE_INSTANCE
56-
? fileOperation.title
57-
: title;
58-
const className = createAddClassName(title);
59-
const icon =
60-
fileOperation.icon ||
61-
(fileOperation.pluginId &&
62-
getPluginEntityIcon(pluginGroups[fileOperation.pluginId]));
63-
64-
return {
65-
startIcon: icon,
66-
className: className,
67-
title,
68-
description:
48+
return data
49+
.map((fileOperation) => {
50+
let title =
51+
fileOperation.entityExplorerTitle ||
52+
fileOperation.dsName ||
53+
fileOperation.title;
54+
55+
title =
6956
fileOperation.focusEntityType === FocusEntity.QUERY_MODULE_INSTANCE
70-
? fileOperation.dsName
71-
: "",
72-
descriptionType: "inline",
73-
onClick: onCreateItemClick.bind(null, fileOperation),
74-
} as ListItemProps;
75-
});
57+
? fileOperation.title
58+
: title;
59+
const className = createAddClassName(title);
60+
const icon =
61+
fileOperation.icon ||
62+
(fileOperation.pluginId &&
63+
getPluginEntityIcon(pluginGroups[fileOperation.pluginId]));
64+
65+
if (fileOperation.pluginId && !pluginGroups[fileOperation.pluginId]) {
66+
return undefined;
67+
}
68+
69+
return {
70+
startIcon: icon,
71+
className: className,
72+
title,
73+
description:
74+
fileOperation.focusEntityType === FocusEntity.QUERY_MODULE_INSTANCE
75+
? fileOperation.dsName
76+
: "",
77+
descriptionType: "inline",
78+
onClick: onCreateItemClick.bind(null, fileOperation),
79+
} as ListItemProps;
80+
})
81+
.filter((item) => item !== undefined);
7682
};
7783

7884
return { getListItems };

app/client/src/components/editorComponents/GlobalSearch/GlobalSearchHooks.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ export const useFilteredFileOperations = ({
6464
}: FilterFileOperationsProps) => {
6565
const { appWideDS = [], otherDS = [] } = useAppWideAndOtherDatasource();
6666
const plugins = useSelector(getPlugins);
67+
const pluginById = useMemo(() => {
68+
return keyBy(plugins, "id");
69+
}, [plugins]);
6770
const moduleOptions = useModuleOptions();
6871
const workflowOptions = useWorkflowOptions();
6972

@@ -106,7 +109,7 @@ export const useFilteredFileOperations = ({
106109
return AiPlugin.id !== ds.pluginId;
107110
}
108111

109-
return true;
112+
return !!pluginById[ds.pluginId]?.id;
110113
});
111114

112115
return useFilteredAndSortedFileOperations({

app/client/src/components/editorComponents/GlobalSearch/index.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import type { ExplorerURLParams } from "ee/pages/Editor/Explorer/helpers";
4343
import { getLastSelectedWidget } from "selectors/ui";
4444
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
4545
import useRecentEntities from "./useRecentEntities";
46-
import { noop } from "lodash";
46+
import { keyBy, noop } from "lodash";
4747
import {
4848
getCurrentPageId,
4949
getPagePermissions,
@@ -179,6 +179,9 @@ function GlobalSearch() {
179179
(state: AppState) => state.ui.globalSearch.filterContext.category,
180180
);
181181
const plugins = useSelector(getPlugins);
182+
const pluginById = useMemo(() => {
183+
return keyBy(plugins, "id");
184+
}, [plugins]);
182185
const setCategory = useCallback(
183186
(category: SearchCategory) => {
184187
dispatch(setGlobalSearchFilterContext({ category: category }));
@@ -233,10 +236,15 @@ function GlobalSearch() {
233236
}, [basePageIdToPageIdMap, params?.basePageId, reducerDatasources]);
234237

235238
const filteredDatasources = useMemo(() => {
236-
if (!query) return datasourcesList;
239+
if (!query)
240+
return datasourcesList.filter(
241+
(datasource) => pluginById[datasource.pluginId]?.id,
242+
);
237243

238-
return datasourcesList.filter((datasource) =>
239-
isMatching(datasource.name, query),
244+
return datasourcesList.filter(
245+
(datasource) =>
246+
isMatching(datasource.name, query) &&
247+
pluginById[datasource.pluginId]?.id,
240248
);
241249
}, [datasourcesList, query]);
242250
const recentEntities = useRecentEntities();

app/client/src/pages/Editor/DataSourceEditor/DSFormHeader.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import type { PluginType } from "entities/Plugin";
2828
import { useLocation } from "react-router";
2929
import { useHeaderActions } from "ee/hooks/datasourceEditorHooks";
3030
import { getIDETypeByUrl } from "ee/entities/IDE/utils";
31+
import { getPlugin } from "ee/selectors/entitiesSelector";
3132

3233
export const ActionWrapper = styled.div`
3334
display: flex;
@@ -118,6 +119,10 @@ export const DSFormHeader = (props: DSFormHeaderProps) => {
118119
const dispatch = useDispatch();
119120
const location = useLocation();
120121
const ideType = getIDETypeByUrl(location.pathname);
122+
const plugin = useSelector((state) =>
123+
getPlugin(state, datasource?.pluginId || ""),
124+
);
125+
const isEditDisabled = !plugin?.id;
121126

122127
const deleteAction = () => {
123128
if (isDeleting) return;
@@ -210,8 +215,11 @@ export const DSFormHeader = (props: DSFormHeaderProps) => {
210215
)}
211216
<Button
212217
className="t--edit-datasource"
218+
isDisabled={isEditDisabled}
213219
kind="secondary"
214220
onClick={() => {
221+
if (isEditDisabled) return;
222+
215223
setDatasourceViewMode({
216224
datasourceId: datasourceId,
217225
viewMode: false,

app/client/src/pages/Editor/DataSourceEditor/NewActionButton.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { getCurrentPageId, getPageList } from "selectors/editorSelectors";
2424
import type { Datasource } from "entities/Datasource";
2525
import type { EventLocation } from "ee/utils/analyticsUtilTypes";
2626
import { getCurrentEnvironmentId } from "ee/selectors/environmentSelectors";
27-
import { getSelectedTableName } from "ee/selectors/entitiesSelector";
27+
import { getPlugin, getSelectedTableName } from "ee/selectors/entitiesSelector";
2828

2929
interface NewActionButtonProps {
3030
datasource?: Datasource;
@@ -75,6 +75,11 @@ function NewActionButton(props: NewActionButtonProps) {
7575
...pages.filter((p) => p.pageId !== currentPageId),
7676
];
7777
const queryDefaultTableName = useSelector(getSelectedTableName);
78+
const plugin = useSelector((state) =>
79+
getPlugin(state, datasource?.pluginId || ""),
80+
);
81+
82+
const isDisabled = !!disabled || !plugin?.id;
7883

7984
const createQueryAction = useCallback(
8085
(pageId: string) => {
@@ -106,7 +111,7 @@ function NewActionButton(props: NewActionButtonProps) {
106111

107112
const handleOnInteraction = useCallback(
108113
(open: boolean) => {
109-
if (disabled || isLoading) return;
114+
if (isDisabled || isLoading) return;
110115

111116
if (!open) {
112117
setIsPageSelectionOpen(false);
@@ -122,7 +127,7 @@ function NewActionButton(props: NewActionButtonProps) {
122127

123128
setIsPageSelectionOpen(true);
124129
},
125-
[pages, createQueryAction, disabled, isLoading],
130+
[pages, createQueryAction, isDisabled, isLoading],
126131
);
127132

128133
const getCreateButtonText = () => {
@@ -139,11 +144,11 @@ function NewActionButton(props: NewActionButtonProps) {
139144

140145
return (
141146
<Menu onOpenChange={handleOnInteraction} open={isPageSelectionOpen}>
142-
<MenuTrigger disabled={disabled}>
147+
<MenuTrigger disabled={isDisabled}>
143148
<Button
144149
className="t--create-query"
145150
id={"create-query"}
146-
isDisabled={!!disabled}
151+
isDisabled={isDisabled}
147152
isLoading={isSelected || isLoading}
148153
kind={isNewQuerySecondaryButton ? "secondary" : "primary"}
149154
onClick={() => handleOnInteraction(true)}

0 commit comments

Comments
 (0)