Skip to content

Commit

Permalink
Update Settings Save/Reset Options (chrisbenincasa#301)
Browse files Browse the repository at this point in the history
* update ux for setting saves

* remove fetch from settings pages

* fixes

* remove logs

* disable field in xmltv

* fix button display on xmltv
  • Loading branch information
markdavella authored Apr 16, 2024
1 parent 2d04084 commit f29e772
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 83 deletions.
6 changes: 6 additions & 0 deletions web/src/external/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ import {
getPlexStreamSettings,
getXmlTvSettings,
updateFfmpegSettings,
updateHdhrSettings,
updatePlexServerEndpoint,
updatePlexStreamSettings,
updateXmlTvSettings,
} from './settingsApi.ts';

export const api = makeApi([
Expand Down Expand Up @@ -320,8 +323,11 @@ export const api = makeApi([
deletePlexServerEndpoint,
getPlexBackendStatus,
getXmlTvSettings,
updateXmlTvSettings,
getHdhrSettings,
updateHdhrSettings,
getPlexStreamSettings,
updatePlexStreamSettings,
getFffmpegSettings,
updateFfmpegSettings,
{
Expand Down
24 changes: 24 additions & 0 deletions web/src/external/settingsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ export const getXmlTvSettings = makeEndpoint({
alias: 'getXmlTvSettings',
});

export const updateXmlTvSettings = makeEndpoint({
method: 'put',
path: '/api/xmltv-settings',
response: XmlTvSettingsSchema,
parameters: parametersBuilder().addBody(XmlTvSettingsSchema).build(),
alias: 'updateXmlTvSettings',
});

export const getFffmpegSettings = makeEndpoint({
method: 'get',
path: '/api/ffmpeg-settings',
Expand All @@ -100,9 +108,25 @@ export const getHdhrSettings = makeEndpoint({
alias: 'getHdhrSettings',
});

export const updateHdhrSettings = makeEndpoint({
method: 'put',
path: '/api/hdhr-settings',
response: HdhrSettingsSchema,
parameters: parametersBuilder().addBody(HdhrSettingsSchema).build(),
alias: 'updateHdhrSettings',
});

export const getPlexStreamSettings = makeEndpoint({
method: 'get',
path: '/api/plex-settings',
response: PlexStreamSettingsSchema,
alias: 'getPlexStreamSettings',
});

export const updatePlexStreamSettings = makeEndpoint({
method: 'put',
path: '/api/plex-settings',
response: PlexStreamSettingsSchema,
parameters: parametersBuilder().addBody(PlexStreamSettingsSchema).build(),
alias: 'updatePlexStreamSettings',
});
63 changes: 51 additions & 12 deletions web/src/pages/settings/FfmpegSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
} from '@mui/material';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { FfmpegSettings, defaultFfmpegSettings } from '@tunarr/types';
import _ from 'lodash-es';
import React, { useEffect } from 'react';
import { Controller, SubmitHandler, useForm } from 'react-hook-form';
import {
Expand Down Expand Up @@ -134,7 +135,7 @@ export default function FfmpegSettingsPage() {
const {
reset,
control,
formState: { isDirty, isValid },
formState: { isDirty, isValid, isSubmitting, defaultValues },
watch,
handleSubmit,
} = useForm<Omit<FfmpegSettings, 'configVersion'>>({
Expand All @@ -145,18 +146,23 @@ export default function FfmpegSettingsPage() {
const enableTranscoding = watch('enableTranscoding');

useEffect(() => {
if (data && !isDirty) {
if (data) {
reset(data);
}
}, [data, isDirty, reset]);
}, [data, reset]);

const [snackStatus, setSnackStatus] = React.useState<boolean>(false);
const [restoreTunarrDefaults, setRestoreTunarrDefaults] =
React.useState<boolean>(false);

const queryClient = useQueryClient();

const updateFfmpegSettingsMutation = useMutation({
mutationFn: apiClient.updateFfmpegSettings,
onSuccess: () => {
onSuccess: (data) => {
setRestoreTunarrDefaults(false);
setSnackStatus(true);
reset(data, { keepValues: true });
return queryClient.invalidateQueries({
queryKey: ['settings', 'ffmpeg-settings'],
});
Expand Down Expand Up @@ -777,14 +783,47 @@ export default function FfmpegSettingsPage() {
</FormControl>
</>
)}

<Stack spacing={2} direction="row" justifyContent="right" sx={{ mt: 2 }}>
<Button variant="outlined" onClick={() => reset()}>
Reset Options
</Button>
<Button variant="contained" disabled={!isValid} type="submit">
Save
</Button>
<Stack spacing={2} direction="row" sx={{ mt: 2 }}>
<Stack
spacing={2}
direction="row"
justifyContent="left"
sx={{ mt: 2, flexGrow: 1 }}
>
{!_.isEqual(defaultValues, defaultFfmpegSettings) && (
<Button
variant="outlined"
onClick={() => {
reset(defaultFfmpegSettings);
setRestoreTunarrDefaults(true);
}}
>
Restore Default Settings
</Button>
)}
</Stack>
<Stack spacing={2} direction="row" justifyContent="right">
{(isDirty || (isDirty && !isSubmitting) || restoreTunarrDefaults) && (
<Button
variant="outlined"
onClick={() => {
reset(data);
setRestoreTunarrDefaults(false);
}}
>
Reset Changes
</Button>
)}
<Button
variant="contained"
disabled={
!isValid || isSubmitting || (!isDirty && !restoreTunarrDefaults)
}
type="submit"
>
Save
</Button>
</Stack>
</Stack>
</Box>
);
Expand Down
6 changes: 3 additions & 3 deletions web/src/pages/settings/GeneralSettingsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Button, Stack } from '@mui/material';
import DarkModeButton from '../../components/settings/DarkModeButton.tsx';

export default function GeneralSettingsPage() {
return (
<>
<DarkModeButton />
<Stack spacing={2} direction="row" justifyContent="right" sx={{ mt: 2 }}>
{/* This is currently not needed for this page as Dark Mode saves automatically */}
{/* <Stack spacing={2} direction="row" justifyContent="right" sx={{ mt: 2 }}>
<Button variant="outlined">Reset Options</Button>
<Button variant="contained">Save</Button>
</Stack>
</Stack> */}
</>
);
}
77 changes: 56 additions & 21 deletions web/src/pages/settings/HdhrSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,56 @@ import {
} from '@mui/material';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { HdhrSettings, defaultHdhrSettings } from '@tunarr/types';
import _ from 'lodash-es';
import React, { useEffect } from 'react';
import { SubmitHandler, useForm } from 'react-hook-form';
import {
CheckboxFormController,
NumericFormControllerText,
} from '../../components/util/TypedController.tsx';
import { apiClient } from '../../external/api.ts';
import { useHdhrSettings } from '../../hooks/settingsHooks.ts';

export default function HdhrSettingsPage() {
const [restoreTunarrDefaults, setRestoreTunarrDefaults] =
React.useState<boolean>(false);

const { data, isPending, error } = useHdhrSettings();

const {
reset,
control,
formState: { isDirty, isValid },
formState: { isDirty, isValid, isSubmitting, defaultValues },
handleSubmit,
} = useForm<HdhrSettings>({
defaultValues: defaultHdhrSettings,
mode: 'onBlur',
});

useEffect(() => {
if (data && !isDirty) {
if (data) {
reset(data);
}
}, [data, isDirty, reset]);
}, [data, reset]);

const [snackStatus, setSnackStatus] = React.useState<boolean>(false);
const queryClient = useQueryClient();

const updateHdhrSettingsMutation = useMutation({
mutationFn: (updateSettings: HdhrSettings) => {
return fetch('http://localhost:8000/api/hdhr-settings', {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(updateSettings),
});
},
onSuccess: () => {
mutationFn: apiClient.updateHdhrSettings,
onSuccess: (data) => {
setSnackStatus(true);
setRestoreTunarrDefaults(false);
reset(data, { keepValues: true });
return queryClient.invalidateQueries({
queryKey: ['settings', 'hdhr-settings'],
});
},
});

const updateHdhrSettings: SubmitHandler<HdhrSettings> = (data) => {
const updateHdhrSettings: SubmitHandler<HdhrSettings> = (
data: HdhrSettings,
) => {
updateHdhrSettingsMutation.mutate({
...data,
});
Expand Down Expand Up @@ -109,13 +110,47 @@ export default function HdhrSettingsPage() {
}}
/>

<Stack spacing={2} direction="row" justifyContent="right" sx={{ mt: 2 }}>
<Button variant="outlined" onClick={() => reset()}>
Reset Options
</Button>
<Button variant="contained" disabled={!isValid} type="submit">
Save
</Button>
<Stack spacing={2} direction="row" sx={{ mt: 2 }}>
<Stack
spacing={2}
direction="row"
justifyContent="left"
sx={{ mt: 2, flexGrow: 1 }}
>
{!_.isEqual(defaultValues, defaultHdhrSettings) && (
<Button
variant="outlined"
onClick={() => {
reset(defaultHdhrSettings);
setRestoreTunarrDefaults(true);
}}
>
Restore Default Settings
</Button>
)}
</Stack>
<Stack spacing={2} direction="row" justifyContent="right">
{isDirty && (
<Button
variant="outlined"
onClick={() => {
reset(data);
setRestoreTunarrDefaults(false);
}}
>
Reset Changes
</Button>
)}
<Button
variant="contained"
disabled={
!isValid || isSubmitting || (!isDirty && !restoreTunarrDefaults)
}
type="submit"
>
Save
</Button>
</Stack>
</Stack>
</Box>
);
Expand Down
Loading

0 comments on commit f29e772

Please sign in to comment.