Skip to content

Commit

Permalink
Merge pull request #1036: Finish adding types to ListResources
Browse files Browse the repository at this point in the history
  • Loading branch information
victorlin authored Oct 3, 2024
2 parents be2b044 + fb2fb81 commit c8560cf
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 23 deletions.
13 changes: 8 additions & 5 deletions static-site/src/components/ListResources/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { ErrorContainer } from "../../pages/404";
import { TooltipWrapper } from "./IndividualResource";
import {ResourceModal, SetModalResourceContext} from "./Modal";
import { ExpandableTiles } from "../ExpandableTiles";
import { ShowcaseTile, FilterOption, Group, QuickLink, Resource, ResourceListingInfo } from './types';
import { ShowcaseTile, FilterOption, Group, QuickLink, Resource, ResourceListingInfo, SortMethod } from './types';
import { HugeSpacer } from "../../layouts/generalComponents";

interface ListResourcesProps extends ListResourcesResponsiveProps {
Expand Down Expand Up @@ -49,9 +49,9 @@ function ListResources({
);
const showcaseTiles = useShowcaseTiles(showcase, groups);
const [selectedFilterOptions, setSelectedFilterOptions] = useState<readonly FilterOption[]>([]);
const [sortMethod, changeSortMethod] = useState("alphabetical");
const [sortMethod, changeSortMethod] = useState<SortMethod>("alphabetical");
const [resourceGroups, setResourceGroups] = useState<Group[]>([]);
useSortAndFilter(sortMethod, selectedFilterOptions, groups, setResourceGroups)
useSortAndFilter(sortMethod, selectedFilterOptions, setResourceGroups, groups)
const availableFilterOptions = useFilterOptions(resourceGroups);
const [modalResource, setModalResource ] = useState<Resource>();

Expand Down Expand Up @@ -171,9 +171,12 @@ function ListResourcesResponsive(props: ListResourcesResponsiveProps) {
export default ListResourcesResponsive


function SortOptions({sortMethod, changeSortMethod}) {
function SortOptions({sortMethod, changeSortMethod}: {
sortMethod: SortMethod,
changeSortMethod: React.Dispatch<React.SetStateAction<SortMethod>>
}) {
function onChangeValue(event:FormEvent<HTMLInputElement>): void {
changeSortMethod(event.currentTarget.value);
changeSortMethod(event.currentTarget.value as SortMethod);
}
return (
<SortContainer>
Expand Down
2 changes: 2 additions & 0 deletions static-site/src/components/ListResources/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export interface FilterOption {
label: string
}

export type SortMethod = "lastUpdated" | "alphabetical";

export interface Group {
groupName: string
nResources: number
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useMemo, useState } from 'react';
import { FilterOption, Group } from './types';

/**
* React hook which recomputes the available search/filtering options (i.e.
Expand All @@ -11,12 +12,12 @@ import { useMemo, useState } from 'react';
* filter) but we don't include the count in the label because the React select
* component doesn't update already-set options and thus we get out-of-sync.
*/
export function useFilterOptions(resourceGroups) {
const [state, setState] = useState([]);
export function useFilterOptions(resourceGroups: Group[]): FilterOption[] {
const [state, setState] = useState<FilterOption[]>([]);

useMemo(() => {
const counts = {};
const increment = (key) => {
const counts: { [key: string]: number } = {};
const increment = (key: string) => {
if (!counts[key]) counts[key] = 0;
counts[key]++
}
Expand All @@ -40,7 +41,7 @@ export function useFilterOptions(resourceGroups) {
return state
}

export function createFilterOption(word) {
export function createFilterOption(word: string): FilterOption {
return {value: word, label: word};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,42 @@
import { useMemo } from 'react';
import { FilterOption, Group, Resource, SortMethod } from './types';


export const useSortAndFilter = (sortMethod, selectedFilterOptions, originalData, setState) => {
export const useSortAndFilter = (
sortMethod: SortMethod,
selectedFilterOptions: readonly FilterOption[],
setState: React.Dispatch<React.SetStateAction<Group[]>>,
originalData?: Group[],
) => {
useMemo(() => {
if (!originalData) return;
/* Following console log is really useful for development */
// console.log(`useSortAndFilter() sortMethod "${sortMethod}" ` + (selectedFilterOptions.length ? `filtering to ${selectedFilterOptions.map((el) => el.value).join(", ")}` : '(no filtering)'))

let _sortGroups, _sortResources;
let _sortGroups: (groupA: Group, groupB: Group) => 1 | -1 | 0,
_sortResources: (a: Resource, b: Resource) => 1 | -1 | 0;
switch (sortMethod) {
case "lastUpdated":
_sortGroups = (groupA, groupB) => _newestFirstSort(groupA.lastUpdated, groupB.lastUpdated);
_sortResources = (a, b) => a.lastUpdated === b.lastUpdated ?
_lexicographicSort(a.name, b.name) : // resources updated on the same day sort alphabetically
_newestFirstSort(a.lastUpdated, b.lastUpdated); // newest updated resources first
_sortGroups = (groupA: Group, groupB: Group) => _newestFirstSort(groupA.lastUpdated, groupB.lastUpdated);
_sortResources = (a: Resource, b: Resource) => {
if (!a.lastUpdated || !b.lastUpdated || a.lastUpdated === b.lastUpdated) {
// resources updated on the same day or without a last updated date
// sort alphabetically
return _lexicographicSort(a.name, b.name)
}
else {
return _newestFirstSort(a.lastUpdated, b.lastUpdated);
}
}
break;
case "alphabetical":
_sortGroups = (groupA, groupB) => _lexicographicSort(groupA.groupName.toLowerCase(), groupB.groupName.toLowerCase()),
_sortResources = (a, b) => _lexicographicSort(a.name, b.name)
_sortGroups = (groupA: Group, groupB: Group) => _lexicographicSort(groupA.groupName.toLowerCase(), groupB.groupName.toLowerCase()),
_sortResources = (a: Resource, b: Resource) => _lexicographicSort(a.name, b.name)
break;
default:
throw new Error(`Unknown sorting method "${sortMethod}"`)
}

const searchValues = selectedFilterOptions.map((o) => o.value);
function _filterResources(resource) {
function _filterResources(resource: Resource) {
if (searchValues.length===0) return true;
return searchValues
.map((searchString) => resource.nameParts.includes(searchString))
Expand All @@ -49,13 +61,13 @@ export const useSortAndFilter = (sortMethod, selectedFilterOptions, originalData
/* helper function to sort alphabetically. If provided with YYYY-MM-DD strings
* this is the same as a chronological sort (oldest to newest)
*/
function _lexicographicSort(a,b) {
function _lexicographicSort(a: string, b: string): 1 | -1 | 0 {
return a<b ? -1 : a>b ? 1 : 0;
}

/* If provided with YYYY-MM-DD strings this sorts chronologically with newest
* first (this is just reverse lexicographic sort)
*/
function _newestFirstSort(a,b) {
function _newestFirstSort(a: string, b: string): 1 | -1 | 0 {
return a<b ? 1 : a>b ? -1 : 0;
}

0 comments on commit c8560cf

Please sign in to comment.