Add extra sorting and filtering options
This commit is contained in:
parent
74ed59921c
commit
f3ee7e34ef
2
server/.gitignore
vendored
2
server/.gitignore
vendored
@ -31,3 +31,5 @@ build/
|
|||||||
|
|
||||||
### VS Code ###
|
### VS Code ###
|
||||||
.vscode/
|
.vscode/
|
||||||
|
.mvn*
|
||||||
|
mvnw*
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<groupId>com.github</groupId>
|
<groupId>com.github</groupId>
|
||||||
<artifactId>awrb</artifactId>
|
<artifactId>awrb</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<name>awrb</name>
|
<name>solr</name>
|
||||||
<description>ISI 2021 Lab 4</description>
|
<description>ISI 2021 Lab 4</description>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
|
@ -2,12 +2,11 @@ package com.github.awrb;
|
|||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration;
|
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class AwrbApplication {
|
public class SolrApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(AwrbApplication.class, args);
|
SpringApplication.run(SolrApplication.class, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,7 +15,7 @@ public class SolrFacade {
|
|||||||
|
|
||||||
private SolrClient solrClient;
|
private SolrClient solrClient;
|
||||||
|
|
||||||
public SolrFacade(@Value("${solr.address") String solrAddress) {
|
public SolrFacade(@Value("${solr.address}") String solrAddress) {
|
||||||
this.solrClient = new HttpSolrClient.Builder(solrAddress).build();
|
this.solrClient = new HttpSolrClient.Builder(solrAddress).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package com.github.awrb.solr.services;
|
package com.github.awrb.solr.services;
|
||||||
|
|
||||||
import com.github.awrb.solr.SolrFacade;
|
import com.github.awrb.solr.SolrFacade;
|
||||||
|
import com.github.awrb.solr.services.data.SolrQueryParams;
|
||||||
import org.apache.solr.client.solrj.SolrServerException;
|
import org.apache.solr.client.solrj.SolrServerException;
|
||||||
import org.apache.solr.common.SolrDocumentList;
|
import org.apache.solr.common.SolrDocumentList;
|
||||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||||
import org.apache.solr.common.params.SolrParams;
|
import org.apache.solr.common.params.SolrParams;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
@ -13,6 +15,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
@CrossOrigin(origins = "http://localhost:3000")
|
||||||
public class SolrService {
|
public class SolrService {
|
||||||
|
|
||||||
private SolrFacade solrFacade;
|
private SolrFacade solrFacade;
|
||||||
@ -23,14 +26,7 @@ public class SolrService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/search")
|
@GetMapping("/search")
|
||||||
public SolrDocumentList search(@RequestParam("q") String query) throws IOException, SolrServerException {
|
public SolrDocumentList search(SolrQueryParams params) throws IOException, SolrServerException {
|
||||||
SolrParams solrParams = solrParamsFromQuery(query);
|
return solrFacade.query(params.toSolrParams()).getResults();
|
||||||
return solrFacade.query(solrParams).getResults();
|
|
||||||
}
|
|
||||||
|
|
||||||
private SolrParams solrParamsFromQuery(String query) {
|
|
||||||
ModifiableSolrParams params = new ModifiableSolrParams();
|
|
||||||
params.set("q", query);
|
|
||||||
return params;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
package com.github.awrb.solr.services.data;
|
||||||
|
|
||||||
|
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||||
|
import org.apache.solr.common.params.SolrParams;
|
||||||
|
|
||||||
|
public class SolrQueryParams {
|
||||||
|
|
||||||
|
private static final String MATCH_ALL = "*";
|
||||||
|
|
||||||
|
private static final int DEFAULT_ROW_COUNT = 10;
|
||||||
|
|
||||||
|
private String query;
|
||||||
|
|
||||||
|
private String reviewText = MATCH_ALL;
|
||||||
|
private String reviewerName = MATCH_ALL;
|
||||||
|
private String summary = MATCH_ALL;
|
||||||
|
private String asin = MATCH_ALL;
|
||||||
|
private Sort sort = Sort.DESC;
|
||||||
|
|
||||||
|
private int rows = DEFAULT_ROW_COUNT;
|
||||||
|
|
||||||
|
public void setQuery(String query) {
|
||||||
|
this.query = query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReviewText(String reviewText) {
|
||||||
|
this.reviewText = reviewText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRows(int rows) {
|
||||||
|
this.rows = rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReviewerName(String reviewerName) {
|
||||||
|
this.reviewerName = reviewerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSummary(String summary) {
|
||||||
|
this.summary = summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAsin(String asin) {
|
||||||
|
this.asin = asin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSort(Sort sort) {
|
||||||
|
this.sort = sort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SolrParams toSolrParams() {
|
||||||
|
ModifiableSolrParams params = new ModifiableSolrParams();
|
||||||
|
params.set("q", buildQ());
|
||||||
|
params.set("rows", rows);
|
||||||
|
// params.set("sort", "overall " + sort.label);
|
||||||
|
System.out.println(params.toQueryString());
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildQ() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("(reviewText:")
|
||||||
|
.append(reviewText)
|
||||||
|
.append(" reviewerName:")
|
||||||
|
.append(reviewerName)
|
||||||
|
.append(" summary:")
|
||||||
|
.append(summary)
|
||||||
|
.append(" asin:")
|
||||||
|
.append(asin)
|
||||||
|
.append(")");
|
||||||
|
// The query string ends up looking like this: (reviewText:* reviewerName:* summary:*)
|
||||||
|
// OR between parameters
|
||||||
|
System.out.println(sb.toString());
|
||||||
|
return sb.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Sort {
|
||||||
|
ASC("asc"), DESC("desc");
|
||||||
|
|
||||||
|
private String label;
|
||||||
|
|
||||||
|
Sort(String label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +1,2 @@
|
|||||||
server.servlet.context-path=/api
|
server.servlet.context-path=/api
|
||||||
solr.address=http://localhost:8983/solr/techproducts
|
solr.address=http://localhost:8983/solr/reviews
|
||||||
|
@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
class AwrbApplicationTests {
|
class SolrApplicationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void contextLoads() {
|
void contextLoads() {
|
2
ui/solr/.gitignore
vendored
2
ui/solr/.gitignore
vendored
@ -21,3 +21,5 @@
|
|||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
yarn.lock
|
||||||
|
package-lock.json
|
||||||
|
@ -3,13 +3,16 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/jest-dom": "^5.11.4",
|
"@material-ui/core": "4.11.3",
|
||||||
"@testing-library/react": "^11.1.0",
|
"@material-ui/icons": "4.11.2",
|
||||||
"@testing-library/user-event": "^12.1.10",
|
"@testing-library/jest-dom": "5.11.4",
|
||||||
"react": "^17.0.1",
|
"@testing-library/react": "11.1.0",
|
||||||
"react-dom": "^17.0.1",
|
"@testing-library/user-event": "12.1.10",
|
||||||
|
"axios": "0.21.1",
|
||||||
|
"react": "17.0.1",
|
||||||
|
"react-dom": "17.0.1",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
"web-vitals": "^1.0.1"
|
"web-vitals": "1.0.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
11
ui/solr/src/api/solr.js
Normal file
11
ui/solr/src/api/solr.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const solr = axios.create({
|
||||||
|
baseURL: "http://localhost:8080/api/",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default solr;
|
108
ui/solr/src/components/App.js
Normal file
108
ui/solr/src/components/App.js
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import SearchBar from "./SearchBar";
|
||||||
|
import SearchResult from "./SearchResult";
|
||||||
|
import SortSelect from "./SortSelect";
|
||||||
|
import solr from "../api/solr";
|
||||||
|
import { List, CircularProgress, Grid } from "@material-ui/core";
|
||||||
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
|
import FilterSelect from "./FilterSelect";
|
||||||
|
import Constants from "../constants";
|
||||||
|
import PaginationSelect from "./PaginationSelect";
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
loader: { margin: 20 },
|
||||||
|
select: { marginLeft: "3vw" },
|
||||||
|
});
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
const [results, setResults] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [filter, setFilter] = useState(Constants.REVIEW_TEXT);
|
||||||
|
const [term, setTerm] = useState("");
|
||||||
|
const [sort, setSort] = useState(Constants.DESC);
|
||||||
|
const [rows, setRows] = useState(10);
|
||||||
|
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
const getParams = () => {
|
||||||
|
const params = {
|
||||||
|
[Constants.REVIEWER_NAME]: "*",
|
||||||
|
[Constants.REVIEW_TEXT]: "*",
|
||||||
|
[Constants.SUMMARY]: "*",
|
||||||
|
[Constants.ASIN]: "*",
|
||||||
|
[Constants.ROWS]: rows,
|
||||||
|
[Constants.SORT]: sort,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (filter === Constants.REVIEW_TEXT) {
|
||||||
|
params[Constants.REVIEW_TEXT] = term;
|
||||||
|
} else if (filter === Constants.REVIEWER_NAME) {
|
||||||
|
params[Constants.REVIEWER_NAME] = term;
|
||||||
|
} else if (filter === Constants.SUMMARY) {
|
||||||
|
params[Constants.SUMMARY] = term;
|
||||||
|
} else {
|
||||||
|
params[Constants.ASIN] = term;
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await solr.get("/search", { params: getParams() });
|
||||||
|
setResults(response.data);
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderResults = () => {
|
||||||
|
return (
|
||||||
|
<List>
|
||||||
|
{results.map((result) => (
|
||||||
|
<SearchResult
|
||||||
|
key={result.id}
|
||||||
|
summary={result.summary[0]}
|
||||||
|
reviewText={result.reviewText[0]}
|
||||||
|
author={result.reviewerName[0]}
|
||||||
|
time={result.reviewTime[0]}
|
||||||
|
asin={result.asin}
|
||||||
|
rating={result.overall[0]}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Grid container>
|
||||||
|
<Grid item>
|
||||||
|
<SearchBar
|
||||||
|
value={term}
|
||||||
|
onChange={(newTerm) => setTerm(newTerm)}
|
||||||
|
onSubmit={onSubmit}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid className={classes.select} item>
|
||||||
|
<FilterSelect
|
||||||
|
value={filter}
|
||||||
|
onChange={(filter) => setFilter(filter)}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid className={classes.select} item>
|
||||||
|
<SortSelect
|
||||||
|
onChange={(sort) => setSort(sort)}
|
||||||
|
value={sort}
|
||||||
|
className={classes.select}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid className={classes.select} item>
|
||||||
|
<PaginationSelect value={rows} onChange={(rows) => setRows(rows)} />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
{loading && <CircularProgress className={classes.loader} />}
|
||||||
|
{!loading && results.length > 0 && renderResults()}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default App;
|
28
ui/solr/src/components/FilterSelect.js
Normal file
28
ui/solr/src/components/FilterSelect.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { InputLabel, MenuItem, Select } from "@material-ui/core";
|
||||||
|
import React from "react";
|
||||||
|
import Constants from "../constants";
|
||||||
|
|
||||||
|
const FilterSelect = ({ onChange, value }) => {
|
||||||
|
const handleChange = (event) => {
|
||||||
|
onChange(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<InputLabel id="filter-select">Filter By</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="filter-select"
|
||||||
|
id="filter-select"
|
||||||
|
value={value}
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
<MenuItem value={Constants.REVIEW_TEXT}>Text</MenuItem>
|
||||||
|
<MenuItem value={Constants.REVIEWER_NAME}>Reviewer Name</MenuItem>
|
||||||
|
<MenuItem value={Constants.SUMMARY}>Summary</MenuItem>
|
||||||
|
<MenuItem value={Constants.ASIN}>ASIN</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FilterSelect;
|
27
ui/solr/src/components/PaginationSelect.js
Normal file
27
ui/solr/src/components/PaginationSelect.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { InputLabel, MenuItem, Select } from "@material-ui/core";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const PaginationSelect = ({ onChange, value }) => {
|
||||||
|
const handleChange = (event) => {
|
||||||
|
onChange(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<InputLabel id="pagination-select">Rows per page</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="pagination-select"
|
||||||
|
id="pagination-select"
|
||||||
|
value={value}
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
<MenuItem value={10}>10</MenuItem>
|
||||||
|
<MenuItem value={30}>30</MenuItem>
|
||||||
|
<MenuItem value={50}>50</MenuItem>
|
||||||
|
<MenuItem value={100}>100</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PaginationSelect;
|
59
ui/solr/src/components/SearchBar.js
Normal file
59
ui/solr/src/components/SearchBar.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
|
import Paper from "@material-ui/core/Paper";
|
||||||
|
import InputBase from "@material-ui/core/InputBase";
|
||||||
|
import IconButton from "@material-ui/core/IconButton";
|
||||||
|
import MenuIcon from "@material-ui/icons/Menu";
|
||||||
|
import SearchIcon from "@material-ui/icons/Search";
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme) => ({
|
||||||
|
root: {
|
||||||
|
padding: "2px 4px",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
width: 400,
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
marginLeft: theme.spacing(1),
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
iconButton: {
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const SearchBar = ({ onSubmit, onChange, value }) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
onSubmit();
|
||||||
|
}}
|
||||||
|
component="form"
|
||||||
|
className={classes.root}
|
||||||
|
>
|
||||||
|
<IconButton className={classes.iconButton} aria-label="menu">
|
||||||
|
<MenuIcon />
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
<InputBase
|
||||||
|
value={value}
|
||||||
|
onChange={(e) => onChange(e.target.value)}
|
||||||
|
className={classes.input}
|
||||||
|
placeholder="Search"
|
||||||
|
inputProps={{ "aria-label": "search" }}
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
type="submit"
|
||||||
|
className={classes.iconButton}
|
||||||
|
aria-label="search"
|
||||||
|
>
|
||||||
|
<SearchIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SearchBar;
|
33
ui/solr/src/components/SearchResult.js
Normal file
33
ui/solr/src/components/SearchResult.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { Divider, ListItem, Paper, Typography } from "@material-ui/core";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const SearchResult = ({
|
||||||
|
key,
|
||||||
|
summary,
|
||||||
|
reviewText,
|
||||||
|
author,
|
||||||
|
time,
|
||||||
|
asin,
|
||||||
|
rating,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<ListItem key={key}>
|
||||||
|
<Paper>
|
||||||
|
<Typography variant="h5">{summary}</Typography>
|
||||||
|
<Typography variant="body">{reviewText}</Typography>
|
||||||
|
<div style={{ marginTop: 30 }}>
|
||||||
|
<Divider />
|
||||||
|
<Typography variant="body">{author}</Typography>
|
||||||
|
<Divider />
|
||||||
|
<Typography variant="body">{time}</Typography>
|
||||||
|
<Divider />
|
||||||
|
<Typography variant="body">{`Rating ${rating}`}</Typography>
|
||||||
|
<Divider />
|
||||||
|
<Typography variant="body">{`ASIN ${asin}`}</Typography>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SearchResult;
|
26
ui/solr/src/components/SortSelect.js
Normal file
26
ui/solr/src/components/SortSelect.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { InputLabel, MenuItem, Select } from "@material-ui/core";
|
||||||
|
import React from "react";
|
||||||
|
import Constants from "../constants";
|
||||||
|
|
||||||
|
const SortSelect = ({ onChange, value }) => {
|
||||||
|
const handleChange = (event) => {
|
||||||
|
onChange(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<InputLabel id="sort-select">Sort by rating</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="sort-select"
|
||||||
|
id="sort-select"
|
||||||
|
value={value}
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
<MenuItem value={Constants.ASC}>Ascending</MenuItem>
|
||||||
|
<MenuItem value={Constants.DESC}>Descending</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SortSelect;
|
21
ui/solr/src/constants.js
Normal file
21
ui/solr/src/constants.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export const REVIEWER_NAME = "reviewerName";
|
||||||
|
export const REVIEW_TEXT = "reviewText";
|
||||||
|
export const SUMMARY = "summary";
|
||||||
|
export const ASIN = "asin";
|
||||||
|
export const ROWS = "rows";
|
||||||
|
export const ASC = "ASC";
|
||||||
|
export const DESC = "DESC";
|
||||||
|
export const SORT = "sort";
|
||||||
|
|
||||||
|
export const CONSTANTS = {
|
||||||
|
REVIEWER_NAME,
|
||||||
|
REVIEW_TEXT,
|
||||||
|
SUMMARY,
|
||||||
|
ASIN,
|
||||||
|
ROWS,
|
||||||
|
DESC,
|
||||||
|
ASC,
|
||||||
|
SORT,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CONSTANTS;
|
@ -1,14 +1,13 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from "react-dom";
|
||||||
import './index.css';
|
import App from "./components/App";
|
||||||
import App from './App';
|
import reportWebVitals from "./reportWebVitals";
|
||||||
import reportWebVitals from './reportWebVitals';
|
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App />
|
<App />
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById('root')
|
document.getElementById("root")
|
||||||
);
|
);
|
||||||
|
|
||||||
// If you want to start measuring performance in your app, pass a function
|
// If you want to start measuring performance in your app, pass a function
|
||||||
|
Loading…
Reference in New Issue
Block a user