Query pane fixes

- Show mongo execute response in seperate cards for each record
- Update postgres read template
- Show query execute error message in the UI.
This commit is contained in:
Akash N 2020-05-14 18:03:44 +05:30
parent a2086ff61b
commit 6bd79982fb
6 changed files with 100 additions and 14 deletions

View File

@ -10,7 +10,6 @@ import {
ColumnsDirective,
ColumnDirective,
} from "@syncfusion/ej2-react-grids";
import ReactJson from "react-json-view";
import styled, { createGlobalStyle } from "styled-components";
import { Popover } from "@blueprintjs/core";
import history from "utils/history";
@ -29,6 +28,8 @@ import { RestAction } from "api/ActionAPI";
import { QUERY_EDITOR_FORM_NAME } from "constants/forms";
import { PLUGIN_PACKAGE_POSTGRES } from "constants/QueryEditorConstants";
import "@syncfusion/ej2-react-grids/styles/material.css";
import { Colors } from "constants/Colors";
import JSONViewer from "./JSONViewer";
const QueryFormContainer = styled.div`
font-size: 20px;
@ -178,6 +179,11 @@ const StyledGridComponent = styled(GridComponent)`
}
`;
const ErrorMessage = styled.p`
font-size: 14px;
color: ${Colors.RED};
`;
type QueryFormProps = {
isCreating: boolean;
onDeleteClick: () => void;
@ -194,6 +200,7 @@ type QueryFormProps = {
executedQueryData: any;
applicationId: string;
selectedPluginPackage: string;
runErrorMessage: string | undefined;
pageId: string;
location: {
state: any;
@ -223,6 +230,7 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
selectedPluginPackage,
createTemplate,
isCreating,
runErrorMessage,
} = props;
const [showTemplateMenu, setMenuVisibility] = useState(true);
@ -251,6 +259,7 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
</LoadingContainer>
);
}
return (
<QueryFormContainer>
<form onSubmit={handleSubmit}>
@ -411,6 +420,13 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
</NoDataSourceContainer>
)}
{runErrorMessage && (
<>
<p className="statementTextArea">Query error</p>
<ErrorMessage>{runErrorMessage}</ErrorMessage>
</>
)}
{executedQueryData && dataSources.length && (
<ResponseContainer>
<p className="statementTextArea">Query response</p>
@ -435,16 +451,7 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
</ColumnsDirective>
</StyledGridComponent>
) : (
<ReactJson
src={executedQueryData.body}
name={null}
enableClipboard={false}
displayObjectSize={false}
displayDataTypes={false}
style={{
fontSize: "14px",
}}
/>
<JSONViewer src={executedQueryData.body} />
)}
</ResponseContent>
</ResponseContainer>

View File

@ -0,0 +1,61 @@
import React from "react";
import ReactJson from "react-json-view";
import styled from "styled-components";
import { Card } from "@blueprintjs/core";
const OutputContainer = styled.div`
background: #f5f6f7;
border: 1px solid #d0d7dd;
box-sizing: border-box;
border-radius: 4px;
padding: 6px;
`;
const Record = styled(Card)`
margin: 5px;
`;
type JSONOutputProps = {
src: [];
};
type Props = JSONOutputProps;
class JSONOutput extends React.Component<Props> {
render() {
const { src } = this.props;
const reactJsonProps = {
name: null,
enableClipboard: false,
displayObjectSize: false,
displayDataTypes: false,
style: {
fontSize: "14px",
},
};
if (!src.length) {
return (
<OutputContainer>
<Record>
<ReactJson src={src} {...reactJsonProps} />
</Record>
</OutputContainer>
);
}
return (
<OutputContainer>
{src.map((record, index) => {
return (
<Record key={index}>
<ReactJson src={record} {...reactJsonProps} />
</Record>
);
})}
</OutputContainer>
);
}
}
export default JSONOutput;

View File

@ -42,7 +42,7 @@ const Templates: Record<string, any> = {
create: `INSERT INTO users(
id, name, gender, avatar, email, address, role)
VALUES (?, ?, ?, ?, ?, ?, ?);`,
read: "SELECT * FROM users LIMIT 10 ORDER BY id",
read: "SELECT * FROM users ORDER BY id LIMIT 10",
delete: `DELETE FROM users WHERE id=?`,
update: `UPDATE users
Set status='APPROVED'

View File

@ -45,6 +45,7 @@ type QueryPageProps = {
submitForm: (name: string) => void;
createAction: (values: RestAction) => void;
runAction: (action: RestAction, actionId: string) => void;
runErrorMessage: Record<string, string>;
deleteAction: (id: string) => void;
updateAction: (data: RestAction) => void;
createTemplate: (template: string) => void;
@ -91,6 +92,7 @@ class QueryEditor extends React.Component<Props> {
selectedPluginPackage,
apiPane,
isCreating,
runErrorMessage,
} = this.props;
const { applicationId, pageId } = this.props.match.params;
@ -139,6 +141,7 @@ class QueryEditor extends React.Component<Props> {
DATASOURCES_OPTIONS={DATASOURCES_OPTIONS}
selectedPluginPackage={selectedPluginPackage}
executedQueryData={executedQueryData[queryId]}
runErrorMessage={runErrorMessage[queryId]}
/>
) : (
<QueryHomeScreen
@ -156,6 +159,7 @@ class QueryEditor extends React.Component<Props> {
}
const mapStateToProps = (state: AppState): any => {
const { runErrorMessage } = state.ui.queryPane;
const formData = getFormValues(QUERY_EDITOR_FORM_NAME)(state) as RestAction;
const initialValues = getFormInitialValues(QUERY_EDITOR_FORM_NAME)(
state,
@ -167,6 +171,7 @@ const mapStateToProps = (state: AppState): any => {
);
return {
runErrorMessage,
apiPane: state.ui.apiPane,
pluginIds: getPluginIdsOfPackageNames(state, PLUGIN_PACKAGE_DBS),
dataSources: getDataSources(state),

View File

@ -5,6 +5,7 @@ import {
ReduxAction,
} from "constants/ReduxActionConstants";
import { RestAction } from "api/ActionAPI";
import _ from "lodash";
const initialState: QueryPaneReduxState = {
isFetching: false,
@ -13,6 +14,7 @@ const initialState: QueryPaneReduxState = {
isSaving: {},
isDeleting: {},
runQuerySuccessData: {},
runErrorMessage: {},
lastUsed: "",
};
@ -22,6 +24,7 @@ export interface QueryPaneReduxState {
isSaving: Record<string, boolean>;
isDeleting: Record<string, boolean>;
runQuerySuccessData: {};
runErrorMessage: Record<string, string>;
lastUsed: string;
isCreating: boolean;
}
@ -134,6 +137,8 @@ const queryPaneReducer = createReducer(initialState, {
state: any,
action: ReduxAction<{ actionId: string; data: object }>,
) => {
const { actionId } = action.payload;
return {
...state,
isRunning: {
@ -144,17 +149,24 @@ const queryPaneReducer = createReducer(initialState, {
...state.runQuerySuccessData,
[action.payload.actionId]: action.payload.data,
},
runErrorMessage: _.omit(state.runErrorMessage, [actionId]),
};
},
[ReduxActionErrorTypes.RUN_QUERY_ERROR]: (
state: any,
action: ReduxAction<{ actionId: string }>,
action: ReduxAction<{ actionId: string; message: string }>,
) => {
const { actionId, message } = action.payload;
return {
...state,
isRunning: {
...state.isRunning,
[action.payload.actionId]: false,
[actionId]: false,
},
runErrorMessage: {
...state.runError,
[actionId]: message,
},
};
},

View File

@ -246,6 +246,7 @@ export function* executeQuerySaga(
type: ReduxActionErrorTypes.RUN_QUERY_ERROR,
payload: {
actionId: actionPayload.payload.actionId,
message: error.message,
show: false,
},
});