Merge branch 'hide-new-api-pane' into 'release'
Add a feature flag for new api pane See merge request theappsmith/internal-tools-client!499
This commit is contained in:
commit
dcf320e4e6
|
|
@ -13,3 +13,10 @@ export const initApiPane = (urlId?: string): ReduxAction<{ id?: string }> => {
|
||||||
payload: { id: urlId },
|
payload: { id: urlId },
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const createNewApiAction = (
|
||||||
|
pageId: string,
|
||||||
|
): ReduxAction<{ pageId: string }> => ({
|
||||||
|
type: ReduxActionTypes.CREATE_NEW_API_ACTION,
|
||||||
|
payload: { pageId },
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
||||||
CLEAR_PROVIDERS: "CLEAR_PROVIDERS",
|
CLEAR_PROVIDERS: "CLEAR_PROVIDERS",
|
||||||
BATCHED_UPDATE: "BATCHED_UPDATE",
|
BATCHED_UPDATE: "BATCHED_UPDATE",
|
||||||
EXECUTE_BATCH: "EXECUTE_BATCH",
|
EXECUTE_BATCH: "EXECUTE_BATCH",
|
||||||
|
CREATE_NEW_API_ACTION: "CREATE_NEW_API_ACTION",
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ReduxActionType = typeof ReduxActionTypes[keyof typeof ReduxActionTypes];
|
export type ReduxActionType = typeof ReduxActionTypes[keyof typeof ReduxActionTypes];
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,7 @@ import { reduxForm, InjectedFormProps, getFormValues } from "redux-form";
|
||||||
import { Icon, Card } from "@blueprintjs/core";
|
import { Icon, Card } from "@blueprintjs/core";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import InfiniteScroll from "react-infinite-scroller";
|
import InfiniteScroll from "react-infinite-scroller";
|
||||||
import {
|
import { DEFAULT_PROVIDER_OPTION } from "constants/ApiEditorConstants";
|
||||||
DEFAULT_API_ACTION,
|
|
||||||
DEFAULT_PROVIDER_OPTION,
|
|
||||||
REST_PLUGIN_PACKAGE_NAME,
|
|
||||||
} from "constants/ApiEditorConstants";
|
|
||||||
import {
|
import {
|
||||||
getCurlImportPageURL,
|
getCurlImportPageURL,
|
||||||
getProviderTemplatesURL,
|
getProviderTemplatesURL,
|
||||||
|
|
@ -35,7 +31,6 @@ import {
|
||||||
fetchProvidersWithCategory,
|
fetchProvidersWithCategory,
|
||||||
clearProviders,
|
clearProviders,
|
||||||
} from "actions/providerActions";
|
} from "actions/providerActions";
|
||||||
import { createNewApiName } from "utils/AppsmithUtils";
|
|
||||||
import { Colors } from "constants/Colors";
|
import { Colors } from "constants/Colors";
|
||||||
import CenteredWrapper from "components/designSystems/appsmith/CenteredWrapper";
|
import CenteredWrapper from "components/designSystems/appsmith/CenteredWrapper";
|
||||||
// import { BaseTextInput } from "components/designSystems/appsmith/TextInputComponent";
|
// import { BaseTextInput } from "components/designSystems/appsmith/TextInputComponent";
|
||||||
|
|
@ -46,7 +41,7 @@ import Spinner from "components/editorComponents/Spinner";
|
||||||
import CurlLogo from "assets/images/Curl-logo.svg";
|
import CurlLogo from "assets/images/Curl-logo.svg";
|
||||||
import { FetchProviderWithCategoryRequest } from "api/ProvidersApi";
|
import { FetchProviderWithCategoryRequest } from "api/ProvidersApi";
|
||||||
import { Plugin } from "api/PluginApi";
|
import { Plugin } from "api/PluginApi";
|
||||||
import _ from "lodash";
|
import { createNewApiAction } from "actions/apiPaneActions";
|
||||||
|
|
||||||
// const SearchContainer = styled.div`
|
// const SearchContainer = styled.div`
|
||||||
// display: flex;
|
// display: flex;
|
||||||
|
|
@ -241,6 +236,7 @@ type ApiHomeScreenProps = {
|
||||||
isFetchingProviders: boolean;
|
isFetchingProviders: boolean;
|
||||||
providersTotal: number;
|
providersTotal: number;
|
||||||
isSwitchingCategory: boolean;
|
isSwitchingCategory: boolean;
|
||||||
|
createNewApiAction: (pageId: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ApiHomeScreenState = {
|
type ApiHomeScreenState = {
|
||||||
|
|
@ -283,20 +279,9 @@ class ApiHomeScreen extends React.Component<Props, ApiHomeScreenState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCreateNew = (params: string) => {
|
handleCreateNew = (params: string) => {
|
||||||
const { actions, plugins } = this.props;
|
|
||||||
const pageId = new URLSearchParams(params).get("importTo");
|
const pageId = new URLSearchParams(params).get("importTo");
|
||||||
const plugin = _.find(plugins, { packageName: REST_PLUGIN_PACKAGE_NAME });
|
if (pageId) {
|
||||||
if (pageId && plugin) {
|
this.props.createNewApiAction(pageId);
|
||||||
const newActionName = createNewApiName(actions, pageId);
|
|
||||||
this.props.createAction({
|
|
||||||
...DEFAULT_API_ACTION,
|
|
||||||
name: newActionName,
|
|
||||||
datasource: {
|
|
||||||
name: "DEFAULT_REST_DATASOURCE",
|
|
||||||
pluginId: plugin.id,
|
|
||||||
},
|
|
||||||
pageId,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -560,6 +545,7 @@ const mapDispatchToProps = (dispatch: any) => ({
|
||||||
dispatch(fetchProvidersWithCategory(request)),
|
dispatch(fetchProvidersWithCategory(request)),
|
||||||
createAction: (data: Partial<RestAction>) =>
|
createAction: (data: Partial<RestAction>) =>
|
||||||
dispatch(createActionRequest(data)),
|
dispatch(createActionRequest(data)),
|
||||||
|
createNewApiAction: (pageId: string) => dispatch(createNewApiAction(pageId)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,16 @@ import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||||
import { getCurrentPageName, getActionById } from "selectors/editorSelectors";
|
import { getCurrentPageName, getActionById } from "selectors/editorSelectors";
|
||||||
import { Plugin } from "api/PluginApi";
|
import { Plugin } from "api/PluginApi";
|
||||||
import { ActionData } from "reducers/entityReducers/actionsReducer";
|
import { ActionData } from "reducers/entityReducers/actionsReducer";
|
||||||
|
import { API_PANE_V2, checkForFlag } from "utils/featureFlags";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
const EmptyStateContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
font-size: 20px;
|
||||||
|
`;
|
||||||
|
|
||||||
interface ReduxStateProps {
|
interface ReduxStateProps {
|
||||||
actions: ActionDataState;
|
actions: ActionDataState;
|
||||||
|
|
@ -139,6 +149,21 @@ class ApiEditor extends React.Component<Props> {
|
||||||
|
|
||||||
const { isSaving, isRunning, isDeleting, drafts } = apiPane;
|
const { isSaving, isRunning, isDeleting, drafts } = apiPane;
|
||||||
const paginationType = _.get(data, "actionConfiguration.paginationType");
|
const paginationType = _.get(data, "actionConfiguration.paginationType");
|
||||||
|
const apiHomeScreen = (
|
||||||
|
<ApiHomeScreen
|
||||||
|
applicationId={this.props.match.params.applicationId}
|
||||||
|
pageId={this.props.match.params.pageId}
|
||||||
|
history={this.props.history}
|
||||||
|
location={this.props.location}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
const defaultHomeScreen = (
|
||||||
|
<EmptyStateContainer>
|
||||||
|
{"Create / Select an API from the list"}
|
||||||
|
</EmptyStateContainer>
|
||||||
|
);
|
||||||
|
const v2Flag = checkForFlag(API_PANE_V2);
|
||||||
|
const homeScreen = v2Flag ? apiHomeScreen : defaultHomeScreen;
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{apiId ? (
|
{apiId ? (
|
||||||
|
|
@ -183,12 +208,7 @@ class ApiEditor extends React.Component<Props> {
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<ApiHomeScreen
|
homeScreen
|
||||||
applicationId={this.props.match.params.applicationId}
|
|
||||||
pageId={this.props.match.params.pageId}
|
|
||||||
history={this.props.history}
|
|
||||||
location={this.props.location}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,11 @@ import {
|
||||||
copyActionRequest,
|
copyActionRequest,
|
||||||
deleteAction,
|
deleteAction,
|
||||||
} from "actions/actionActions";
|
} from "actions/actionActions";
|
||||||
import { changeApi, initApiPane } from "actions/apiPaneActions";
|
import {
|
||||||
|
changeApi,
|
||||||
|
createNewApiAction,
|
||||||
|
initApiPane,
|
||||||
|
} from "actions/apiPaneActions";
|
||||||
import { RestAction } from "api/ActionAPI";
|
import { RestAction } from "api/ActionAPI";
|
||||||
import { getPluginIdOfName } from "selectors/entitiesSelector";
|
import { getPluginIdOfName } from "selectors/entitiesSelector";
|
||||||
import { PLUGIN_NAME } from "constants/ApiEditorConstants";
|
import { PLUGIN_NAME } from "constants/ApiEditorConstants";
|
||||||
|
|
@ -20,6 +24,7 @@ import EditorSidebar from "pages/Editor/EditorSidebar";
|
||||||
import { getNextEntityName } from "utils/AppsmithUtils";
|
import { getNextEntityName } from "utils/AppsmithUtils";
|
||||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||||
import { API_EDITOR_URL_WITH_SELECTED_PAGE_ID } from "constants/routes";
|
import { API_EDITOR_URL_WITH_SELECTED_PAGE_ID } from "constants/routes";
|
||||||
|
import { API_PANE_V2, checkForFlag } from "utils/featureFlags";
|
||||||
|
|
||||||
const HTTPMethod = styled.span<{ method?: string }>`
|
const HTTPMethod = styled.span<{ method?: string }>`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
@ -73,6 +78,7 @@ interface ReduxDispatchProps {
|
||||||
) => void;
|
) => void;
|
||||||
copyAction: (id: string, pageId: string, name: string) => void;
|
copyAction: (id: string, pageId: string, name: string) => void;
|
||||||
deleteAction: (id: string, name: string) => void;
|
deleteAction: (id: string, name: string) => void;
|
||||||
|
createNewApiAction: (pageId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Props = ReduxStateProps &
|
type Props = ReduxStateProps &
|
||||||
|
|
@ -159,8 +165,10 @@ class ApiSidebar extends React.Component<Props> {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleCreateNewApiClick = (selectedPageId: string) => {
|
handleCreateNewApiClick = (selectedPageId: string) => {
|
||||||
const { history } = this.props;
|
const { history, createNewApiAction } = this.props;
|
||||||
const { pageId, applicationId } = this.props.match.params;
|
const { pageId, applicationId } = this.props.match.params;
|
||||||
|
const v2Flag = checkForFlag(API_PANE_V2);
|
||||||
|
if (v2Flag) {
|
||||||
history.push(
|
history.push(
|
||||||
API_EDITOR_URL_WITH_SELECTED_PAGE_ID(
|
API_EDITOR_URL_WITH_SELECTED_PAGE_ID(
|
||||||
applicationId,
|
applicationId,
|
||||||
|
|
@ -168,6 +176,9 @@ class ApiSidebar extends React.Component<Props> {
|
||||||
selectedPageId,
|
selectedPageId,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
createNewApiAction(selectedPageId);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
@ -223,6 +234,7 @@ const mapDispatchToProps = (dispatch: Function): ReduxDispatchProps => ({
|
||||||
dispatch(copyActionRequest({ id, destinationPageId, name })),
|
dispatch(copyActionRequest({ id, destinationPageId, name })),
|
||||||
deleteAction: (id: string, name: string) =>
|
deleteAction: (id: string, name: string) =>
|
||||||
dispatch(deleteAction({ id, name })),
|
dispatch(deleteAction({ id, name })),
|
||||||
|
createNewApiAction: (pageId: string) => dispatch(createNewApiAction(pageId)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(ApiSidebar);
|
export default connect(mapStateToProps, mapDispatchToProps)(ApiSidebar);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,11 @@ import {
|
||||||
} from "constants/ReduxActionConstants";
|
} from "constants/ReduxActionConstants";
|
||||||
import { getFormData } from "selectors/formSelectors";
|
import { getFormData } from "selectors/formSelectors";
|
||||||
import { API_EDITOR_FORM_NAME, API_HOME_SCREEN_FORM } from "constants/forms";
|
import { API_EDITOR_FORM_NAME, API_HOME_SCREEN_FORM } from "constants/forms";
|
||||||
import { POST_BODY_FORMAT_OPTIONS } from "constants/ApiEditorConstants";
|
import {
|
||||||
|
DEFAULT_API_ACTION,
|
||||||
|
POST_BODY_FORMAT_OPTIONS,
|
||||||
|
REST_PLUGIN_PACKAGE_NAME,
|
||||||
|
} from "constants/ApiEditorConstants";
|
||||||
import history from "utils/history";
|
import history from "utils/history";
|
||||||
import { API_EDITOR_ID_URL, API_EDITOR_URL } from "constants/routes";
|
import { API_EDITOR_ID_URL, API_EDITOR_URL } from "constants/routes";
|
||||||
import {
|
import {
|
||||||
|
|
@ -31,6 +35,11 @@ import {
|
||||||
VALID_FUNCTION_NAME_ERROR,
|
VALID_FUNCTION_NAME_ERROR,
|
||||||
} from "constants/messages";
|
} from "constants/messages";
|
||||||
import { fetchProvidersWithCategory } from "actions/providerActions";
|
import { fetchProvidersWithCategory } from "actions/providerActions";
|
||||||
|
import { createNewApiName } from "utils/AppsmithUtils";
|
||||||
|
import { getPluginIdOfPackageName } from "sagas/selectors";
|
||||||
|
import { getActions } from "selectors/entitiesSelector";
|
||||||
|
import { ActionData } from "reducers/entityReducers/actionsReducer";
|
||||||
|
import { createActionRequest } from "actions/actionActions";
|
||||||
|
|
||||||
const getApiDraft = (state: AppState, id: string) => {
|
const getApiDraft = (state: AppState, id: string) => {
|
||||||
const drafts = state.ui.apiPane.drafts;
|
const drafts = state.ui.apiPane.drafts;
|
||||||
|
|
@ -38,7 +47,7 @@ const getApiDraft = (state: AppState, id: string) => {
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getActions = (state: AppState) =>
|
const getActionConfigs = (state: AppState): ActionData["config"][] =>
|
||||||
state.entities.actions.map(a => a.config);
|
state.entities.actions.map(a => a.config);
|
||||||
|
|
||||||
const getLastUsedAction = (state: AppState) => state.ui.apiPane.lastUsed;
|
const getLastUsedAction = (state: AppState) => state.ui.apiPane.lastUsed;
|
||||||
|
|
@ -234,7 +243,7 @@ function* validateInputSaga(
|
||||||
payload,
|
payload,
|
||||||
meta: { field },
|
meta: { field },
|
||||||
} = actionPayload;
|
} = actionPayload;
|
||||||
const actions: RestAction[] = yield select(getActions);
|
const actions: RestAction[] = yield select(getActionConfigs);
|
||||||
const sameNames = actions.filter(
|
const sameNames = actions.filter(
|
||||||
(action: RestAction) => action.name === payload && action.id,
|
(action: RestAction) => action.name === payload && action.id,
|
||||||
);
|
);
|
||||||
|
|
@ -375,6 +384,34 @@ function* handleMoveOrCopySaga(actionPayload: ReduxAction<{ id: string }>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function* handleCreateNewApiActionSaga(
|
||||||
|
action: ReduxAction<{ pageId: string }>,
|
||||||
|
) {
|
||||||
|
const pluginId = yield select(
|
||||||
|
getPluginIdOfPackageName,
|
||||||
|
REST_PLUGIN_PACKAGE_NAME,
|
||||||
|
);
|
||||||
|
const { pageId } = action.payload;
|
||||||
|
if (pageId && pluginId) {
|
||||||
|
const actions = yield select(getActions);
|
||||||
|
const pageActions = actions.filter(
|
||||||
|
(a: ActionData) => a.config.pageId === pageId,
|
||||||
|
);
|
||||||
|
const newActionName = createNewApiName(pageActions, pageId);
|
||||||
|
yield put(
|
||||||
|
createActionRequest({
|
||||||
|
...DEFAULT_API_ACTION,
|
||||||
|
name: newActionName,
|
||||||
|
datasource: {
|
||||||
|
name: "DEFAULT_REST_DATASOURCE",
|
||||||
|
pluginId,
|
||||||
|
},
|
||||||
|
pageId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function* root() {
|
export default function* root() {
|
||||||
yield all([
|
yield all([
|
||||||
takeEvery(ReduxActionTypes.INIT_API_PANE, initApiPaneSaga),
|
takeEvery(ReduxActionTypes.INIT_API_PANE, initApiPaneSaga),
|
||||||
|
|
@ -384,6 +421,10 @@ export default function* root() {
|
||||||
takeEvery(ReduxActionTypes.DELETE_ACTION_SUCCESS, handleActionDeletedSaga),
|
takeEvery(ReduxActionTypes.DELETE_ACTION_SUCCESS, handleActionDeletedSaga),
|
||||||
takeEvery(ReduxActionTypes.MOVE_ACTION_SUCCESS, handleMoveOrCopySaga),
|
takeEvery(ReduxActionTypes.MOVE_ACTION_SUCCESS, handleMoveOrCopySaga),
|
||||||
takeEvery(ReduxActionTypes.COPY_ACTION_SUCCESS, handleMoveOrCopySaga),
|
takeEvery(ReduxActionTypes.COPY_ACTION_SUCCESS, handleMoveOrCopySaga),
|
||||||
|
takeEvery(
|
||||||
|
ReduxActionTypes.CREATE_NEW_API_ACTION,
|
||||||
|
handleCreateNewApiActionSaga,
|
||||||
|
),
|
||||||
// Intercepting the redux-form change actionType
|
// Intercepting the redux-form change actionType
|
||||||
takeEvery(ReduxFormActionTypes.VALUE_CHANGE, formValueChangeSaga),
|
takeEvery(ReduxFormActionTypes.VALUE_CHANGE, formValueChangeSaga),
|
||||||
takeEvery(ReduxFormActionTypes.ARRAY_REMOVE, formValueChangeSaga),
|
takeEvery(ReduxFormActionTypes.ARRAY_REMOVE, formValueChangeSaga),
|
||||||
|
|
|
||||||
|
|
@ -74,3 +74,13 @@ export const getWidgetByName = (
|
||||||
widget => widget.widgetName === widgetName,
|
widget => widget.widgetName === widgetName,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getPluginIdOfPackageName = (
|
||||||
|
state: AppState,
|
||||||
|
name: string,
|
||||||
|
): string | undefined => {
|
||||||
|
const plugins = state.entities.plugins.list;
|
||||||
|
const plugin = _.find(plugins, { packageName: name });
|
||||||
|
if (plugin) return plugin.id;
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
|
||||||
5
app/client/src/utils/featureFlags.ts
Normal file
5
app/client/src/utils/featureFlags.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
export const API_PANE_V2 = "ApiPaneV2";
|
||||||
|
|
||||||
|
export const checkForFlag = (flagName: string) => {
|
||||||
|
return localStorage.getItem(flagName);
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user