Merge branch 'fix/queryPane' into 'release'
Fix/query pane - Show mongo execute response in seperate cards for each record - Update postgres read template - Show query execute error message in the UI. See merge request theappsmith/internal-tools-client!595
This commit is contained in:
commit
be113dd069
|
|
@ -10,7 +10,6 @@ import {
|
||||||
ColumnsDirective,
|
ColumnsDirective,
|
||||||
ColumnDirective,
|
ColumnDirective,
|
||||||
} from "@syncfusion/ej2-react-grids";
|
} from "@syncfusion/ej2-react-grids";
|
||||||
import ReactJson from "react-json-view";
|
|
||||||
import styled, { createGlobalStyle } from "styled-components";
|
import styled, { createGlobalStyle } from "styled-components";
|
||||||
import { Popover, Icon } from "@blueprintjs/core";
|
import { Popover, Icon } from "@blueprintjs/core";
|
||||||
import { components, MenuListComponentProps } from "react-select";
|
import { components, MenuListComponentProps } from "react-select";
|
||||||
|
|
@ -29,8 +28,9 @@ import { Datasource } from "api/DatasourcesApi";
|
||||||
import { RestAction } from "api/ActionAPI";
|
import { RestAction } from "api/ActionAPI";
|
||||||
import { QUERY_EDITOR_FORM_NAME } from "constants/forms";
|
import { QUERY_EDITOR_FORM_NAME } from "constants/forms";
|
||||||
import { PLUGIN_PACKAGE_POSTGRES } from "constants/QueryEditorConstants";
|
import { PLUGIN_PACKAGE_POSTGRES } from "constants/QueryEditorConstants";
|
||||||
import { Colors } from "constants/Colors";
|
|
||||||
import "@syncfusion/ej2-react-grids/styles/material.css";
|
import "@syncfusion/ej2-react-grids/styles/material.css";
|
||||||
|
import { Colors } from "constants/Colors";
|
||||||
|
import JSONViewer from "./JSONViewer";
|
||||||
|
|
||||||
const QueryFormContainer = styled.div`
|
const QueryFormContainer = styled.div`
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
|
@ -180,6 +180,10 @@ const StyledGridComponent = styled(GridComponent)`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const ErrorMessage = styled.p`
|
||||||
|
font-size: 14px;
|
||||||
|
color: ${Colors.RED};
|
||||||
|
`;
|
||||||
const CreateDatasource = styled.div`
|
const CreateDatasource = styled.div`
|
||||||
height: 44px;
|
height: 44px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -212,6 +216,7 @@ type QueryFormProps = {
|
||||||
executedQueryData: any;
|
executedQueryData: any;
|
||||||
applicationId: string;
|
applicationId: string;
|
||||||
selectedPluginPackage: string;
|
selectedPluginPackage: string;
|
||||||
|
runErrorMessage: string | undefined;
|
||||||
pageId: string;
|
pageId: string;
|
||||||
location: {
|
location: {
|
||||||
state: any;
|
state: any;
|
||||||
|
|
@ -241,6 +246,7 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
|
||||||
selectedPluginPackage,
|
selectedPluginPackage,
|
||||||
createTemplate,
|
createTemplate,
|
||||||
isCreating,
|
isCreating,
|
||||||
|
runErrorMessage,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [showTemplateMenu, setMenuVisibility] = useState(true);
|
const [showTemplateMenu, setMenuVisibility] = useState(true);
|
||||||
|
|
@ -446,6 +452,13 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
|
||||||
</NoDataSourceContainer>
|
</NoDataSourceContainer>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{runErrorMessage && (
|
||||||
|
<>
|
||||||
|
<p className="statementTextArea">Query error</p>
|
||||||
|
<ErrorMessage>{runErrorMessage}</ErrorMessage>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{executedQueryData && dataSources.length && (
|
{executedQueryData && dataSources.length && (
|
||||||
<ResponseContainer>
|
<ResponseContainer>
|
||||||
<p className="statementTextArea">Query response</p>
|
<p className="statementTextArea">Query response</p>
|
||||||
|
|
@ -470,16 +483,7 @@ const QueryEditorForm: React.FC<Props> = (props: Props) => {
|
||||||
</ColumnsDirective>
|
</ColumnsDirective>
|
||||||
</StyledGridComponent>
|
</StyledGridComponent>
|
||||||
) : (
|
) : (
|
||||||
<ReactJson
|
<JSONViewer src={executedQueryData.body} />
|
||||||
src={executedQueryData.body}
|
|
||||||
name={null}
|
|
||||||
enableClipboard={false}
|
|
||||||
displayObjectSize={false}
|
|
||||||
displayDataTypes={false}
|
|
||||||
style={{
|
|
||||||
fontSize: "14px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</ResponseContent>
|
</ResponseContent>
|
||||||
</ResponseContainer>
|
</ResponseContainer>
|
||||||
|
|
|
||||||
61
app/client/src/pages/Editor/QueryEditor/JSONViewer.tsx
Normal file
61
app/client/src/pages/Editor/QueryEditor/JSONViewer.tsx
Normal 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;
|
||||||
|
|
@ -42,7 +42,7 @@ const Templates: Record<string, any> = {
|
||||||
create: `INSERT INTO users(
|
create: `INSERT INTO users(
|
||||||
id, name, gender, avatar, email, address, role)
|
id, name, gender, avatar, email, address, role)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?);`,
|
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=?`,
|
delete: `DELETE FROM users WHERE id=?`,
|
||||||
update: `UPDATE users
|
update: `UPDATE users
|
||||||
Set status='APPROVED'
|
Set status='APPROVED'
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ type QueryPageProps = {
|
||||||
submitForm: (name: string) => void;
|
submitForm: (name: string) => void;
|
||||||
createAction: (values: RestAction) => void;
|
createAction: (values: RestAction) => void;
|
||||||
runAction: (action: RestAction, actionId: string) => void;
|
runAction: (action: RestAction, actionId: string) => void;
|
||||||
|
runErrorMessage: Record<string, string>;
|
||||||
deleteAction: (id: string) => void;
|
deleteAction: (id: string) => void;
|
||||||
updateAction: (data: RestAction) => void;
|
updateAction: (data: RestAction) => void;
|
||||||
createTemplate: (template: string) => void;
|
createTemplate: (template: string) => void;
|
||||||
|
|
@ -91,6 +92,7 @@ class QueryEditor extends React.Component<Props> {
|
||||||
selectedPluginPackage,
|
selectedPluginPackage,
|
||||||
apiPane,
|
apiPane,
|
||||||
isCreating,
|
isCreating,
|
||||||
|
runErrorMessage,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { applicationId, pageId } = this.props.match.params;
|
const { applicationId, pageId } = this.props.match.params;
|
||||||
|
|
||||||
|
|
@ -135,6 +137,7 @@ class QueryEditor extends React.Component<Props> {
|
||||||
DATASOURCES_OPTIONS={DATASOURCES_OPTIONS}
|
DATASOURCES_OPTIONS={DATASOURCES_OPTIONS}
|
||||||
selectedPluginPackage={selectedPluginPackage}
|
selectedPluginPackage={selectedPluginPackage}
|
||||||
executedQueryData={executedQueryData[queryId]}
|
executedQueryData={executedQueryData[queryId]}
|
||||||
|
runErrorMessage={runErrorMessage[queryId]}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<QueryHomeScreen
|
<QueryHomeScreen
|
||||||
|
|
@ -152,6 +155,7 @@ class QueryEditor extends React.Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: AppState): any => {
|
const mapStateToProps = (state: AppState): any => {
|
||||||
|
const { runErrorMessage } = state.ui.queryPane;
|
||||||
const formData = getFormValues(QUERY_EDITOR_FORM_NAME)(state) as RestAction;
|
const formData = getFormValues(QUERY_EDITOR_FORM_NAME)(state) as RestAction;
|
||||||
const initialValues = getFormInitialValues(QUERY_EDITOR_FORM_NAME)(
|
const initialValues = getFormInitialValues(QUERY_EDITOR_FORM_NAME)(
|
||||||
state,
|
state,
|
||||||
|
|
@ -163,6 +167,7 @@ const mapStateToProps = (state: AppState): any => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
runErrorMessage,
|
||||||
apiPane: state.ui.apiPane,
|
apiPane: state.ui.apiPane,
|
||||||
pluginIds: getPluginIdsOfPackageNames(state, PLUGIN_PACKAGE_DBS),
|
pluginIds: getPluginIdsOfPackageNames(state, PLUGIN_PACKAGE_DBS),
|
||||||
dataSources: getDataSources(state),
|
dataSources: getDataSources(state),
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
ReduxAction,
|
ReduxAction,
|
||||||
} from "constants/ReduxActionConstants";
|
} from "constants/ReduxActionConstants";
|
||||||
import { RestAction } from "api/ActionAPI";
|
import { RestAction } from "api/ActionAPI";
|
||||||
|
import _ from "lodash";
|
||||||
|
|
||||||
const initialState: QueryPaneReduxState = {
|
const initialState: QueryPaneReduxState = {
|
||||||
isFetching: false,
|
isFetching: false,
|
||||||
|
|
@ -13,6 +14,7 @@ const initialState: QueryPaneReduxState = {
|
||||||
isSaving: {},
|
isSaving: {},
|
||||||
isDeleting: {},
|
isDeleting: {},
|
||||||
runQuerySuccessData: {},
|
runQuerySuccessData: {},
|
||||||
|
runErrorMessage: {},
|
||||||
lastUsed: "",
|
lastUsed: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -22,6 +24,7 @@ export interface QueryPaneReduxState {
|
||||||
isSaving: Record<string, boolean>;
|
isSaving: Record<string, boolean>;
|
||||||
isDeleting: Record<string, boolean>;
|
isDeleting: Record<string, boolean>;
|
||||||
runQuerySuccessData: {};
|
runQuerySuccessData: {};
|
||||||
|
runErrorMessage: Record<string, string>;
|
||||||
lastUsed: string;
|
lastUsed: string;
|
||||||
isCreating: boolean;
|
isCreating: boolean;
|
||||||
}
|
}
|
||||||
|
|
@ -134,6 +137,8 @@ const queryPaneReducer = createReducer(initialState, {
|
||||||
state: any,
|
state: any,
|
||||||
action: ReduxAction<{ actionId: string; data: object }>,
|
action: ReduxAction<{ actionId: string; data: object }>,
|
||||||
) => {
|
) => {
|
||||||
|
const { actionId } = action.payload;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
isRunning: {
|
isRunning: {
|
||||||
|
|
@ -144,17 +149,24 @@ const queryPaneReducer = createReducer(initialState, {
|
||||||
...state.runQuerySuccessData,
|
...state.runQuerySuccessData,
|
||||||
[action.payload.actionId]: action.payload.data,
|
[action.payload.actionId]: action.payload.data,
|
||||||
},
|
},
|
||||||
|
runErrorMessage: _.omit(state.runErrorMessage, [actionId]),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[ReduxActionErrorTypes.RUN_QUERY_ERROR]: (
|
[ReduxActionErrorTypes.RUN_QUERY_ERROR]: (
|
||||||
state: any,
|
state: any,
|
||||||
action: ReduxAction<{ actionId: string }>,
|
action: ReduxAction<{ actionId: string; message: string }>,
|
||||||
) => {
|
) => {
|
||||||
|
const { actionId, message } = action.payload;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
isRunning: {
|
isRunning: {
|
||||||
...state.isRunning,
|
...state.isRunning,
|
||||||
[action.payload.actionId]: false,
|
[actionId]: false,
|
||||||
|
},
|
||||||
|
runErrorMessage: {
|
||||||
|
...state.runError,
|
||||||
|
[actionId]: message,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,7 @@ export function* executeQuerySaga(
|
||||||
type: ReduxActionErrorTypes.RUN_QUERY_ERROR,
|
type: ReduxActionErrorTypes.RUN_QUERY_ERROR,
|
||||||
payload: {
|
payload: {
|
||||||
actionId: actionPayload.payload.actionId,
|
actionId: actionPayload.payload.actionId,
|
||||||
|
message: error.message,
|
||||||
show: false,
|
show: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user