PromucFlow_constructor/app/client/src/pages/Editor/ApiSidebar.tsx
2020-04-22 09:15:24 +00:00

243 lines
6.8 KiB
TypeScript

import React from "react";
import { connect } from "react-redux";
import { RouteComponentProps } from "react-router";
import styled from "styled-components";
import { AppState } from "reducers";
import { ActionDataState } from "reducers/entityReducers/actionsReducer";
import { APIEditorRouteParams } from "constants/routes";
import { ApiPaneReduxState } from "reducers/uiReducers/apiPaneReducer";
import {
createActionRequest,
moveActionRequest,
copyActionRequest,
deleteAction,
} from "actions/actionActions";
import {
changeApi,
createNewApiAction,
initApiPane,
} from "actions/apiPaneActions";
import { RestAction } from "api/ActionAPI";
import { getPluginIdOfName } from "selectors/entitiesSelector";
import { PLUGIN_NAME } from "constants/ApiEditorConstants";
import EditorSidebar from "pages/Editor/EditorSidebar";
import { getNextEntityName } from "utils/AppsmithUtils";
import AnalyticsUtil from "utils/AnalyticsUtil";
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 }>`
flex: 1;
font-size: 12px;
color: ${props => {
switch (props.method) {
case "GET":
return "#29CCA3";
case "POST":
return "#F7C75B";
case "PUT":
return "#30A5E0";
case "PATCH":
return "#8E8E8E";
case "DELETE":
return "#CE4257";
default:
return "#333";
}
}};
`;
const ActionItem = styled.div`
flex: 1;
display: flex;
align-items: center;
`;
const ActionName = styled.span`
flex: 3;
padding: 0 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100px;
`;
interface ReduxStateProps {
actions: ActionDataState;
apiPane: ApiPaneReduxState;
pluginId: string | undefined;
}
interface ReduxDispatchProps {
createAction: (data: Partial<RestAction>) => void;
onApiChange: (id: string) => void;
initApiPane: (urlId?: string) => void;
moveAction: (
id: string,
pageId: string,
name: string,
originalPageId: string,
) => void;
copyAction: (id: string, pageId: string, name: string) => void;
deleteAction: (id: string, name: string) => void;
createNewApiAction: (pageId: string) => void;
}
type Props = ReduxStateProps &
ReduxDispatchProps &
RouteComponentProps<APIEditorRouteParams>;
class ApiSidebar extends React.Component<Props> {
componentDidMount(): void {
this.props.initApiPane(this.props.match.params.apiId);
}
shouldComponentUpdate(nextProps: Readonly<Props>): boolean {
if (
Object.keys(nextProps.apiPane.drafts) !==
Object.keys(this.props.apiPane.drafts)
) {
return true;
}
return nextProps.actions !== this.props.actions;
}
handleApiChange = (actionId: string) => {
this.props.onApiChange(actionId);
};
handleMove = (itemId: string, destinationPageId: string) => {
const action = this.props.actions.filter(a => a.config.id === itemId)[0];
const pageApiNames = this.props.actions
.filter(a => a.config.pageId === destinationPageId)
.map(a => a.config.name);
let name = action.config.name;
if (pageApiNames.indexOf(action.config.name) > -1) {
name = getNextEntityName(name, pageApiNames);
}
this.props.moveAction(
itemId,
destinationPageId,
name,
action.config.pageId,
);
};
handleCopy = (itemId: string, destinationPageId: string) => {
const action = this.props.actions.filter(a => a.config.id === itemId)[0];
const pageApiNames = this.props.actions
.filter(a => a.config.pageId === destinationPageId)
.map(a => a.config.name);
let name = `${action.config.name}Copy`;
if (pageApiNames.indexOf(name) > -1) {
name = getNextEntityName(name, pageApiNames);
}
this.props.copyAction(itemId, destinationPageId, name);
};
handleDelete = (itemId: string, itemName: string, pageName: string) => {
AnalyticsUtil.logEvent("DELETE_API_CLICK", {
apiId: itemId,
apiName: itemName,
pageName: pageName,
});
this.props.deleteAction(itemId, itemName);
};
renderItem = (action: RestAction) => {
return (
<ActionItem
onClick={() => {
AnalyticsUtil.logEvent("API_SELECT", {
apiId: action.id,
apiName: action.name,
});
}}
>
{action.actionConfiguration ? (
<HTTPMethod method={action.actionConfiguration.httpMethod}>
{action.actionConfiguration.httpMethod}
</HTTPMethod>
) : (
<HTTPMethod />
)}
<ActionName>{action.name}</ActionName>
</ActionItem>
);
};
handleCreateNewApiClick = (selectedPageId: string) => {
const { history, createNewApiAction } = this.props;
const { pageId, applicationId } = this.props.match.params;
const v2Flag = checkForFlag(API_PANE_V2);
if (v2Flag) {
history.push(
API_EDITOR_URL_WITH_SELECTED_PAGE_ID(
applicationId,
pageId,
selectedPageId,
),
);
} else {
createNewApiAction(selectedPageId);
}
};
render() {
const {
apiPane: { isFetching, drafts },
match: {
params: { apiId },
},
actions,
pluginId,
} = this.props;
if (!pluginId) return null;
const data = actions.map(a => a.config);
return (
<EditorSidebar
isLoading={isFetching}
list={data}
selectedItemId={apiId}
draftIds={Object.keys(drafts)}
itemRender={this.renderItem}
onItemCreateClick={this.handleCreateNewApiClick}
onItemSelected={this.handleApiChange}
moveItem={this.handleMove}
copyItem={this.handleCopy}
deleteItem={this.handleDelete}
createButtonTitle="Create new API"
/>
);
}
}
const mapStateToProps = (state: AppState): ReduxStateProps => ({
pluginId: getPluginIdOfName(state, PLUGIN_NAME),
actions: state.entities.actions,
apiPane: state.ui.apiPane,
});
const mapDispatchToProps = (dispatch: Function): ReduxDispatchProps => ({
createAction: (data: Partial<RestAction>) =>
dispatch(createActionRequest(data)),
onApiChange: (actionId: string) => dispatch(changeApi(actionId)),
initApiPane: (urlId?: string) => dispatch(initApiPane(urlId)),
moveAction: (
id: string,
destinationPageId: string,
name: string,
originalPageId: string,
) =>
dispatch(
moveActionRequest({ id, destinationPageId, originalPageId, name }),
),
copyAction: (id: string, destinationPageId: string, name: string) =>
dispatch(copyActionRequest({ id, destinationPageId, name })),
deleteAction: (id: string, name: string) =>
dispatch(deleteAction({ id, name })),
createNewApiAction: (pageId: string) => dispatch(createNewApiAction(pageId)),
});
export default connect(mapStateToProps, mapDispatchToProps)(ApiSidebar);