Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/op 81/query param filters #357

Merged
merged 12 commits into from
Oct 27, 2023
7 changes: 4 additions & 3 deletions pwa/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pwa/src/components/breadcrumbs/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import _ from "lodash";
import { Container } from "@conduction/components";
import { isHomepage } from "../../services/isHomepage";
import { BreadcrumbNav, BreadcrumbNavLink, BreadcrumbNavSeparator, Icon } from "@utrecht/component-library-react";
import { GatsbyContext } from "../../context/gatsby";
import { useGatsbyContext } from "../../context/gatsby";
import { navigate } from "gatsby";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronRight } from "@fortawesome/free-solid-svg-icons";
Expand All @@ -18,7 +18,7 @@ export const Breadcrumbs: React.FC = () => {
breadcrumb: { crumbs },
},
location: { pathname },
} = React.useContext(GatsbyContext);
} = useGatsbyContext();

const translatedCrumbs = crumbs.map((crumb: any) => ({ ...crumb, crumbLabel: t(_.upperFirst(crumb.crumbLabel)) }));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react";
import * as styles from "./ResultsDisplaySwitch.module.css";
import { Button, ButtonGroup } from "@utrecht/component-library-react/dist/css-module";
import { useTranslation } from "react-i18next";
import { FiltersContext } from "../../context/filters";
import { useFiltersContext } from "../../context/filters";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCircleNodes, faGripVertical, faLayerGroup, faTable } from "@fortawesome/free-solid-svg-icons";
import clsx from "clsx";
Expand All @@ -26,7 +26,7 @@ interface ResultsDisplaySwitchProps {

const ResultsDisplaySwitch: React.FC<ResultsDisplaySwitchProps> = ({ layoutClassName, resultsDisplayType }) => {
const { t } = useTranslation();
const [filters, setFilters] = React.useContext(FiltersContext);
const { filters, setFilters } = useFiltersContext();

const acceptedFilters: AcceptedFilters = {
resultDisplayLayout: ["table", "cards", "layer"],
Expand Down
21 changes: 15 additions & 6 deletions pwa/src/context/filters.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import * as React from "react";
import { GlobalContext } from "./global";

export type TComponentResultsLayout = "table" | "cards" | "layer";
export type TComponentDependenciesLayout = "layer" | "relations";
export type TLandingDisplayLayout = "layer" | "cards";
export type TCatagoryDisplayLayout = "table" | "cards" | "layer";
export type TOrganizationsResultDisplayLayout = "table" | "cards";

export interface IFilters {
export interface IFiltersContext {
resultDisplayLayout: TComponentResultsLayout;
dependenciesDisplayLayout: TComponentDependenciesLayout;
landingDisplayLayout: TLandingDisplayLayout;
Expand All @@ -29,7 +30,7 @@ export interface IFilters {
"embedded.nl.embedded.gemma.bedrijfsfuncties"?: string[];
"embedded.nl.embedded.gemma.bedrijfsservices"?: string[];
"embedded.nl.embedded.gemma.referentieComponenten"?: string[];
"embedded.nl.embedded.gemma.applicatiefunctie": string;
"embedded.nl.embedded.gemma.applicatiefunctie"?: string;
"embedded.nl.embedded.upl"?: string[];
"embedded.maintenance.type"?: string;
"embedded.legal.license"?: string;
Expand All @@ -40,7 +41,7 @@ export interface IFilters {
showMoreSupport?: boolean;
}

export const baseFilters = {
export const defaultFiltersContext: IFiltersContext = {
resultDisplayLayout: "table",
dependenciesDisplayLayout: "layer",
landingDisplayLayout: "cards",
Expand All @@ -53,8 +54,16 @@ export const baseFilters = {
organizationSearch: "",
developmentStatusObsolete: true,
isBasedOn: true,
} as IFilters;
};

export const FiltersContext = React.createContext<[IFilters, (_: IFilters) => void]>([baseFilters, () => null]);
export const useFiltersContext = () => {
const [globalContext, setGlobalContext] = React.useContext(GlobalContext);

export const FiltersProvider = FiltersContext.Provider;
const filters: IFiltersContext = globalContext.filters;

const setFilters = (newFilters: IFiltersContext) => {
setGlobalContext((oldGlobalContext) => ({ ...oldGlobalContext, filters: newFilters }));
};

return { filters, setFilters };
};
13 changes: 10 additions & 3 deletions pwa/src/context/gatsby.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from "react";
import { GlobalContext } from "./global";

export type TScreenSize = "mobile" | "tablet" | "desktop";

Expand All @@ -8,10 +9,16 @@ export interface IGatsbyContext {
screenSize: TScreenSize;
}

export const GatsbyContext = React.createContext<IGatsbyContext>({
export const defaultGatsbyContext: IGatsbyContext = {
pageContext: null,
location: null,
screenSize: "mobile",
});
};

export const GatsbyProvider = GatsbyContext.Provider;
export const useGatsbyContext = () => {
const [globalContext] = React.useContext(GlobalContext);

const gatsbyContext: IGatsbyContext = globalContext.gatsby;

return gatsbyContext;
};
21 changes: 21 additions & 0 deletions pwa/src/context/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from "react";
import { defaultGatsbyContext, IGatsbyContext } from "./gatsby";
import { defaultFiltersContext, IFiltersContext } from "./filters";

export interface IGlobalContext {
initiated: boolean;
gatsby: IGatsbyContext;
filters: IFiltersContext;
}

export const defaultGlobalContext: IGlobalContext = {
initiated: false,
gatsby: defaultGatsbyContext,
filters: defaultFiltersContext,
};

export const GlobalContext = React.createContext<
[IGlobalContext, React.Dispatch<React.SetStateAction<IGlobalContext>>]
>([defaultGlobalContext, () => null]);

export const GlobalProvider = GlobalContext.Provider;
4 changes: 2 additions & 2 deletions pwa/src/hooks/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import * as React from "react";
import { QueryClient, useQuery } from "react-query";
import APIService from "../apiService/apiService";
import APIContext from "../apiService/apiContext";
import { IFilters } from "../context/filters";
import { IFiltersContext } from "../context/filters";

export const useApplications = (queryClient: QueryClient) => {
const API: APIService | null = React.useContext(APIContext);

const getAll = (filters: IFilters) =>
const getAll = (filters: IFiltersContext) =>
useQuery<any, Error>(["applications", filters], () => API?.Applications.getAll(filters), {
onError: (error) => {
throw new Error(error.message);
Expand Down
81 changes: 32 additions & 49 deletions pwa/src/layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import * as React from "react";
import "../styling/index.css";
import * as styles from "./Layout.module.css";

import "../styling/index.css";
import "./../translations/i18n";

import { GlobalProvider, IGlobalContext, defaultGlobalContext } from "../context/global";
import APIContext, { APIProvider } from "../apiService/apiContext";
import APIService from "../apiService/apiService";
import { GatsbyProvider, IGatsbyContext, TScreenSize } from "../context/gatsby";
import { TScreenSize } from "../context/gatsby";
import { HeaderTemplate } from "../templates/templateParts/header/HeaderTemplate";
import { FooterTemplate } from "../templates/templateParts/footer/FooterTemplate";
import { FiltersProvider, IFilters, baseFilters as _filters } from "../context/filters";
import { useTranslation } from "react-i18next";
import _ from "lodash";
import { Head } from "./Head";
import { getScreenSize } from "../services/getScreenSize";
import Favicon from "react-favicon";
Expand All @@ -27,29 +27,15 @@ interface LayoutProps {
}

const Layout: React.FC<LayoutProps> = ({ children, pageContext, location }) => {
const [filters, setFilters] = React.useState<IFilters>(_filters);
const [globalContext, setGlobalContext] = React.useState<IGlobalContext>(defaultGlobalContext);
const [API, setAPI] = React.useState<APIService | null>(React.useContext(APIContext));
const [, setBreadcrumbs] = React.useState<any>(null);
const [screenSize, setScreenSize] = React.useState<TScreenSize>("mobile");
const [gatsbyContext, setGatsbyContext] = React.useState<IGatsbyContext>({
...{ pageContext, location, screenSize: "mobile" },
});

const { t } = useTranslation();

React.useEffect(() => {
// initiate API Service
setAPI(new APIService());
}, []);

React.useEffect(() => {
setGatsbyContext({ ...{ pageContext, location, screenSize: getScreenSize(window.innerWidth) } });

const JWT = sessionStorage.getItem("JWT");

API && !API.authenticated && JWT && API.setAuthentication(JWT);
}, [pageContext, location, screenSize]);

React.useEffect(() => {
// initiate screen size watcher
const handleWindowResize = () => {
setScreenSize(getScreenSize(window.innerWidth));
};
Expand All @@ -60,47 +46,44 @@ const Layout: React.FC<LayoutProps> = ({ children, pageContext, location }) => {
}, []);

React.useEffect(() => {
if (!gatsbyContext) return;
// keep track of authentication
const JWT = sessionStorage.getItem("JWT");

const {
pageContext: {
breadcrumb: { crumbs },
},
} = gatsbyContext;
API && !API.authenticated && JWT && API.setAuthentication(JWT);

setBreadcrumbs(
crumbs.map((crumb: any) => ({
...crumb,
crumbLabel: t(_.upperFirst(crumb.crumbLabel)),
})),
);
}, [gatsbyContext]);
// keep track of gatsby context
setGlobalContext((context) => ({
...context,
initiated: true,
gatsby: {
...{ pageContext, location, screenSize: getScreenSize(window.innerWidth) },
},
}));
}, [pageContext, location, screenSize]);

if (!API) return <></>;
if (!globalContext.initiated) return <></>;

return (
<>
<Head />

<GatsbyProvider value={gatsbyContext}>
<GlobalProvider value={[globalContext, setGlobalContext]}>
<APIProvider value={API}>
<FiltersProvider value={[filters, setFilters]}>
<Surface>
<Document>
<ToolTip id={TOOLTIP_ID} />
<Surface>
<Document>
<ToolTip id={TOOLTIP_ID} />

<Favicon url={Logo} />
<Favicon url={Logo} />

<HeaderTemplate layoutClassName={styles.header} />
<HeaderTemplate layoutClassName={styles.header} />

<div className={styles.pageContent}>{children}</div>
<div className={styles.pageContent}>{children}</div>

<FooterTemplate layoutClassName={styles.footer} />
</Document>
</Surface>
</FiltersProvider>
<FooterTemplate layoutClassName={styles.footer} />
</Document>
</Surface>
</APIProvider>
</GatsbyProvider>
</GlobalProvider>
</>
);
};
Expand Down
4 changes: 2 additions & 2 deletions pwa/src/pages/github/[md].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import * as React from "react";
import qs from "qs";
import { PageProps } from "gatsby";
import { MarkdownContentTemplate } from "../../templates/markdown/MarkdownContentTemplate";
import { GatsbyContext } from "../../context/gatsby";
import { useGatsbyContext } from "../../context/gatsby";
import { useTranslation } from "react-i18next";

const MarkdownPage: React.FC<PageProps> = (props: PageProps) => {
const { t } = useTranslation();
const { location } = React.useContext(GatsbyContext);
const { location } = useGatsbyContext();

const url = location.search;
const [, params] = url.split("?");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react";
import * as styles from "./ApplicationsTemplate.module.css";
import { Heading, Paragraph, Icon, Link } from "@utrecht/component-library-react/dist/css-module";
import { Container, Pagination } from "@conduction/components";
import { FiltersContext } from "../../context/filters";
import { useFiltersContext } from "../../context/filters";
import { useTranslation } from "react-i18next";
import { ApplicationCard } from "../../components/applicationCard/ApplicationCard";
import { QueryClient } from "react-query";
Expand All @@ -11,7 +11,7 @@ import Skeleton from "react-loading-skeleton";
import { IconExternalLink } from "@tabler/icons-react";

export const ApplicationsTemplate: React.FC = () => {
const [filters, setFilters] = React.useContext(FiltersContext);
const { filters, setFilters } = useFiltersContext();
const { t } = useTranslation();

const queryClient = new QueryClient();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import Skeleton from "react-loading-skeleton";
import { TEMPORARY_DOMAINS } from "../../data/domains";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faGripVertical, faLayerGroup, faTable, faTags } from "@fortawesome/free-solid-svg-icons";
import { FiltersContext } from "../../context/filters";
import { useFiltersContext } from "../../context/filters";
import { ComponentResultTemplate } from "../templateParts/resultsTemplates/ComponentResultsTemplate";
import { ExpandableLeadParagraph } from "../../components/expandableLeadParagraph/ExpandableLeadParagraph";
import { navigate } from "gatsby-link";
Expand All @@ -27,7 +27,7 @@ interface CategoryDetailTemplateProps {
}

export const CategoryDetailTemplate: React.FC<CategoryDetailTemplateProps> = ({ categoryId }) => {
const [filters, setFilters] = React.useContext(FiltersContext);
const { filters, setFilters } = useFiltersContext();
const { t } = useTranslation();

const portfolio = TEMPORARY_PORTFOLIOS.find((category) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { categories, TCategories } from "../../data/categories";
import { OrganizationCard } from "../../components/organizationCard/OrganizationCard";
import { GitHubLogo } from "../../assets/svgs/GitHub";
import { DependenciesTemplate } from "../templateParts/dependenciesTemplates/ComponentDependenciesTemplate";
import { FiltersContext } from "../../context/filters";
import { useFiltersContext } from "../../context/filters";
import { ComponentCardsAccordionTemplate } from "../templateParts/componentCardsAccordion/ComponentCardsAccordionTemplate";
import { DownloadTemplate } from "../templateParts/download/DownloadTemplate";
import { RatingOverview } from "../templateParts/ratingOverview/RatingOverview";
Expand All @@ -52,7 +52,7 @@ interface ComponentsDetailTemplateProps {

export const ComponentsDetailTemplate: React.FC<ComponentsDetailTemplateProps> = ({ componentId, sizeKb }) => {
const { t } = useTranslation();
const [filters] = React.useContext(FiltersContext);
const { filters } = useFiltersContext();

const NotificationPopUpController = _NotificationPopUp.controller;
const NotificationPopUp = _NotificationPopUp.NotificationPopUp;
Expand Down
4 changes: 2 additions & 2 deletions pwa/src/templates/components/ComponentsTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from "react";
import * as styles from "./ComponentsTemplate.module.css";
import { Container, Pagination } from "@conduction/components";
import { ComponentResultTemplate } from "../templateParts/resultsTemplates/ComponentResultsTemplate";
import { FiltersContext } from "../../context/filters";
import { useFiltersContext } from "../../context/filters";
import { useTranslation } from "react-i18next";
import { QueryClient } from "react-query";
import { VerticalFiltersTemplate } from "../templateParts/filters/verticalFilters/VerticalFiltersTemplate";
Expand All @@ -16,7 +16,7 @@ import { Alert, Heading, Icon, Paragraph } from "@utrecht/component-library-reac
import { IconInfoCircle } from "@tabler/icons-react";

export const ComponentsTemplate: React.FC = () => {
const [filters, setFilters] = React.useContext(FiltersContext);
const { filters, setFilters } = useFiltersContext();
const { t } = useTranslation();

const queryClient = new QueryClient();
Expand Down
Loading
Loading