From 274c4c6489104a11f00e2051e3c671de3472cd73 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Sun, 1 Sep 2024 03:04:34 +0200 Subject: [PATCH] Add server log file rotation settings --- public/locales/en.json | 14 ++++++++ .../settings/text/TextSettingDialog.tsx | 14 ++++++-- .../graphql/fragments/SettingsFragments.ts | 3 ++ src/lib/graphql/generated/apollo-helpers.ts | 15 ++++++-- src/lib/graphql/generated/graphql.ts | 20 ++++++++--- src/screens/settings/ServerSettings.tsx | 36 +++++++++++++++++++ versionToServerVersionMapping.json | 2 +- 7 files changed, 94 insertions(+), 10 deletions(-) diff --git a/public/locales/en.json b/public/locales/en.json index 8d2e6b0d..efaa5011 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -997,6 +997,20 @@ } }, "misc": { + "log_files": { + "file_cleanup": { + "title": "Log file cleanup", + "value": "Delete backups that are older than $t(global.date.value.label.day)" + }, + "file_size": { + "description": "Example for possible values: 1 (bytes), 1KB (kilobytes), 1MB (megabytes), 1GB (gigabytes)", + "title": "Maximum log file size" + }, + "total_size": { + "description": "$t(settings.server.misc.log_files.file_size.description)", + "title": "Maximum size of all log files" + } + }, "log_level": { "graphql": { "label": { diff --git a/src/components/settings/text/TextSettingDialog.tsx b/src/components/settings/text/TextSettingDialog.tsx index 810369e8..a727a9df 100644 --- a/src/components/settings/text/TextSettingDialog.tsx +++ b/src/components/settings/text/TextSettingDialog.tsx @@ -27,6 +27,7 @@ export type TextSettingDialogProps = { placeholder?: string; isDialogOpen: boolean; setIsDialogOpen: (open: boolean) => void; + validate?: (value: string) => boolean; }; export const TextSettingDialog = ({ @@ -39,10 +40,12 @@ export const TextSettingDialog = ({ placeholder = '', isDialogOpen, setIsDialogOpen, + validate = () => true, }: TextSettingDialogProps) => { const { t } = useTranslation(); const [dialogValue, setDialogValue] = useState(value ?? ''); + const [isValidValue, setIsValidValue] = useState(true); const TextFieldComponent = useMemo(() => (isPassword ? PasswordTextField : TextField), [isPassword]); @@ -82,14 +85,21 @@ export const TextSettingDialog = ({ autoFocus placeholder={placeholder} value={dialogValue} - onChange={(e) => setDialogValue(e.target.value)} + error={!isValidValue} + helperText={!isValidValue ? t('global.error.label.invalid_input') : ''} + onChange={(e) => { + const newValue = e.target.value; + + setIsValidValue(validate(newValue)); + setDialogValue(newValue); + }} /> - diff --git a/src/lib/graphql/fragments/SettingsFragments.ts b/src/lib/graphql/fragments/SettingsFragments.ts index cdda5e08..385b6510 100644 --- a/src/lib/graphql/fragments/SettingsFragments.ts +++ b/src/lib/graphql/fragments/SettingsFragments.ts @@ -60,6 +60,9 @@ export const SERVER_SETTINGS = gql` debugLogsEnabled gqlDebugLogsEnabled systemTrayEnabled + maxLogFileSize + maxLogFiles + maxLogFolderSize # backup backupPath diff --git a/src/lib/graphql/generated/apollo-helpers.ts b/src/lib/graphql/generated/apollo-helpers.ts index 9b2cc242..8e731230 100644 --- a/src/lib/graphql/generated/apollo-helpers.ts +++ b/src/lib/graphql/generated/apollo-helpers.ts @@ -522,7 +522,7 @@ export type PageInfoFieldPolicy = { hasPreviousPage?: FieldPolicy | FieldReadFunction, startCursor?: FieldPolicy | FieldReadFunction }; -export type PartialSettingsTypeKeySpecifier = ('autoDownloadAheadLimit' | 'autoDownloadIgnoreReUploads' | 'autoDownloadNewChapters' | 'autoDownloadNewChaptersLimit' | 'backupInterval' | 'backupPath' | 'backupTTL' | 'backupTime' | 'basicAuthEnabled' | 'basicAuthPassword' | 'basicAuthUsername' | 'debugLogsEnabled' | 'downloadAsCbz' | 'downloadsPath' | 'electronPath' | 'excludeCompleted' | 'excludeEntryWithUnreadChapters' | 'excludeNotStarted' | 'excludeUnreadChapters' | 'extensionRepos' | 'flareSolverrAsResponseFallback' | 'flareSolverrEnabled' | 'flareSolverrSessionName' | 'flareSolverrSessionTtl' | 'flareSolverrTimeout' | 'flareSolverrUrl' | 'globalUpdateInterval' | 'gqlDebugLogsEnabled' | 'initialOpenInBrowserEnabled' | 'ip' | 'localSourcePath' | 'maxSourcesInParallel' | 'port' | 'socksProxyEnabled' | 'socksProxyHost' | 'socksProxyPassword' | 'socksProxyPort' | 'socksProxyUsername' | 'socksProxyVersion' | 'systemTrayEnabled' | 'updateMangas' | 'webUIChannel' | 'webUIFlavor' | 'webUIInterface' | 'webUIUpdateCheckInterval' | PartialSettingsTypeKeySpecifier)[]; +export type PartialSettingsTypeKeySpecifier = ('autoDownloadAheadLimit' | 'autoDownloadIgnoreReUploads' | 'autoDownloadNewChapters' | 'autoDownloadNewChaptersLimit' | 'backupInterval' | 'backupPath' | 'backupTTL' | 'backupTime' | 'basicAuthEnabled' | 'basicAuthPassword' | 'basicAuthUsername' | 'debugLogsEnabled' | 'downloadAsCbz' | 'downloadsPath' | 'electronPath' | 'excludeCompleted' | 'excludeEntryWithUnreadChapters' | 'excludeNotStarted' | 'excludeUnreadChapters' | 'extensionRepos' | 'flareSolverrAsResponseFallback' | 'flareSolverrEnabled' | 'flareSolverrSessionName' | 'flareSolverrSessionTtl' | 'flareSolverrTimeout' | 'flareSolverrUrl' | 'globalUpdateInterval' | 'gqlDebugLogsEnabled' | 'initialOpenInBrowserEnabled' | 'ip' | 'localSourcePath' | 'maxLogFileSize' | 'maxLogFiles' | 'maxLogFolderSize' | 'maxSourcesInParallel' | 'port' | 'socksProxyEnabled' | 'socksProxyHost' | 'socksProxyPassword' | 'socksProxyPort' | 'socksProxyUsername' | 'socksProxyVersion' | 'systemTrayEnabled' | 'updateMangas' | 'webUIChannel' | 'webUIFlavor' | 'webUIInterface' | 'webUIUpdateCheckInterval' | PartialSettingsTypeKeySpecifier)[]; export type PartialSettingsTypeFieldPolicy = { autoDownloadAheadLimit?: FieldPolicy | FieldReadFunction, autoDownloadIgnoreReUploads?: FieldPolicy | FieldReadFunction, @@ -555,6 +555,9 @@ export type PartialSettingsTypeFieldPolicy = { initialOpenInBrowserEnabled?: FieldPolicy | FieldReadFunction, ip?: FieldPolicy | FieldReadFunction, localSourcePath?: FieldPolicy | FieldReadFunction, + maxLogFileSize?: FieldPolicy | FieldReadFunction, + maxLogFiles?: FieldPolicy | FieldReadFunction, + maxLogFolderSize?: FieldPolicy | FieldReadFunction, maxSourcesInParallel?: FieldPolicy | FieldReadFunction, port?: FieldPolicy | FieldReadFunction, socksProxyEnabled?: FieldPolicy | FieldReadFunction, @@ -661,7 +664,7 @@ export type SetSourceMetaPayloadFieldPolicy = { clientMutationId?: FieldPolicy | FieldReadFunction, meta?: FieldPolicy | FieldReadFunction }; -export type SettingsKeySpecifier = ('autoDownloadAheadLimit' | 'autoDownloadIgnoreReUploads' | 'autoDownloadNewChapters' | 'autoDownloadNewChaptersLimit' | 'backupInterval' | 'backupPath' | 'backupTTL' | 'backupTime' | 'basicAuthEnabled' | 'basicAuthPassword' | 'basicAuthUsername' | 'debugLogsEnabled' | 'downloadAsCbz' | 'downloadsPath' | 'electronPath' | 'excludeCompleted' | 'excludeEntryWithUnreadChapters' | 'excludeNotStarted' | 'excludeUnreadChapters' | 'extensionRepos' | 'flareSolverrAsResponseFallback' | 'flareSolverrEnabled' | 'flareSolverrSessionName' | 'flareSolverrSessionTtl' | 'flareSolverrTimeout' | 'flareSolverrUrl' | 'globalUpdateInterval' | 'gqlDebugLogsEnabled' | 'initialOpenInBrowserEnabled' | 'ip' | 'localSourcePath' | 'maxSourcesInParallel' | 'port' | 'socksProxyEnabled' | 'socksProxyHost' | 'socksProxyPassword' | 'socksProxyPort' | 'socksProxyUsername' | 'socksProxyVersion' | 'systemTrayEnabled' | 'updateMangas' | 'webUIChannel' | 'webUIFlavor' | 'webUIInterface' | 'webUIUpdateCheckInterval' | SettingsKeySpecifier)[]; +export type SettingsKeySpecifier = ('autoDownloadAheadLimit' | 'autoDownloadIgnoreReUploads' | 'autoDownloadNewChapters' | 'autoDownloadNewChaptersLimit' | 'backupInterval' | 'backupPath' | 'backupTTL' | 'backupTime' | 'basicAuthEnabled' | 'basicAuthPassword' | 'basicAuthUsername' | 'debugLogsEnabled' | 'downloadAsCbz' | 'downloadsPath' | 'electronPath' | 'excludeCompleted' | 'excludeEntryWithUnreadChapters' | 'excludeNotStarted' | 'excludeUnreadChapters' | 'extensionRepos' | 'flareSolverrAsResponseFallback' | 'flareSolverrEnabled' | 'flareSolverrSessionName' | 'flareSolverrSessionTtl' | 'flareSolverrTimeout' | 'flareSolverrUrl' | 'globalUpdateInterval' | 'gqlDebugLogsEnabled' | 'initialOpenInBrowserEnabled' | 'ip' | 'localSourcePath' | 'maxLogFileSize' | 'maxLogFiles' | 'maxLogFolderSize' | 'maxSourcesInParallel' | 'port' | 'socksProxyEnabled' | 'socksProxyHost' | 'socksProxyPassword' | 'socksProxyPort' | 'socksProxyUsername' | 'socksProxyVersion' | 'systemTrayEnabled' | 'updateMangas' | 'webUIChannel' | 'webUIFlavor' | 'webUIInterface' | 'webUIUpdateCheckInterval' | SettingsKeySpecifier)[]; export type SettingsFieldPolicy = { autoDownloadAheadLimit?: FieldPolicy | FieldReadFunction, autoDownloadIgnoreReUploads?: FieldPolicy | FieldReadFunction, @@ -694,6 +697,9 @@ export type SettingsFieldPolicy = { initialOpenInBrowserEnabled?: FieldPolicy | FieldReadFunction, ip?: FieldPolicy | FieldReadFunction, localSourcePath?: FieldPolicy | FieldReadFunction, + maxLogFileSize?: FieldPolicy | FieldReadFunction, + maxLogFiles?: FieldPolicy | FieldReadFunction, + maxLogFolderSize?: FieldPolicy | FieldReadFunction, maxSourcesInParallel?: FieldPolicy | FieldReadFunction, port?: FieldPolicy | FieldReadFunction, socksProxyEnabled?: FieldPolicy | FieldReadFunction, @@ -709,7 +715,7 @@ export type SettingsFieldPolicy = { webUIInterface?: FieldPolicy | FieldReadFunction, webUIUpdateCheckInterval?: FieldPolicy | FieldReadFunction }; -export type SettingsTypeKeySpecifier = ('autoDownloadAheadLimit' | 'autoDownloadIgnoreReUploads' | 'autoDownloadNewChapters' | 'autoDownloadNewChaptersLimit' | 'backupInterval' | 'backupPath' | 'backupTTL' | 'backupTime' | 'basicAuthEnabled' | 'basicAuthPassword' | 'basicAuthUsername' | 'debugLogsEnabled' | 'downloadAsCbz' | 'downloadsPath' | 'electronPath' | 'excludeCompleted' | 'excludeEntryWithUnreadChapters' | 'excludeNotStarted' | 'excludeUnreadChapters' | 'extensionRepos' | 'flareSolverrAsResponseFallback' | 'flareSolverrEnabled' | 'flareSolverrSessionName' | 'flareSolverrSessionTtl' | 'flareSolverrTimeout' | 'flareSolverrUrl' | 'globalUpdateInterval' | 'gqlDebugLogsEnabled' | 'initialOpenInBrowserEnabled' | 'ip' | 'localSourcePath' | 'maxSourcesInParallel' | 'port' | 'socksProxyEnabled' | 'socksProxyHost' | 'socksProxyPassword' | 'socksProxyPort' | 'socksProxyUsername' | 'socksProxyVersion' | 'systemTrayEnabled' | 'updateMangas' | 'webUIChannel' | 'webUIFlavor' | 'webUIInterface' | 'webUIUpdateCheckInterval' | SettingsTypeKeySpecifier)[]; +export type SettingsTypeKeySpecifier = ('autoDownloadAheadLimit' | 'autoDownloadIgnoreReUploads' | 'autoDownloadNewChapters' | 'autoDownloadNewChaptersLimit' | 'backupInterval' | 'backupPath' | 'backupTTL' | 'backupTime' | 'basicAuthEnabled' | 'basicAuthPassword' | 'basicAuthUsername' | 'debugLogsEnabled' | 'downloadAsCbz' | 'downloadsPath' | 'electronPath' | 'excludeCompleted' | 'excludeEntryWithUnreadChapters' | 'excludeNotStarted' | 'excludeUnreadChapters' | 'extensionRepos' | 'flareSolverrAsResponseFallback' | 'flareSolverrEnabled' | 'flareSolverrSessionName' | 'flareSolverrSessionTtl' | 'flareSolverrTimeout' | 'flareSolverrUrl' | 'globalUpdateInterval' | 'gqlDebugLogsEnabled' | 'initialOpenInBrowserEnabled' | 'ip' | 'localSourcePath' | 'maxLogFileSize' | 'maxLogFiles' | 'maxLogFolderSize' | 'maxSourcesInParallel' | 'port' | 'socksProxyEnabled' | 'socksProxyHost' | 'socksProxyPassword' | 'socksProxyPort' | 'socksProxyUsername' | 'socksProxyVersion' | 'systemTrayEnabled' | 'updateMangas' | 'webUIChannel' | 'webUIFlavor' | 'webUIInterface' | 'webUIUpdateCheckInterval' | SettingsTypeKeySpecifier)[]; export type SettingsTypeFieldPolicy = { autoDownloadAheadLimit?: FieldPolicy | FieldReadFunction, autoDownloadIgnoreReUploads?: FieldPolicy | FieldReadFunction, @@ -742,6 +748,9 @@ export type SettingsTypeFieldPolicy = { initialOpenInBrowserEnabled?: FieldPolicy | FieldReadFunction, ip?: FieldPolicy | FieldReadFunction, localSourcePath?: FieldPolicy | FieldReadFunction, + maxLogFileSize?: FieldPolicy | FieldReadFunction, + maxLogFiles?: FieldPolicy | FieldReadFunction, + maxLogFolderSize?: FieldPolicy | FieldReadFunction, maxSourcesInParallel?: FieldPolicy | FieldReadFunction, port?: FieldPolicy | FieldReadFunction, socksProxyEnabled?: FieldPolicy | FieldReadFunction, diff --git a/src/lib/graphql/generated/graphql.ts b/src/lib/graphql/generated/graphql.ts index da581c94..e9a60dd7 100644 --- a/src/lib/graphql/generated/graphql.ts +++ b/src/lib/graphql/generated/graphql.ts @@ -1474,6 +1474,9 @@ export type PartialSettingsType = Settings & { initialOpenInBrowserEnabled?: Maybe; ip?: Maybe; localSourcePath?: Maybe; + maxLogFileSize?: Maybe; + maxLogFiles?: Maybe; + maxLogFolderSize?: Maybe; maxSourcesInParallel?: Maybe; port?: Maybe; socksProxyEnabled?: Maybe; @@ -1521,6 +1524,9 @@ export type PartialSettingsTypeInput = { initialOpenInBrowserEnabled?: InputMaybe; ip?: InputMaybe; localSourcePath?: InputMaybe; + maxLogFileSize?: InputMaybe; + maxLogFiles?: InputMaybe; + maxLogFolderSize?: InputMaybe; maxSourcesInParallel?: InputMaybe; port?: InputMaybe; socksProxyEnabled?: InputMaybe; @@ -1892,6 +1898,9 @@ export type Settings = { initialOpenInBrowserEnabled?: Maybe; ip?: Maybe; localSourcePath?: Maybe; + maxLogFileSize?: Maybe; + maxLogFiles?: Maybe; + maxLogFolderSize?: Maybe; maxSourcesInParallel?: Maybe; port?: Maybe; socksProxyEnabled?: Maybe; @@ -1942,6 +1951,9 @@ export type SettingsType = Settings & { initialOpenInBrowserEnabled: Scalars['Boolean']['output']; ip: Scalars['String']['output']; localSourcePath: Scalars['String']['output']; + maxLogFileSize: Scalars['String']['output']; + maxLogFiles: Scalars['Int']['output']; + maxLogFolderSize: Scalars['String']['output']; maxSourcesInParallel: Scalars['Int']['output']; port: Scalars['Int']['output']; socksProxyEnabled: Scalars['Boolean']['output']; @@ -2745,7 +2757,7 @@ export type MangaScreenFieldsFragment = { __typename?: 'MangaType', artist?: str export type MangaLibraryDuplicateScreenFieldsFragment = { __typename?: 'MangaType', description?: string | null, id: number, title: string, thumbnailUrl?: string | null, thumbnailUrlLastFetched?: string | null, inLibrary: boolean, initialized: boolean, sourceId: string, unreadCount: number, downloadCount: number, bookmarkCount: number, hasDuplicateChapters: boolean, chapters: { __typename?: 'ChapterNodeList', totalCount: number } }; -export type ServerSettingsFragment = { __typename?: 'SettingsType', ip: string, port: number, socksProxyEnabled: boolean, socksProxyVersion: number, socksProxyHost: string, socksProxyPort: string, socksProxyUsername: string, socksProxyPassword: string, webUIFlavor: WebUiFlavor, initialOpenInBrowserEnabled: boolean, webUIInterface: WebUiInterface, electronPath: string, webUIChannel: WebUiChannel, webUIUpdateCheckInterval: number, downloadAsCbz: boolean, downloadsPath: string, autoDownloadNewChapters: boolean, excludeEntryWithUnreadChapters: boolean, autoDownloadNewChaptersLimit: number, autoDownloadIgnoreReUploads?: boolean | null, extensionRepos: Array, maxSourcesInParallel: number, excludeUnreadChapters: boolean, excludeNotStarted: boolean, excludeCompleted: boolean, globalUpdateInterval: number, updateMangas: boolean, basicAuthEnabled: boolean, basicAuthUsername: string, basicAuthPassword: string, debugLogsEnabled: boolean, gqlDebugLogsEnabled: boolean, systemTrayEnabled: boolean, backupPath: string, backupTime: string, backupInterval: number, backupTTL: number, localSourcePath: string, flareSolverrEnabled: boolean, flareSolverrUrl: string, flareSolverrTimeout: number, flareSolverrSessionName: string, flareSolverrSessionTtl: number, flareSolverrAsResponseFallback: boolean }; +export type ServerSettingsFragment = { __typename?: 'SettingsType', ip: string, port: number, socksProxyEnabled: boolean, socksProxyVersion: number, socksProxyHost: string, socksProxyPort: string, socksProxyUsername: string, socksProxyPassword: string, webUIFlavor: WebUiFlavor, initialOpenInBrowserEnabled: boolean, webUIInterface: WebUiInterface, electronPath: string, webUIChannel: WebUiChannel, webUIUpdateCheckInterval: number, downloadAsCbz: boolean, downloadsPath: string, autoDownloadNewChapters: boolean, excludeEntryWithUnreadChapters: boolean, autoDownloadNewChaptersLimit: number, autoDownloadIgnoreReUploads?: boolean | null, extensionRepos: Array, maxSourcesInParallel: number, excludeUnreadChapters: boolean, excludeNotStarted: boolean, excludeCompleted: boolean, globalUpdateInterval: number, updateMangas: boolean, basicAuthEnabled: boolean, basicAuthUsername: string, basicAuthPassword: string, debugLogsEnabled: boolean, gqlDebugLogsEnabled: boolean, systemTrayEnabled: boolean, maxLogFileSize: string, maxLogFiles: number, maxLogFolderSize: string, backupPath: string, backupTime: string, backupInterval: number, backupTTL: number, localSourcePath: string, flareSolverrEnabled: boolean, flareSolverrUrl: string, flareSolverrTimeout: number, flareSolverrSessionName: string, flareSolverrSessionTtl: number, flareSolverrAsResponseFallback: boolean }; export type SourceBaseFieldsFragment = { __typename?: 'SourceType', id: string, name: string, displayName: string }; @@ -3099,14 +3111,14 @@ export type ResetServerSettingsMutationVariables = Exact<{ }>; -export type ResetServerSettingsMutation = { __typename?: 'Mutation', resetSettings: { __typename?: 'ResetSettingsPayload', settings: { __typename?: 'SettingsType', ip: string, port: number, socksProxyEnabled: boolean, socksProxyVersion: number, socksProxyHost: string, socksProxyPort: string, socksProxyUsername: string, socksProxyPassword: string, webUIFlavor: WebUiFlavor, initialOpenInBrowserEnabled: boolean, webUIInterface: WebUiInterface, electronPath: string, webUIChannel: WebUiChannel, webUIUpdateCheckInterval: number, downloadAsCbz: boolean, downloadsPath: string, autoDownloadNewChapters: boolean, excludeEntryWithUnreadChapters: boolean, autoDownloadNewChaptersLimit: number, autoDownloadIgnoreReUploads?: boolean | null, extensionRepos: Array, maxSourcesInParallel: number, excludeUnreadChapters: boolean, excludeNotStarted: boolean, excludeCompleted: boolean, globalUpdateInterval: number, updateMangas: boolean, basicAuthEnabled: boolean, basicAuthUsername: string, basicAuthPassword: string, debugLogsEnabled: boolean, gqlDebugLogsEnabled: boolean, systemTrayEnabled: boolean, backupPath: string, backupTime: string, backupInterval: number, backupTTL: number, localSourcePath: string, flareSolverrEnabled: boolean, flareSolverrUrl: string, flareSolverrTimeout: number, flareSolverrSessionName: string, flareSolverrSessionTtl: number, flareSolverrAsResponseFallback: boolean } } }; +export type ResetServerSettingsMutation = { __typename?: 'Mutation', resetSettings: { __typename?: 'ResetSettingsPayload', settings: { __typename?: 'SettingsType', ip: string, port: number, socksProxyEnabled: boolean, socksProxyVersion: number, socksProxyHost: string, socksProxyPort: string, socksProxyUsername: string, socksProxyPassword: string, webUIFlavor: WebUiFlavor, initialOpenInBrowserEnabled: boolean, webUIInterface: WebUiInterface, electronPath: string, webUIChannel: WebUiChannel, webUIUpdateCheckInterval: number, downloadAsCbz: boolean, downloadsPath: string, autoDownloadNewChapters: boolean, excludeEntryWithUnreadChapters: boolean, autoDownloadNewChaptersLimit: number, autoDownloadIgnoreReUploads?: boolean | null, extensionRepos: Array, maxSourcesInParallel: number, excludeUnreadChapters: boolean, excludeNotStarted: boolean, excludeCompleted: boolean, globalUpdateInterval: number, updateMangas: boolean, basicAuthEnabled: boolean, basicAuthUsername: string, basicAuthPassword: string, debugLogsEnabled: boolean, gqlDebugLogsEnabled: boolean, systemTrayEnabled: boolean, maxLogFileSize: string, maxLogFiles: number, maxLogFolderSize: string, backupPath: string, backupTime: string, backupInterval: number, backupTTL: number, localSourcePath: string, flareSolverrEnabled: boolean, flareSolverrUrl: string, flareSolverrTimeout: number, flareSolverrSessionName: string, flareSolverrSessionTtl: number, flareSolverrAsResponseFallback: boolean } } }; export type UpdateServerSettingsMutationVariables = Exact<{ input: SetSettingsInput; }>; -export type UpdateServerSettingsMutation = { __typename?: 'Mutation', setSettings: { __typename?: 'SetSettingsPayload', settings: { __typename?: 'SettingsType', ip: string, port: number, socksProxyEnabled: boolean, socksProxyVersion: number, socksProxyHost: string, socksProxyPort: string, socksProxyUsername: string, socksProxyPassword: string, webUIFlavor: WebUiFlavor, initialOpenInBrowserEnabled: boolean, webUIInterface: WebUiInterface, electronPath: string, webUIChannel: WebUiChannel, webUIUpdateCheckInterval: number, downloadAsCbz: boolean, downloadsPath: string, autoDownloadNewChapters: boolean, excludeEntryWithUnreadChapters: boolean, autoDownloadNewChaptersLimit: number, autoDownloadIgnoreReUploads?: boolean | null, extensionRepos: Array, maxSourcesInParallel: number, excludeUnreadChapters: boolean, excludeNotStarted: boolean, excludeCompleted: boolean, globalUpdateInterval: number, updateMangas: boolean, basicAuthEnabled: boolean, basicAuthUsername: string, basicAuthPassword: string, debugLogsEnabled: boolean, gqlDebugLogsEnabled: boolean, systemTrayEnabled: boolean, backupPath: string, backupTime: string, backupInterval: number, backupTTL: number, localSourcePath: string, flareSolverrEnabled: boolean, flareSolverrUrl: string, flareSolverrTimeout: number, flareSolverrSessionName: string, flareSolverrSessionTtl: number, flareSolverrAsResponseFallback: boolean } } }; +export type UpdateServerSettingsMutation = { __typename?: 'Mutation', setSettings: { __typename?: 'SetSettingsPayload', settings: { __typename?: 'SettingsType', ip: string, port: number, socksProxyEnabled: boolean, socksProxyVersion: number, socksProxyHost: string, socksProxyPort: string, socksProxyUsername: string, socksProxyPassword: string, webUIFlavor: WebUiFlavor, initialOpenInBrowserEnabled: boolean, webUIInterface: WebUiInterface, electronPath: string, webUIChannel: WebUiChannel, webUIUpdateCheckInterval: number, downloadAsCbz: boolean, downloadsPath: string, autoDownloadNewChapters: boolean, excludeEntryWithUnreadChapters: boolean, autoDownloadNewChaptersLimit: number, autoDownloadIgnoreReUploads?: boolean | null, extensionRepos: Array, maxSourcesInParallel: number, excludeUnreadChapters: boolean, excludeNotStarted: boolean, excludeCompleted: boolean, globalUpdateInterval: number, updateMangas: boolean, basicAuthEnabled: boolean, basicAuthUsername: string, basicAuthPassword: string, debugLogsEnabled: boolean, gqlDebugLogsEnabled: boolean, systemTrayEnabled: boolean, maxLogFileSize: string, maxLogFiles: number, maxLogFolderSize: string, backupPath: string, backupTime: string, backupInterval: number, backupTTL: number, localSourcePath: string, flareSolverrEnabled: boolean, flareSolverrUrl: string, flareSolverrTimeout: number, flareSolverrSessionName: string, flareSolverrSessionTtl: number, flareSolverrAsResponseFallback: boolean } } }; export type GetSourceMangasFetchMutationVariables = Exact<{ input: FetchSourceMangaInput; @@ -3466,7 +3478,7 @@ export type GetWebuiUpdateStatusQuery = { __typename?: 'Query', getWebUIUpdateSt export type GetServerSettingsQueryVariables = Exact<{ [key: string]: never; }>; -export type GetServerSettingsQuery = { __typename?: 'Query', settings: { __typename?: 'SettingsType', ip: string, port: number, socksProxyEnabled: boolean, socksProxyVersion: number, socksProxyHost: string, socksProxyPort: string, socksProxyUsername: string, socksProxyPassword: string, webUIFlavor: WebUiFlavor, initialOpenInBrowserEnabled: boolean, webUIInterface: WebUiInterface, electronPath: string, webUIChannel: WebUiChannel, webUIUpdateCheckInterval: number, downloadAsCbz: boolean, downloadsPath: string, autoDownloadNewChapters: boolean, excludeEntryWithUnreadChapters: boolean, autoDownloadNewChaptersLimit: number, autoDownloadIgnoreReUploads?: boolean | null, extensionRepos: Array, maxSourcesInParallel: number, excludeUnreadChapters: boolean, excludeNotStarted: boolean, excludeCompleted: boolean, globalUpdateInterval: number, updateMangas: boolean, basicAuthEnabled: boolean, basicAuthUsername: string, basicAuthPassword: string, debugLogsEnabled: boolean, gqlDebugLogsEnabled: boolean, systemTrayEnabled: boolean, backupPath: string, backupTime: string, backupInterval: number, backupTTL: number, localSourcePath: string, flareSolverrEnabled: boolean, flareSolverrUrl: string, flareSolverrTimeout: number, flareSolverrSessionName: string, flareSolverrSessionTtl: number, flareSolverrAsResponseFallback: boolean } }; +export type GetServerSettingsQuery = { __typename?: 'Query', settings: { __typename?: 'SettingsType', ip: string, port: number, socksProxyEnabled: boolean, socksProxyVersion: number, socksProxyHost: string, socksProxyPort: string, socksProxyUsername: string, socksProxyPassword: string, webUIFlavor: WebUiFlavor, initialOpenInBrowserEnabled: boolean, webUIInterface: WebUiInterface, electronPath: string, webUIChannel: WebUiChannel, webUIUpdateCheckInterval: number, downloadAsCbz: boolean, downloadsPath: string, autoDownloadNewChapters: boolean, excludeEntryWithUnreadChapters: boolean, autoDownloadNewChaptersLimit: number, autoDownloadIgnoreReUploads?: boolean | null, extensionRepos: Array, maxSourcesInParallel: number, excludeUnreadChapters: boolean, excludeNotStarted: boolean, excludeCompleted: boolean, globalUpdateInterval: number, updateMangas: boolean, basicAuthEnabled: boolean, basicAuthUsername: string, basicAuthPassword: string, debugLogsEnabled: boolean, gqlDebugLogsEnabled: boolean, systemTrayEnabled: boolean, maxLogFileSize: string, maxLogFiles: number, maxLogFolderSize: string, backupPath: string, backupTime: string, backupInterval: number, backupTTL: number, localSourcePath: string, flareSolverrEnabled: boolean, flareSolverrUrl: string, flareSolverrTimeout: number, flareSolverrSessionName: string, flareSolverrSessionTtl: number, flareSolverrAsResponseFallback: boolean } }; export type GetSourceBrowseQueryVariables = Exact<{ id: Scalars['LongString']['input']; diff --git a/src/screens/settings/ServerSettings.tsx b/src/screens/settings/ServerSettings.tsx index 0d5c1867..793fe77f 100644 --- a/src/screens/settings/ServerSettings.tsx +++ b/src/screens/settings/ServerSettings.tsx @@ -14,6 +14,7 @@ import ListItem from '@mui/material/ListItem'; import ListItemText from '@mui/material/ListItemText'; import Switch from '@mui/material/Switch'; import ListSubheader from '@mui/material/ListSubheader'; +import { t as translate } from 'i18next'; import { NavBarContext } from '@/components/context/NavbarContext.tsx'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { useLocalStorage } from '@/util/useStorage.tsx'; @@ -43,6 +44,9 @@ type ServerSettingsType = Pick< | 'debugLogsEnabled' | 'gqlDebugLogsEnabled' | 'systemTrayEnabled' + | 'maxLogFiles' + | 'maxLogFileSize' + | 'maxLogFolderSize' | 'basicAuthEnabled' | 'basicAuthUsername' | 'basicAuthPassword' @@ -66,6 +70,9 @@ const extractServerSettings = (settings: GqlServerSettings): ServerSettingsType debugLogsEnabled: settings.debugLogsEnabled, gqlDebugLogsEnabled: settings.gqlDebugLogsEnabled, systemTrayEnabled: settings.systemTrayEnabled, + maxLogFiles: settings.maxLogFiles, + maxLogFileSize: settings.maxLogFileSize, + maxLogFolderSize: settings.maxLogFolderSize, basicAuthEnabled: settings.basicAuthEnabled, basicAuthUsername: settings.basicAuthUsername, basicAuthPassword: settings.basicAuthPassword, @@ -77,6 +84,14 @@ const extractServerSettings = (settings: GqlServerSettings): ServerSettingsType flareSolverrAsResponseFallback: settings.flareSolverrAsResponseFallback, }); +const getLogFilesCleanupDisplayValue = (ttl: number): string => { + if (ttl === 0) { + return translate('global.label.never'); + } + + return translate('settings.server.misc.log_files.file_cleanup.value', { days: ttl, count: ttl }); +}; + export const ServerSettings = () => { const { t } = useTranslation(); const { setTitle, setAction } = useContext(NavBarContext); @@ -408,6 +423,27 @@ export const ServerSettings = () => { onChange={(e) => updateSetting('systemTrayEnabled', e.target.checked)} /> + updateSetting('maxLogFiles', maxFiles)} + /> + !!value.match(/^[0-9]+(|kb|KB|mb|MB|gb|GB)$/g)} + handleChange={(maxLogFileSize) => updateSetting('maxLogFileSize', maxLogFileSize)} + /> + !!value.match(/^[0-9]+(|kb|KB|mb|MB|gb|GB)$/g)} + handleChange={(maxLogFolderSize) => updateSetting('maxLogFolderSize', maxLogFolderSize)} + /> ); diff --git a/versionToServerVersionMapping.json b/versionToServerVersionMapping.json index 5e9fdd0d..9b30321c 100644 --- a/versionToServerVersionMapping.json +++ b/versionToServerVersionMapping.json @@ -1,7 +1,7 @@ [ { "uiVersion": "PREVIEW", - "serverVersion": "r1548" + "serverVersion": "r1566" }, { "tag": "v1.1.0",