Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Adding no access state for Datasource tab based on permissions given via GAC #38268

Merged
merged 11 commits into from
Dec 23, 2024
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from "react";
import { Flex } from "@appsmith/ads";
import { Flex, Icon } from "@appsmith/ads";
import { getAssetUrl } from "ee/utils/airgapHelpers";
import { EntityIcon } from "pages/Editor/Explorer/ExplorerIcons";
import { useSelector } from "react-redux";
import {
getPluginIdFromDatasourceId,
getPluginImages,
} from "ee/selectors/entitiesSelector";
import { createMessage, SELECT_DATASOURCE } from "ee/constants/messages";

interface Props {
datasourceId: string;
Expand All @@ -24,9 +25,13 @@ const CurrentDataSource = ({ datasourceId, datasourceName }: Props) => {
return (
<Flex alignItems="center" gap="spaces-2">
<EntityIcon height="16px" width="16px">
<img alt="entityIcon" src={getAssetUrl(datasourceIcon)} />
{datasourceIcon ? (
<img alt="entityIcon" src={getAssetUrl(datasourceIcon)} />
) : (
<Icon name="datasource-v3" />
)}
</EntityIcon>
{datasourceName}
{datasourceName || createMessage(SELECT_DATASOURCE)}
</Flex>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const DatasourceInfo = ({
datasourceName={datasourceName}
plugin={plugin}
/>
{showEditButton && (
{showEditButton && datasourceName && (
<Tooltip content={createMessage(EDIT_DS_CONFIG)} placement="top">
<Button
isIconButton
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from "react";
import { useSelector } from "react-redux";
import { Flex } from "@appsmith/ads";
import { CREATE_NEW_DATASOURCE, createMessage } from "ee/constants/messages";
import {
CREATE_NEW_DATASOURCE,
createMessage,
NOT_FOUND,
} from "ee/constants/messages";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";
import {
Expand Down Expand Up @@ -66,7 +70,7 @@ export const PluginDatasourceSelector = ({
const userWorkspacePermissions = useSelector(
(state: AppState) => getCurrentAppWorkspace(state).userPermissions ?? [],
);
const isChangePermitted = getHasManageActionPermission(
const isActionChangePermitted = getHasManageActionPermission(
isFeatureEnabled,
currentActionConfig?.userPermissions,
);
Expand Down Expand Up @@ -108,7 +112,7 @@ export const PluginDatasourceSelector = ({
});
}

if (!showDatasourceSelector || !isChangePermitted) {
if (!showDatasourceSelector || !isActionChangePermitted) {
return (
<CurrentDataSourceLink
datasourceId={datasourceId}
Expand All @@ -117,6 +121,13 @@ export const PluginDatasourceSelector = ({
);
}

if (DATASOURCES_OPTIONS.length < 1) {
DATASOURCES_OPTIONS.push({
label: createMessage(NOT_FOUND),
value: "not found",
});
}
ankitakinger marked this conversation as resolved.
Show resolved Hide resolved

return (
<Flex>
<MenuField
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ export interface DatasourceProps {
}

const DatasourceSelector = (props: DatasourceProps) => {
return props.plugin ? (
return props.plugin &&
API_FORM_COMPONENTS.includes(props.plugin.uiComponent) ? (
<ApiDatasourceSelector {...props} formName={API_EDITOR_FORM_NAME} />
) : (
<QueryDatasourceSelector {...props} formName={QUERY_EDITOR_FORM_NAME} />
)
) : null;
<ApiDatasourceSelector {...props} formName={API_EDITOR_FORM_NAME} />
) : (
<QueryDatasourceSelector {...props} formName={QUERY_EDITOR_FORM_NAME} />
);
};

export default DatasourceSelector;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
getIsFetchingDatasourceStructure,
getPluginIdFromDatasourceId,
getPluginDatasourceComponentFromId,
getDatasource,
} from "ee/selectors/entitiesSelector";
import type { AppState } from "ee/reducers";
import { fetchDatasourceStructure } from "actions/datasourceActions";
Expand All @@ -26,24 +27,32 @@ import { useEditorType } from "ee/hooks";
import { useParentEntityInfo } from "ee/hooks/datasourceEditorHooks";
import DatasourceInfo from "./DatasourceInfo";
import { getPlugin } from "ee/selectors/entitiesSelector";
import {
getHasCreateDatasourceActionPermission,
getHasManageDatasourcePermission,
} from "ee/utils/BusinessFeatures/permissionPageHelpers";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "ee/entities/FeatureFlag";

interface Props {
datasourceId: string;
datasourceName: string;
currentActionId: string;
}

const Datasource = (props: Props) => {
const DatasourceTab = (props: Props) => {
const dispatch = useDispatch();

const { datasourceId, datasourceName } = props;

const datasourceStructure = useSelector((state) =>
getDatasourceStructureById(state, props.datasourceId),
getDatasourceStructureById(state, datasourceId),
);

const { responseTabHeight } = useSelector(getPluginActionDebuggerState);

const pluginId = useSelector((state) =>
getPluginIdFromDatasourceId(state, props.datasourceId),
getPluginIdFromDatasourceId(state, datasourceId),
);

const plugin = useSelector((state) => getPlugin(state, pluginId || ""));
Expand All @@ -54,32 +63,46 @@ const Datasource = (props: Props) => {
const [selectedTable, setSelectedTable] = useState<string>();

const isLoading = useSelector((state: AppState) =>
getIsFetchingDatasourceStructure(state, props.datasourceId),
getIsFetchingDatasourceStructure(state, datasourceId),
);

const pluginDatasourceForm = useSelector((state) =>
getPluginDatasourceComponentFromId(state, pluginId || ""),
);

const datasource = useSelector((state) => getDatasource(state, datasourceId));

const isFeatureEnabled = useFeatureFlag(FEATURE_FLAG.license_gac_enabled);

const canCreateDatasourceActions = getHasCreateDatasourceActionPermission(
isFeatureEnabled,
datasource?.userPermissions || [],
);

const canManageDatasourceActions = getHasManageDatasourcePermission(
isFeatureEnabled,
datasource?.userPermissions || [],
);

useEffect(
function resetSelectedTable() {
setSelectedTable(undefined);
},
[props.datasourceId],
[datasourceId],
);

useEffect(
function fetchDatasourceStructureEffect() {
function fetchStructure() {
if (
props.datasourceId &&
datasourceId &&
datasourceStructure === undefined &&
pluginDatasourceForm !==
DatasourceComponentTypes.RestAPIDatasourceForm
) {
dispatch(
fetchDatasourceStructure(
props.datasourceId,
datasourceId,
true,
DatasourceStructureContext.QUERY_EDITOR,
),
Expand All @@ -89,7 +112,7 @@ const Datasource = (props: Props) => {

fetchStructure();
},
[props.datasourceId, datasourceStructure, dispatch, pluginDatasourceForm],
[datasourceId, datasourceStructure, dispatch, pluginDatasourceForm],
);

useEffect(
Expand All @@ -98,22 +121,22 @@ const Datasource = (props: Props) => {
setSelectedTable(datasourceStructure.tables[0].name);
}
},
[selectedTable, props.datasourceId, isLoading, datasourceStructure],
[selectedTable, datasourceId, isLoading, datasourceStructure],
);

// eslint-disable-next-line react-perf/jsx-no-new-function-as-prop
const editDatasource = () => {
const entryPoint = DatasourceEditEntryPoints.QUERY_EDITOR_DATASOURCE_SCHEMA;

AnalyticsUtil.logEvent("EDIT_DATASOURCE_CLICK", {
datasourceId: props.datasourceId,
datasourceId,
pluginName: "",
entryPoint: entryPoint,
});

const url = datasourcesEditorIdURL({
baseParentEntityId: parentEntityId,
datasourceId: props.datasourceId,
datasourceId,
params: { ...omit(getQueryParams(), "viewMode"), viewMode: false },
generateEditorPath: true,
});
Expand All @@ -124,6 +147,8 @@ const Datasource = (props: Props) => {
const getStatusState = () => {
if (isLoading) return SchemaDisplayStatus.SCHEMA_LOADING;

if (!canCreateDatasourceActions) return SchemaDisplayStatus.NOACCESS;

if (!datasourceStructure) return SchemaDisplayStatus.NOSCHEMA;

if (datasourceStructure && "error" in datasourceStructure)
Expand All @@ -144,10 +169,10 @@ const Datasource = (props: Props) => {
return (
<Flex flexDirection="column" padding="spaces-3">
<DatasourceInfo
datasourceId={props.datasourceId}
datasourceName={props.datasourceName}
datasourceId={datasourceId}
datasourceName={datasourceName}
plugin={plugin}
showEditButton={!isLoading}
showEditButton={!isLoading && canManageDatasourceActions}
/>
<StatusDisplay
editDatasource={editDatasource}
Expand All @@ -171,8 +196,8 @@ const Datasource = (props: Props) => {
<Flex h="100%">
<DatasourceTables
currentActionId={props.currentActionId}
datasourceId={props.datasourceId}
datasourceName={props.datasourceName}
datasourceId={datasourceId}
datasourceName={datasourceName}
datasourceStructure={datasourceStructure}
plugin={plugin}
selectedTable={selectedTable}
Expand Down Expand Up @@ -200,4 +225,4 @@ const Datasource = (props: Props) => {
);
};

export { Datasource };
export { DatasourceTab };
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./Datasource";
export * from "./DatasourceTab";
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
} from "PluginActionEditor/store";
import { doesPluginRequireDatasource } from "ee/entities/Engine/actionHelpers";
import useShowSchema from "PluginActionEditor/components/PluginActionResponse/hooks/useShowSchema";
import { Datasource } from "PluginActionEditor/components/PluginActionResponse/components/DatasourceTab";
import { DatasourceTab } from "PluginActionEditor/components/PluginActionResponse/components/DatasourceTab";
import {
useBlockExecution,
useHandleRunClick,
Expand Down Expand Up @@ -64,7 +64,7 @@ function usePluginActionResponseTabs() {
key: DEBUGGER_TAB_KEYS.DATASOURCE_TAB,
title: "Datasource",
panelComponent: (
<Datasource
<DatasourceTab
currentActionId={action.id}
datasourceId={datasource?.id || ""}
datasourceName={datasource?.name || ""}
Expand Down Expand Up @@ -119,7 +119,7 @@ function usePluginActionResponseTabs() {
key: DEBUGGER_TAB_KEYS.DATASOURCE_TAB,
title: "Datasource",
panelComponent: (
<Datasource
<DatasourceTab
currentActionId={action.id}
datasourceId={datasource?.id || ""}
datasourceName={datasource?.name || ""}
Expand Down
2 changes: 2 additions & 0 deletions app/client/src/ce/constants/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ export const CREATE_NEW_DATASOURCE_MOST_POPULAR_HEADER = () => "Most popular";
export const CREATE_NEW_DATASOURCE_REST_API = () => "REST API";
export const SAMPLE_DATASOURCES = () => "Sample datasources";
export const EDIT_DS_CONFIG = () => "Edit datasource configuration";
export const NOT_FOUND = () => "Not found";
export const SELECT_DATASOURCE = () => "Select a datasource";

export const ERROR_EVAL_ERROR_GENERIC = () =>
`Unexpected error occurred while evaluating the application`;
Expand Down
8 changes: 4 additions & 4 deletions app/client/src/ce/selectors/appIDESelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { getJSTabs, getQueryTabs } from "selectors/ideSelectors";
import type { AppState } from "ee/reducers";
import { identifyEntityFromPath } from "navigation/FocusEntity";
import { getCurrentPageId } from "selectors/editorSelectors";
import { getCurrentBasePageId } from "selectors/editorSelectors";
import { getQueryEntityItemUrl } from "ee/pages/Editor/IDE/EditorPane/Query/utils";

export type EditorSegmentList = Array<{
Expand Down Expand Up @@ -74,10 +74,10 @@ export const selectQuerySegmentEditorTabs = (state: AppState) => {

export const getLastQueryTab = createSelector(
selectQuerySegmentEditorTabs,
getCurrentPageId,
(tabs, pageId) => {
getCurrentBasePageId,
(tabs, basePageId) => {
if (tabs.length) {
const url = getQueryEntityItemUrl(tabs[tabs.length - 1], pageId);
const url = getQueryEntityItemUrl(tabs[tabs.length - 1], basePageId);
const urlWithoutQueryParams = url.split("?")[0];

return identifyEntityFromPath(urlWithoutQueryParams);
Expand Down
Loading
Loading