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:
Hetu Nandu 2020-04-20 08:26:19 +00:00
commit dcf320e4e6
8 changed files with 120 additions and 38 deletions

View File

@ -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 },
});

View File

@ -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];

View File

@ -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(

View File

@ -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>
); );

View File

@ -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);

View File

@ -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),

View File

@ -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;
};

View File

@ -0,0 +1,5 @@
export const API_PANE_V2 = "ApiPaneV2";
export const checkForFlag = (flagName: string) => {
return localStorage.getItem(flagName);
};