Add pagination and improve the ui
This commit is contained in:
parent
f3ee7e34ef
commit
f119b962fa
@ -1,5 +1,7 @@
|
|||||||
package com.github.awrb.solr.services.data;
|
package com.github.awrb.solr.services.data;
|
||||||
|
|
||||||
|
import org.apache.solr.common.StringUtils;
|
||||||
|
import org.apache.solr.common.params.CursorMarkParams;
|
||||||
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;
|
||||||
|
|
||||||
@ -15,7 +17,9 @@ public class SolrQueryParams {
|
|||||||
private String reviewerName = MATCH_ALL;
|
private String reviewerName = MATCH_ALL;
|
||||||
private String summary = MATCH_ALL;
|
private String summary = MATCH_ALL;
|
||||||
private String asin = MATCH_ALL;
|
private String asin = MATCH_ALL;
|
||||||
|
private int start;
|
||||||
private Sort sort = Sort.DESC;
|
private Sort sort = Sort.DESC;
|
||||||
|
private String nextCursorMark;
|
||||||
|
|
||||||
private int rows = DEFAULT_ROW_COUNT;
|
private int rows = DEFAULT_ROW_COUNT;
|
||||||
|
|
||||||
@ -27,6 +31,10 @@ public class SolrQueryParams {
|
|||||||
this.reviewText = reviewText;
|
this.reviewText = reviewText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNextCursorMark(String nextCursorMark) {
|
||||||
|
this.nextCursorMark = nextCursorMark;
|
||||||
|
}
|
||||||
|
|
||||||
public void setRows(int rows) {
|
public void setRows(int rows) {
|
||||||
this.rows = rows;
|
this.rows = rows;
|
||||||
}
|
}
|
||||||
@ -47,11 +55,25 @@ public class SolrQueryParams {
|
|||||||
this.sort = sort;
|
this.sort = sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setStart(int start) {
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
public SolrParams toSolrParams() {
|
public SolrParams toSolrParams() {
|
||||||
ModifiableSolrParams params = new ModifiableSolrParams();
|
ModifiableSolrParams params = new ModifiableSolrParams();
|
||||||
params.set("q", buildQ());
|
params.set("q", buildQ());
|
||||||
params.set("rows", rows);
|
params.set("rows", rows);
|
||||||
|
|
||||||
|
if (start > 0) {
|
||||||
|
params.set("start", start);
|
||||||
|
}
|
||||||
|
|
||||||
|
// params.set(CursorMarkParams.CURSOR_MARK_PARAM, "*");
|
||||||
|
// if (!StringUtils.isEmpty(nextCursorMark)) {
|
||||||
|
// ModifiableSolrParams set = params.set(CursorMarkParams.CURSOR_MARK_NEXT, nextCursorMark);
|
||||||
|
// }
|
||||||
// params.set("sort", "overall " + sort.label);
|
// params.set("sort", "overall " + sort.label);
|
||||||
|
|
||||||
System.out.println(params.toQueryString());
|
System.out.println(params.toQueryString());
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
@ -67,6 +89,7 @@ public class SolrQueryParams {
|
|||||||
.append(" asin:")
|
.append(" asin:")
|
||||||
.append(asin)
|
.append(asin)
|
||||||
.append(")");
|
.append(")");
|
||||||
|
|
||||||
// The query string ends up looking like this: (reviewText:* reviewerName:* summary:*)
|
// The query string ends up looking like this: (reviewText:* reviewerName:* summary:*)
|
||||||
// OR between parameters
|
// OR between parameters
|
||||||
System.out.println(sb.toString());
|
System.out.println(sb.toString());
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import SearchBar from "./SearchBar";
|
import SearchBar from "./SearchBar";
|
||||||
import SearchResult from "./SearchResult";
|
import SearchResult from "./SearchResult";
|
||||||
|
import PageArrows from "./PageArrows";
|
||||||
import SortSelect from "./SortSelect";
|
import SortSelect from "./SortSelect";
|
||||||
import solr from "../api/solr";
|
import solr from "../api/solr";
|
||||||
import { List, CircularProgress, Grid } from "@material-ui/core";
|
import { List, CircularProgress, Grid } from "@material-ui/core";
|
||||||
@ -12,6 +13,9 @@ import PaginationSelect from "./PaginationSelect";
|
|||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
loader: { margin: 20 },
|
loader: { margin: 20 },
|
||||||
select: { marginLeft: "3vw" },
|
select: { marginLeft: "3vw" },
|
||||||
|
center: {
|
||||||
|
marginLeft: "50%",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
@ -21,6 +25,7 @@ const App = () => {
|
|||||||
const [term, setTerm] = useState("");
|
const [term, setTerm] = useState("");
|
||||||
const [sort, setSort] = useState(Constants.DESC);
|
const [sort, setSort] = useState(Constants.DESC);
|
||||||
const [rows, setRows] = useState(10);
|
const [rows, setRows] = useState(10);
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
@ -34,14 +39,20 @@ const App = () => {
|
|||||||
[Constants.SORT]: sort,
|
[Constants.SORT]: sort,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (page > 1) {
|
||||||
|
params[Constants.START] = (page - 1) * rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchTerm = "*" + term + "*";
|
||||||
|
|
||||||
if (filter === Constants.REVIEW_TEXT) {
|
if (filter === Constants.REVIEW_TEXT) {
|
||||||
params[Constants.REVIEW_TEXT] = term;
|
params[Constants.REVIEW_TEXT] = searchTerm;
|
||||||
} else if (filter === Constants.REVIEWER_NAME) {
|
} else if (filter === Constants.REVIEWER_NAME) {
|
||||||
params[Constants.REVIEWER_NAME] = term;
|
params[Constants.REVIEWER_NAME] = searchTerm;
|
||||||
} else if (filter === Constants.SUMMARY) {
|
} else if (filter === Constants.SUMMARY) {
|
||||||
params[Constants.SUMMARY] = term;
|
params[Constants.SUMMARY] = searchTerm;
|
||||||
} else {
|
} else {
|
||||||
params[Constants.ASIN] = term;
|
params[Constants.ASIN] = searchTerm;
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
@ -60,12 +71,13 @@ const App = () => {
|
|||||||
{results.map((result) => (
|
{results.map((result) => (
|
||||||
<SearchResult
|
<SearchResult
|
||||||
key={result.id}
|
key={result.id}
|
||||||
summary={result.summary[0]}
|
summary={result.summary}
|
||||||
reviewText={result.reviewText[0]}
|
reviewText={result.reviewText}
|
||||||
author={result.reviewerName[0]}
|
author={result.reviewerName}
|
||||||
time={result.reviewTime[0]}
|
time={result.reviewTime}
|
||||||
asin={result.asin}
|
asin={result.asin}
|
||||||
rating={result.overall[0]}
|
rating={result.overall}
|
||||||
|
query={term}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
@ -101,6 +113,25 @@ const App = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
{loading && <CircularProgress className={classes.loader} />}
|
{loading && <CircularProgress className={classes.loader} />}
|
||||||
{!loading && results.length > 0 && renderResults()}
|
{!loading && results.length > 0 && renderResults()}
|
||||||
|
<div className={classes.center}>
|
||||||
|
{results.length > 0 && (
|
||||||
|
<PageArrows
|
||||||
|
currentPage={page}
|
||||||
|
onClickBack={() => {
|
||||||
|
if (page === 1) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
setPage(page - 1);
|
||||||
|
}
|
||||||
|
onSubmit();
|
||||||
|
}}
|
||||||
|
onClickNext={() => {
|
||||||
|
setPage(page + 1);
|
||||||
|
onSubmit();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
21
ui/solr/src/components/PageArrows.js
Normal file
21
ui/solr/src/components/PageArrows.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Grid, Typography } from "@material-ui/core";
|
||||||
|
import { NavigateBefore, NavigateNext } from "@material-ui/icons";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const PageArrows = ({ onClickBack, onClickNext, currentPage }) => {
|
||||||
|
return (
|
||||||
|
<Grid container>
|
||||||
|
<Grid item>
|
||||||
|
<NavigateBefore onClick={onClickBack} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item style={{ marginTop: 5 }}>
|
||||||
|
{currentPage}
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<NavigateNext onClick={onClickNext} />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PageArrows;
|
17
ui/solr/src/components/RatingStars.js
Normal file
17
ui/solr/src/components/RatingStars.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Grid } from "@material-ui/core";
|
||||||
|
import { Star } from "@material-ui/icons";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const RatingStars = ({ className, rating }) => {
|
||||||
|
return (
|
||||||
|
<Grid className={className} item>
|
||||||
|
{Array(rating)
|
||||||
|
.fill()
|
||||||
|
.map((i) => (
|
||||||
|
<Star style={{ color: "#FFDF00" }} />
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RatingStars;
|
@ -3,7 +3,6 @@ import { makeStyles } from "@material-ui/core/styles";
|
|||||||
import Paper from "@material-ui/core/Paper";
|
import Paper from "@material-ui/core/Paper";
|
||||||
import InputBase from "@material-ui/core/InputBase";
|
import InputBase from "@material-ui/core/InputBase";
|
||||||
import IconButton from "@material-ui/core/IconButton";
|
import IconButton from "@material-ui/core/IconButton";
|
||||||
import MenuIcon from "@material-ui/icons/Menu";
|
|
||||||
import SearchIcon from "@material-ui/icons/Search";
|
import SearchIcon from "@material-ui/icons/Search";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
@ -34,10 +33,6 @@ const SearchBar = ({ onSubmit, onChange, value }) => {
|
|||||||
component="form"
|
component="form"
|
||||||
className={classes.root}
|
className={classes.root}
|
||||||
>
|
>
|
||||||
<IconButton className={classes.iconButton} aria-label="menu">
|
|
||||||
<MenuIcon />
|
|
||||||
</IconButton>
|
|
||||||
|
|
||||||
<InputBase
|
<InputBase
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => onChange(e.target.value)}
|
onChange={(e) => onChange(e.target.value)}
|
||||||
|
@ -1,5 +1,29 @@
|
|||||||
import { Divider, ListItem, Paper, Typography } from "@material-ui/core";
|
import {
|
||||||
|
Divider,
|
||||||
|
Grid,
|
||||||
|
ListItem,
|
||||||
|
makeStyles,
|
||||||
|
Paper,
|
||||||
|
Typography,
|
||||||
|
} from "@material-ui/core";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import RatingStars from "./RatingStars";
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
bottomCell: {
|
||||||
|
marginTop: 15,
|
||||||
|
marginBottom: 15,
|
||||||
|
},
|
||||||
|
date: {
|
||||||
|
color: "#808080",
|
||||||
|
margin: 0,
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const SearchResult = ({
|
const SearchResult = ({
|
||||||
key,
|
key,
|
||||||
@ -9,22 +33,40 @@ const SearchResult = ({
|
|||||||
time,
|
time,
|
||||||
asin,
|
asin,
|
||||||
rating,
|
rating,
|
||||||
|
query,
|
||||||
}) => {
|
}) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
const getHighlightedText = () => {
|
||||||
|
const parts = reviewText.split(new RegExp(`(${query})`, "gi"));
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{parts.map((part) =>
|
||||||
|
part.toLowerCase() === query.toLowerCase() ? <b>{part}</b> : part
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItem key={key}>
|
<ListItem key={key}>
|
||||||
<Paper>
|
<Paper elevation="4">
|
||||||
|
<Grid container spacing={6}>
|
||||||
|
<Grid className={classes.grid} item>
|
||||||
<Typography variant="h5">{summary}</Typography>
|
<Typography variant="h5">{summary}</Typography>
|
||||||
<Typography variant="body">{reviewText}</Typography>
|
</Grid>
|
||||||
<div style={{ marginTop: 30 }}>
|
<RatingStars className={classes.grid} rating={rating} />
|
||||||
<Divider />
|
<Grid className={classes.grid} item>
|
||||||
|
<Typography className={classes.date} variant="body">
|
||||||
|
{time}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Typography variant="body">{getHighlightedText()}</Typography>
|
||||||
|
<Divider className={classes.bottomCell} />
|
||||||
<Typography variant="body">{author}</Typography>
|
<Typography variant="body">{author}</Typography>
|
||||||
<Divider />
|
<Divider className={classes.bottomCell} />
|
||||||
<Typography variant="body">{time}</Typography>
|
|
||||||
<Divider />
|
|
||||||
<Typography variant="body">{`Rating ${rating}`}</Typography>
|
|
||||||
<Divider />
|
|
||||||
<Typography variant="body">{`ASIN ${asin}`}</Typography>
|
<Typography variant="body">{`ASIN ${asin}`}</Typography>
|
||||||
</div>
|
|
||||||
</Paper>
|
</Paper>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
);
|
);
|
||||||
|
@ -6,6 +6,7 @@ export const ROWS = "rows";
|
|||||||
export const ASC = "ASC";
|
export const ASC = "ASC";
|
||||||
export const DESC = "DESC";
|
export const DESC = "DESC";
|
||||||
export const SORT = "sort";
|
export const SORT = "sort";
|
||||||
|
export const START = "start";
|
||||||
|
|
||||||
export const CONSTANTS = {
|
export const CONSTANTS = {
|
||||||
REVIEWER_NAME,
|
REVIEWER_NAME,
|
||||||
@ -16,6 +17,7 @@ export const CONSTANTS = {
|
|||||||
DESC,
|
DESC,
|
||||||
ASC,
|
ASC,
|
||||||
SORT,
|
SORT,
|
||||||
|
START,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CONSTANTS;
|
export default CONSTANTS;
|
||||||
|
Loading…
Reference in New Issue
Block a user