Add backup flags to backup import

This commit is contained in:
schroda
2025-10-04 21:48:44 +02:00
parent faa53b049f
commit f0c6e789cd
8 changed files with 41 additions and 26 deletions

View File

@@ -1260,7 +1260,7 @@
"settings": "Settings" "settings": "Settings"
}, },
"history": "History", "history": "History",
"manga": "Manga", "manga": "Library entries",
"server_settings": "Server settings", "server_settings": "Server settings",
"tracking": "Tracking" "tracking": "Tracking"
}, },

View File

@@ -10,6 +10,7 @@ import { BackupFlag, BackupFlagGroup } from '@/features/backup/Backup.types.ts';
import { TranslationKey } from '@/base/Base.types.ts'; import { TranslationKey } from '@/base/Base.types.ts';
export const BACKUP_FLAGS_TO_TRANSLATION: Record<BackupFlag, TranslationKey> = { export const BACKUP_FLAGS_TO_TRANSLATION: Record<BackupFlag, TranslationKey> = {
includeManga: 'settings.backup.flag.manga',
includeCategories: 'settings.backup.flag.categories', includeCategories: 'settings.backup.flag.categories',
includeChapters: 'settings.backup.flag.chapters', includeChapters: 'settings.backup.flag.chapters',
includeClientData: 'settings.backup.flag.client_data', includeClientData: 'settings.backup.flag.client_data',
@@ -26,6 +27,6 @@ export const BACKUP_FLAG_GROUP_TO_TRANSLATION: Record<BackupFlagGroup, Translati
export const BACKUP_FLAGS = Object.keys(BACKUP_FLAGS_TO_TRANSLATION) as readonly BackupFlag[]; export const BACKUP_FLAGS = Object.keys(BACKUP_FLAGS_TO_TRANSLATION) as readonly BackupFlag[];
export const BACKUP_FLAGS_BY_GROUP: Record<BackupFlagGroup, BackupFlag[]> = { export const BACKUP_FLAGS_BY_GROUP: Record<BackupFlagGroup, BackupFlag[]> = {
[BackupFlagGroup.LIBRARY]: ['includeChapters', 'includeTracking', 'includeHistory', 'includeCategories'], [BackupFlagGroup.LIBRARY]: ['includeManga', 'includeChapters', 'includeTracking', 'includeHistory', 'includeCategories'],
[BackupFlagGroup.SETTINGS]: ['includeClientData', 'includeServerSettings'], [BackupFlagGroup.SETTINGS]: ['includeClientData', 'includeServerSettings'],
}; };

View File

@@ -6,13 +6,13 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
import { CreateBackupInput } from '@/lib/graphql/generated/graphql.ts'; import { PartialBackupFlagsInput } from '@/lib/graphql/generated/graphql.ts';
export enum BackupFlagGroup { export enum BackupFlagGroup {
LIBRARY = 'library', LIBRARY = 'library',
SETTINGS = 'settings', SETTINGS = 'settings',
} }
export type BackupFlag = keyof Omit<CreateBackupInput, 'clientMutationId'>; export type BackupFlag = keyof PartialBackupFlagsInput;
export type BackupFlagInclusionState = Record<BackupFlag, boolean>; export type BackupFlagInclusionState = Record<BackupFlag, boolean>;

View File

@@ -26,7 +26,11 @@ import {
} from '@/features/backup/Backup.constants.ts'; } from '@/features/backup/Backup.constants.ts';
import { BackupFlagGroup, BackupFlagInclusionState } from '@/features/backup/Backup.types.ts'; import { BackupFlagGroup, BackupFlagInclusionState } from '@/features/backup/Backup.types.ts';
export const BackupFlagInclusionDialog = ({ onCancel, onConfirm }: DialogProps<BackupFlagInclusionState>) => { export const BackupFlagInclusionDialog = ({
onCancel,
onConfirm,
title,
}: DialogProps<BackupFlagInclusionState> & { title: string }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [includeStateByFlag, setIncludeStateByFlag] = useState( const [includeStateByFlag, setIncludeStateByFlag] = useState(
@@ -34,12 +38,12 @@ export const BackupFlagInclusionDialog = ({ onCancel, onConfirm }: DialogProps<B
); );
return ( return (
<Dialog open onAbort={onCancel} maxWidth="xs" fullWidth> <Dialog open onAbort={onCancel} maxWidth="xs" fullWidth onClose={onCancel}>
<DialogTitle>{t('settings.backup.action.create.label.title')}</DialogTitle> <DialogTitle>{title}</DialogTitle>
<DialogContent> <DialogContent>
<FormGroup sx={{ gap: 2 }}> <FormGroup sx={{ gap: 2 }}>
{Object.entries(BACKUP_FLAGS_BY_GROUP).map(([group, flags]) => ( {Object.entries(BACKUP_FLAGS_BY_GROUP).map(([group, flags]) => (
<Stack> <Stack key={group}>
<Typography>{t(BACKUP_FLAG_GROUP_TO_TRANSLATION[group as BackupFlagGroup])}</Typography> <Typography>{t(BACKUP_FLAG_GROUP_TO_TRANSLATION[group as BackupFlagGroup])}</Typography>
{flags.map((flag) => ( {flags.map((flag) => (
<CheckboxInput <CheckboxInput

View File

@@ -117,12 +117,14 @@ export function Backup() {
}; };
const createBackup = async () => { const createBackup = async () => {
const backupFlagInclusionState = await GlobalDialogManager.show(BackupFlagInclusionDialog); const flags = await GlobalDialogManager.show(BackupFlagInclusionDialog, {
title: t('settings.backup.action.create.label.title'),
});
makeToast(t('settings.backup.action.create.label.in_progress'), 'info'); makeToast(t('settings.backup.action.create.label.in_progress'), 'info');
try { try {
const backupFileResponse = await requestManager.createBackupFile(backupFlagInclusionState).response; const backupFileResponse = await requestManager.createBackupFile({ flags }).response;
const backupFileUrl = backupFileResponse.data?.createBackup.url; const backupFileUrl = backupFileResponse.data?.createBackup.url;
if (!backupFileUrl) { if (!backupFileUrl) {
@@ -171,11 +173,15 @@ export function Backup() {
return false; return false;
}; };
const restoreBackup = async (file: File) => { const restoreBackup = async (backup: File) => {
const flags = await GlobalDialogManager.show(BackupFlagInclusionDialog, {
title: t('settings.backup.action.restore.label.title'),
});
try { try {
makeToast(t('settings.backup.action.restore.label.in_progress'), 'info'); makeToast(t('settings.backup.action.restore.label.in_progress'), 'info');
const response = await requestManager.restoreBackupFile(file).response; const response = await requestManager.restoreBackupFile({ backup, flags }).response;
backupRestoreId = response.data?.restoreBackup.id; backupRestoreId = response.data?.restoreBackup.id;
setTriggerReRender(Date.now()); setTriggerReRender(Date.now());
} catch (e) { } catch (e) {

View File

@@ -336,12 +336,7 @@ export type ConnectKoSyncAccountInput = {
export type CreateBackupInput = { export type CreateBackupInput = {
clientMutationId?: InputMaybe<Scalars['String']['input']>; clientMutationId?: InputMaybe<Scalars['String']['input']>;
includeCategories?: InputMaybe<Scalars['Boolean']['input']>; flags?: InputMaybe<PartialBackupFlagsInput>;
includeChapters?: InputMaybe<Scalars['Boolean']['input']>;
includeClientData?: InputMaybe<Scalars['Boolean']['input']>;
includeHistory?: InputMaybe<Scalars['Boolean']['input']>;
includeServerSettings?: InputMaybe<Scalars['Boolean']['input']>;
includeTracking?: InputMaybe<Scalars['Boolean']['input']>;
}; };
export type CreateBackupPayload = { export type CreateBackupPayload = {
@@ -1646,6 +1641,16 @@ export type PageInfo = {
startCursor?: Maybe<Scalars['Cursor']['output']>; startCursor?: Maybe<Scalars['Cursor']['output']>;
}; };
export type PartialBackupFlagsInput = {
includeCategories?: InputMaybe<Scalars['Boolean']['input']>;
includeChapters?: InputMaybe<Scalars['Boolean']['input']>;
includeClientData?: InputMaybe<Scalars['Boolean']['input']>;
includeHistory?: InputMaybe<Scalars['Boolean']['input']>;
includeManga?: InputMaybe<Scalars['Boolean']['input']>;
includeServerSettings?: InputMaybe<Scalars['Boolean']['input']>;
includeTracking?: InputMaybe<Scalars['Boolean']['input']>;
};
export type PartialSettingsType = Settings & { export type PartialSettingsType = Settings & {
__typename?: 'PartialSettingsType'; __typename?: 'PartialSettingsType';
authMode?: Maybe<AuthMode>; authMode?: Maybe<AuthMode>;
@@ -2066,6 +2071,7 @@ export type ResetSettingsPayload = {
export type RestoreBackupInput = { export type RestoreBackupInput = {
backup: Scalars['Upload']['input']; backup: Scalars['Upload']['input'];
clientMutationId?: InputMaybe<Scalars['String']['input']>; clientMutationId?: InputMaybe<Scalars['String']['input']>;
flags?: InputMaybe<PartialBackupFlagsInput>;
}; };
export type RestoreBackupPayload = { export type RestoreBackupPayload = {
@@ -3266,6 +3272,7 @@ export type CreateBackupMutation = { __typename?: 'Mutation', createBackup: { __
export type RestoreBackupMutationVariables = Exact<{ export type RestoreBackupMutationVariables = Exact<{
backup: Scalars['Upload']['input']; backup: Scalars['Upload']['input'];
flags?: InputMaybe<PartialBackupFlagsInput>;
}>; }>;

View File

@@ -17,8 +17,8 @@ export const CREATE_BACKUP = gql`
`; `;
export const RESTORE_BACKUP = gql` export const RESTORE_BACKUP = gql`
mutation RESTORE_BACKUP($backup: Upload!) { mutation RESTORE_BACKUP($backup: Upload!, $flags: PartialBackupFlagsInput) {
restoreBackup(input: { backup: $backup }) { restoreBackup(input: { backup: $backup, flags: $flags }) {
id id
status { status {
mangaProgress mangaProgress

View File

@@ -219,6 +219,7 @@ import {
CreateBackupInput, CreateBackupInput,
CreateBackupMutation, CreateBackupMutation,
CreateBackupMutationVariables, CreateBackupMutationVariables,
RestoreBackupInput,
} from '@/lib/graphql/generated/graphql.ts'; } from '@/lib/graphql/generated/graphql.ts';
import { GET_GLOBAL_METADATAS } from '@/lib/graphql/queries/GlobalMetadataQuery.ts'; import { GET_GLOBAL_METADATAS } from '@/lib/graphql/queries/GlobalMetadataQuery.ts';
import { DELETE_GLOBAL_METADATA, SET_GLOBAL_METADATA } from '@/lib/graphql/mutations/GlobalMetadataMutation.ts'; import { DELETE_GLOBAL_METADATA, SET_GLOBAL_METADATA } from '@/lib/graphql/mutations/GlobalMetadataMutation.ts';
@@ -2720,13 +2721,13 @@ export class RequestManager {
} }
public restoreBackupFile( public restoreBackupFile(
file: File, input: RestoreBackupInput,
options?: MutationOptions<RestoreBackupMutation, RestoreBackupMutationVariables>, options?: MutationOptions<RestoreBackupMutation, RestoreBackupMutationVariables>,
): AbortableApolloMutationResponse<RestoreBackupMutation> { ): AbortableApolloMutationResponse<RestoreBackupMutation> {
return this.doRequest<RestoreBackupMutation, RestoreBackupMutationVariables>( return this.doRequest<RestoreBackupMutation, RestoreBackupMutationVariables>(
GQLMethod.MUTATION, GQLMethod.MUTATION,
RESTORE_BACKUP, RESTORE_BACKUP,
{ backup: file }, input,
{ {
...options, ...options,
}, },
@@ -2747,10 +2748,6 @@ export class RequestManager {
return this.doRequest(GQLMethod.USE_QUERY, GET_RESTORE_STATUS, { id }, options); return this.doRequest(GQLMethod.USE_QUERY, GET_RESTORE_STATUS, { id }, options);
} }
public getExportBackupUrl(): string {
return this.getValidUrlFor('backup/export/file');
}
public startDownloads( public startDownloads(
options?: MutationOptions<StartDownloaderMutation, StartDownloaderMutationVariables>, options?: MutationOptions<StartDownloaderMutation, StartDownloaderMutationVariables>,
): AbortableApolloMutationResponse<StartDownloaderMutation> { ): AbortableApolloMutationResponse<StartDownloaderMutation> {