From 69b42e7206bae33d8319a9bf92c317fdfd7885ee Mon Sep 17 00:00:00 2001
From: Byron Duvall
Date: Fri, 8 Jan 2021 14:57:57 -0500
Subject: [PATCH 01/34] fix eslint errors in curent-query component
---
src/components/current-query/index.js | 234 ++++++++++++++------------
1 file changed, 131 insertions(+), 103 deletions(-)
diff --git a/src/components/current-query/index.js b/src/components/current-query/index.js
index c720e7a..e281bc3 100644
--- a/src/components/current-query/index.js
+++ b/src/components/current-query/index.js
@@ -5,21 +5,27 @@ import moment from 'moment';
import { LiveMessenger } from 'react-aria-live';
import helpers from '../../helpers';
-
// Create dumb component which can be configured by props.
-const FacetType = props => (
-
{/* Only render the values for visible facets / filters */}
- {fields.filter((searchField) => !searchField.isHidden).map((searchField, i) => {
+ {fields.filter((searchField) => !searchField.isHidden).map((searchField) => {
// Determine which child component to render.
const MyFacetType = facetTypes[searchField.type];
return (
Date: Wed, 13 Jan 2021 11:09:02 -0500
Subject: [PATCH 04/34] fix eslint errors in federated-solr-faceted-search
component
---
.../federated-solr-faceted-search.js | 126 ++++++++++++------
1 file changed, 83 insertions(+), 43 deletions(-)
diff --git a/src/components/federated-solr-faceted-search.js b/src/components/federated-solr-faceted-search.js
index 19810c5..f889b34 100644
--- a/src/components/federated-solr-faceted-search.js
+++ b/src/components/federated-solr-faceted-search.js
@@ -3,14 +3,17 @@ import PropTypes from 'prop-types';
import { LiveAnnouncer } from 'react-aria-live';
import FederatedSolrComponentPack from './federated_solr_component_pack';
import helpers from '../helpers';
-//import componentPack from "./component-pack";
-const getFacetValues = (type, results, field, lowerBound, upperBound) => {
- return type === 'period-range-facet'
- ? (results.facets[lowerBound] || []).concat(results.facets[upperBound] || [])
- : type === 'list-facet' || type === 'range-facet'
- ? results.facets[field] || []
- : null;
+const getFacetValues = function (type, results, field, lowerBound, upperBound) {
+ let values = null;
+
+ if (type === 'period-range-facet') {
+ values = (results.facets[lowerBound] || []).concat(results.facets[upperBound] || []);
+ } else if (type === 'list-facet' || type === 'range-facet') {
+ values = results.facets[field] || [];
+ }
+
+ return values;
};
class FederatedSolrFacetedSearch extends React.Component {
@@ -21,24 +24,28 @@ class FederatedSolrFacetedSearch extends React.Component {
}
resetFilters() {
- let { query } = this.props;
+ const { query, onSearchFieldChange } = this.props;
let searchTerm = '';
// Keep only the value of the main search field.
- for (const field of query.searchFields) {
+ query.searchField.map((field) => {
+ const newField = field;
+
if (field.field !== query.mainQueryField) {
// Remove the field value.
- delete (field.value);
+ delete (newField.value);
// Collapse the sidebar filter toggle.
- field.collapse = true;
+ newField.collapse = true;
// Collapse the terms sidebar filter toggle.
if (Object.hasOwnProperty.call(field, 'expandedHierarchies')) {
- field.expandedHierarchies = [];
+ newField.expandedHierarchies = [];
}
} else {
// Extract the value of the main search term to use when setting new URL for this state.
searchTerm = field.value;
}
- }
+
+ return newField;
+ });
// Set new parsed params based on only search term value.
const parsed = {
search: searchTerm,
@@ -46,10 +53,8 @@ class FederatedSolrFacetedSearch extends React.Component {
// Add new url to browser window history.
helpers.qs.addNewUrlToBrowserHistory(parsed);
- // Update state to remove the filter field values.
- this.setState({ query });
// Execute search.
- this.props.onSearchFieldChange();
+ onSearchFieldChange();
}
render() {
@@ -64,6 +69,8 @@ class FederatedSolrFacetedSearch extends React.Component {
onTextInputChange,
onSortFieldChange,
onPageChange,
+ sidebarFilters,
+ onSelectDoc,
} = this.props;
const { searchFields, sortFields, rows } = query;
const start = query.start ? query.start : 0;
@@ -84,9 +91,11 @@ class FederatedSolrFacetedSearch extends React.Component {
? ()
: null;
- const pagination = query.pageStrategy === 'paginate' ?
- :
- null;
+ /* eslint-disable react/jsx-props-no-spreading */
+
+ const pagination = query.pageStrategy === 'paginate'
+ ?
+ : null;
const preloadListItem = query.pageStrategy === 'cursor'
&& results.docs.length < results.numFound
@@ -94,8 +103,8 @@ class FederatedSolrFacetedSearch extends React.Component {
: null;
let pageTitle;
- if (this.props.options.pageTitle != null) {
- pageTitle = {this.props.options.pageTitle}
;
+ if (options.pageTitle != null) {
+ pageTitle = {options.pageTitle}
;
}
return (
@@ -105,14 +114,14 @@ class FederatedSolrFacetedSearch extends React.Component {
{/* Only render the visible facets / filters.
Note: their values may still be used in the query, if they were pre-set. */}
{searchFields
- .filter(searchField => this.props.sidebarFilters.indexOf(searchField.field) > -1
+ .filter((searchField) => sidebarFilters.indexOf(searchField.field) > -1
&& !searchField.isHidden)
- .map((searchField, i) => {
+ .map((searchField) => {
const {
type,
field,
@@ -124,7 +133,7 @@ class FederatedSolrFacetedSearch extends React.Component {
return (
);
- })
- }
+ })}
@@ -147,7 +155,7 @@ class FederatedSolrFacetedSearch extends React.Component {
label="Enter search term:"
onSuggest={onTextInputChange}
onChange={onSearchFieldChange}
- value={searchFields.find(sf => sf.field === 'tm_rendered_item').value}
+ value={searchFields.find((sf) => sf.field === 'tm_rendered_item').value}
/>
- sf.field === 'tm_rendered_item').value || this.props.options.showEmptySearchResults) ? 'solr-search-results-container__prompt fs-element-invisible' : 'solr-search-results-container__prompt'}>{this.props.options.searchPrompt || 'Please enter a search term.'}
- sf.field === 'tm_rendered_item').value || this.props.options.showEmptySearchResults) ? 'solr-search-results-container__wrapper' : 'solr-search-results-container__wrapper fs-element-invisible'}>
+
sf.field === 'tm_rendered_item').value || options.showEmptySearchResults) ? 'solr-search-results-container__prompt fs-element-invisible' : 'solr-search-results-container__prompt'}>{options.searchPrompt || 'Please enter a search term.'}
+
sf.field === 'tm_rendered_item').value || options.showEmptySearchResults) ? 'solr-search-results-container__wrapper' : 'solr-search-results-container__wrapper fs-element-invisible'}>
sf.field === 'tm_rendered_item').value}
+ noResultsText={options.noResults || null}
+ termValue={searchFields.find((sf) => sf.field === 'tm_rendered_item').value}
/>
{resultPending}
@@ -181,12 +189,12 @@ class FederatedSolrFacetedSearch extends React.Component {
doc={doc}
fields={searchFields}
key={doc.id || i}
- onSelect={this.props.onSelectDoc}
+ onSelect={onSelectDoc}
resultIndex={i}
rows={rows}
start={start}
highlight={results.highlighting[doc.id]}
- hostname={this.props.options.hostname}
+ hostname={options.hostname}
/>
))}
{preloadListItem}
@@ -198,6 +206,8 @@ class FederatedSolrFacetedSearch extends React.Component {
);
+
+ /* eslint-enable react/jsx-props-no-spreading */
}
}
@@ -220,19 +230,49 @@ FederatedSolrFacetedSearch.defaultProps = {
FederatedSolrFacetedSearch.propTypes = {
bootstrapCss: PropTypes.bool,
- customComponents: PropTypes.object,
- onCsvExport: PropTypes.func,
- onNewSearch: PropTypes.func,
- onPageChange: PropTypes.func,
+ customComponents: PropTypes.shape(FederatedSolrComponentPack),
+ pageStrategy: PropTypes.string,
+ rows: PropTypes.number,
+ searchFields: PropTypes.arrayOf(PropTypes.shape({
+ type: PropTypes.string,
+ field: PropTypes.string,
+ })),
+ sortFields: PropTypes.arrayOf(PropTypes.shape({
+ label: PropTypes.string,
+ field: PropTypes.string,
+ })),
+ onCsvExport: PropTypes.func.isRequired,
+ onNewSearch: PropTypes.func.isRequired,
+ onPageChange: PropTypes.func.isRequired,
onSearchFieldChange: PropTypes.func.isRequired,
- onTextInputChange: PropTypes.func,
- onSelectDoc: PropTypes.func,
+ onTextInputChange: PropTypes.func.isRequired,
+ onSelectDoc: PropTypes.func.isRequired,
onSortFieldChange: PropTypes.func.isRequired,
- query: PropTypes.object,
- results: PropTypes.object,
+ query: PropTypes.shape({
+ searchField: PropTypes.arrayOf(PropTypes.object),
+ searchFields: PropTypes.arrayOf(PropTypes.object),
+ mainQueryField: PropTypes.string,
+ sortFields: PropTypes.arrayOf(PropTypes.shape({
+ label: PropTypes.string,
+ field: PropTypes.string,
+ })),
+ rows: PropTypes.number,
+ start: PropTypes.number,
+ pageStrategy: PropTypes.string,
+ }).isRequired,
+ results: PropTypes.shape(FederatedSolrComponentPack.results).isRequired,
showCsvExport: PropTypes.bool,
truncateFacetListsAt: PropTypes.number,
- options: PropTypes.object,
+ options: PropTypes.shape({
+ pageTitle: PropTypes.string,
+ autocomplete: PropTypes.bool,
+ showEmptySearchResults: PropTypes.bool,
+ searchPrompt: PropTypes.string,
+ noResults: PropTypes.string,
+ hostname: PropTypes.string,
+ }),
+ sidebarFilters: PropTypes.arrayOf(PropTypes.string),
+
};
export default FederatedSolrFacetedSearch;
From 932f6f53c2bc6809f2cf05b5052569e06ddf6e9b Mon Sep 17 00:00:00 2001
From: Byron Duvall
Date: Thu, 14 Jan 2021 09:46:27 -0500
Subject: [PATCH 05/34] fix eslint errors in FederatedSolrComponentPack
---
.../federated_solr_component_pack.js | 36 +++++++++----------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/src/components/federated_solr_component_pack.js b/src/components/federated_solr_component_pack.js
index c558215..56f7a37 100644
--- a/src/components/federated_solr_component_pack.js
+++ b/src/components/federated_solr_component_pack.js
@@ -1,36 +1,36 @@
// Create a custom component pack from the default component pack
-import {defaultComponentPack} from "../solr-faceted-search-react/src/index";
-import FederatedResult from "./results/result";
-import FederatedTextSearch from "./text-search/index";
-import FederatedListFacet from "./list-facet/index";
-import FederatedRangeFacet from "./range-facet/index";
-import FederatedSearchFieldContainer from "./search-field-container";
-import FederatedResultList from "./results/list";
-import FederatedPagination from "./results/pagination";
-import FederatedCountLabel from "./results/count-label";
-import FederatedCurrentQuery from "./current-query";
-import FederatedSortMenu from "./sort-menu";
+import { defaultComponentPack } from '../solr-faceted-search-react/src/index';
+import FederatedResult from './results/result';
+import FederatedTextSearch from './text-search/index';
+import FederatedListFacet from './list-facet/index';
+import FederatedRangeFacet from './range-facet/index';
+import FederatedSearchFieldContainer from './search-field-container';
+import FederatedResultList from './results/list';
+import FederatedPagination from './results/pagination';
+import FederatedCountLabel from './results/count-label';
+import FederatedCurrentQuery from './current-query';
+import FederatedSortMenu from './sort-menu';
const FederatedSolrComponentPack = {
...defaultComponentPack,
searchFields: {
...defaultComponentPack.searchFields,
text: FederatedTextSearch,
- "list-facet": FederatedListFacet,
- "range-facet": FederatedRangeFacet,
+ 'list-facet': FederatedListFacet,
+ 'range-facet': FederatedRangeFacet,
container: FederatedSearchFieldContainer,
- currentQuery: FederatedCurrentQuery
+ currentQuery: FederatedCurrentQuery,
},
results: {
...defaultComponentPack.results,
result: FederatedResult,
list: FederatedResultList,
paginate: FederatedPagination,
- resultCount: FederatedCountLabel
+ resultCount: FederatedCountLabel,
},
sortFields: {
- menu: FederatedSortMenu
- }
-}
+ menu: FederatedSortMenu,
+ },
+};
export default FederatedSolrComponentPack;
From 2299f74f27cd4894476ab318bfabd77c62a4bab7 Mon Sep 17 00:00:00 2001
From: Byron Duvall
Date: Thu, 14 Jan 2021 09:52:20 -0500
Subject: [PATCH 06/34] fix eslint errors in chevron icon
---
src/components/icons/chevrons.js | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/src/components/icons/chevrons.js b/src/components/icons/chevrons.js
index 8749b4d..ca9088d 100644
--- a/src/components/icons/chevrons.js
+++ b/src/components/icons/chevrons.js
@@ -3,22 +3,33 @@
* @todo consider using an svg loader package (i.e. https://www.npmjs.com/package/react-svg-loader) to import and return the svg elements directly vs duplicating markup
*/
-import React from "react";
+import React from 'react';
const DoubleChevronLeft = () => (
-
+
);
const ChevronLeft = () => (
-
+
);
const ChevronRight = () => (
-
+
);
-const DoubleChevronRight = () => (
-
+const DoubleChevronRight = () => (
+
);
-export {DoubleChevronLeft, ChevronLeft, ChevronRight, DoubleChevronRight};
+export {
+ DoubleChevronLeft,
+ ChevronLeft,
+ ChevronRight,
+ DoubleChevronRight,
+};
From 16d5a75b411de8057e829b372496af891c3ea4b7 Mon Sep 17 00:00:00 2001
From: Byron Duvall
Date: Thu, 14 Jan 2021 09:56:15 -0500
Subject: [PATCH 07/34] fix eslint errors in search icon
---
src/components/icons/search.js | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/components/icons/search.js b/src/components/icons/search.js
index 8031f4f..66ee822 100644
--- a/src/components/icons/search.js
+++ b/src/components/icons/search.js
@@ -1,11 +1,9 @@
-import React from "react";
+import React from 'react';
-class Search extends React.Component {
- render() {
- return (
-
- );
- }
-}
+const Search = () => (
+
+);
-export default Search;
\ No newline at end of file
+export default Search;
From 3908a8a0818dd0e5aee4428c0989f255578f6caf Mon Sep 17 00:00:00 2001
From: Byron Duvall
Date: Fri, 15 Jan 2021 10:24:04 -0500
Subject: [PATCH 08/34] fix eslint errors in FederatedListFacet component
---
package.json | 1 +
src/components/list-facet/index.js | 152 +++++++++++++++++------------
2 files changed, 93 insertions(+), 60 deletions(-)
diff --git a/package.json b/package.json
index 25f231d..2cdf3bc 100644
--- a/package.json
+++ b/package.json
@@ -56,6 +56,7 @@
"postinstall": "patch-package"
},
"dependencies": {
+ "classnames": "^2.2.5",
"he": "1.2.0",
"intl": "^1.2.5",
"patch-package": "^6.2.0",
diff --git a/src/components/list-facet/index.js b/src/components/list-facet/index.js
index 28155c0..7482822 100644
--- a/src/components/list-facet/index.js
+++ b/src/components/list-facet/index.js
@@ -5,7 +5,6 @@ import AnimateHeight from 'react-animate-height';
import helpers from '../../helpers';
class FederatedListFacet extends React.Component {
-
constructor(props) {
super(props);
@@ -15,16 +14,18 @@ class FederatedListFacet extends React.Component {
};
}
- handleClick(value) {
+ handleClick(clickValue) {
+ const { field, value, onChange } = this.props;
+
const {
foundIdx,
parsed,
isQsParamField,
param,
} = helpers.qs.getFieldQsInfo({
- field: this.props.field,
- values: this.props.value,
- value,
+ field,
+ values: value,
+ value: clickValue,
});
// Define var for new parsed qs params object.
@@ -38,35 +39,35 @@ class FederatedListFacet extends React.Component {
if (param) {
// Add value to parsed qs params.
newParsed = helpers.qs.addValueToQsParam({
- field: this.props.field,
- value,
+ field,
+ value: clickValue,
param,
parsed,
});
} else { // If there is not already a qs param for this field value.
// Add new qs param for field + value.
newParsed = helpers.qs.addQsParam({
- field: this.props.field,
- value,
+ field,
+ value: clickValue,
parsed,
});
}
// Send new query based on app state.
- this.props.onChange(this.props.field, this.props.value.concat(value));
+ onChange(field, value.concat(clickValue));
} else { // If the click is removing this field value.
// If their is already a qs param for this field value.
if (param) {
newParsed = helpers.qs.removeValueFromQsParam({
- field: this.props.field,
- value,
+ field,
+ value: clickValue,
param,
parsed,
});
}
// Send new query based on app state.
- this.props.onChange(this.props.field, this.props.value.filter((v, i) => i !== foundIdx));
+ onChange(field, value.filter((v, i) => i !== foundIdx));
}
helpers.qs.addNewUrlToBrowserHistory(newParsed);
@@ -74,18 +75,25 @@ class FederatedListFacet extends React.Component {
}
toggleExpand(hierarchyFacetValue) {
- this.props.onSetCollapse(this.props.field, !(this.props.collapse || false));
+ const {
+ onSetCollapse,
+ field,
+ collapse,
+ expandedHierarchies,
+ } = this.props;
+
+ onSetCollapse(field, !collapse);
// If this is a hierarchical list facet.
if (hierarchyFacetValue) {
// Determine the current state of the expanded hierarchical list facets.
- const indexOfExpandedHierarchyFacetValue = this.props.expandedHierarchies
+ const indexOfExpandedHierarchyFacetValue = expandedHierarchies
.indexOf(hierarchyFacetValue);
if (indexOfExpandedHierarchyFacetValue > -1) {
// This accordion is currently expanded, so collapse it.
- this.props.expandedHierarchies.splice(indexOfExpandedHierarchyFacetValue,1);
+ expandedHierarchies.splice(indexOfExpandedHierarchyFacetValue, 1);
} else {
// This accordion is currently collapsed, so expand it.
- this.props.expandedHierarchies.push(hierarchyFacetValue);
+ expandedHierarchies.push(hierarchyFacetValue);
}
}
}
@@ -100,9 +108,9 @@ class FederatedListFacet extends React.Component {
hierarchy,
options,
} = this.props;
- const { truncateFacetListsAt } = this.state;
+ const { truncateFacetListsAt, filter } = this.state;
- const siteList = options.siteList;
+ const { siteList } = options;
const facetCounts = facets.filter((facet, i) => i % 2 === 1);
const facetValues = facets.filter((facet, i) => i % 2 === 0);
// Create an object of facets {value: count} to keep consistent for inputs.
@@ -120,15 +128,14 @@ class FederatedListFacet extends React.Component {
if (value.length < 1 && Object.keys(facetInputs).length < 2) {
return null;
}
- }
- else {
+ } else {
facetValues.forEach((v, i) => {
const key = facetValues[i];
facetInputs[key] = facetCounts[i];
});
}
- const expanded = !(collapse || false);
+ const expanded = !collapse;
const height = expanded ? 'auto' : 0;
// If we need to generate multiple list-fact accordion groups
@@ -151,6 +158,8 @@ class FederatedListFacet extends React.Component {
// }
const terms = {};
facetValues.forEach((facetValue, i) => {
+ const { expandedHierarchies } = this.props;
+
// Create array of [Type, Term] from Type>Term.
const pieces = facetValue.split('>');
types.push(pieces[0]);
@@ -158,7 +167,7 @@ class FederatedListFacet extends React.Component {
if (!Object.hasOwnProperty.call(terms, pieces[0])) {
terms[pieces[0]] = {};
terms[pieces[0]].items = [];
- terms[pieces[0]].expanded = (this.props.expandedHierarchies.indexOf(pieces[0]) > -1);
+ terms[pieces[0]].expanded = (expandedHierarchies.indexOf(pieces[0]) > -1);
terms[pieces[0]].height = terms[pieces[0]].expanded ? 'auto' : 0;
}
// Add the object for this facet value to the array of terms for this type.
@@ -178,31 +187,41 @@ class FederatedListFacet extends React.Component {
const listFacetHierarchyLis = [];
// Define array of checkbox Lis which we'll populate with react fragments, per type.
const listFacetHierarchyTermsLis = [];
+
+ /* eslint-disable react/no-array-index-key */
+
// Iterate through types (accordion lis).
uniqueTypes.forEach((type, i) => {
// Populate the checkbox lis react fragments for each type.
listFacetHierarchyTermsLis[type] = [];
- terms[type].items.forEach((termObj, i) => termObj.facetCount
- && listFacetHierarchyTermsLis[type].push(
-
- ));
+ terms[type].items.forEach((termObj, j) => termObj.facetCount
+ && listFacetHierarchyTermsLis[type].push(
+
+ {/* eslint jsx-a11y/label-has-associated-control: ["error", { assert: "either" } ] */}
+
+ ,
+ ));
// Populate the accordion lis array with all of its checkboxes.
+ /* eslint no-unused-expressions: [2, { allowShortCircuit: true }] */
listFacetHierarchyTermsLis[type].length && listFacetHierarchyLis.push(
- Toggle filter group for {type}
+ Toggle filter group for
+ {type}
- );
+ ,
+ );
});
+
+ /* eslint-enable react/no-array-index-key */
+
// Render the group of accordion lis with their facet value checkbox lists.
return listFacetHierarchyLis;
}
@@ -233,6 +257,7 @@ class FederatedListFacet extends React.Component {
return (
- Toggle filter group for {label}
+ Toggle filter group for
+ {label}
{facetValues.filter((facetValue, i) => facetInputs[facetValue] > 0
&& (truncateFacetListsAt < 0 || i < truncateFacetListsAt))
- .map((facetValue, i) => {
- if (this.state.filter.length === 0
- || facetValue.toLowerCase().indexOf(this.state.filter.toLowerCase()) > -1) {
+ .map((facetValue) => {
+ if (filter.length === 0
+ || facetValue.toLowerCase().indexOf(filter.toLowerCase()) > -1) {
return (
@@ -285,24 +313,28 @@ FederatedListFacet.defaultProps = {
hierarchy: false,
expandedHierarchies: [],
value: [],
+ collapse: false,
};
FederatedListFacet.propTypes = {
- bootstrapCss: PropTypes.bool,
- children: PropTypes.array,
collapse: PropTypes.bool,
- expandedHierarchies: PropTypes.array,
- facetSort: PropTypes.string,
- facets: PropTypes.array.isRequired,
+ expandedHierarchies: PropTypes.arrayOf(PropTypes.string),
+ facets: PropTypes.arrayOf(
+ PropTypes.arrayOf(PropTypes.number),
+ ).isRequired,
field: PropTypes.string.isRequired,
hierarchy: PropTypes.bool,
- label: PropTypes.string,
- onChange: PropTypes.func,
- onFacetSortChange: PropTypes.func,
- onSetCollapse: PropTypes.func,
- query: PropTypes.object,
- truncateFacetListsAt: PropTypes.number,
- value: PropTypes.array,
+ label: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+ onSetCollapse: PropTypes.func.isRequired,
+ truncateFacetListsAt: PropTypes.number.isRequired,
+ value: PropTypes.arrayOf(PropTypes.number),
+ options: PropTypes.shape({
+ siteList: PropTypes.shape({
+ length: PropTypes.number,
+ indexOf: PropTypes.func,
+ }),
+ }).isRequired,
};
export default FederatedListFacet;
From f44d1e2223ff6fac8a116484407e28d0493bba0b Mon Sep 17 00:00:00 2001
From: Byron Duvall
Date: Wed, 20 Jan 2021 11:00:16 -0500
Subject: [PATCH 09/34] fix eslint errors in FederatedRangeFacet component
---
src/components/range-facet/index.js | 174 +++++++++++++++-------------
1 file changed, 93 insertions(+), 81 deletions(-)
diff --git a/src/components/range-facet/index.js b/src/components/range-facet/index.js
index d9542ea..b9abc44 100644
--- a/src/components/range-facet/index.js
+++ b/src/components/range-facet/index.js
@@ -1,78 +1,85 @@
import PropTypes from 'prop-types';
-import React from "react";
-import cx from "classnames";
-import moment from "moment";
+import React from 'react';
+import cx from 'classnames';
+import moment from 'moment';
import 'react-dates/initialize';
import { DateRangePicker } from 'react-dates';
import AnimateHeight from 'react-animate-height';
class FederatedRangeFacet extends React.Component {
-
constructor(props) {
super(props);
this.state = {
- filter: "",
- truncateFacetListsAt: props.truncateFacetListsAt,
startDate: null,
endDate: null,
focusedInput: null,
};
}
- toggleExpand() {
- this.props.onSetCollapse(this.props.field, !(this.props.collapse || false));
+ // See: https://reactjs.org/docs/react-component.html#the-component-lifecycle
+ componentDidUpdate(nextProps) {
+ const { value } = this.props;
+ // Clear component inputs when rangeFacet value transitions from populated->empty.
+ if (value.length && !nextProps.value.length) {
+ /* eslint-disable react/no-did-update-set-state */
+ this.setState({
+ startDate: null,
+ endDate: null,
+ });
+ /* eslint-enable react/no-did-update-set-state */
+ }
+ }
+
+ handleDatesChange(startDate, endDate) {
+ const { onChange, field } = this.props;
+ this.setState({ startDate, endDate });
+ // If there are no start/end dates, something has just cleared them, so update props.
+ if (startDate === null && endDate === null) {
+ onChange(field, []);
+ }
}
handleCalendarClose(value) {
+ const { onChange, field } = this.props;
// If there are not start/end dates, we've likely just cleared them, so update props.
if (value.startDate !== null && value.endDate !== null) {
// The default time is noon, so start date should start at midnight.
- const momentToSolrStart = moment(value.startDate).subtract({hours:12}).format("YYYY-MM-DDTHH:mm:ss") + 'Z';
+ const momentToSolrStart = `${moment(value.startDate).subtract({ hours: 12 }).format('YYYY-MM-DDTHH:mm:ss')}Z`;
// The default time is noon, so end date should end at 11:59:59.
- const momentToSolrEnd = moment(value.endDate).add({hours:11, minutes:59, seconds: 59}).format("YYYY-MM-DDTHH:mm:ss") + 'Z';
- this.props.onChange(this.props.field, [momentToSolrStart, momentToSolrEnd]);
+ const momentToSolrEnd = `${moment(value.endDate).add({ hours: 11, minutes: 59, seconds: 59 }).format('YYYY-MM-DDTHH:mm:ss')}Z`;
+ onChange(field, [momentToSolrStart, momentToSolrEnd]);
}
}
- handleDatesChange(startDate,endDate) {
- this.setState({startDate, endDate});
- // If there are no start/end dates, something has just cleared them, so update props.
- if (startDate === null && endDate === null) {
- this.props.onChange(this.props.field, []);
- }
- }
-
- // See: https://reactjs.org/docs/react-component.html#the-component-lifecycle
- componentDidUpdate(nextProps) {
- // Clear component inputs when rangeFacet value transitions from populated->empty.
- if (this.props.value.length && !nextProps.value.length) {
- this.setState({
- startDate: null,
- endDate: null
- });
- }
+ toggleExpand() {
+ const { onSetCollapse, field, collapse } = this.props;
+ onSetCollapse(field, collapse);
}
render() {
- const {label, facets, field, collapse } = this.props;
+ const {
+ label, facets, field, collapse,
+ } = this.props;
+
+ const { startDate, endDate, focusedInput } = this.state;
- const expanded = !(collapse || false);
+ const expanded = collapse;
const height = expanded ? 'auto' : 0;
// Set better react date props for responsive behavior.
// See: https://github.com/airbnb/react-dates/issues/262
- let calendarOrientation = undefined; // prop will not be added unless set.
- let calendarFullScreen = undefined; // prop will not be added unless set.
+ let calendarOrientation; // prop will not be added unless set.
+ let calendarFullScreen; // prop will not be added unless set.
let calendarMonths = 2; // view 2 months on large screens
// When viewing 2 months, the last month should be the current.
let getLastMonth = () => moment().subtract(1, 'months');
// Set prop values for mobile.
- if (window.matchMedia("(max-width: 600px)").matches) {
+ if (window.matchMedia('(max-width: 600px)').matches) {
/* the viewport is less than 600 pixels wide */
calendarMonths = 1;
- calendarOrientation = "vertical";
+ calendarOrientation = 'vertical';
calendarFullScreen = true;
getLastMonth = undefined; // prop will not be added on mobile.
}
@@ -80,12 +87,15 @@ class FederatedRangeFacet extends React.Component {
return (
{if (event.keyCode === 13) {this.toggleExpand()}}}
- >{label}
+ onKeyDown={(event) => { if (event.keyCode === 13) { this.toggleExpand(); } }}
+ >
+ {label}
+
{/* See: https://github.com/airbnb/react-dates#daterangepicker */}
this.handleDatesChange(startDate,endDate)} // PropTypes.func.isRequired,
- focusedInput={this.state.focusedInput} // PropTypes.oneOf([START_DATE, END_DATE]) or null,
- onFocusChange={focusedInput => this.setState({ focusedInput })} // PropTypes.func.isRequired,
+ onDatesChange={({ newStartDate, newEndDate }) => this.handleDatesChange(
+ newStartDate,
+ newEndDate,
+ )} // PropTypes.func.isRequired,
+ focusedInput={focusedInput} // PropTypes.oneOf([START_DATE, END_DATE]) or null,
+ onFocusChange={(newFocusedInput) => this.setState(
+ { focusedInput: newFocusedInput },
+ )} // PropTypes.func.isRequired,
isOutsideRange={(day) => {
const today = moment().format('YYYY-MM-DD');
- return day.diff(today, 'days') > 0 || moment(day).isBefore(facets[0])
+ return day.diff(today, 'days') > 0 || moment(day).isBefore(facets[0]);
}} // allow only past dates & dates after earliest facet value
minimumNights={0} // allow just 1 day (same start/end date)
- small={true} // use the smaller theme
+ small // use the smaller theme
showClearDates // show the clear dates button
- onClose={(value)=> this.handleCalendarClose(value)}
+ onClose={(value) => this.handleCalendarClose(value)}
// custom phrases for screenreader
phrases={{
- calendarLabel: "Calendar",
+ calendarLabel: 'Calendar',
chooseAvailableStartDate: ({ date }) => `Choose ${date} as your search filter start date.`,
chooseAvailableEndDate: ({ date }) => `Choose ${date} as your search filter end date.`,
- clearDates: "Clear Dates",
- closeDatePicker: "Close",
+ clearDates: 'Clear Dates',
+ closeDatePicker: 'Close',
dateIsSelected: ({ date }) => `You have selected ${date}.`,
dateIsUnavailable: ({ date }) => `Sorry, ${date} is unavailable.`,
- enterKey: "Enter key",
- escape: "Escape key",
- focusStartDate: "Interact with the calendar and add the check-in date for your trip.",
- hideKeyboardShortcutsPanel: "Close the shortcuts panel.",
- homeEnd: "Home and end keys",
- jumpToNextMonth: "Move forward to switch to the next month.",
- jumpToPrevMonth: "Move backward to switch to the previous month.",
- keyboardNavigationInstructions: "Press the down arrow key to interact with the calendar and\n select a date. Press the question mark key to get the keyboard shortcuts for changing dates.",
- keyboardShortcuts: "Keyboard Shortcuts",
- leftArrowRightArrow: "Right and left arrow keys",
- moveFocusByOneDay: "Move backward (left) and forward (right) by one day.",
- moveFocusByOneMonth: "Switch months.",
- moveFocusByOneWeek: "Move backward (up) and forward (down) by one week.",
- moveFocustoStartAndEndOfWeek: "Go to the first or last day of a week.",
- openThisPanel: "Open this panel.",
- pageUpPageDown: "page up and page down keys",
- questionMark: "Question mark",
- returnFocusToInput: "Return to the date input field.",
- selectFocusedDate: "Select the date in focus.",
- showKeyboardShortcutsPanel: "Open the keyboard shortcuts panel.",
- upArrowDownArrow: "up and down arrow keys"
+ enterKey: 'Enter key',
+ escape: 'Escape key',
+ focusStartDate: 'Interact with the calendar and add the check-in date for your trip.',
+ hideKeyboardShortcutsPanel: 'Close the shortcuts panel.',
+ homeEnd: 'Home and end keys',
+ jumpToNextMonth: 'Move forward to switch to the next month.',
+ jumpToPrevMonth: 'Move backward to switch to the previous month.',
+ keyboardNavigationInstructions: 'Press the down arrow key to interact with the calendar and\n select a date. Press the question mark key to get the keyboard shortcuts for changing dates.',
+ keyboardShortcuts: 'Keyboard Shortcuts',
+ leftArrowRightArrow: 'Right and left arrow keys',
+ moveFocusByOneDay: 'Move backward (left) and forward (right) by one day.',
+ moveFocusByOneMonth: 'Switch months.',
+ moveFocusByOneWeek: 'Move backward (up) and forward (down) by one week.',
+ moveFocustoStartAndEndOfWeek: 'Go to the first or last day of a week.',
+ openThisPanel: 'Open this panel.',
+ pageUpPageDown: 'page up and page down keys',
+ questionMark: 'Question mark',
+ returnFocusToInput: 'Return to the date input field.',
+ selectFocusedDate: 'Select the date in focus.',
+ showKeyboardShortcutsPanel: 'Open the keyboard shortcuts panel.',
+ upArrowDownArrow: 'up and down arrow keys',
}}
// > mobile only props
initialVisibleMonth={getLastMonth} // large viewports only
@@ -156,23 +171,20 @@ class FederatedRangeFacet extends React.Component {
}
FederatedRangeFacet.defaultProps = {
- value: []
+ value: [],
+ collapse: false,
};
FederatedRangeFacet.propTypes = {
- bootstrapCss: PropTypes.bool,
- children: PropTypes.array,
collapse: PropTypes.bool,
- facetSort: PropTypes.string,
- facets: PropTypes.array.isRequired,
+ facets: PropTypes.arrayOf(
+ PropTypes.arrayOf(PropTypes.number),
+ ).isRequired,
field: PropTypes.string.isRequired,
- label: PropTypes.string,
- onChange: PropTypes.func,
- onFacetSortChange: PropTypes.func,
- onSetCollapse: PropTypes.func,
- query: PropTypes.object,
- truncateFacetListsAt: PropTypes.number,
- value: PropTypes.array
+ label: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+ onSetCollapse: PropTypes.func.isRequired,
+ value: PropTypes.arrayOf(PropTypes.number),
};
export default FederatedRangeFacet;
From 08ecbd5309bb9d93098e27e317d86a71ed900d84 Mon Sep 17 00:00:00 2001
From: Byron Duvall
Date: Wed, 20 Jan 2021 15:37:54 -0500
Subject: [PATCH 10/34] fix eslint errors in FederatedCountLabel component
---
src/components/results/count-label.js | 82 ++++++++++++++++++---------
1 file changed, 55 insertions(+), 27 deletions(-)
diff --git a/src/components/results/count-label.js b/src/components/results/count-label.js
index 9217ff3..ca2abc8 100644
--- a/src/components/results/count-label.js
+++ b/src/components/results/count-label.js
@@ -9,17 +9,45 @@ function searchResultsStat(currentPage, numFound, rows, pageAmt, noResultsText,
if (numFound > rows) { // Many pages
a11yMessage = `Showing page ${currentPage + 1} of ${pageAmt} (${numFound} results).`;
message = (
- Showing page
- {currentPage + 1} of
- {pageAmt} ({numFound} results).
+
+ Showing page
+
+ {' '}
+ {currentPage + 1}
+
+ {' '}
+ of
+
+ {' '}
+ {pageAmt}
+
+ {' '}
+ (
+ {numFound}
+ {' '}
+ results).
);
} else if (numFound <= rows && numFound > 1) { // Single page
a11yMessage = `Showing ${numFound} results.`;
- message = (Showing {numFound} results.);
+ message = (
+
+ Showing
+ {numFound}
+ {' '}
+ results.
+
+ );
} else if (numFound === 1) { // Single item
a11yMessage = `Showing ${numFound} result.`;
- message = (Showing {numFound} result.);
+ message = (
+
+ Showing
+ {numFound}
+ {' '}
+ result.
+
+ );
} else if (numFound === 0) { // No results
message = noResultsText || 'Sorry, your search yielded no results.';
a11yMessage = message;
@@ -27,40 +55,40 @@ function searchResultsStat(currentPage, numFound, rows, pageAmt, noResultsText,
// Don't announce total results when wildcard query sent on term clear.
a11yMessage = termValue ? a11yMessage : '';
return (
-
+ <>
{message}
-
+ >
);
}
-class FederatedCountLabel extends React.Component {
- render() {
- const {
- numFound,
- start,
- rows,
- noResultsText,
- termValue,
- } = this.props;
- const currentPage = start / rows;
- const pageAmt = Math.ceil(numFound / rows);
- return (
-
- {searchResultsStat(currentPage, numFound, rows, pageAmt, noResultsText, termValue)}
-
- );
- }
-}
+const FederatedCountLabel = function ({
+ numFound,
+ start,
+ rows,
+ noResultsText,
+ termValue,
+}) {
+ const currentPage = start / rows;
+ const pageAmt = Math.ceil(numFound / rows);
+ return (
+ <>
+ {searchResultsStat(currentPage, numFound, rows, pageAmt, noResultsText, termValue)}
+ >
+ );
+};
FederatedCountLabel.propTypes = {
numFound: PropTypes.number.isRequired,
start: PropTypes.number.isRequired,
- rows: PropTypes.number,
+ rows: PropTypes.number.isRequired,
+ noResultsText: PropTypes.string,
+ termValue: PropTypes.string,
};
FederatedCountLabel.defaultProps = {
- start: 0,
+ noResultsText: '',
+ termValue: '',
};
export default FederatedCountLabel;
From 035495dfb85a5f16b81a813a7ee868a09091163c Mon Sep 17 00:00:00 2001
From: Byron Duvall
Date: Sat, 23 Jan 2021 16:08:46 -0500
Subject: [PATCH 11/34] fix date picker in FederatedRangeFacet component
---
src/components/range-facet/index.js | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/src/components/range-facet/index.js b/src/components/range-facet/index.js
index b9abc44..5e21149 100644
--- a/src/components/range-facet/index.js
+++ b/src/components/range-facet/index.js
@@ -54,7 +54,7 @@ class FederatedRangeFacet extends React.Component {
toggleExpand() {
const { onSetCollapse, field, collapse } = this.props;
- onSetCollapse(field, collapse);
+ onSetCollapse(field, !collapse);
}
render() {
@@ -64,7 +64,7 @@ class FederatedRangeFacet extends React.Component {
const { startDate, endDate, focusedInput } = this.state;
- const expanded = collapse;
+ const expanded = !collapse;
const height = expanded ? 'auto' : 0;
// Set better react date props for responsive behavior.
@@ -108,7 +108,13 @@ class FederatedRangeFacet extends React.Component {
startDateId="solr-start-date" // PropTypes.string.isRequired,
endDate={endDate} // momentPropTypes.momentObj or null,
endDateId="solr-end-date" // PropTypes.string.isRequired,
- onDatesChange={({ newStartDate, newEndDate }) => this.handleDatesChange(
+ // We need to rename the destructured date variables, because they are already used
+ // in the outer scope.
+ // See https://wesbos.com/destructuring-renaming
+ onDatesChange={({
+ startDate: newStartDate,
+ endDate: newEndDate,
+ }) => this.handleDatesChange(
newStartDate,
newEndDate,
)} // PropTypes.func.isRequired,
@@ -177,9 +183,7 @@ FederatedRangeFacet.defaultProps = {
FederatedRangeFacet.propTypes = {
collapse: PropTypes.bool,
- facets: PropTypes.arrayOf(
- PropTypes.arrayOf(PropTypes.number),
- ).isRequired,
+ facets: PropTypes.arrayOf(PropTypes.string).isRequired,
field: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
From c71d6d270f5d42a9b4511f9444a4a5ee60a7f04e Mon Sep 17 00:00:00 2001
From: Byron Duvall
Date: Sat, 23 Jan 2021 16:19:50 -0500
Subject: [PATCH 12/34] fix eslint errors in FederatedResultList component
---
src/components/results/list.js | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/src/components/results/list.js b/src/components/results/list.js
index 1ab4220..5049392 100644
--- a/src/components/results/list.js
+++ b/src/components/results/list.js
@@ -1,22 +1,21 @@
import PropTypes from 'prop-types';
-import React from "react";
+import React from 'react';
-class FederatedResultList extends React.Component {
+const FederatedResultList = ({ children }) => (
+ <>
+ Search results
+
+ >
+);
- render() {
- return (
-
- Search results
-
- {this.props.children}
-
-
- );
- }
-}
+FederatedResultList.defaultProps = {
+ children: [],
+};
FederatedResultList.propTypes = {
- children: PropTypes.array
+ children: PropTypes.arrayOf(PropTypes.object),
};
export default FederatedResultList;
From dcf6d85f3f6921d0d1d91482df906f1c8f6d8dcb Mon Sep 17 00:00:00 2001
From: Byron Duvall
Date: Mon, 25 Jan 2021 09:38:22 -0500
Subject: [PATCH 13/34] fix eslint errors in FederatedPagination component
---
src/components/results/pagination.js | 94 ++++++++++++++++------------
1 file changed, 55 insertions(+), 39 deletions(-)
diff --git a/src/components/results/pagination.js b/src/components/results/pagination.js
index 79c964e..9f65b2f 100644
--- a/src/components/results/pagination.js
+++ b/src/components/results/pagination.js
@@ -1,16 +1,19 @@
import PropTypes from 'prop-types';
-import React from "react";
-import cx from "classnames";
-import {DoubleChevronLeft, ChevronLeft, ChevronRight, DoubleChevronRight} from "../icons/chevrons";
+import React from 'react';
+import cx from 'classnames';
+import {
+ DoubleChevronLeft, ChevronLeft, ChevronRight, DoubleChevronRight,
+} from '../icons/chevrons';
class FederatedPagination extends React.Component {
-
onPageChange(page, pageAmt) {
+ const { onChange } = this.props;
+
if (page >= pageAmt || page < 0) { return; }
- this.props.onChange(page);
+ onChange(page);
- if(document.getElementById("stat") != null) {
- document.getElementById("stat").focus({preventScroll: false});
+ if (document.getElementById('stat') != null) {
+ document.getElementById('stat').focus({ preventScroll: false });
}
}
@@ -21,78 +24,79 @@ class FederatedPagination extends React.Component {
};
renderPage(page, currentPage, key) {
- let isCurrentPage = page === currentPage;
+ const isCurrentPage = page === currentPage;
return (
-
-
- Page{page + 1}
+
+
+ Page
+ {page + 1}
);
}
render() {
- const { query, results } = this.props;
+ const { query, results, options } = this.props;
const { start, rows } = query;
const { numFound } = results;
const pageAmt = Math.ceil(numFound / rows);
const currentPage = start / rows;
- const numButtons = this.props.options.paginationButtons || 5;
+ const numButtons = options.paginationButtons;
let rangeStart = currentPage - 2 < 0 ? 0 : currentPage - 2;
- let rangeEnd = rangeStart + numButtons > pageAmt ? pageAmt : rangeStart + numButtons;
+ const rangeEnd = rangeStart + numButtons > pageAmt ? pageAmt : rangeStart + numButtons;
if (rangeEnd - rangeStart < numButtons && rangeStart > 0) {
rangeStart = rangeEnd - numButtons;
if (rangeStart < 0) { rangeStart = 0; }
}
- let pages = [];
- for (let page = rangeStart; page < rangeEnd; page++) {
+ const pages = [];
+ for (let page = rangeStart; page < rangeEnd; page += 1) {
if (pages.indexOf(page) < 0) {
pages.push(page);
}
}
- let firstPageHidden = (currentPage === 0);
- let prevPageHidden = (currentPage - 1 < 0);
- let nextPageHidden = (currentPage + 1 >= pageAmt);
- let lastPageHidden = (pageAmt === 0 || currentPage === pageAmt - 1);
+ const firstPageHidden = (currentPage === 0);
+ const prevPageHidden = (currentPage - 1 < 0);
+ const nextPageHidden = (currentPage + 1 >= pageAmt);
+ const lastPageHidden = (pageAmt === 0 || currentPage === pageAmt - 1);
return (