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.
|
||||
*/
|
||||
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) => {
|
||||
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 { 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 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 { 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` */
|
||||
const AboutPage: React.FC = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { slug } = useParams<{ slug?: string }>();
|
||||
const { slug = 'index' } = useParams<{ slug?: string }>();
|
||||
|
||||
const settings = useSettings();
|
||||
const plFeConfig = usePlFeConfig();
|
||||
|
||||
const [pageHtml, setPageHtml] = useState<string>('');
|
||||
const [locale, setLocale] = useState<string>(settings.locale);
|
||||
|
||||
const { aboutPages } = plFeConfig;
|
||||
|
||||
const page = aboutPages[slug || 'about'];
|
||||
const page = aboutPages[slug];
|
||||
const defaultLocale = page?.defaultLocale;
|
||||
const pageLocales = page?.locales || [];
|
||||
const fetchLocale = Boolean(page && locale !== defaultLocale && pageLocales.includes(locale));
|
||||
|
||||
useEffect(() => {
|
||||
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 { data: pageHtml } = useAboutPage(slug, fetchLocale ? locale : undefined);
|
||||
|
||||
const alsoAvailable = (defaultLocale) && (
|
||||
<div>
|
||||
|
@ -67,7 +57,7 @@ const AboutPage: React.FC = () => {
|
|||
<div>
|
||||
<Card variant='rounded'>
|
||||
<div className='prose mx-auto py-4 dark:prose-invert sm:p-6'>
|
||||
<div dangerouslySetInnerHTML={{ __html: pageHtml }} />
|
||||
{pageHtml && <div dangerouslySetInnerHTML={{ __html: pageHtml }} />}
|
||||
{alsoAvailable}
|
||||
</div>
|
||||
</Card>
|
||||
|
|
Loading…
Reference in a new issue