Add pagination and improve the ui

This commit is contained in:
Aleksy Wroblewski 2021-03-24 19:23:53 +01:00
parent f3ee7e34ef
commit f119b962fa
7 changed files with 159 additions and 28 deletions

View File

@ -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());

View File

@ -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>
); );
}; };

View 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;

View 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;

View File

@ -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)}

View File

@ -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>
); );

View File

@ -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;