@civicactions/cmsds-open-data-components 4.0.19-alpha.2 → 4.0.19-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -1426,8 +1426,6 @@ async function $eff7d34c30f5a0fc$export$2d2256cb46e92ff7(rootUrl, options, ACA)
1426
1426
 
1427
1427
 
1428
1428
  const $e873081a6e8f024e$export$1040147c129fdde9 = (query)=>{
1429
- // Only allow letters, numbers, spaces, and empty string
1430
- // A search containing any special character will be rejected
1431
1429
  return /^[a-zA-Z0-9 ]*$/.test(query.trim());
1432
1430
  };
1433
1431
  const $e873081a6e8f024e$var$DatasetSearch = (props)=>{
@@ -1454,101 +1452,87 @@ const $e873081a6e8f024e$var$DatasetSearch = (props)=>{
1454
1452
  value: 'titleZA'
1455
1453
  }
1456
1454
  ];
1457
- const defaultSortBy = "";
1458
- const defaultFulltext = "";
1459
- const defaultSelectedFacets = {
1460
- theme: [],
1461
- keyword: []
1462
- };
1463
- const defaultSortOrder = "";
1464
- const defaultPage = 1;
1465
1455
  const location = (0, $hgUW1$useLocation)();
1466
- const transformedParams = (0, $eff7d34c30f5a0fc$export$60ec7cc1d341a524)(location.search, defaultSort);
1467
- const [currentResultNumbers, setCurrentResultNumbers] = (0, $hgUW1$useState)({
1468
- total: 0,
1469
- startingNumber: 0,
1470
- endingNumber: 0
1471
- });
1472
- const [noResults, setNoResults] = (0, $hgUW1$useState)(false);
1473
- const [announcementText, setAnnouncementText] = (0, $hgUW1$useState)('');
1474
- let [searchParams, setSearchParams] = (0, $hgUW1$useSearchParams)();
1475
- const [fulltext, setFullText] = (0, $hgUW1$useState)(transformedParams.fulltext);
1476
- const [filterText, setFilterText] = (0, $hgUW1$useState)(transformedParams.fulltext);
1477
- const [totalItems, setTotalItems] = (0, $hgUW1$useState)(0);
1478
- const [page, setPage] = (0, $hgUW1$useState)(transformedParams.page ? transformedParams.page : defaultPage);
1479
- const [sort, setSort] = (0, $hgUW1$useState)(transformedParams.sort ? transformedParams.sort : defaultSort ? defaultSort.defaultSort : defaultSortBy);
1480
- const [sortOrder, setSortOrder] = (0, $hgUW1$useState)(transformedParams.sortOrder ? transformedParams.sortOrder : defaultSort ? defaultSort.defaultOrder : defaultSortOrder);
1481
- const [sortDisplay, setSortDisplay] = (0, $hgUW1$useState)(()=>{
1482
- return sort === 'modified' ? sortOrder === 'desc' ? 'newest' : 'oldest' : sortOrder === 'desc' ? 'titleZA' : 'titleAZ';
1483
- });
1484
- const [selectedFacets, setSelectedFacets] = (0, $hgUW1$useState)(transformedParams.selectedFacets ? transformedParams.selectedFacets : {
1485
- theme: [],
1486
- keyword: []
1487
- });
1456
+ const [searchParams, setSearchParams] = (0, $hgUW1$useSearchParams)();
1457
+ // Derive all search state from URL params
1458
+ const selectedFacets = (0, $hgUW1$useMemo)(()=>({
1459
+ theme: searchParams.getAll('theme'),
1460
+ keyword: searchParams.getAll('keyword')
1461
+ }), [
1462
+ searchParams
1463
+ ]);
1464
+ const page = Number(searchParams.get('page')) || 1;
1465
+ const sort = searchParams.get('sort') || defaultSort.defaultSort;
1466
+ const sortOrder = searchParams.get('sortOrder') || defaultSort.defaultOrder;
1467
+ const fulltext = searchParams.get('fulltext') || '';
1468
+ const sortDisplay = sort === 'modified' ? sortOrder === 'desc' ? 'newest' : 'oldest' : sortOrder === 'desc' ? 'titleZA' : 'titleAZ';
1469
+ // Local UI state only
1470
+ const [filterText, setFilterText] = (0, $hgUW1$useState)(fulltext);
1488
1471
  const [invalidSearch, setInvalidSearch] = (0, $hgUW1$useState)(false);
1489
- const setSortOptions = (value)=>{
1490
- setSortDisplay(value);
1472
+ // Sync filterText from URL on back/forward
1473
+ (0, $hgUW1$useEffect)(()=>{
1474
+ setFilterText(fulltext);
1475
+ }, [
1476
+ fulltext
1477
+ ]);
1478
+ function buildNextParams(overrides) {
1479
+ const next = new URLSearchParams(searchParams);
1480
+ Object.entries(overrides).forEach(([key, value])=>{
1481
+ next.delete(key);
1482
+ if (value === null) return;
1483
+ const values = Array.isArray(value) ? value : [
1484
+ value
1485
+ ];
1486
+ values.forEach((v)=>next.append(key, v));
1487
+ });
1488
+ return next;
1489
+ }
1490
+ function updateSelectedFacets(key, value) {
1491
+ const current = searchParams.getAll(key);
1492
+ const idx = current.indexOf(value);
1493
+ const updated = idx > -1 ? current.filter((_, i)=>i !== idx) : [
1494
+ ...current,
1495
+ value
1496
+ ];
1497
+ setSearchParams(buildNextParams({
1498
+ [key]: updated.length ? updated : null,
1499
+ page: null
1500
+ }));
1501
+ }
1502
+ const setSortOptionsHandler = (value)=>{
1503
+ let nextSort;
1504
+ let nextSortOrder;
1491
1505
  switch(value){
1492
1506
  case 'newest':
1493
- setSort('modified');
1494
- setSortOrder('desc');
1507
+ nextSort = 'modified';
1508
+ nextSortOrder = 'desc';
1495
1509
  break;
1496
1510
  case 'oldest':
1497
- setSort('modified');
1498
- setSortOrder('asc');
1511
+ nextSort = 'modified';
1512
+ nextSortOrder = 'asc';
1499
1513
  break;
1500
1514
  case 'titleAZ':
1501
- setSort('title');
1502
- setSortOrder('asc');
1515
+ nextSort = 'title';
1516
+ nextSortOrder = 'asc';
1503
1517
  break;
1504
1518
  case 'titleZA':
1505
- setSort('title');
1506
- setSortOrder('desc');
1519
+ nextSort = 'title';
1520
+ nextSortOrder = 'desc';
1507
1521
  break;
1522
+ default:
1523
+ return;
1508
1524
  }
1509
- };
1510
- function updateSelectedFacets(key, value) {
1511
- const newFacets = {
1512
- theme: [
1513
- ...selectedFacets.theme
1514
- ],
1515
- keyword: [
1516
- ...selectedFacets.keyword
1517
- ]
1525
+ const overrides = {
1526
+ sort: nextSort === defaultSort.defaultSort ? null : nextSort,
1527
+ sortOrder: nextSortOrder === defaultSort.defaultOrder ? null : nextSortOrder
1518
1528
  };
1519
- if (key === 'theme') {
1520
- const existingFacet = newFacets.theme.findIndex((s)=>s === value);
1521
- if (existingFacet > -1) newFacets.theme.splice(existingFacet, 1);
1522
- else newFacets.theme.push(value);
1523
- }
1524
- if (key === 'keyword') {
1525
- const existingFacet = newFacets.keyword.findIndex((s)=>s === value);
1526
- if (existingFacet > -1) newFacets.keyword.splice(existingFacet, 1);
1527
- else newFacets.keyword.push(value);
1528
- }
1529
- setSelectedFacets(newFacets);
1530
- }
1531
- const pageSize = defaultPageSize;
1529
+ setSearchParams(buildNextParams(overrides));
1530
+ };
1532
1531
  function resetFilters() {
1533
- setFullText(defaultFulltext);
1534
- setFilterText(defaultFulltext);
1535
- setSelectedFacets(defaultSelectedFacets);
1536
- setPage(defaultPage);
1537
- }
1538
- function buildSearchParams(includePage) {
1539
- let newParams = {};
1540
- if (Number(page) !== 1 && includePage) newParams.page = page;
1541
- if (sort !== defaultSort.defaultSort) newParams.sort = sort;
1542
- if (sortOrder !== defaultSort.defaultOrder) newParams.sortOrder = sortOrder;
1543
- if (fulltext !== '') newParams.fulltext = fulltext;
1544
- Object.keys(selectedFacets).forEach((key)=>{
1545
- if (selectedFacets[key].length) newParams[key] = selectedFacets[key];
1546
- });
1547
- return (0, $hgUW1$qs).stringify(newParams, {
1548
- addQueryPrefix: includePage,
1549
- encode: true
1550
- });
1532
+ setFilterText('');
1533
+ setSearchParams({});
1551
1534
  }
1535
+ const pageSize = defaultPageSize;
1552
1536
  let params = {
1553
1537
  fulltext: fulltext ? fulltext : undefined,
1554
1538
  ...selectedFacets,
@@ -1569,54 +1553,30 @@ const $e873081a6e8f024e$var$DatasetSearch = (props)=>{
1569
1553
  })}`);
1570
1554
  }
1571
1555
  });
1572
- // Sync totalItems state with API response data
1573
- // Moved to useEffect to prevent state updates during render (which can cause infinite loops)
1574
- (0, $hgUW1$useEffect)(()=>{
1575
- if (data?.data?.total !== undefined && data.data.total !== totalItems) setTotalItems(data.data.total);
1576
- }, [
1577
- data?.data?.total
1578
- ]);
1556
+ const totalItems = data?.data?.total ? Number(data.data.total) : 0;
1579
1557
  const facets = data && data.data.facets ? (0, $eff7d34c30f5a0fc$export$959638e8dca60ce6)(data ? data.data.facets : []) : {
1580
1558
  theme: null,
1581
1559
  keyword: null
1582
1560
  };
1583
- (0, $hgUW1$useEffect)(()=>{
1584
- const baseNumber = Number(totalItems) > 0 ? 1 : 0;
1585
- const startingNumber = baseNumber + (Number(pageSize) * Number(page) - Number(pageSize));
1586
- const endingNumber = Number(pageSize) * Number(page);
1587
- setCurrentResultNumbers({
1588
- total: Number(totalItems),
1589
- startingNumber: Number(totalItems) >= startingNumber ? startingNumber : 0,
1590
- endingNumber: Number(totalItems) < endingNumber ? Number(totalItems) : endingNumber
1591
- });
1592
- if (totalItems <= 0 && currentResultNumbers !== null) setNoResults(true);
1593
- else setNoResults(false);
1561
+ const currentResultNumbers = (0, $hgUW1$useMemo)(()=>{
1562
+ const baseNumber = totalItems > 0 ? 1 : 0;
1563
+ const startingNumber = baseNumber + (pageSize * page - pageSize);
1564
+ const endingNumber = pageSize * page;
1565
+ return {
1566
+ total: totalItems,
1567
+ startingNumber: totalItems >= startingNumber ? startingNumber : 0,
1568
+ endingNumber: totalItems < endingNumber ? totalItems : endingNumber
1569
+ };
1594
1570
  }, [
1595
1571
  totalItems,
1596
1572
  pageSize,
1597
1573
  page
1598
1574
  ]);
1599
- (0, $hgUW1$useEffect)(()=>{
1600
- if (page !== 1 && (transformedParams.fulltext !== fulltext || transformedParams.selectedFacets !== selectedFacets)) setPage(1);
1601
- }, [
1602
- fulltext,
1603
- selectedFacets
1604
- ]);
1605
- (0, $hgUW1$useEffect)(()=>{
1606
- var params = buildSearchParams(true);
1607
- if (params !== location.search) setSearchParams(params);
1608
- }, [
1609
- page,
1610
- sort,
1611
- sortOrder,
1612
- fulltext,
1613
- selectedFacets
1614
- ]);
1615
- (0, $hgUW1$useEffect)(()=>{
1616
- // No results found
1617
- if (noResults) setAnnouncementText('No results found.');
1618
- else if (!isPending && (!data || !data.data.results)) setAnnouncementText('Could not connect to the API.');
1619
- else setAnnouncementText(`Showing ${currentResultNumbers.startingNumber} to ${currentResultNumbers.endingNumber} of ${currentResultNumbers.total} datasets`);
1575
+ const noResults = totalItems <= 0 && !isPending;
1576
+ const announcementText = (0, $hgUW1$useMemo)(()=>{
1577
+ if (noResults) return 'No results found.';
1578
+ if (!isPending && (!data || !data.data.results)) return 'Could not connect to the API.';
1579
+ return `Showing ${currentResultNumbers.startingNumber} to ${currentResultNumbers.endingNumber} of ${currentResultNumbers.total} datasets`;
1620
1580
  }, [
1621
1581
  data,
1622
1582
  isPending,
@@ -1667,7 +1627,10 @@ const $e873081a6e8f024e$var$DatasetSearch = (props)=>{
1667
1627
  if (filterText) {
1668
1628
  if ($e873081a6e8f024e$export$1040147c129fdde9(filterText)) {
1669
1629
  setInvalidSearch(false);
1670
- setFullText(filterText);
1630
+ setSearchParams(buildNextParams({
1631
+ fulltext: filterText,
1632
+ page: null
1633
+ }));
1671
1634
  } else setInvalidSearch(true);
1672
1635
  }
1673
1636
  },
@@ -1761,7 +1724,7 @@ const $e873081a6e8f024e$var$DatasetSearch = (props)=>{
1761
1724
  label: "Sort",
1762
1725
  labelClassName: "ds-u-margin-top--0",
1763
1726
  name: "dataset_search_sort",
1764
- onChange: (e)=>setSortOptions(e.target.value)
1727
+ onChange: (e)=>setSortOptionsHandler(e.target.value)
1765
1728
  })
1766
1729
  })
1767
1730
  ]
@@ -1794,7 +1757,6 @@ const $e873081a6e8f024e$var$DatasetSearch = (props)=>{
1794
1757
  };
1795
1758
  let topicProps = {};
1796
1759
  if (showTopics) {
1797
- // Generate topic slugs mapping for this item's themes
1798
1760
  let topicSlugs = {};
1799
1761
  if (item.theme && Array.isArray(item.theme)) item.theme.forEach((topic)=>{
1800
1762
  if (topic) topicSlugs[topic] = topicSlugFunction ? topicSlugFunction(topic) : topic.split(' ').join('-').toLowerCase();
@@ -1832,12 +1794,15 @@ const $e873081a6e8f024e$var$DatasetSearch = (props)=>{
1832
1794
  onPageChange: (evt, page)=>{
1833
1795
  evt.preventDefault();
1834
1796
  window.scroll(0, 0);
1835
- setPage(page);
1797
+ setSearchParams(buildNextParams({
1798
+ page: page > 1 ? String(page) : null
1799
+ }));
1836
1800
  },
1837
- renderHref: (page)=>{
1838
- const searchParams = buildSearchParams(false);
1839
- const includeAnd = searchParams ? '&' : '';
1840
- return `/datasets?page=${page}${includeAnd}${searchParams}`;
1801
+ renderHref: (p)=>{
1802
+ const next = buildNextParams({
1803
+ page: p > 1 ? String(p) : null
1804
+ });
1805
+ return `/datasets?${next.toString()}`;
1841
1806
  }
1842
1807
  })
1843
1808
  ]