[Fix] create new api not working from saved google sheet state (#5681)

* fix show proper icons for queries

* Using query creation action creator for google sheet

* Properly setting up action config, if data source is of type api

* minor loading state fixed

* fixed warnings

* Handling the action for apis as well

* Re introduced the new query btn for google sheets
This commit is contained in:
Pranav Kanade 2021-07-08 12:47:56 +05:30 committed by GitHub
parent b0a6cc87dd
commit f28b9bd20b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 136 additions and 112 deletions

View File

@ -7,21 +7,19 @@ import Button from "components/ads/Button";
import { getDatasource, getPlugin } from "selectors/entitiesSelector";
import { Colors } from "constants/Colors";
import { HeaderIcons } from "icons/HeaderIcons";
import history from "utils/history";
import styled from "styled-components";
import { createActionRequest } from "actions/actionActions";
import { INTEGRATION_EDITOR_URL, INTEGRATION_TABS } from "constants/routes";
import { createNewApiName, createNewQueryName } from "utils/AppsmithUtils";
import { createNewQueryName } from "utils/AppsmithUtils";
import { getCurrentPageId } from "selectors/editorSelectors";
import { DEFAULT_API_ACTION_CONFIG } from "constants/ApiEditorConstants";
import { ApiActionConfig, PluginType, QueryAction } from "entities/Action";
import { ApiActionConfig, Action } from "entities/Action";
import { renderDatasourceSection } from "./DatasourceSection";
import { Toaster } from "components/ads/Toast";
import { Variant } from "components/ads/common";
import { OnboardingStep } from "constants/OnboardingConstants";
import { inOnboarding } from "sagas/OnboardingSagas";
import OnboardingIndicator from "components/editorComponents/Onboarding/Indicator";
import { createMessage, ERROR_ADD_API_INVALID_URL } from "constants/messages";
import { Toaster } from "components/ads/Toast";
import { Variant } from "components/ads/common";
import { ERROR_ADD_API_INVALID_URL } from "constants/messages";
import { DEFAULT_API_ACTION_CONFIG } from "constants/ApiEditorConstants";
const ConnectedText = styled.div`
color: ${Colors.OXFORD_BLUE};
@ -75,13 +73,32 @@ function Connected() {
const datasourceFormConfigs = useSelector(
(state: AppState) => state.entities.plugins.formConfigs,
);
const plugin = useSelector((state: AppState) =>
getPlugin(state, datasource?.pluginId ?? ""),
);
const isDBDatasource = plugin?.type === PluginType.DB;
const createQueryAction = useCallback(() => {
const newQueryName = createNewQueryName(actions, currentPageId || "");
if (
plugin?.type === "API" &&
(!datasource ||
!datasource.datasourceConfiguration ||
!datasource.datasourceConfiguration.url)
) {
Toaster.show({
text: ERROR_ADD_API_INVALID_URL(),
variant: Variant.danger,
});
return;
}
const headers = datasource?.datasourceConfiguration?.headers ?? [];
const defaultApiActionConfig: ApiActionConfig = {
...DEFAULT_API_ACTION_CONFIG,
headers: headers.length ? headers : DEFAULT_API_ACTION_CONFIG.headers,
};
let payload = {
name: newQueryName,
pageId: currentPageId,
@ -89,12 +106,13 @@ function Connected() {
datasource: {
id: datasource?.id,
},
actionConfiguration: {},
actionConfiguration: plugin?.type === "API" ? defaultApiActionConfig : {},
eventData: {
actionType: "Query",
from: "datasource-pane",
},
} as Partial<QueryAction>; // TODO: refactor later. Handle case for undefined datasource before we reach here.
} as Partial<Action>;
if (datasource)
if (isInOnboarding) {
// If in onboarding and tooltip is being shown
@ -108,55 +126,8 @@ function Connected() {
}
dispatch(createActionRequest(payload));
history.push(
INTEGRATION_EDITOR_URL(
params.applicationId,
currentPageId,
INTEGRATION_TABS.ACTIVE,
),
);
}, [dispatch, actions, currentPageId, params.applicationId, datasource]);
const createApiAction = useCallback(() => {
const newApiName = createNewApiName(actions, currentPageId || "");
const headers = datasource?.datasourceConfiguration?.headers ?? [];
const defaultApiActionConfig: ApiActionConfig = {
...DEFAULT_API_ACTION_CONFIG,
headers: headers.length ? headers : DEFAULT_API_ACTION_CONFIG.headers,
};
if (!datasource?.datasourceConfiguration?.url) {
Toaster.show({
text: createMessage(ERROR_ADD_API_INVALID_URL),
variant: Variant.danger,
});
return;
}
dispatch(
createActionRequest({
name: newApiName,
pageId: currentPageId,
pluginId: datasource.pluginId,
datasource: {
id: datasource.id,
},
eventData: {
actionType: "API",
from: "datasource-pane",
},
actionConfiguration: defaultApiActionConfig,
}),
);
history.push(
INTEGRATION_EDITOR_URL(
params.applicationId,
currentPageId,
INTEGRATION_TABS.NEW,
),
);
}, [dispatch, actions, currentPageId, params.applicationId, datasource]);
const currentFormConfig: Array<any> =
datasourceFormConfigs[datasource?.pluginId ?? ""];
@ -177,8 +148,8 @@ function Connected() {
<ActionButton
className="t--create-query"
icon="plus"
onClick={isDBDatasource ? createQueryAction : createApiAction}
text={isDBDatasource ? "New Query" : "New API"}
onClick={createQueryAction}
text={"New Query"}
/>
</OnboardingIndicator>
</Header>

View File

@ -281,6 +281,7 @@ class DatasourceRestAPIEditor extends React.Component<Props> {
text: "Unable to create API. Try adding a url to the datasource",
variant: Variant.danger,
});
return;
}
const newApiName = createNewApiName(actions, pageId || "");

View File

@ -30,7 +30,9 @@ export const ExplorerActionsGroup = memo((props: ExplorerActionsGroupProps) => {
const icon = props.config?.getIcon(
action.config,
props.plugins[action.config.datasource.pluginId],
props.plugins[
action.config.pluginId || action.config.datasource.pluginId
],
);
return (
<ExplorerActionEntity

View File

@ -1,18 +1,19 @@
import React from "react";
import styled from "styled-components";
import { Spinner } from "@blueprintjs/core";
import { connect } from "react-redux";
import { AppState } from "reducers";
import { createNewQueryName } from "utils/AppsmithUtils";
import { ActionDataState } from "reducers/entityReducers/actionsReducer";
import { Datasource } from "entities/Datasource";
import { createActionRequest } from "actions/actionActions";
import { QueryAction } from "entities/Action";
import CenteredWrapper from "components/designSystems/appsmith/CenteredWrapper";
import { Action, ApiActionConfig, PluginType } from "entities/Action";
import DatasourceCard from "./DatasourceCard";
import Text, { TextType } from "components/ads/Text";
import Button, { Category, Size } from "components/ads/Button";
import { thinScrollbar } from "constants/DefaultTheme";
import { Toaster } from "../../../components/ads/Toast";
import { Variant } from "../../../components/ads/common";
import { DEFAULT_API_ACTION_CONFIG } from "../../../constants/ApiEditorConstants";
const QueryHomePage = styled.div`
${thinScrollbar};
@ -45,15 +46,11 @@ const EmptyActiveDatasource = styled.div`
justify-content: center;
`;
const LoadingContainer = styled(CenteredWrapper)`
height: 50%;
`;
type ActiveDataSourceProps = {
dataSources: Datasource[];
applicationId: string;
pageId: string;
createAction: (data: Partial<QueryAction> & { eventData: any }) => void;
createAction: (data: Partial<Action> & { eventData: any }) => void;
actions: ActionDataState;
isCreating: boolean;
location: {
@ -67,11 +64,30 @@ type ActiveDataSourceProps = {
};
class ActiveDataSources extends React.Component<ActiveDataSourceProps> {
handleCreateNewQuery = (dataSource: Datasource) => {
handleCreateNewQuery = (dataSource: Datasource, pluginType: PluginType) => {
const { actions, pageId } = this.props;
if (
pluginType === "API" &&
(!dataSource ||
!dataSource.datasourceConfiguration ||
!dataSource.datasourceConfiguration.url)
) {
Toaster.show({
text: "Unable to create API. Try adding a url to the datasource",
variant: Variant.danger,
});
return;
}
if (pageId) {
const newQueryName = createNewQueryName(actions, pageId);
const headers = dataSource?.datasourceConfiguration?.headers ?? [];
const defaultApiActionConfig: ApiActionConfig = {
...DEFAULT_API_ACTION_CONFIG,
headers: headers.length ? headers : DEFAULT_API_ACTION_CONFIG.headers,
};
this.props.createAction({
name: newQueryName,
pageId,
@ -84,7 +100,7 @@ class ActiveDataSources extends React.Component<ActiveDataSourceProps> {
dataSource: dataSource.name,
},
pluginId: dataSource.pluginId,
actionConfiguration: {},
actionConfiguration: pluginType === "API" ? defaultApiActionConfig : {},
});
}
};
@ -92,13 +108,13 @@ class ActiveDataSources extends React.Component<ActiveDataSourceProps> {
render() {
const { dataSources, isCreating } = this.props;
if (isCreating) {
return (
<LoadingContainer>
<Spinner size={30} />
</LoadingContainer>
);
}
// if (isCreating) {
// return (
// <LoadingContainer>
// <Spinner size={30} />
// </LoadingContainer>
// );
// }
if (dataSources.length === 0) {
return (
@ -123,6 +139,7 @@ class ActiveDataSources extends React.Component<ActiveDataSourceProps> {
return (
<DatasourceCard
datasource={datasource}
isCreating={isCreating}
key={`${datasource.id}_${idx}`}
onCreateQuery={this.handleCreateNewQuery}
/>
@ -138,7 +155,7 @@ const mapStateToProps = (state: AppState) => ({
});
const mapDispatchToProps = (dispatch: any) => ({
createAction: (data: Partial<QueryAction> & { eventData: any }) => {
createAction: (data: Partial<Action> & { eventData: any }) => {
dispatch(createActionRequest(data));
},
});

View File

@ -1,7 +1,7 @@
import { Datasource } from "entities/Datasource";
import { isStoredDatasource, PluginType } from "entities/Action";
import Button, { Category } from "components/ads/Button";
import React, { useMemo } from "react";
import React, { useCallback, useMemo, useState } from "react";
import { isNil, keyBy } from "lodash";
import { useDispatch, useSelector } from "react-redux";
import { Colors } from "constants/Colors";
@ -94,14 +94,16 @@ const ButtonsWrapper = styled.div`
type DatasourceCardProps = {
datasource: Datasource;
onCreateQuery: (datasource: Datasource) => void;
onCreateQuery: (datasource: Datasource, pluginType: PluginType) => void;
isCreating?: boolean;
};
function DatasourceCard(props: DatasourceCardProps) {
const dispatch = useDispatch();
const [isSelected, setIsSelected] = useState(false);
const pluginImages = useSelector(getPluginImages);
const params = useParams<{ applicationId: string; pageId: string }>();
const { datasource } = props;
const { datasource, isCreating } = props;
const datasourceFormConfigs = useSelector(
(state: AppState) => state.entities.plugins.formConfigs,
);
@ -119,7 +121,7 @@ function DatasourceCard(props: DatasourceCardProps) {
return state.entities.plugins.list;
});
const pluginGroups = useMemo(() => keyBy(plugins, "id"), [plugins]);
const editDatasource = () => {
const editDatasource = useCallback(() => {
const plugin = pluginGroups[datasource.pluginId];
if (plugin && plugin.type === PluginType.SAAS) {
history.push(
@ -146,7 +148,13 @@ function DatasourceCard(props: DatasourceCardProps) {
),
);
}
};
}, [datasource.id, params]);
const onCreateNewQuery = useCallback(() => {
setIsSelected(true);
const plugin = pluginGroups[datasource.pluginId];
props.onCreateQuery(datasource, plugin.type);
}, []);
return (
<Wrapper className="t--datasource">
@ -176,7 +184,8 @@ function DatasourceCard(props: DatasourceCardProps) {
<ActionButton
className="t--create-query"
icon="plus"
onClick={() => props.onCreateQuery(datasource)}
isLoading={isCreating && isSelected}
onClick={onCreateNewQuery}
text="New Query"
/>
</ButtonsWrapper>

View File

@ -19,7 +19,7 @@ import {
redirectAuthorizationCode,
updateDatasource,
} from "actions/datasourceActions";
import { createNewApiName } from "utils/AppsmithUtils";
import { createNewQueryName } from "utils/AppsmithUtils";
import { createActionRequest } from "actions/actionActions";
import { ActionDataState } from "reducers/entityReducers/actionsReducer";
import {
@ -38,7 +38,7 @@ import {
} from "constants/messages";
import { Variant } from "components/ads/common";
import { Toaster } from "components/ads/Toast";
import { PluginType, SaaSAction } from "entities/Action";
import { Action, PluginType } from "entities/Action";
import AnalyticsUtil from "utils/AnalyticsUtil";
import Connected from "../DataSourceEditor/Connected";
import { Colors } from "constants/Colors";
@ -58,7 +58,7 @@ interface DispatchFunctions {
updateDatasource: (formData: any, onSuccess?: ReduxAction<unknown>) => void;
deleteDatasource: (id: string, onSuccess?: ReduxAction<unknown>) => void;
getOAuthAccessToken: (id: string) => void;
createAction: (data: Partial<SaaSAction>) => void;
createAction: (data: Partial<Action>) => void;
}
type DatasourceSaaSEditorProps = StateProps &
@ -90,6 +90,18 @@ const EditDatasourceButton = styled(AdsButton)`
}
`;
const NewQueryBtn = styled(AdsButton)`
padding: 10px 20px;
&&&& {
height: 36px;
//max-width: 120px;
width: auto;
}
span > svg > path {
stroke: white;
}
`;
class DatasourceSaaSEditor extends JSONtoForm<Props> {
componentDidMount() {
super.componentDidMount();
@ -122,34 +134,39 @@ class DatasourceSaaSEditor extends JSONtoForm<Props> {
this.props.updateDatasource(normalizedValues, onSuccess);
};
createApiAction = () => {
const {
actions,
formData,
match: {
params: { pageId },
},
} = this.props;
const newApiName = createNewApiName(actions, pageId || "");
this.save(
createActionRequest({
name: newApiName,
pageId: pageId,
pluginId: formData.pluginId,
datasource: {
id: formData.id,
},
}),
);
};
render() {
const { formConfig } = this.props;
const content = this.renderDataSourceConfigForm(formConfig);
return this.renderForm(content);
}
createQueryAction = () => {
const {
actions,
datasource,
match: {
params: { pageId },
},
} = this.props;
const newQueryName = createNewQueryName(actions, pageId || "");
const payload = {
name: newQueryName,
pageId: pageId,
pluginId: datasource?.pluginId,
datasource: {
id: datasource?.id,
},
actionConfiguration: {},
eventData: {
actionType: "Query",
from: "datasource-pane",
},
} as Partial<Action>;
this.props.createAction(payload);
};
renderDataSourceConfigForm = (sections: any) => {
const {
deleteDatasource,
@ -173,7 +190,7 @@ class DatasourceSaaSEditor extends JSONtoForm<Props> {
<PluginImage alt="Datasource" src={this.props.pluginImage} />
<FormTitle focusOnMount={this.props.isNewDatasource} />
</FormTitleContainer>
{viewMode && (
{viewMode ? (
<EditDatasourceButton
category={Category.tertiary}
className="t--edit-datasource"
@ -192,6 +209,13 @@ class DatasourceSaaSEditor extends JSONtoForm<Props> {
}}
text="EDIT"
/>
) : (
<NewQueryBtn
className="t--create-query"
icon="plus"
onClick={this.createQueryAction}
text={"New Query"}
/>
)}
</Header>
{!viewMode ? (
@ -277,7 +301,7 @@ const mapDispatchToProps = (dispatch: any): DispatchFunctions => {
dispatch(updateDatasource(formData, onSuccess)),
getOAuthAccessToken: (datasourceId: string) =>
dispatch(getOAuthAccessToken(datasourceId)),
createAction: (data: Partial<SaaSAction>) => {
createAction: (data: Partial<Action>) => {
dispatch(createActionRequest(data));
},
};