mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-19 21:46:43 -04:00
Convert Form Components to TypeScript
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user