pl-fe: migrate backups to tanstack query

Signed-off-by: mkljczk <git@mkljczk.pl>
This commit is contained in:
mkljczk 2024-12-05 11:34:58 +01:00
parent 15d7d4dfc3
commit 29cd637a6b
10 changed files with 42 additions and 129 deletions

View file

@ -256,7 +256,7 @@ interface PlApiClientConstructorOpts {
/**
* @category Clients
*
*
* Mastodon API client.
*/
class PlApiClient {

View file

@ -8,7 +8,7 @@ import { datetimeSchema, mimeSchema } from './utils';
*/
const backupSchema = v.object({
id: v.pipe(v.unknown(), v.transform(String)),
contentType: mimeSchema,
content_type: mimeSchema,
file_size: v.fallback(v.number(), 0),
inserted_at: datetimeSchema,
processed: v.fallback(v.boolean(), false),

View file

@ -1,6 +1,6 @@
{
"name": "pl-api",
"version": "1.0.0-rc.3",
"version": "1.0.0-rc.4",
"type": "module",
"homepage": "https://github.com/mkljczk/pl-fe/tree/develop/packages/pl-api",
"repository": {

View file

@ -101,7 +101,7 @@
"multiselect-react-dropdown": "^2.0.25",
"mutative": "^1.1.0",
"path-browserify": "^1.0.1",
"pl-api": "^1.0.0-rc.3",
"pl-api": "^1.0.0-rc.4",
"postcss": "^8.4.47",
"process": "^0.11.10",
"punycode": "^2.1.1",

View file

@ -1,81 +0,0 @@
import { getClient } from '../api';
import type { Backup } from 'pl-api';
import type { AppDispatch, RootState } from 'pl-fe/store';
const BACKUPS_FETCH_REQUEST = 'BACKUPS_FETCH_REQUEST' as const;
const BACKUPS_FETCH_SUCCESS = 'BACKUPS_FETCH_SUCCESS' as const;
const BACKUPS_FETCH_FAIL = 'BACKUPS_FETCH_FAIL' as const;
const BACKUPS_CREATE_REQUEST = 'BACKUPS_CREATE_REQUEST' as const;
const BACKUPS_CREATE_SUCCESS = 'BACKUPS_CREATE_SUCCESS' as const;
const BACKUPS_CREATE_FAIL = 'BACKUPS_CREATE_FAIL' as const;
interface BackupsFetchRequestAction {
type: typeof BACKUPS_FETCH_REQUEST;
}
interface BackupsFetchSuccessAction {
type: typeof BACKUPS_FETCH_SUCCESS;
backups: Array<Backup>;
}
interface BackupsFetchFailAction {
type: typeof BACKUPS_FETCH_FAIL;
error: unknown;
}
const fetchBackups = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch<BackupsFetchRequestAction>({ type: BACKUPS_FETCH_REQUEST });
return getClient(getState).settings.getBackups().then((backups) =>
dispatch<BackupsFetchSuccessAction>({ type: BACKUPS_FETCH_SUCCESS, backups }),
).catch(error => {
dispatch<BackupsFetchFailAction>({ type: BACKUPS_FETCH_FAIL, error });
});
};
interface BackupsCreateRequestAction {
type: typeof BACKUPS_CREATE_REQUEST;
}
interface BackupsCreateSuccessAction {
type: typeof BACKUPS_CREATE_SUCCESS;
backups: Array<Backup>;
}
interface BackupsCreateFailAction {
type: typeof BACKUPS_CREATE_FAIL;
error: unknown;
}
const createBackup = () =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch<BackupsCreateRequestAction>({ type: BACKUPS_CREATE_REQUEST });
return getClient(getState).settings.createBackup().then((backup) =>
dispatch<BackupsCreateSuccessAction>({ type: BACKUPS_CREATE_SUCCESS, backups: [backup] }),
).catch(error => {
dispatch<BackupsCreateFailAction>({ type: BACKUPS_CREATE_FAIL, error });
});
};
type BackupsAction =
| BackupsFetchRequestAction
| BackupsFetchSuccessAction
| BackupsFetchFailAction
| BackupsCreateRequestAction
| BackupsCreateSuccessAction
| BackupsCreateFailAction;
export {
BACKUPS_FETCH_REQUEST,
BACKUPS_FETCH_SUCCESS,
BACKUPS_FETCH_FAIL,
BACKUPS_CREATE_REQUEST,
BACKUPS_CREATE_SUCCESS,
BACKUPS_CREATE_FAIL,
fetchBackups,
createBackup,
type BackupsAction,
};

View file

@ -1,7 +1,6 @@
import React, { useEffect, useState } from 'react';
import React from 'react';
import { FormattedDate, defineMessages, useIntl } from 'react-intl';
import { fetchBackups, createBackup } from 'pl-fe/actions/backups';
import Button from 'pl-fe/components/ui/button';
import Card from 'pl-fe/components/ui/card';
import Column from 'pl-fe/components/ui/column';
@ -10,8 +9,7 @@ import HStack from 'pl-fe/components/ui/hstack';
import Spinner from 'pl-fe/components/ui/spinner';
import Stack from 'pl-fe/components/ui/stack';
import Text from 'pl-fe/components/ui/text';
import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch';
import { useAppSelector } from 'pl-fe/hooks/use-app-selector';
import { useBackupsQuery, useCreateBackupMutation } from 'pl-fe/queries/settings/use-backups';
import type { Backup as BackupEntity } from 'pl-api';
@ -63,23 +61,15 @@ const Backup: React.FC<IBackup> = ({ backup }) => {
const Backups = () => {
const intl = useIntl();
const dispatch = useAppDispatch();
const backups = useAppSelector((state) => Object.values(state.backups).toSorted((a, b) => a.inserted_at.localeCompare(b.inserted_at)));
const [isLoading, setIsLoading] = useState(true);
const { data: backups = [], isLoading } = useBackupsQuery();
const { mutate: createBackup } = useCreateBackupMutation();
const handleCreateBackup: React.MouseEventHandler = e => {
dispatch(createBackup());
createBackup();
e.preventDefault();
};
useEffect(() => {
dispatch(fetchBackups()).then(() => {
setIsLoading(false);
}).catch(() => {});
}, []);
const showLoading = isLoading && backups.length === 0;
const emptyMessage = (

View file

@ -0,0 +1,29 @@
import { useMutation, useQuery } from '@tanstack/react-query';
import { useClient } from 'pl-fe/hooks/use-client';
import { queryClient } from '../client';
const useBackupsQuery = () => {
const client = useClient();
return useQuery({
queryKey: ['settings', 'backups'],
queryFn: () => client.settings.getBackups(),
select: (backups) => backups.toSorted((a, b) => a.inserted_at.localeCompare(b.inserted_at)),
});
};
const useCreateBackupMutation = () => {
const client = useClient();
return useMutation({
mutationKey: ['settings', 'backups'],
mutationFn: () => client.settings.createBackup(),
onSuccess: () => queryClient.invalidateQueries({
queryKey: ['settings', 'backups'],
}),
});
};
export { useBackupsQuery, useCreateBackupMutation };

View file

@ -1,23 +0,0 @@
import { create } from 'mutative';
import { BACKUPS_FETCH_SUCCESS, BACKUPS_CREATE_SUCCESS, type BackupsAction } from '../actions/backups';
import type { Backup } from 'pl-api';
type State = Record<string, Backup>;
const initialState: State = {};
const backups = (state = initialState, action: BackupsAction) => {
switch (action.type) {
case BACKUPS_FETCH_SUCCESS:
case BACKUPS_CREATE_SUCCESS:
return create(state, (draft) => action.backups.forEach((backup) => draft[backup.inserted_at] = backup));
default:
return state;
}
};
export {
backups as default,
};

View file

@ -9,7 +9,6 @@ import admin from './admin';
import admin_user_index from './admin-user-index';
import aliases from './aliases';
import auth from './auth';
import backups from './backups';
import compose from './compose';
import contexts from './contexts';
import conversations from './conversations';
@ -43,7 +42,6 @@ const reducers = {
admin_user_index,
aliases,
auth,
backups,
compose,
contexts,
conversations,

View file

@ -7834,10 +7834,10 @@ pkg-dir@^4.1.0:
dependencies:
find-up "^4.0.0"
pl-api@^1.0.0-rc.3:
version "1.0.0-rc.3"
resolved "https://registry.yarnpkg.com/pl-api/-/pl-api-1.0.0-rc.3.tgz#36a3f093bd2935e4b59a2efaa225a5baa4af5dea"
integrity sha512-ILNesTpz+Y+4S/65S2KX597YBXxEmYuuxKGkzX56cny8tBReiw4ar07H6ZrjEBog8Ramq6N6IaRch5Dt9ZPE3A==
pl-api@^1.0.0-rc.4:
version "1.0.0-rc.4"
resolved "https://registry.yarnpkg.com/pl-api/-/pl-api-1.0.0-rc.4.tgz#6119fdef8362104ba238a0e33620d35982b91be6"
integrity sha512-TsORtRUV41NAp4McbYrhcw4pCAiiM99q+gGJpPoPOnyw/5G69JQ1lBCcDFYQzsbgvuQ4yseM5kZolNO6sTxRGg==
dependencies:
blurhash "^2.0.5"
http-link-header "^1.1.3"