feat(lists): integrate Omegabrr (#1885)

* feat(lists): integrate Omegabrr

* feat(lists): add missing lists index

* feat(lists): add db repo

* feat(lists): add db migrations

* feat(lists): labels

* feat(lists): url lists and more arrs

* fix(lists): db migrations client_id wrong type

* fix(lists): db fields

* feat(lists): create list form wip

* feat(lists): show in list and create

* feat(lists): update and delete

* feat(lists): trigger via webhook

* feat(lists): add webhook handler

* fix(arr): encode json to pointer

* feat(lists): rename endpoint to lists

* feat(lists): fetch tags from arr

* feat(lists): process plaintext lists

* feat(lists): add background refresh job

* run every 6th hour with a random start delay between 1-35 seconds

* feat(lists): refresh on save and improve logging

* feat(lists): cast arr client to pointer

* feat(lists): improve error handling

* feat(lists): reset shows field with match release

* feat(lists): filter opts all lists

* feat(lists): trigger on update if enabled

* feat(lists): update option for lists

* feat(lists): show connected filters in list

* feat(lists): missing listSvc dep

* feat(lists): cleanup

* feat(lists): typo arr list

* feat(lists): radarr include original

* feat(lists): rename ExcludeAlternateTitle to IncludeAlternateTitle

* fix(lists): arr client type conversion to pointer

* fix(actions): only log panic recover if err not nil

* feat(lists): show spinner on save

* feat(lists): show icon in filters list

* feat(lists): change icon color in filters list

* feat(lists): delete relations on filter delete
This commit is contained in:
ze0s 2024-12-25 13:23:37 +01:00 committed by GitHub
parent b68ae334ca
commit 221bc35371
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
77 changed files with 5025 additions and 254 deletions

View file

@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import { JSX } from "react";
import { Field as FormikField } from "formik";
import Select from "react-select";
import { Field, Label, Description } from "@headlessui/react";
@ -33,6 +34,7 @@ interface TextFieldWideProps {
placeholder?: string;
defaultValue?: string;
required?: boolean;
disabled?: boolean;
autoComplete?: string;
hidden?: boolean;
tooltip?: JSX.Element;
@ -46,6 +48,7 @@ export const TextFieldWide = ({
placeholder,
defaultValue,
required,
disabled,
autoComplete,
tooltip,
hidden,
@ -68,6 +71,7 @@ export const TextFieldWide = ({
value={defaultValue}
required={required}
validate={validate}
disabled={disabled}
>
{({ field, meta }: FieldProps) => (
<input
@ -76,11 +80,13 @@ export const TextFieldWide = ({
type="text"
value={field.value ? field.value : defaultValue ?? ""}
onChange={field.onChange}
disabled={disabled}
className={classNames(
meta.touched && meta.error
? "border-red-500 focus:ring-red-500 focus:border-red-500"
: "border-gray-300 dark:border-gray-700 focus:ring-blue-500 dark:focus:ring-blue-500 focus:border-blue-500 dark:focus:border-blue-500",
"block w-full shadow-sm sm:text-sm rounded-md border py-2.5 bg-gray-100 dark:bg-gray-850 dark:text-gray-100"
"block w-full shadow-sm sm:text-sm rounded-md border py-2.5 dark:text-gray-100",
disabled ? "bg-gray-200 dark:bg-gray-700" : "bg-gray-100 dark:bg-gray-850 "
)}
placeholder={placeholder}
hidden={hidden}
@ -273,7 +279,7 @@ export const SwitchGroupWide = ({
</div>
</Label>
{description && (
<Description className="text-sm text-gray-500 dark:text-gray-700">
<Description className="text-sm text-gray-500 dark:text-gray-500">
{description}
</Description>
)}

View file

@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import { JSX } from "react";
import { Field } from "formik";
import Select from "react-select";
import CreatableSelect from "react-select/creatable";
@ -11,6 +12,8 @@ import type { FieldProps } from "formik";
import { OptionBasicTyped } from "@domain/constants";
import * as common from "@components/inputs/common";
import { DocsTooltip } from "@components/tooltips/DocsTooltip";
import { MultiSelect as RMSC } from "react-multi-select-component";
import { MultiSelectOption } from "@components/inputs/select.tsx";
interface SelectFieldProps<T> {
name: string;
@ -228,3 +231,67 @@ export function SelectFieldBasic<T>({ name, label, help, placeholder, required,
</div>
);
}
export interface MultiSelectFieldProps {
name: string;
label: string;
help?: string;
placeholder?: string;
required?: boolean;
tooltip?: JSX.Element;
options: OptionBasicTyped<number>[];
}
interface ListFilterMultiSelectOption {
id: number;
name: string;
}
export function ListFilterMultiSelectField({ name, label, help, tooltip, options }: MultiSelectFieldProps) {
return (
<div className="flex items-center space-y-1 p-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4">
<div>
<label
htmlFor={name}
className="block ml-px text-sm font-medium text-gray-900 dark:text-white"
>
<div className="flex">
{tooltip ? (
<DocsTooltip label={label}>{tooltip}</DocsTooltip>
) : label}
</div>
</label>
</div>
<div className="sm:col-span-2">
<Field name={name} type="select">
{({
field,
form: { setFieldValue }
}: FieldProps) => (
<>
<RMSC
{...field}
options={options}
// disabled={disabled}
labelledBy={name}
// isCreatable={creatable}
// onCreateOption={handleNewField}
value={field.value && field.value.map((item: ListFilterMultiSelectOption) => ({
value: item.id,
label: item.name
}))}
onChange={(values: MultiSelectOption[]) => {
const item = values && values.map((i) => ({ id: i.value, name: i.label }));
setFieldValue(field.name, item);
}}
/>
</>
)}
</Field>
{help && (
<p className="mt-2 text-sm text-gray-500" id={`${name}-description`}>{help}</p>
)}
</div>
</div>
);
}