* Some div soup to semantic markup. * Small refactor to inline mapping of available tags. * Renamed <ItemListTags /> component to <TagList />. * Now a select is used for picking a tag to filter on. * Added custom Cypress command to create an article. * Added documentation for the create article custom command. * Removed unnecesary properties from payload to create an article. * reading list mobile view wip. * Reworked styles in <TagList />. * Reworked reading list to use <MediaQuery /> component. * Removed bottom padding from reading list header. * styling tweaks if there are no available tags. * Added some E2E tests. * Removed reading list component test in favour of e2e test. * Made breakpoint values numbers. * Added some padding and more grid gap to filter on small screens. * Adjusted jest coverage thresholds as we're moving some tests to e2e tests. * Reverting a VS Code setting change caused by one of my extensions. * First pass for E2E tests for the reading list. * Added some more grid gap. * Fixed load next page to send tags properly. * Added some more tests. * Improved label and placeholder for text filter in reading list. * Added more tests * Fixed media queries so it works in Chrome as well. * Removed aside as tag filters are not complimentary information. * Update app/javascript/readingList/components/TagList.jsx Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Update docs/tests/e2e-tests.md Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Turned off deprecated rule in jsx-a11y eslint plugin. * Reverted to links instead of radio buttons. * Added an all tags link and select option. * Fixed relayout issue. * Fixed View Archive button size. * Fixed styling of the load more button. * Fixed empty list issue toggling between archive and reading list. * Fixed request changes from PR review. * Removed CSS change that is no longer required. * Trigger Build * Fixed centering of items in top fieldset. * Fixed issue with search text field resetting reading list. * Fixed component tests for the reading list. * Fixed empty state popping up between search queries. * Fixed casing of fixture filenames. * Update app/javascript/readingList/readingList.jsx Co-authored-by: Suzanne Aitchison <suzanne@forem.com> * Reverted change in reading list component test. * Added missing JSDoc comment. * Now links are in an unordered list. * Promoted some CSS classes from the <nav /> to the <ul /> for spacing. Co-authored-by: Suzanne Aitchison <suzanne@forem.com>
137 lines
3.7 KiB
JavaScript
137 lines
3.7 KiB
JavaScript
// Shared behavior between the reading list and history pages
|
|
import { fetchSearch } from '../utilities/search';
|
|
|
|
// Starts the search when the user types in the search box
|
|
export function onSearchBoxType(event) {
|
|
const component = this;
|
|
|
|
const query = event.target.value;
|
|
const { selectedTag, statusView } = component.state;
|
|
|
|
component.setState({ page: 0 });
|
|
component.search(query, {
|
|
tags: selectedTag ? [selectedTag] : [],
|
|
statusView,
|
|
appendItems: false,
|
|
});
|
|
}
|
|
|
|
export function selectTag(event) {
|
|
event.preventDefault();
|
|
const { value, dataset } = event.target;
|
|
const selectedTag = value ?? dataset.tag;
|
|
const component = this;
|
|
const { query, statusView } = component.state;
|
|
|
|
component.setState({ selectedTag, page: 0, items: [] });
|
|
component.search(query, {
|
|
tags: selectedTag ? [selectedTag] : [],
|
|
statusView,
|
|
appendItems: false,
|
|
});
|
|
}
|
|
|
|
export function clearSelectedTags(event) {
|
|
event.preventDefault();
|
|
|
|
const component = this;
|
|
const { query, statusView } = component.state;
|
|
component.setState({ selectedTag: '', page: 0, items: [] });
|
|
component.search(query, { tags: [], statusView, appendItems: false });
|
|
}
|
|
|
|
// Perform the initial search
|
|
export function performInitialSearch({ searchOptions = {} }) {
|
|
const component = this;
|
|
const { hitsPerPage } = component.state;
|
|
const dataHash = { page: 0, per_page: hitsPerPage };
|
|
|
|
component.setState({ loading: true });
|
|
|
|
if (searchOptions.status) {
|
|
dataHash.status = searchOptions.status.split(',');
|
|
}
|
|
|
|
const responsePromise = fetchSearch('reactions', dataHash);
|
|
return responsePromise.then((response) => {
|
|
const reactions = response.result;
|
|
// FIXME: [@rhymes] the list of tags in the left column of the reading list
|
|
// is populated with only the tags belonging to items in the first page
|
|
const availableTags = [
|
|
...new Set(reactions.flatMap((rxn) => rxn.reactable.tag_list)),
|
|
].sort();
|
|
component.setState({
|
|
page: 0,
|
|
items: reactions,
|
|
itemsLoaded: true,
|
|
itemsTotal: response.total,
|
|
showLoadMoreButton: hitsPerPage < response.total,
|
|
availableTags,
|
|
loading: false,
|
|
});
|
|
});
|
|
}
|
|
|
|
// Main search function
|
|
export function search(query, { page, tags, statusView, appendItems = false }) {
|
|
const component = this;
|
|
|
|
component.setState({ loading: true });
|
|
|
|
// allow the page number to come from the calling function
|
|
// we check `undefined` because page can be 0
|
|
const newPage = page === undefined ? component.state.page : page;
|
|
|
|
const { hitsPerPage, items: existingItems } = component.state;
|
|
|
|
const dataHash = {
|
|
search_fields: query,
|
|
page: newPage,
|
|
per_page: hitsPerPage,
|
|
};
|
|
|
|
if (tags && tags.length > 0) {
|
|
dataHash.tag_names = tags;
|
|
dataHash.tag_boolean_mode = 'all';
|
|
}
|
|
|
|
if (statusView) {
|
|
dataHash.status = statusView.split(',');
|
|
}
|
|
|
|
const responsePromise = fetchSearch('reactions', dataHash);
|
|
return responsePromise.then((response) => {
|
|
const reactions = response.result;
|
|
|
|
let items;
|
|
if (appendItems) {
|
|
// we append the new reactions at the bottom of the list, for pagination
|
|
items = [...existingItems, ...reactions];
|
|
} else {
|
|
items = reactions;
|
|
}
|
|
|
|
component.setState({
|
|
query,
|
|
page: newPage,
|
|
items,
|
|
itemsTotal: response.total,
|
|
showLoadMoreButton: items.length < response.total,
|
|
loading: false,
|
|
});
|
|
});
|
|
}
|
|
|
|
// Retrieve the results in the next page
|
|
export function loadNextPage() {
|
|
const component = this;
|
|
|
|
const { query, selectedTag, page, statusView } = component.state;
|
|
component.setState({ page: page + 1 });
|
|
component.search(query, {
|
|
page: page + 1,
|
|
tags: [selectedTag],
|
|
statusView,
|
|
appendItems: true,
|
|
});
|
|
}
|