mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-03-05 13:20:20 -05:00
165 lines
4.1 KiB
TypeScript
165 lines
4.1 KiB
TypeScript
import { isEqual } from 'lodash';
|
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
import { createSelector } from 'reselect';
|
|
import AppState from 'App/State/AppState';
|
|
import ProviderOptionsAppState, {
|
|
ProviderOptions,
|
|
} from 'App/State/ProviderOptionsAppState';
|
|
import usePrevious from 'Helpers/Hooks/usePrevious';
|
|
import {
|
|
clearOptions,
|
|
fetchOptions,
|
|
} from 'Store/Actions/providerOptionActions';
|
|
import { FieldSelectOption } from 'typings/Field';
|
|
import EnhancedSelectInput, {
|
|
EnhancedSelectInputProps,
|
|
EnhancedSelectInputValue,
|
|
} from './EnhancedSelectInput';
|
|
|
|
const importantFieldNames = ['baseUrl', 'apiPath', 'apiKey', 'authToken'];
|
|
|
|
function getProviderDataKey(providerData: ProviderOptions) {
|
|
if (!providerData || !providerData.fields) {
|
|
return null;
|
|
}
|
|
|
|
const fields = providerData.fields
|
|
.filter((f) => importantFieldNames.includes(f.name))
|
|
.map((f) => f.value);
|
|
|
|
return fields;
|
|
}
|
|
|
|
function getSelectOptions(items: FieldSelectOption<unknown>[]) {
|
|
if (!items) {
|
|
return [];
|
|
}
|
|
|
|
return items.map((option) => {
|
|
return {
|
|
key: option.value,
|
|
value: option.name,
|
|
hint: option.hint,
|
|
parentKey: option.parentValue,
|
|
isDisabled: option.isDisabled,
|
|
additionalProperties: option.additionalProperties,
|
|
};
|
|
});
|
|
}
|
|
|
|
function createProviderOptionsSelector(
|
|
selectOptionsProviderAction: keyof Omit<ProviderOptionsAppState, 'devices'>
|
|
) {
|
|
return createSelector(
|
|
(state: AppState) => state.providerOptions[selectOptionsProviderAction],
|
|
(options) => {
|
|
if (!options) {
|
|
return {
|
|
isFetching: false,
|
|
values: [],
|
|
};
|
|
}
|
|
|
|
return {
|
|
isFetching: options.isFetching,
|
|
values: getSelectOptions(options.items),
|
|
};
|
|
}
|
|
);
|
|
}
|
|
|
|
interface ProviderOptionSelectInputProps
|
|
extends Omit<
|
|
EnhancedSelectInputProps<EnhancedSelectInputValue<unknown>, unknown>,
|
|
'values'
|
|
> {
|
|
provider: string;
|
|
providerData: ProviderOptions;
|
|
name: string;
|
|
value: unknown;
|
|
selectOptionsProviderAction: keyof Omit<ProviderOptionsAppState, 'devices'>;
|
|
}
|
|
|
|
function ProviderOptionSelectInput({
|
|
provider,
|
|
providerData,
|
|
selectOptionsProviderAction,
|
|
...otherProps
|
|
}: ProviderOptionSelectInputProps) {
|
|
const dispatch = useDispatch();
|
|
const [isRefetchRequired, setIsRefetchRequired] = useState(false);
|
|
const previousProviderData = usePrevious(providerData);
|
|
const { isFetching, values } = useSelector(
|
|
createProviderOptionsSelector(selectOptionsProviderAction)
|
|
);
|
|
|
|
const handleOpen = useCallback(() => {
|
|
if (isRefetchRequired && selectOptionsProviderAction) {
|
|
setIsRefetchRequired(false);
|
|
|
|
dispatch(
|
|
fetchOptions({
|
|
section: selectOptionsProviderAction,
|
|
action: selectOptionsProviderAction,
|
|
provider,
|
|
providerData,
|
|
})
|
|
);
|
|
}
|
|
}, [
|
|
isRefetchRequired,
|
|
provider,
|
|
providerData,
|
|
selectOptionsProviderAction,
|
|
dispatch,
|
|
]);
|
|
|
|
useEffect(() => {
|
|
if (selectOptionsProviderAction) {
|
|
dispatch(
|
|
fetchOptions({
|
|
section: selectOptionsProviderAction,
|
|
action: selectOptionsProviderAction,
|
|
provider,
|
|
providerData,
|
|
})
|
|
);
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [selectOptionsProviderAction, dispatch]);
|
|
|
|
useEffect(() => {
|
|
if (!previousProviderData) {
|
|
return;
|
|
}
|
|
|
|
const prevKey = getProviderDataKey(previousProviderData);
|
|
const nextKey = getProviderDataKey(providerData);
|
|
|
|
if (!isEqual(prevKey, nextKey)) {
|
|
setIsRefetchRequired(true);
|
|
}
|
|
}, [providerData, previousProviderData, setIsRefetchRequired]);
|
|
|
|
useEffect(() => {
|
|
return () => {
|
|
if (selectOptionsProviderAction) {
|
|
dispatch(clearOptions({ section: selectOptionsProviderAction }));
|
|
}
|
|
};
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
|
|
return (
|
|
<EnhancedSelectInput
|
|
{...otherProps}
|
|
isFetching={isFetching}
|
|
values={values}
|
|
onOpen={handleOpen}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export default ProviderOptionSelectInput;
|