From 53bdcc2001cb120fb2ba139fec4cbbb3fed830ab Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Fri, 16 Aug 2024 15:09:55 -0400 Subject: [PATCH 01/17] Simplifying `changeAdvancedFilter`. --- .../components/FiltersContainer/index.js | 72 +++++++------------ 1 file changed, 27 insertions(+), 45 deletions(-) diff --git a/src/modules/advanced/components/FiltersContainer/index.js b/src/modules/advanced/components/FiltersContainer/index.js index 650867ec..77c5610b 100644 --- a/src/modules/advanced/components/FiltersContainer/index.js +++ b/src/modules/advanced/components/FiltersContainer/index.js @@ -91,52 +91,34 @@ const FiltersContainer = ({ datastore }) => { const filters = getFilters({ activeFilters, filterGroups }); const changeAdvancedFilter = ({ filterGroupUid, filterType, filterValue }) => { - switch (filterType) { - case 'scope_down': - // Clear active filters - if (['institution', 'location'].includes(filterGroupUid) && filterValue) { - dispatch(setAdvancedFilter({ - datastoreUid: datastore.uid, - filterGroupUid: 'collection', - filterType, - onlyOneFilterValue: true - })); - if (filterGroupUid === 'institution') { - dispatch(setAdvancedFilter({ - datastoreUid: datastore.uid, - filterGroupUid: 'location', - filterType, - onlyOneFilterValue: true - })); - } - } - dispatch(setAdvancedFilter({ - datastoreUid: datastore.uid, - filterGroupUid, - filterType, - filterValue, - onlyOneFilterValue: true - })); - break; - case 'checkbox': - case 'date_range_input': - dispatch(setAdvancedFilter({ - datastoreUid: datastore.uid, - filterGroupUid, - filterValue, - onlyOneFilterValue: true - })); - break; - case 'multiple_select': - dispatch(setAdvancedFilter({ - datastoreUid: datastore.uid, - filterGroupUid, - filterValue - })); - break; - default: - break; + const baseFilter = { + datastoreUid: datastore.uid, + filterGroupUid, + filterType, + filterValue, + onlyOneFilterValue: true + }; + const actions = []; + const createAction = (overrides = {}) => { + actions.push(setAdvancedFilter({ ...baseFilter, ...overrides })); + }; + + if (filterType === 'scope_down' && ['institution', 'location'].includes(filterGroupUid) && filterValue) { + createAction({ filterGroupUid: 'collection', filterValue: null }); + if (filterGroupUid === 'institution') { + createAction({ filterGroupUid: 'location', filterValue: null }); + } + } + + if (['checkbox', 'date_range_input', 'scope_down'].includes(filterType)) { + createAction(); } + + if (filterType === 'multiple_select') { + createAction({ onlyOneFilterValue: false }); + } + + actions.forEach(dispatch); }; if (filters?.length === 0) { From 047facbc229ad0079816b34599a0aa744281bf8e Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Mon, 19 Aug 2024 16:11:38 -0400 Subject: [PATCH 02/17] Simplifying functions. --- .../components/AdvancedFilter/index.js | 109 +++++------------- 1 file changed, 32 insertions(+), 77 deletions(-) diff --git a/src/modules/advanced/components/AdvancedFilter/index.js b/src/modules/advanced/components/AdvancedFilter/index.js index 1a823d79..3551b63c 100644 --- a/src/modules/advanced/components/AdvancedFilter/index.js +++ b/src/modules/advanced/components/AdvancedFilter/index.js @@ -5,93 +5,48 @@ import PropTypes from 'prop-types'; import React from 'react'; const getIsCheckboxFilterChecked = ({ advancedFilter }) => { - const hasActiveFilter = advancedFilter.activeFilters?.length > 0; + const { activeFilters, conditions } = advancedFilter; + const hasActiveFilters = activeFilters?.length > 0; - if (!hasActiveFilter && advancedFilter.conditions.default === 'checked') { - return true; - } - - if (hasActiveFilter && advancedFilter.activeFilters[0] === advancedFilter.conditions.checked) { - return true; - } - - return false; + return (!hasActiveFilters && conditions.default === 'checked') + || (hasActiveFilters && activeFilters[0] === conditions.checked); }; const getDateRangeValue = ({ beginDateQuery, endDateQuery, selectedRange }) => { - switch (selectedRange) { - case 'Before': - if (endDateQuery) { - return `before ${endDateQuery}`; - } - return null; - case 'After': - if (beginDateQuery) { - return `after ${beginDateQuery}`; - } - return null; - case 'Between': - if (beginDateQuery && endDateQuery) { - return `${beginDateQuery} to ${endDateQuery}`; - } - return null; - case 'In': - if (beginDateQuery) { - return beginDateQuery; - } - return null; - default: - return null; - } + const dateRanges = { + After: beginDateQuery && `after ${beginDateQuery}`, + Before: endDateQuery && `before ${endDateQuery}`, + Between: (beginDateQuery && endDateQuery) && `${beginDateQuery} to ${endDateQuery}`, + In: beginDateQuery + }; + + return dateRanges[selectedRange] || null; }; const getStateDateRangeValues = ({ advancedFilter }) => { - if (advancedFilter.activeFilters?.length > 0) { - const [filterValue] = advancedFilter.activeFilters; - - // Before - if (filterValue.indexOf('before') !== -1) { - const values = filterValue.split('before'); - - return { - stateEndQuery: values[1], - stateSelectedRangeOption: 0 - }; - } - - // After - if (filterValue.indexOf('after') !== -1) { - const values = filterValue.split('after'); - - return { - stateBeginQuery: values[1], - stateSelectedRangeOption: 1 - }; - } - - // Between - if (filterValue.indexOf('to') !== -1) { - const values = filterValue.split('to'); - - return { - stateBeginQuery: values[0], - stateEndQuery: values[1], - stateSelectedRangeOption: 2 - }; - } + const rangeValues = { + stateSelectedRangeOption: 0 + }; + const dates = [null, null]; - // In or other - return { - stateBeginQuery: filterValue, - stateSelectedRangeOption: 3 - }; + if (advancedFilter?.activeFilters?.length) { + const ranges = ['before', 'after', 'to']; + rangeValues.stateSelectedRangeOption = ranges.length; + const [filterValue] = advancedFilter.activeFilters; + dates.unshift(...filterValue.match(/\d+/gu)); + ranges.forEach((range, index) => { + if (filterValue.includes(range)) { + rangeValues.stateSelectedRangeOption = index; + if (range === ranges[0]) { + dates.unshift(null); + } + } + }); } - return { - stateBeginQuery: '', - stateEndQuery: '', - stateSelectedRangeOption: 0 - }; + [rangeValues.stateBeginQuery, rangeValues.stateEndQuery] = dates; + + return rangeValues; }; const AdvancedFilter = ({ advancedFilter, changeAdvancedFilter }) => { From 1e8efd458883538b7fe489fedfeaf82fad19d636 Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Wed, 21 Aug 2024 10:55:08 -0400 Subject: [PATCH 03/17] Adding remove active filter options and styling. Note: Cannot remove individual filters. Currently can only remove all but the selected filter in the same group. --- .../components/FiltersContainer/index.js | 138 +++++++++++------- .../components/FiltersContainer/styles.css | 13 +- .../filters/components/Filters/styles.css | 1 + 3 files changed, 97 insertions(+), 55 deletions(-) diff --git a/src/modules/advanced/components/FiltersContainer/index.js b/src/modules/advanced/components/FiltersContainer/index.js index 77c5610b..87f952cb 100644 --- a/src/modules/advanced/components/FiltersContainer/index.js +++ b/src/modules/advanced/components/FiltersContainer/index.js @@ -1,4 +1,5 @@ import './styles.css'; +import '../../../filters/components/Filters/styles.css'; import { useDispatch, useSelector } from 'react-redux'; import AdvancedFilter from '../AdvancedFilter'; import getFilters from './getFilters'; @@ -7,71 +8,98 @@ import PropTypes from 'prop-types'; import React from 'react'; import { setAdvancedFilter } from '../../../advanced'; -const ActiveAdvancedFilters = (datastore) => { - const currentDatastore = datastore.datastore.uid; - const { advanced } = useSelector((state) => { - return state; - }); - const activeAdditionalSearchOptions = advanced[currentDatastore].activeFilters; - // Check if object exists - if (!activeAdditionalSearchOptions) { - return null; - } - // Remove properties that have undefined values - Object.keys(activeAdditionalSearchOptions).forEach((option) => { - if (!activeAdditionalSearchOptions[option]) { - delete activeAdditionalSearchOptions[option]; - } - }); - - const filterGroups = {}; - advanced[currentDatastore].filters.forEach((filterGroup) => { - filterGroups[filterGroup.uid] = { ...filterGroup }; +const FilterList = ({ datastoreUid }) => { + const dispatch = useDispatch(); + const { activeFilters = {}, filters: filterGroup } = useSelector((state) => { + return state.advanced[datastoreUid] || {}; }); - const items = Object.keys(activeAdditionalSearchOptions).reduce((acc, group) => { - // Just don't show the checkbox filters as active filter items. - if (!filterGroups[group] || filterGroups[group].type !== 'checkbox') { - const activeFiltersToAdd = activeAdditionalSearchOptions[group].map((value) => { - return { group, value }; + // Create filter list based on active filters + const filterList = Object.entries(activeFilters).reduce((acc, [groupUid, filters]) => { + if (filters) { + const groupName = filterGroup.find((group) => { + return group.uid === groupUid; + }); + filters.forEach((value) => { + acc.push({ + groupUid, + name: groupName?.groupBy || groupName?.name, + value + }); }); - return [...acc, ...activeFiltersToAdd]; } return acc; }, []); - if (!items.length) { - return null; - } + const handleRemoveFilter = ({ groupUid, value }) => { + const baseFilter = { + datastoreUid, + filterGroupUid: groupUid, + filterValue: value, + onlyOneFilterValue: true + }; + const actions = []; + const createAction = (overrides = {}) => { + actions.push(setAdvancedFilter({ ...baseFilter, ...overrides })); + }; - const titleCase = (string) => { - return string.toLowerCase().split('_').map((word) => { - return word.replace(word[0], word[0].toUpperCase()); - }).join(' '); + // Example logic for removing specific filters based on type and group + createAction(); + + // Dispatch all created actions + actions.forEach(dispatch); + }; + + const handleClearFilters = () => { + Object.keys(activeFilters).forEach((groupUid) => { + const filters = activeFilters[groupUid]; + filters.forEach(() => { + dispatch(setAdvancedFilter({ + datastoreUid, + filterGroupUid: groupUid, + filterValue: null, + onlyOneFilterValue: true + })); + }); + }); }; + if (filterList.length === 0) { + return null; + } + return (
-

- Active filters - {' '} - - ({items.length}) - -

- -

- Unselect active filters through the options below. -

- -
    - {items.map((item, index) => { +
    +

    + Active filters ({filterList.length}) +

    + {filterList.length > 1 && ( + + )} +
    +
      + {filterList.map(({ groupUid, name, value }) => { return ( -
    • - {filterGroups[item.group]?.name || titleCase(item.group)}: {item.value} +
    • +
    • ); })} @@ -80,6 +108,10 @@ const ActiveAdvancedFilters = (datastore) => { ); }; +FilterList.propTypes = { + datastoreUid: PropTypes.string +}; + const FiltersContainer = ({ datastore }) => { const dispatch = useDispatch(); const filterGroups = useSelector((state) => { @@ -129,7 +161,7 @@ const FiltersContainer = ({ datastore }) => { return ( <> - +

      Additional search options

      {filterGroupings.map((filterGroup, groupIndex) => { diff --git a/src/modules/advanced/components/FiltersContainer/styles.css b/src/modules/advanced/components/FiltersContainer/styles.css index cf379c8d..7646d73d 100644 --- a/src/modules/advanced/components/FiltersContainer/styles.css +++ b/src/modules/advanced/components/FiltersContainer/styles.css @@ -3,6 +3,15 @@ } .active-filter-list { - font-size: 0.9rem; - margin-left: 2.5rem; + flex: 1; + flex-wrap: wrap; + gap: 1rem; +} + +.active-filter-list > li { + max-width: calc(33.33% - 0.75rem); +} + +.active-filter-list > li > button { + text-align: left; } diff --git a/src/modules/filters/components/Filters/styles.css b/src/modules/filters/components/Filters/styles.css index bc142c33..b2e6082e 100644 --- a/src/modules/filters/components/Filters/styles.css +++ b/src/modules/filters/components/Filters/styles.css @@ -14,6 +14,7 @@ border: solid 1px var(--ds-color-green-200); border-radius: 4px; color: var(--ds-color-green-500); + cursor: pointer; display: flex; gap: 0.5rem; justify-content: space-between; From ad255ea84e82a2299ac73ea4f1f58991a0a3e5a4 Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Wed, 21 Aug 2024 13:51:24 -0400 Subject: [PATCH 04/17] Finessing styling. --- .../components/FiltersContainer/index.js | 4 ++-- .../components/FiltersContainer/styles.css | 24 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/modules/advanced/components/FiltersContainer/index.js b/src/modules/advanced/components/FiltersContainer/index.js index 87f952cb..45ff8777 100644 --- a/src/modules/advanced/components/FiltersContainer/index.js +++ b/src/modules/advanced/components/FiltersContainer/index.js @@ -70,7 +70,7 @@ const FilterList = ({ datastoreUid }) => { return (
      -
      +

      Active filters ({filterList.length})

      @@ -86,7 +86,7 @@ const FilterList = ({ datastoreUid }) => { )}
      -
        +
          {filterList.map(({ groupUid, name, value }) => { return (
        • diff --git a/src/modules/advanced/components/FiltersContainer/styles.css b/src/modules/advanced/components/FiltersContainer/styles.css index 7646d73d..f2e2325f 100644 --- a/src/modules/advanced/components/FiltersContainer/styles.css +++ b/src/modules/advanced/components/FiltersContainer/styles.css @@ -2,16 +2,32 @@ font-weight: 400; } -.active-filter-list { - flex: 1; +.active-filters-header { + align-items: flex-start; flex-wrap: wrap; +} + +.active-filter-list { + display: grid; gap: 1rem; + grid-template-columns: repeat(1, 1fr); } -.active-filter-list > li { - max-width: calc(33.33% - 0.75rem); +@media screen and (min-width: 640px) { + .active-filter-list { + grid-template-columns: repeat(2, 1fr); + } } +@media screen and (min-width: 820px) { + .active-filter-list { + grid-template-columns: repeat(3, 1fr); + } +} + + .active-filter-list > li > button { + height: 100%; text-align: left; + width: 100%; } From 0d83e44dbc4a5d66baa7858bc75f3596036f5e38 Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Wed, 21 Aug 2024 14:54:51 -0400 Subject: [PATCH 05/17] Separating `FilterList` into its own directory. --- .../advanced/components/FilterList/index.js | 113 ++++++++++++++++++ .../styles.css | 8 +- .../components/FiltersContainer/index.js | 107 +---------------- 3 files changed, 118 insertions(+), 110 deletions(-) create mode 100644 src/modules/advanced/components/FilterList/index.js rename src/modules/advanced/components/{FiltersContainer => FilterList}/styles.css (91%) diff --git a/src/modules/advanced/components/FilterList/index.js b/src/modules/advanced/components/FilterList/index.js new file mode 100644 index 00000000..ca6d4465 --- /dev/null +++ b/src/modules/advanced/components/FilterList/index.js @@ -0,0 +1,113 @@ +import './styles.css'; +import '../../../filters/components/Filters/styles.css'; +import { useDispatch, useSelector } from 'react-redux'; +import { Icon } from '../../../reusable'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { setAdvancedFilter } from '../../../advanced'; + +const FilterList = ({ datastoreUid }) => { + const dispatch = useDispatch(); + const { activeFilters = {}, filters: filterGroup } = useSelector((state) => { + return state.advanced[datastoreUid] || {}; + }); + + // Create filter list based on active filters + const filterList = Object.entries(activeFilters).reduce((acc, [groupUid, filters]) => { + if (filters) { + const groupName = filterGroup.find((group) => { + return group.uid === groupUid; + }); + filters.forEach((value) => { + acc.push({ + groupUid, + name: groupName?.groupBy || groupName?.name, + value + }); + }); + } + return acc; + }, []); + + const handleRemoveFilter = ({ groupUid, value }) => { + const baseFilter = { + datastoreUid, + filterGroupUid: groupUid, + filterValue: value, + onlyOneFilterValue: true + }; + const actions = []; + const createAction = (overrides = {}) => { + actions.push(setAdvancedFilter({ ...baseFilter, ...overrides })); + }; + + // Example logic for removing specific filters based on type and group + createAction(); + + // Dispatch all created actions + actions.forEach(dispatch); + }; + + const handleClearFilters = () => { + Object.keys(activeFilters).forEach((groupUid) => { + const filters = activeFilters[groupUid]; + filters.forEach(() => { + dispatch(setAdvancedFilter({ + datastoreUid, + filterGroupUid: groupUid, + filterValue: null, + onlyOneFilterValue: true + })); + }); + }); + }; + + if (filterList.length === 0) { + return null; + } + + return ( +
          +
          +

          + Active filters ({filterList.length}) +

          + {filterList.length > 1 && ( + + )} +
          +
            + {filterList.map(({ groupUid, name, value }) => { + return ( +
          • + +
          • + ); + })} +
          +
          + ); +}; + +FilterList.propTypes = { + datastoreUid: PropTypes.string +}; + +export default FilterList; diff --git a/src/modules/advanced/components/FiltersContainer/styles.css b/src/modules/advanced/components/FilterList/styles.css similarity index 91% rename from src/modules/advanced/components/FiltersContainer/styles.css rename to src/modules/advanced/components/FilterList/styles.css index f2e2325f..bb8e40fa 100644 --- a/src/modules/advanced/components/FiltersContainer/styles.css +++ b/src/modules/advanced/components/FilterList/styles.css @@ -1,12 +1,12 @@ -#active-filters > .text-grey__light { - font-weight: 400; -} - .active-filters-header { align-items: flex-start; flex-wrap: wrap; } +.active-filters-header > .text-grey__light { + font-weight: 400; +} + .active-filter-list { display: grid; gap: 1rem; diff --git a/src/modules/advanced/components/FiltersContainer/index.js b/src/modules/advanced/components/FiltersContainer/index.js index 45ff8777..5726cc03 100644 --- a/src/modules/advanced/components/FiltersContainer/index.js +++ b/src/modules/advanced/components/FiltersContainer/index.js @@ -1,117 +1,12 @@ -import './styles.css'; -import '../../../filters/components/Filters/styles.css'; import { useDispatch, useSelector } from 'react-redux'; import AdvancedFilter from '../AdvancedFilter'; +import FilterList from '../FilterList'; import getFilters from './getFilters'; import { Icon } from '../../../reusable'; import PropTypes from 'prop-types'; import React from 'react'; import { setAdvancedFilter } from '../../../advanced'; -const FilterList = ({ datastoreUid }) => { - const dispatch = useDispatch(); - const { activeFilters = {}, filters: filterGroup } = useSelector((state) => { - return state.advanced[datastoreUid] || {}; - }); - - // Create filter list based on active filters - const filterList = Object.entries(activeFilters).reduce((acc, [groupUid, filters]) => { - if (filters) { - const groupName = filterGroup.find((group) => { - return group.uid === groupUid; - }); - filters.forEach((value) => { - acc.push({ - groupUid, - name: groupName?.groupBy || groupName?.name, - value - }); - }); - } - return acc; - }, []); - - const handleRemoveFilter = ({ groupUid, value }) => { - const baseFilter = { - datastoreUid, - filterGroupUid: groupUid, - filterValue: value, - onlyOneFilterValue: true - }; - const actions = []; - const createAction = (overrides = {}) => { - actions.push(setAdvancedFilter({ ...baseFilter, ...overrides })); - }; - - // Example logic for removing specific filters based on type and group - createAction(); - - // Dispatch all created actions - actions.forEach(dispatch); - }; - - const handleClearFilters = () => { - Object.keys(activeFilters).forEach((groupUid) => { - const filters = activeFilters[groupUid]; - filters.forEach(() => { - dispatch(setAdvancedFilter({ - datastoreUid, - filterGroupUid: groupUid, - filterValue: null, - onlyOneFilterValue: true - })); - }); - }); - }; - - if (filterList.length === 0) { - return null; - } - - return ( -
          -
          -

          - Active filters ({filterList.length}) -

          - {filterList.length > 1 && ( - - )} -
          -
            - {filterList.map(({ groupUid, name, value }) => { - return ( -
          • - -
          • - ); - })} -
          -
          - ); -}; - -FilterList.propTypes = { - datastoreUid: PropTypes.string -}; - const FiltersContainer = ({ datastore }) => { const dispatch = useDispatch(); const filterGroups = useSelector((state) => { From d1ce71bf4139d839b4c1b09e231a08a13149f7c9 Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Thu, 22 Aug 2024 10:04:06 -0400 Subject: [PATCH 06/17] Adding logic for removing `multiple_select` types. --- .../advanced/components/FilterList/index.js | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/modules/advanced/components/FilterList/index.js b/src/modules/advanced/components/FilterList/index.js index ca6d4465..85e09da9 100644 --- a/src/modules/advanced/components/FilterList/index.js +++ b/src/modules/advanced/components/FilterList/index.js @@ -22,6 +22,7 @@ const FilterList = ({ datastoreUid }) => { acc.push({ groupUid, name: groupName?.groupBy || groupName?.name, + type: groupName?.type, value }); }); @@ -29,10 +30,11 @@ const FilterList = ({ datastoreUid }) => { return acc; }, []); - const handleRemoveFilter = ({ groupUid, value }) => { + const handleRemoveFilter = ({ groupUid, type, value }) => { const baseFilter = { datastoreUid, filterGroupUid: groupUid, + filterType: type, filterValue: value, onlyOneFilterValue: true }; @@ -41,10 +43,21 @@ const FilterList = ({ datastoreUid }) => { actions.push(setAdvancedFilter({ ...baseFilter, ...overrides })); }; - // Example logic for removing specific filters based on type and group - createAction(); + if (type === 'scope_down' && ['institution', 'location'].includes(groupUid) && value) { + createAction({ filterGroupUid: 'collection', filterValue: null }); + if (groupUid === 'institution') { + createAction({ filterGroupUid: 'location', filterValue: null }); + } + } + + if (['checkbox', 'date_range_input', 'scope_down'].includes(type)) { + createAction(); + } + + if (type === 'multiple_select') { + createAction({ onlyOneFilterValue: false }); + } - // Dispatch all created actions actions.forEach(dispatch); }; @@ -85,14 +98,14 @@ const FilterList = ({ datastoreUid }) => { )}
        - {filterList.map(({ groupUid, name, value }) => { + {filterList.map(({ groupUid, name, type, value }) => { return (
      • From 205623c3633db1216c84a184cf11b29857f92a32 Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Fri, 6 Sep 2024 15:36:42 -0400 Subject: [PATCH 08/17] Adding removal logic for `Narrow Search To` filters. --- .../advanced/components/FilterList/index.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/modules/advanced/components/FilterList/index.js b/src/modules/advanced/components/FilterList/index.js index 8dfcf1d1..d466a4a5 100644 --- a/src/modules/advanced/components/FilterList/index.js +++ b/src/modules/advanced/components/FilterList/index.js @@ -12,6 +12,8 @@ const FilterList = ({ datastoreUid }) => { return state.advanced[datastoreUid] || {}; }); + console.log(datastoreUid, activeFilters, filterGroup); + // Create filter list based on active filters const filterList = Object.entries(activeFilters).reduce((acc, [groupUid, filters]) => { if (filters) { @@ -39,7 +41,7 @@ const FilterList = ({ datastoreUid }) => { datastoreUid, filterGroupUid: groupUid, filterType: type, - filterValue: value, + filterValue: null, onlyOneFilterValue: true }; const actions = []; @@ -47,10 +49,15 @@ const FilterList = ({ datastoreUid }) => { actions.push(setAdvancedFilter({ ...baseFilter, ...overrides })); }; - if (type === 'scope_down' && ['institution', 'location'].includes(groupUid) && value) { - createAction({ filterGroupUid: 'collection', filterValue: null }); + console.log(groupUid); + + if (['institution', 'location', 'collection'].includes(groupUid) && value) { + createAction({ filterGroupUid: 'collection' }); + if (!['collection'].includes(groupUid)) { + createAction({ filterGroupUid: 'location' }); + } if (groupUid === 'institution') { - createAction({ filterGroupUid: 'location', filterValue: null }); + createAction({ filterGroupUid: 'institution' }); } } @@ -59,7 +66,7 @@ const FilterList = ({ datastoreUid }) => { } if (type === 'multiple_select') { - createAction({ onlyOneFilterValue: false }); + createAction({ filterValue: value, onlyOneFilterValue: false }); } actions.forEach(dispatch); From fa4c6f4d206bfd13d5416514af766d5e73ecc782 Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Mon, 9 Sep 2024 10:49:33 -0400 Subject: [PATCH 09/17] Adding group information for `Narrow Search To` filters. --- .../advanced/components/FilterList/index.js | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/modules/advanced/components/FilterList/index.js b/src/modules/advanced/components/FilterList/index.js index d466a4a5..d72d63a2 100644 --- a/src/modules/advanced/components/FilterList/index.js +++ b/src/modules/advanced/components/FilterList/index.js @@ -6,19 +6,37 @@ import PropTypes from 'prop-types'; import React from 'react'; import { setAdvancedFilter } from '../../../advanced'; +const narrowSearchTo = [ + { + groupBy: 'Library', + type: 'scope_down', + uid: 'institution' + }, + { + groupBy: 'Location', + type: 'scope_down', + uid: 'location' + }, + { + groupBy: 'Collection', + type: 'scope_down', + uid: 'collection' + } +]; + const FilterList = ({ datastoreUid }) => { const dispatch = useDispatch(); const { activeFilters = {}, filters: filterGroup } = useSelector((state) => { return state.advanced[datastoreUid] || {}; }); - console.log(datastoreUid, activeFilters, filterGroup); - // Create filter list based on active filters const filterList = Object.entries(activeFilters).reduce((acc, [groupUid, filters]) => { if (filters) { const groupName = filterGroup.find((group) => { return group.uid === groupUid; + }) || narrowSearchTo.find((group) => { + return group.uid === groupUid; }); // Only proceed if groupName type is not 'checkbox' From c9afaa3ca8c119ff5a7b519b38a99bfa75fb4515 Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Mon, 9 Sep 2024 14:57:31 -0400 Subject: [PATCH 10/17] Simplifying logic. --- .../advanced/components/FilterList/index.js | 54 +++++-------------- 1 file changed, 13 insertions(+), 41 deletions(-) diff --git a/src/modules/advanced/components/FilterList/index.js b/src/modules/advanced/components/FilterList/index.js index d72d63a2..f8abd7ef 100644 --- a/src/modules/advanced/components/FilterList/index.js +++ b/src/modules/advanced/components/FilterList/index.js @@ -6,48 +6,24 @@ import PropTypes from 'prop-types'; import React from 'react'; import { setAdvancedFilter } from '../../../advanced'; -const narrowSearchTo = [ - { - groupBy: 'Library', - type: 'scope_down', - uid: 'institution' - }, - { - groupBy: 'Location', - type: 'scope_down', - uid: 'location' - }, - { - groupBy: 'Collection', - type: 'scope_down', - uid: 'collection' - } -]; - const FilterList = ({ datastoreUid }) => { const dispatch = useDispatch(); const { activeFilters = {}, filters: filterGroup } = useSelector((state) => { return state.advanced[datastoreUid] || {}; }); - // Create filter list based on active filters const filterList = Object.entries(activeFilters).reduce((acc, [groupUid, filters]) => { if (filters) { - const groupName = filterGroup.find((group) => { - return group.uid === groupUid; - }) || narrowSearchTo.find((group) => { + const { + name = groupUid === 'institution' ? 'Library' : groupUid.charAt(0).toUpperCase() + groupUid.slice(1).replaceAll('_', ' '), + type = 'scope_down' + } = filterGroup.find((group) => { return group.uid === groupUid; - }); + }) || {}; - // Only proceed if groupName type is not 'checkbox' - if (groupName?.type !== 'checkbox') { + if (type !== 'checkbox') { filters.forEach((value) => { - acc.push({ - groupUid, - name: groupName?.groupBy || groupName?.name, - type: groupName?.type, - value - }); + acc.push({ groupUid, name, type, value }); }); } } @@ -67,19 +43,15 @@ const FilterList = ({ datastoreUid }) => { actions.push(setAdvancedFilter({ ...baseFilter, ...overrides })); }; - console.log(groupUid); - - if (['institution', 'location', 'collection'].includes(groupUid) && value) { + if (['institution', 'location'].includes(groupUid)) { createAction({ filterGroupUid: 'collection' }); - if (!['collection'].includes(groupUid)) { - createAction({ filterGroupUid: 'location' }); - } - if (groupUid === 'institution') { - createAction({ filterGroupUid: 'institution' }); - } } - if (['checkbox', 'date_range_input', 'scope_down'].includes(type)) { + if (groupUid === 'institution') { + createAction({ filterGroupUid: 'location' }); + } + + if (['date_range_input', 'scope_down'].includes(type)) { createAction(); } From 253dd9ba3e11b5138c117696bde27577672fe7a2 Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Mon, 9 Sep 2024 15:42:31 -0400 Subject: [PATCH 11/17] Simplifying logic. --- .../advanced/components/FilterList/index.js | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src/modules/advanced/components/FilterList/index.js b/src/modules/advanced/components/FilterList/index.js index f8abd7ef..aaf5775a 100644 --- a/src/modules/advanced/components/FilterList/index.js +++ b/src/modules/advanced/components/FilterList/index.js @@ -12,23 +12,19 @@ const FilterList = ({ datastoreUid }) => { return state.advanced[datastoreUid] || {}; }); - const filterList = Object.entries(activeFilters).reduce((acc, [groupUid, filters]) => { - if (filters) { - const { - name = groupUid === 'institution' ? 'Library' : groupUid.charAt(0).toUpperCase() + groupUid.slice(1).replaceAll('_', ' '), - type = 'scope_down' - } = filterGroup.find((group) => { - return group.uid === groupUid; - }) || {}; - - if (type !== 'checkbox') { - filters.forEach((value) => { - acc.push({ groupUid, name, type, value }); - }); - } - } - return acc; - }, []); + const filterList = Object.entries(activeFilters).flatMap(([groupUid, filters]) => { + const { + name = groupUid === 'institution' ? 'Library' : groupUid.charAt(0).toUpperCase() + groupUid.slice(1).replaceAll('_', ' '), + type = 'scope_down' + } = filterGroup.find((group) => { + return group.uid === groupUid; + }) || {}; + return type === 'checkbox' + ? [] + : filters.map((value) => { + return { groupUid, name, type, value }; + }); + }); const handleRemoveFilter = ({ groupUid, type, value }) => { const baseFilter = { @@ -38,9 +34,8 @@ const FilterList = ({ datastoreUid }) => { filterValue: null, onlyOneFilterValue: true }; - const actions = []; const createAction = (overrides = {}) => { - actions.push(setAdvancedFilter({ ...baseFilter, ...overrides })); + dispatch(setAdvancedFilter({ ...baseFilter, ...overrides })); }; if (['institution', 'location'].includes(groupUid)) { @@ -58,13 +53,10 @@ const FilterList = ({ datastoreUid }) => { if (type === 'multiple_select') { createAction({ filterValue: value, onlyOneFilterValue: false }); } - - actions.forEach(dispatch); }; const handleClearFilters = () => { - Object.keys(activeFilters).forEach((groupUid) => { - const filters = activeFilters[groupUid]; + Object.entries(activeFilters).forEach(([groupUid, filters]) => { filters.forEach(() => { dispatch(setAdvancedFilter({ datastoreUid, @@ -76,7 +68,7 @@ const FilterList = ({ datastoreUid }) => { }); }; - if (filterList.length === 0) { + if (!filterList.length) { return null; } From 52e0f1f5c6229cc17fedcf13f3f1615cf3ceb747 Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Tue, 10 Sep 2024 08:33:02 -0400 Subject: [PATCH 12/17] Simplifying logic. --- .../advanced/components/FilterList/index.js | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/modules/advanced/components/FilterList/index.js b/src/modules/advanced/components/FilterList/index.js index aaf5775a..c18a6b7c 100644 --- a/src/modules/advanced/components/FilterList/index.js +++ b/src/modules/advanced/components/FilterList/index.js @@ -27,15 +27,17 @@ const FilterList = ({ datastoreUid }) => { }); const handleRemoveFilter = ({ groupUid, type, value }) => { - const baseFilter = { - datastoreUid, - filterGroupUid: groupUid, - filterType: type, - filterValue: null, - onlyOneFilterValue: true - }; const createAction = (overrides = {}) => { - dispatch(setAdvancedFilter({ ...baseFilter, ...overrides })); + dispatch(setAdvancedFilter({ + ...{ + datastoreUid, + filterGroupUid: groupUid, + filterType: type, + filterValue: type === 'multiple_select' ? value : null, + onlyOneFilterValue: type !== 'multiple_select' + }, + ...overrides + })); }; if (['institution', 'location'].includes(groupUid)) { @@ -46,13 +48,7 @@ const FilterList = ({ datastoreUid }) => { createAction({ filterGroupUid: 'location' }); } - if (['date_range_input', 'scope_down'].includes(type)) { - createAction(); - } - - if (type === 'multiple_select') { - createAction({ filterValue: value, onlyOneFilterValue: false }); - } + createAction(); }; const handleClearFilters = () => { From 5db3737da7d07511ab69d360f5c9241486aeeb1e Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Tue, 10 Sep 2024 09:49:11 -0400 Subject: [PATCH 13/17] Linting. --- src/modules/advanced/components/FilterList/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/advanced/components/FilterList/index.js b/src/modules/advanced/components/FilterList/index.js index c18a6b7c..73cb4e30 100644 --- a/src/modules/advanced/components/FilterList/index.js +++ b/src/modules/advanced/components/FilterList/index.js @@ -33,7 +33,7 @@ const FilterList = ({ datastoreUid }) => { datastoreUid, filterGroupUid: groupUid, filterType: type, - filterValue: type === 'multiple_select' ? value : null, + filterValue: type === 'multiple_select' ? value : null, onlyOneFilterValue: type !== 'multiple_select' }, ...overrides From 6436147455a66f09dffffd1f08d6e4c46b65805c Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Wed, 11 Sep 2024 09:31:39 -0400 Subject: [PATCH 14/17] Simplifying logic and optimizing performance. --- .../components/NarrowSearchTo/index.js | 68 ++++++++----------- src/stylesheets/main.css | 8 --- 2 files changed, 29 insertions(+), 47 deletions(-) diff --git a/src/modules/advanced/components/NarrowSearchTo/index.js b/src/modules/advanced/components/NarrowSearchTo/index.js index 0a32bd28..fac82fb3 100644 --- a/src/modules/advanced/components/NarrowSearchTo/index.js +++ b/src/modules/advanced/components/NarrowSearchTo/index.js @@ -2,45 +2,35 @@ import PropTypes from 'prop-types'; import React from 'react'; const NarrowSearchTo = ({ handleChange, options }) => { - return ( - <> - {options.map((option) => { - const { activeFilter, filters, label } = option; - - if (filters.length <= 1) { - return null; - } - - const slug = `narrow-search-to-${label.toLowerCase().replaceAll(' ', '-')}`; - - return ( -
        - Narrow Search Options - - -
        - ); - })} - - ); + return options + .filter(({ filters }) => { + return filters.length > 1; + }) + .map(({ activeFilter, filters, label, uid }, index) => { + const slug = `narrow-search-to-${label.toLowerCase().replaceAll(' ', '-')}`; + return ( +
        0 ? 'margin-top__xs' : ''}`} key={slug}> + Narrow Search Options + + +
        + ); + }); }; NarrowSearchTo.propTypes = { diff --git a/src/stylesheets/main.css b/src/stylesheets/main.css index f0da8811..9a7553b4 100644 --- a/src/stylesheets/main.css +++ b/src/stylesheets/main.css @@ -1918,14 +1918,6 @@ body { width: 100%; } -.narrow-search-to-dropdown-container + .narrow-search-to-dropdown-container { - margin-top: 0.5rem; -} - -.narrow-search-to-dropdown { - width: 100%; -} - .advanced-fields-container { padding: 1.5rem; border-radius: 4px; From f4f4f374747252aac0e020e47d182964c46a4a21 Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Mon, 14 Oct 2024 11:26:23 -0400 Subject: [PATCH 15/17] Changing props to just `datastoreUid` to pass in a string and not an object. --- .../advanced/components/AdvancedSearchForm/index.js | 2 +- .../advanced/components/FiltersContainer/index.js | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/advanced/components/AdvancedSearchForm/index.js b/src/modules/advanced/components/AdvancedSearchForm/index.js index e2d1bec0..ca814d6a 100644 --- a/src/modules/advanced/components/AdvancedSearchForm/index.js +++ b/src/modules/advanced/components/AdvancedSearchForm/index.js @@ -158,7 +158,7 @@ const AdvancedSearchForm = ({ datastore }) => { Advanced Search - + ); }; diff --git a/src/modules/advanced/components/FiltersContainer/index.js b/src/modules/advanced/components/FiltersContainer/index.js index 5726cc03..da4d334a 100644 --- a/src/modules/advanced/components/FiltersContainer/index.js +++ b/src/modules/advanced/components/FiltersContainer/index.js @@ -7,19 +7,19 @@ import PropTypes from 'prop-types'; import React from 'react'; import { setAdvancedFilter } from '../../../advanced'; -const FiltersContainer = ({ datastore }) => { +const FiltersContainer = ({ datastoreUid }) => { const dispatch = useDispatch(); const filterGroups = useSelector((state) => { - return state.advanced[datastore.uid]?.filters; + return state.advanced[datastoreUid]?.filters; }); const activeFilters = useSelector((state) => { - return state.advanced[datastore.uid]?.activeFilters; + return state.advanced[datastoreUid]?.activeFilters; }); const filters = getFilters({ activeFilters, filterGroups }); const changeAdvancedFilter = ({ filterGroupUid, filterType, filterValue }) => { const baseFilter = { - datastoreUid: datastore.uid, + datastoreUid, filterGroupUid, filterType, filterValue, @@ -56,7 +56,7 @@ const FiltersContainer = ({ datastore }) => { return ( <> - +

        Additional search options

        {filterGroupings.map((filterGroup, groupIndex) => { @@ -107,7 +107,7 @@ const FiltersContainer = ({ datastore }) => { }; FiltersContainer.propTypes = { - datastore: PropTypes.object + datastoreUid: PropTypes.string }; export default FiltersContainer; From b74e284c830517c3f11fb9327ae28d98d43a314a Mon Sep 17 00:00:00 2001 From: "Erin E. Sullivan" Date: Tue, 15 Oct 2024 15:12:22 -0400 Subject: [PATCH 16/17] Resolving `useSelector` warning. Adding `booleanTypes` for `FieldInput`. --- .../components/AdvancedSearchForm/index.js | 24 +++++++++---------- .../advanced/components/FieldInput/index.js | 4 +++- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/modules/advanced/components/AdvancedSearchForm/index.js b/src/modules/advanced/components/AdvancedSearchForm/index.js index ca814d6a..7382ea46 100644 --- a/src/modules/advanced/components/AdvancedSearchForm/index.js +++ b/src/modules/advanced/components/AdvancedSearchForm/index.js @@ -18,27 +18,24 @@ const AdvancedSearchForm = ({ datastore }) => { const [errors, setErrors] = useState([]); const dispatch = useDispatch(); - const fields = useSelector((state) => { - return state.advanced[datastore.uid].fields; + const { activeFilters: advancedFilters = {}, fieldedSearches, fields } = useSelector((state) => { + return state.advanced[datastore.uid] || {}; }); - const booleanTypes = useSelector((state) => { - return state.advanced.booleanTypes; - }); - const fieldedSearches = useSelector((state) => { - return state.advanced[datastore.uid].fieldedSearches; + const { booleanTypes } = useSelector((state) => { + return state.advanced; }); const institution = useSelector((state) => { return state.institution; }); - const activeFilters = useSelector((state) => { - const currentFilters = state.advanced[datastore.uid].activeFilters || {}; + const activeFilters = () => { + const currentFilters = advancedFilters; Object.keys(currentFilters).forEach((filter) => { if (!currentFilters[filter]) { delete currentFilters[filter]; } }); return currentFilters; - }); + }; // Functions wrapped with useCallback to prevent unnecessary re-creation const changeFieldedSearch = useCallback(({ booleanType, fieldedSearchIndex, query, selectedFieldUid }) => { @@ -87,9 +84,9 @@ const AdvancedSearchForm = ({ datastore }) => { }, []) .join(' '); - if (query.length > 0 || (Object.keys(activeFilters).length > 0)) { + if (query.length > 0 || (Object.keys(activeFilters()).length > 0)) { const search = { - filter: { ...activeFilters }, + filter: { ...activeFilters() }, query }; @@ -110,7 +107,7 @@ const AdvancedSearchForm = ({ datastore }) => { ]); window.scrollTo(0, 0); } - }, [navigate, institution, booleanTypes, fieldedSearches, activeFilters, datastore]); + }, [navigate, institution, booleanTypes, fieldedSearches, activeFilters(), datastore]); return (
        @@ -132,6 +129,7 @@ const AdvancedSearchForm = ({ datastore }) => { return ( Boolean operator for field {fieldedSearchIndex} and field {fieldedSearchIndex + 1} - {['AND', 'OR', 'NOT'].map((option, index) => { + {booleanTypes.map((option, index) => { return (