Skip to content

Commit 151b25b

Browse files
committed
Template query logic and user experience improved
1 parent 5371dda commit 151b25b

File tree

2 files changed

+68
-52
lines changed

2 files changed

+68
-52
lines changed

src/components/ListResultTable/ListResultTable.jsx

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import {ListBase, Loading, useListController,} from "react-admin";
22
import PropTypes from "prop-types";
3-
import {Component, useEffect} from "react";
3+
import {Component} from "react";
44
import QueryResultList from "./QueryResultList/QueryResultList";
55

6-
import {useLocation, useNavigate} from 'react-router-dom'
7-
86
/**
97
* @param {object} props - the props passed down to the component
108
* @returns {Component} custom List as defined by react-admin which either shows a loading indicator or the query results
@@ -23,23 +21,6 @@ function ListResultTable(props) {
2321
...rest
2422
} = props;
2523

26-
const location = useLocation();
27-
const navigate = useNavigate();
28-
29-
useEffect(() => {
30-
if (variables) {
31-
const queryParams = new URLSearchParams(location.search);
32-
33-
for (const [variableName, variableValue] of Object.entries(variables)) {
34-
queryParams.set(variableName, variableValue)
35-
}
36-
37-
navigate(
38-
`?${queryParams.toString()}`
39-
);
40-
}
41-
}, [location.search, navigate]);
42-
4324
const {isLoading} = useListController({
4425
queryOptions: {
4526
meta: {
Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,94 @@
11
import {useState} from 'react';
22
import ListResultTable from "./ListResultTable.jsx";
33
import {SelectInput, SimpleForm, useResourceContext, required} from "react-admin";
4-
import {useLocation} from 'react-router-dom';
4+
import {useLocation, useNavigate} from 'react-router-dom';
5+
import {Component} from "react";
56

67
import config from "../../config";
78

89
/**
910
* A custom form to set/choose values for variables for a templated query before that query is executed
10-
* @param props
11+
* @param {object} props - the props passed down to the component
1112
* @returns {Component} the templated query form component
1213
*/
1314
const TemplatedQueryForm = (props) => {
1415
const resource = useResourceContext();
16+
const location = useLocation();
17+
const navigate = useNavigate();
18+
const [variables, setVariables] = useState({});
1519

1620
const query = config.queries.filter(
1721
(query) => query.id === resource
1822
)[0];
23+
const isTemplatedQuery = query.variables !== undefined;
24+
let tableEnabled = !isTemplatedQuery;
1925

20-
if (!query.variables) {
21-
return <ListResultTable {...props}/>;
22-
}
23-
24-
const location = useLocation();
25-
const queryParams = new URLSearchParams(location.search);
26-
27-
const urlVariables = {}
28-
for (const variableName of Object.keys(query.variables)) {
29-
if (queryParams.has(variableName)) {
30-
urlVariables[variableName] = queryParams.get(variableName)
26+
if (isTemplatedQuery) {
27+
// Update variables from query parameters
28+
const queryParams = new URLSearchParams(location.search);
29+
const queryVariables = {};
30+
for (const variableName of Object.keys(query.variables)) {
31+
if (queryParams.has(variableName)) {
32+
queryVariables[variableName] = queryParams.get(variableName);
33+
}
34+
}
35+
if (!equalSimpleObjects(variables, queryVariables)) {
36+
setVariables(queryVariables);
37+
} else {
38+
tableEnabled = (Object.keys(variables).length === Object.keys(query.variables).length);
3139
}
32-
}
33-
const [variables, setVariables] = useState(urlVariables);
34-
35-
const [redirectToList, setRedirectToList] = useState(Object.keys(urlVariables).length === Object.keys(query.variables).length)
36-
if (redirectToList) {
37-
return <ListResultTable {...props} variables={variables}/>;
3840
}
3941

40-
const onSubmit = (data) => {
41-
setVariables(data)
42-
setRedirectToList(true);
42+
const onSubmit = (formVariables) => {
43+
// Update query parameters from the form fields
44+
const queryParams = new URLSearchParams(location.search);
45+
for (const [variableName, variableValue] of Object.entries(formVariables)) {
46+
if (variableValue) {
47+
queryParams.set(variableName, variableValue);
48+
}
49+
}
50+
const queryString= queryParams.toString();
51+
if (queryString.length > 0) {
52+
navigate(`?${queryString}`);
53+
}
4354
}
4455

4556
return (
46-
<SimpleForm onSubmit={onSubmit}>
47-
{Object.entries(query.variables).map(([name, options]) => (
48-
<SelectInput key={name} source={name} name={name} label={name} validate={required()} choices={
49-
options.map((option) => ({
50-
id: option,
51-
name: option
52-
}))
53-
}/>
54-
))}
55-
</SimpleForm>
57+
<>
58+
{isTemplatedQuery && !tableEnabled && (
59+
<SimpleForm onSubmit={onSubmit}>
60+
{Object.entries(query.variables).map(([name, options]) => (
61+
<SelectInput key={name} source={name} name={name} label={name} validate={required()} choices={
62+
options.map((option) => ({
63+
id: option,
64+
name: option
65+
}))
66+
}/>
67+
))}
68+
</SimpleForm>
69+
)}
70+
{tableEnabled && (
71+
<ListResultTable {...props} variables={variables}/>
72+
)}
73+
</>
5674
)
5775
}
5876

77+
/**
78+
* Check if two objects have the same property values (of type a primitive value or a string)
79+
* @param {object} obj1 - the first object
80+
* @param {object} obj2 - the second object
81+
* @returns {boolean} true means equal
82+
*/
83+
function equalSimpleObjects(obj1, obj2) {
84+
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
85+
return false;
86+
}
87+
for (const key1 in obj1) {
88+
if (obj1[key1] !== obj2[key1]) {
89+
return false;
90+
}
91+
}
92+
return true;
93+
}
5994
export default TemplatedQueryForm;

0 commit comments

Comments
 (0)