pl-fe: migrate about page to tanstack query
Signed-off-by: mkljczk <git@mkljczk.pl>
This commit is contained in:
parent
9fa4509870
commit
32fed66477
5 changed files with 27 additions and 117 deletions
|
@ -1,44 +0,0 @@
|
||||||
// import MockAdapter from 'axios-mock-adapter';
|
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
|
||||||
|
|
||||||
// import { staticClient } from 'pl-fe/api';
|
|
||||||
import { mockStore } from 'pl-fe/jest/test-helpers';
|
|
||||||
|
|
||||||
import {
|
|
||||||
FETCH_ABOUT_PAGE_REQUEST,
|
|
||||||
// FETCH_ABOUT_PAGE_SUCCESS,
|
|
||||||
FETCH_ABOUT_PAGE_FAIL,
|
|
||||||
fetchAboutPage,
|
|
||||||
} from './about';
|
|
||||||
|
|
||||||
describe('fetchAboutPage()', () => {
|
|
||||||
// it('creates the expected actions on success', () => {
|
|
||||||
|
|
||||||
// const mock = new MockAdapter(staticClient);
|
|
||||||
|
|
||||||
// mock.onGet('/instance/about/index.html')
|
|
||||||
// .reply(200, '<h1>Hello world</h1>');
|
|
||||||
|
|
||||||
// const expectedActions = [
|
|
||||||
// { type: FETCH_ABOUT_PAGE_REQUEST, slug: 'index' },
|
|
||||||
// { type: FETCH_ABOUT_PAGE_SUCCESS, slug: 'index', html: '<h1>Hello world</h1>' },
|
|
||||||
// ];
|
|
||||||
// const store = mockStore(ImmutableMap());
|
|
||||||
|
|
||||||
// return store.dispatch(fetchAboutPage()).then(() => {
|
|
||||||
// expect(store.getActions()).toEqual(expectedActions);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
it('creates the expected actions on failure', () => {
|
|
||||||
const expectedActions = [
|
|
||||||
{ type: FETCH_ABOUT_PAGE_REQUEST, slug: 'asdf' },
|
|
||||||
{ type: FETCH_ABOUT_PAGE_FAIL, slug: 'asdf', error: new Error('Request failed with status code 404') },
|
|
||||||
];
|
|
||||||
const store = mockStore(ImmutableMap());
|
|
||||||
|
|
||||||
return store.dispatch(fetchAboutPage('asdf')).catch(() => {
|
|
||||||
expect(store.getActions()).toEqual(expectedActions);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,55 +0,0 @@
|
||||||
import { staticFetch } from '../api';
|
|
||||||
|
|
||||||
import type { AppDispatch, RootState } from 'pl-fe/store';
|
|
||||||
|
|
||||||
const FETCH_ABOUT_PAGE_REQUEST = 'FETCH_ABOUT_PAGE_REQUEST' as const;
|
|
||||||
const FETCH_ABOUT_PAGE_SUCCESS = 'FETCH_ABOUT_PAGE_SUCCESS' as const;
|
|
||||||
const FETCH_ABOUT_PAGE_FAIL = 'FETCH_ABOUT_PAGE_FAIL' as const;
|
|
||||||
|
|
||||||
interface FetchAboutPageRequestAction {
|
|
||||||
type: typeof FETCH_ABOUT_PAGE_REQUEST;
|
|
||||||
slug: string;
|
|
||||||
locale?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FetchAboutPageSuccessAction {
|
|
||||||
type: typeof FETCH_ABOUT_PAGE_SUCCESS;
|
|
||||||
slug: string;
|
|
||||||
locale?: string;
|
|
||||||
html: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FetchAboutPageFailAction {
|
|
||||||
type: typeof FETCH_ABOUT_PAGE_FAIL;
|
|
||||||
slug: string;
|
|
||||||
locale?: string;
|
|
||||||
error: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchAboutPage = (slug = 'index', locale?: string) => (dispatch: AppDispatch, getState: () => RootState) => {
|
|
||||||
dispatch({ type: FETCH_ABOUT_PAGE_REQUEST, slug, locale });
|
|
||||||
|
|
||||||
const filename = `${slug}${locale ? `.${locale}` : ''}.html`;
|
|
||||||
return staticFetch(`/instance/about/${filename}`)
|
|
||||||
.then(({ data: html }) => {
|
|
||||||
dispatch({ type: FETCH_ABOUT_PAGE_SUCCESS, slug, locale, html });
|
|
||||||
return html;
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
dispatch({ type: FETCH_ABOUT_PAGE_FAIL, slug, locale, error });
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
type AboutAction =
|
|
||||||
| FetchAboutPageRequestAction
|
|
||||||
| FetchAboutPageSuccessAction
|
|
||||||
| FetchAboutPageFailAction;
|
|
||||||
|
|
||||||
export {
|
|
||||||
fetchAboutPage,
|
|
||||||
FETCH_ABOUT_PAGE_REQUEST,
|
|
||||||
FETCH_ABOUT_PAGE_SUCCESS,
|
|
||||||
FETCH_ABOUT_PAGE_FAIL,
|
|
||||||
type AboutAction,
|
|
||||||
};
|
|
19
packages/pl-fe/src/api/hooks/pl-fe/use-about-page.ts
Normal file
19
packages/pl-fe/src/api/hooks/pl-fe/use-about-page.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
import { staticFetch } from 'pl-fe/api';
|
||||||
|
|
||||||
|
const fetchAboutPage = async (slug: string, locale?: string) => {
|
||||||
|
const filename = `${slug}${locale ? `.${locale}` : ''}.html`;
|
||||||
|
|
||||||
|
const { data } = await staticFetch(`/instance/about/${filename}`);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useAboutPage = (slug = 'index', locale?: string) =>
|
||||||
|
useQuery({
|
||||||
|
queryKey: ['pl-fe', 'aboutPages', slug, locale],
|
||||||
|
queryFn: () => fetchAboutPage(slug, locale),
|
||||||
|
});
|
||||||
|
|
||||||
|
export { useAboutPage };
|
|
@ -14,7 +14,7 @@ type PlfeResponse<T = any> = Response & { data: string; json: T };
|
||||||
* No authorization is needed.
|
* No authorization is needed.
|
||||||
*/
|
*/
|
||||||
const staticFetch = (input: URL | RequestInfo, init?: RequestInit | undefined) => {
|
const staticFetch = (input: URL | RequestInfo, init?: RequestInit | undefined) => {
|
||||||
const fullPath = buildFullPath(input.toString(), BuildConfig.FE_SUBDIRECTORY);
|
const fullPath = buildFullPath(input.toString(), BuildConfig.BACKEND_URL);
|
||||||
|
|
||||||
return fetch(fullPath, init).then(async (response) => {
|
return fetch(fullPath, init).then(async (response) => {
|
||||||
if (!response.ok) throw { response };
|
if (!response.ok) throw { response };
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { fetchAboutPage } from 'pl-fe/actions/about';
|
import { useAboutPage } from 'pl-fe/api/hooks/pl-fe/use-about-page';
|
||||||
import { Navlinks } from 'pl-fe/components/navlinks';
|
import { Navlinks } from 'pl-fe/components/navlinks';
|
||||||
import Card from 'pl-fe/components/ui/card';
|
import Card from 'pl-fe/components/ui/card';
|
||||||
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
|
|
||||||
import { usePlFeConfig } from 'pl-fe/hooks/use-pl-fe-config';
|
import { usePlFeConfig } from 'pl-fe/hooks/use-pl-fe-config';
|
||||||
import { useSettings } from 'pl-fe/hooks/use-settings';
|
import { useSettings } from 'pl-fe/hooks/use-settings';
|
||||||
|
|
||||||
|
@ -13,30 +12,21 @@ import { languages } from '../preferences';
|
||||||
|
|
||||||
/** Displays arbitrary user-uploaded HTML on a page at `/about/:slug` */
|
/** Displays arbitrary user-uploaded HTML on a page at `/about/:slug` */
|
||||||
const AboutPage: React.FC = () => {
|
const AboutPage: React.FC = () => {
|
||||||
const dispatch = useAppDispatch();
|
const { slug = 'index' } = useParams<{ slug?: string }>();
|
||||||
const { slug } = useParams<{ slug?: string }>();
|
|
||||||
|
|
||||||
const settings = useSettings();
|
const settings = useSettings();
|
||||||
const plFeConfig = usePlFeConfig();
|
const plFeConfig = usePlFeConfig();
|
||||||
|
|
||||||
const [pageHtml, setPageHtml] = useState<string>('');
|
|
||||||
const [locale, setLocale] = useState<string>(settings.locale);
|
const [locale, setLocale] = useState<string>(settings.locale);
|
||||||
|
|
||||||
const { aboutPages } = plFeConfig;
|
const { aboutPages } = plFeConfig;
|
||||||
|
|
||||||
const page = aboutPages[slug || 'about'];
|
const page = aboutPages[slug];
|
||||||
const defaultLocale = page?.defaultLocale;
|
const defaultLocale = page?.defaultLocale;
|
||||||
const pageLocales = page?.locales || [];
|
const pageLocales = page?.locales || [];
|
||||||
|
const fetchLocale = Boolean(page && locale !== defaultLocale && pageLocales.includes(locale));
|
||||||
|
|
||||||
useEffect(() => {
|
const { data: pageHtml } = useAboutPage(slug, fetchLocale ? locale : undefined);
|
||||||
const fetchLocale = Boolean(page && locale !== defaultLocale && pageLocales.includes(locale));
|
|
||||||
dispatch(fetchAboutPage(slug, fetchLocale ? locale : undefined)).then(html => {
|
|
||||||
setPageHtml(html);
|
|
||||||
}).catch(error => {
|
|
||||||
// TODO: Better error handling. 404 page?
|
|
||||||
setPageHtml('<h1>Page not found</h1>');
|
|
||||||
});
|
|
||||||
}, [locale, slug]);
|
|
||||||
|
|
||||||
const alsoAvailable = (defaultLocale) && (
|
const alsoAvailable = (defaultLocale) && (
|
||||||
<div>
|
<div>
|
||||||
|
@ -67,7 +57,7 @@ const AboutPage: React.FC = () => {
|
||||||
<div>
|
<div>
|
||||||
<Card variant='rounded'>
|
<Card variant='rounded'>
|
||||||
<div className='prose mx-auto py-4 dark:prose-invert sm:p-6'>
|
<div className='prose mx-auto py-4 dark:prose-invert sm:p-6'>
|
||||||
<div dangerouslySetInnerHTML={{ __html: pageHtml }} />
|
{pageHtml && <div dangerouslySetInnerHTML={{ __html: pageHtml }} />}
|
||||||
{alsoAvailable}
|
{alsoAvailable}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
Loading…
Reference in a new issue