feat(filters): perfect flac disable fields (#605)

* feat(filters): perfect flac disable fields

* feat(filters): logscore min 0 max 100

* feat(filters): validate numberfield 0 value

* feat(filters): cleanup logs

* feat(filters): set default priority 0
This commit is contained in:
ze0s 2023-01-01 16:47:07 +01:00 committed by GitHub
parent 84c7a4484e
commit 5972d421d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 17 deletions

View file

@ -1,4 +1,5 @@
import { Field, FieldProps } from "formik"; import { Field, FieldProps } from "formik";
import { classNames } from "../../utils";
interface ErrorFieldProps { interface ErrorFieldProps {
name: string; name: string;
@ -19,12 +20,14 @@ interface CheckboxFieldProps {
name: string; name: string;
label: string; label: string;
sublabel?: string; sublabel?: string;
disabled?: boolean;
} }
const CheckboxField = ({ const CheckboxField = ({
name, name,
label, label,
sublabel sublabel,
disabled
}: CheckboxFieldProps) => ( }: CheckboxFieldProps) => (
<div className="relative flex items-start"> <div className="relative flex items-start">
<div className="flex items-center h-5"> <div className="flex items-center h-5">
@ -32,7 +35,8 @@ const CheckboxField = ({
id={name} id={name}
name={name} name={name}
type="checkbox" type="checkbox"
className="focus:ring-bkue-500 h-4 w-4 text-blue-600 border-gray-300 rounded" className={classNames("focus:ring-blue-500 h-4 w-4 text-blue-600 border-gray-300 rounded", disabled ? "bg-gray-200" : "")}
disabled={disabled}
/> />
</div> </div>
<div className="ml-3 text-sm"> <div className="ml-3 text-sm">

View file

@ -2,6 +2,7 @@ import { Field, FieldProps } from "formik";
import { classNames } from "../../utils"; import { classNames } from "../../utils";
import { EyeIcon, EyeSlashIcon } from "@heroicons/react/24/solid"; import { EyeIcon, EyeSlashIcon } from "@heroicons/react/24/solid";
import { useToggle } from "../../hooks/hooks"; import { useToggle } from "../../hooks/hooks";
import { log } from "util";
type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
@ -204,6 +205,9 @@ interface NumberFieldProps {
placeholder?: string; placeholder?: string;
step?: number; step?: number;
disabled?: boolean; disabled?: boolean;
required?: boolean;
min?: number;
max?: number;
} }
export const NumberField = ({ export const NumberField = ({
@ -211,7 +215,10 @@ export const NumberField = ({
label, label,
placeholder, placeholder,
step, step,
disabled min,
max,
disabled,
required
}: NumberFieldProps) => ( }: NumberFieldProps) => (
<div className="col-span-12 sm:col-span-6"> <div className="col-span-12 sm:col-span-6">
<label htmlFor={name} className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide"> <label htmlFor={name} className="block text-xs font-bold text-gray-700 dark:text-gray-200 uppercase tracking-wide">
@ -221,13 +228,18 @@ export const NumberField = ({
<Field name={name} type="number"> <Field name={name} type="number">
{({ {({
field, field,
meta meta,
form
}: FieldProps) => ( }: FieldProps) => (
<div className="sm:col-span-2"> <div className="sm:col-span-2">
<input <input
type="number" type="number"
step={step}
{...field} {...field}
step={step}
min={min}
max={max}
inputMode="numeric"
required={required}
className={classNames( className={classNames(
meta.touched && meta.error meta.touched && meta.error
? "focus:ring-red-500 focus:border-red-500 border-red-500" ? "focus:ring-red-500 focus:border-red-500 border-red-500"
@ -237,6 +249,16 @@ export const NumberField = ({
)} )}
placeholder={placeholder} placeholder={placeholder}
disabled={disabled} disabled={disabled}
onChange={event => {
// safeguard and validation if user removes the number
// it will then set 0 by default. Formik can't handle this properly
if (event.target.value == "") {
form.setFieldValue(field.name, 0);
return;
}
form.setFieldValue(field.name, event.target.value);
}}
/> />
{meta.touched && meta.error && ( {meta.touched && meta.error && (
<div className="error">{meta.error}</div> <div className="error">{meta.error}</div>

View file

@ -20,6 +20,7 @@ interface MultiSelectProps {
options: MultiSelectOption[]; options: MultiSelectOption[];
columns?: COL_WIDTHS; columns?: COL_WIDTHS;
creatable?: boolean; creatable?: boolean;
disabled?: boolean;
} }
export const MultiSelect = ({ export const MultiSelect = ({
@ -27,7 +28,8 @@ export const MultiSelect = ({
label, label,
options, options,
columns, columns,
creatable creatable,
disabled
}: MultiSelectProps) => { }: MultiSelectProps) => {
const settingsContext = SettingsContext.useValue(); const settingsContext = SettingsContext.useValue();
@ -58,6 +60,7 @@ export const MultiSelect = ({
<RMSC <RMSC
{...field} {...field}
options={[...[...options, ...field.value.map((i: MultiSelectOption) => ({ value: i.value ?? i, label: i.label ?? i }))].reduce((map, obj) => map.set(obj.value, obj), new Map()).values()]} options={[...[...options, ...field.value.map((i: MultiSelectOption) => ({ value: i.value ?? i, label: i.label ?? i }))].reduce((map, obj) => map.set(obj.value, obj), new Map()).values()]}
disabled={disabled}
labelledBy={name} labelledBy={name}
isCreatable={creatable} isCreatable={creatable}
onCreateOption={handleNewField} onCreateOption={handleNewField}

View file

@ -235,7 +235,7 @@ export default function FilterDetails() {
min_size: filter.min_size, min_size: filter.min_size,
max_size: filter.max_size, max_size: filter.max_size,
delay: filter.delay, delay: filter.delay,
priority: filter.priority, priority: filter.priority ?? 0,
max_downloads: filter.max_downloads, max_downloads: filter.max_downloads,
max_downloads_unit: filter.max_downloads_unit, max_downloads_unit: filter.max_downloads_unit,
use_regex: filter.use_regex || false, use_regex: filter.use_regex || false,
@ -297,7 +297,7 @@ export default function FilterDetails() {
<Routes> <Routes>
<Route index element={<General />} /> <Route index element={<General />} />
<Route path="movies-tv" element={<MoviesTv />} /> <Route path="movies-tv" element={<MoviesTv />} />
<Route path="music" element={<Music />} /> <Route path="music" element={<Music values={values} />} />
<Route path="advanced" element={<Advanced values={values} />} /> <Route path="advanced" element={<Advanced values={values} />} />
<Route path="external" element={<External />} /> <Route path="external" element={<External />} />
<Route path="actions" element={<FilterActions filter={filter} values={values} />} /> <Route path="actions" element={<FilterActions filter={filter} values={values} />} />
@ -346,7 +346,7 @@ export function General() {
<TextField name="min_size" label="Min size" columns={6} placeholder="eg. 100MiB, 80GB" /> <TextField name="min_size" label="Min size" columns={6} placeholder="eg. 100MiB, 80GB" />
<TextField name="max_size" label="Max size" columns={6} placeholder="eg. 100MiB, 80GB" /> <TextField name="max_size" label="Max size" columns={6} placeholder="eg. 100MiB, 80GB" />
<NumberField name="delay" label="Delay" placeholder="Number of seconds to delay actions" /> <NumberField name="delay" label="Delay" placeholder="Number of seconds to delay actions" />
<NumberField name="priority" label="Priority" placeholder="Higher number = higher prio" /> <NumberField name="priority" label="Priority" placeholder="Higher number = higher prio" min={0} required={true} />
<NumberField name="max_downloads" label="Max downloads" placeholder="Takes any number (0 is infinite)" /> <NumberField name="max_downloads" label="Max downloads" placeholder="Takes any number (0 is infinite)" />
<Select name="max_downloads_unit" label="Max downloads per" options={downloadsPerUnitOptions} optionDefaultText="Select unit" /> <Select name="max_downloads_unit" label="Max downloads per" options={downloadsPerUnitOptions} optionDefaultText="Select unit" />
@ -409,7 +409,7 @@ export function MoviesTv() {
); );
} }
export function Music() { export function Music({ values }: AdvancedProps) {
return ( return (
<div> <div>
<div className="mt-6 grid grid-cols-12 gap-6"> <div className="mt-6 grid grid-cols-12 gap-6">
@ -422,17 +422,17 @@ export function Music() {
<TitleSubtitle title="Quality" subtitle="Format, source, log etc." /> <TitleSubtitle title="Quality" subtitle="Format, source, log etc." />
<div className="mt-6 grid grid-cols-12 gap-6"> <div className="mt-6 grid grid-cols-12 gap-6">
<MultiSelect name="formats" options={FORMATS_OPTIONS} label="Format" columns={6} /> <MultiSelect name="formats" options={FORMATS_OPTIONS} label="Format" columns={6} disabled={values.perfect_flac} />
<MultiSelect name="quality" options={QUALITY_MUSIC_OPTIONS} label="Quality" columns={6} /> <MultiSelect name="quality" options={QUALITY_MUSIC_OPTIONS} label="Quality" columns={6} disabled={values.perfect_flac} />
</div> </div>
<div className="mt-6 grid grid-cols-12 gap-6"> <div className="mt-6 grid grid-cols-12 gap-6">
<MultiSelect name="media" options={SOURCES_MUSIC_OPTIONS} label="Media" columns={6} /> <MultiSelect name="media" options={SOURCES_MUSIC_OPTIONS} label="Media" columns={6} disabled={values.perfect_flac} />
<MultiSelect name="match_release_types" options={RELEASE_TYPE_MUSIC_OPTIONS} label="Type" columns={6} /> <MultiSelect name="match_release_types" options={RELEASE_TYPE_MUSIC_OPTIONS} label="Type" columns={6} disabled={values.perfect_flac} />
</div> </div>
<div className="mt-6 grid grid-cols-12 gap-6"> <div className="mt-6 grid grid-cols-12 gap-6">
<NumberField name="log_score" label="Log score" placeholder="eg. 100" /> <NumberField name="log_score" label="Log score" placeholder="eg. 100" min={0} max={100} disabled={values.perfect_flac} />
</div> </div>
</div> </div>
@ -448,8 +448,8 @@ export function Music() {
</div> */} </div> */}
<div className="mt-4 sm:mt-0 sm:col-span-2"> <div className="mt-4 sm:mt-0 sm:col-span-2">
<div className="max-w-lg space-y-4"> <div className="max-w-lg space-y-4">
<CheckboxField name="log" label="Log" sublabel="Must include Log" /> <CheckboxField name="log" label="Log" sublabel="Must include Log" disabled={values.perfect_flac} />
<CheckboxField name="cue" label="Cue" sublabel="Must include Cue"/> <CheckboxField name="cue" label="Cue" sublabel="Must include Cue" disabled={values.perfect_flac} />
<CheckboxField name="perfect_flac" label="Perfect FLAC" sublabel="Override all options about quality, source, format, and cue/log/log score"/> <CheckboxField name="perfect_flac" label="Perfect FLAC" sublabel="Override all options about quality, source, format, and cue/log/log score"/>
</div> </div>
</div> </div>