diff --git a/app/javascript/readingList/readingList.jsx b/app/javascript/readingList/readingList.jsx index 7f8acffe3..3615afe44 100644 --- a/app/javascript/readingList/readingList.jsx +++ b/app/javascript/readingList/readingList.jsx @@ -7,6 +7,7 @@ import { performInitialSearch, search, selectTag, + checkForPersistedTag, clearSelectedTags, } from '../searchableItemList/searchableItemList'; import { addSnackbarItem } from '../Snackbar'; @@ -69,12 +70,20 @@ export class ReadingList extends Component { this.clearSelectedTags = clearSelectedTags.bind(this); } - componentDidMount() { + async componentDidMount() { const { statusView } = this.state; - this.performInitialSearch({ + await this.performInitialSearch({ searchOptions: { status: `${statusView}` }, }); + + const persistedTag = checkForPersistedTag(); + if (persistedTag) { + this.selectTag({ + target: { value: persistedTag }, + preventDefault(){}, + }); + } } toggleStatusView = (event) => { diff --git a/app/javascript/searchableItemList/searchableItemList.js b/app/javascript/searchableItemList/searchableItemList.js index b768bace0..917faaf7b 100644 --- a/app/javascript/searchableItemList/searchableItemList.js +++ b/app/javascript/searchableItemList/searchableItemList.js @@ -19,7 +19,8 @@ export function onSearchBoxType(event) { export function selectTag(event) { event.preventDefault(); const { value, dataset } = event.target; - const selectedTag = value ?? dataset.tag; + const selectedTagOrAll = value ?? dataset.tag; + const selectedTag = selectedTagOrAll?.match(/all tags/i) ? null : selectedTagOrAll; const component = this; const { query, statusView } = component.state; @@ -29,6 +30,9 @@ export function selectTag(event) { statusView, appendItems: false, }); + + // persist the selected tag in query params + window.history.pushState(null, null, `/readinglist${selectedTag ? `?selectedTag=${selectedTag}` : ''}`); } export function clearSelectedTags(event) { @@ -41,7 +45,7 @@ export function clearSelectedTags(event) { } // Perform the initial search -export function performInitialSearch({ searchOptions = {} }) { +export async function performInitialSearch({ searchOptions = {} }) { const component = this; const { hitsPerPage } = component.state; const dataHash = { page: 0, per_page: hitsPerPage }; @@ -135,3 +139,12 @@ export function loadNextPage() { appendItems: true, }); } + +export function checkForPersistedTag() { + // credit: https://stackoverflow.com/a/9870540 + const params = (new URL(window.location)).searchParams + const selectedTag = params.get('selectedTag'); + + return selectedTag || ''; +} + diff --git a/cypress/e2e/seededFlows/readingListFlows/readingList.spec.js b/cypress/e2e/seededFlows/readingListFlows/readingList.spec.js index 7f0fbf3db..849a9f879 100644 --- a/cypress/e2e/seededFlows/readingListFlows/readingList.spec.js +++ b/cypress/e2e/seededFlows/readingListFlows/readingList.spec.js @@ -145,6 +145,31 @@ describe('Reading List Archive', () => { cy.get('@main').findByText('Test Article 1'); cy.get('@main').findByText('Test Article 2').should('not.exist'); cy.get('@main').findByText('Test Article 3'); + + cy.url().should('eq', Cypress.config().baseUrl + 'readinglist?selectedTag=productivity'); + }); + + it('should persist filtering by tag via query params', () => { + cy.intercept( + Cypress.config().baseUrl + + 'search/reactions?search_fields=&page=0&per_page=80&tag_names%5B%5D=productivity&tag_boolean_mode=all&status%5B%5D=valid&status%5B%5D=confirmed', + { fixture: 'search/readingListFilterByTagProductivity.json' }, + ).as('filteredReadingList'); + + cy.visit('/readinglist?selectedTag=productivity'); + cy.wait('@filteredReadingList'); + + cy.findByRole('main') + .as('main') + .findByLabelText('Filter by tag') + .as('tagFilter'); + + cy.get('@main').findByText('Test Article 1'); + cy.get('@main').findByText('Test Article 2').should('not.exist'); + cy.get('@main').findByText('Test Article 3'); + + cy.get('@tagFilter').select('all tags'); + cy.url().should('eq', Cypress.config().baseUrl + 'readinglist'); }); }); @@ -197,6 +222,31 @@ describe('Reading List Archive', () => { cy.get('@main').findByText('Test Article 1'); cy.get('@main').findByText('Test Article 2').should('not.exist'); cy.get('@main').findByText('Test Article 3'); + + cy.url().should('eq', Cypress.config().baseUrl + 'readinglist?selectedTag=productivity'); + }); + + it('should persist filtering by tag via query params', () => { + cy.intercept( + Cypress.config().baseUrl + + 'search/reactions?search_fields=&page=0&per_page=80&tag_names%5B%5D=productivity&tag_boolean_mode=all&status%5B%5D=valid&status%5B%5D=confirmed', + { fixture: 'search/readingListFilterByTagProductivity.json' }, + ).as('filteredReadingList'); + + cy.visit('/readinglist?selectedTag=productivity'); + cy.wait('@filteredReadingList'); + + cy.findByRole('main') + .as('main') + .findByRole('navigation', { name: /^Filter by tag$/i }) + .as('tagFilter'); + + cy.get('@main').findByText('Test Article 1'); + cy.get('@main').findByText('Test Article 2').should('not.exist'); + cy.get('@main').findByText('Test Article 3'); + + cy.get('@tagFilter').findByText('All tags').click(); + cy.url().should('eq', Cypress.config().baseUrl + 'readinglist'); }); }); });