Refactoring: Moved First run components to Typescript function components
This commit is contained in:
parent
b1527f9abb
commit
2013a1f877
|
@ -24,7 +24,9 @@ export interface DownloadClientAppState
|
||||||
isTestingAll: boolean;
|
isTestingAll: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GeneralAppState = AppSectionItemState<General>;
|
export interface GeneralAppState
|
||||||
|
extends AppSectionItemState<General>,
|
||||||
|
AppSectionSaveState {}
|
||||||
|
|
||||||
export interface ImportListAppState
|
export interface ImportListAppState
|
||||||
extends AppSectionState<ImportList>,
|
extends AppSectionState<ImportList>,
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React from 'react';
|
|
||||||
import Modal from 'Components/Modal/Modal';
|
|
||||||
import { sizes } from 'Helpers/Props';
|
|
||||||
import AuthenticationRequiredModalContentConnector from './AuthenticationRequiredModalContentConnector';
|
|
||||||
|
|
||||||
function onModalClose() {
|
|
||||||
// No-op
|
|
||||||
}
|
|
||||||
|
|
||||||
function AuthenticationRequiredModal(props) {
|
|
||||||
const {
|
|
||||||
isOpen
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
size={sizes.MEDIUM}
|
|
||||||
isOpen={isOpen}
|
|
||||||
closeOnBackgroundClick={false}
|
|
||||||
onModalClose={onModalClose}
|
|
||||||
>
|
|
||||||
<AuthenticationRequiredModalContentConnector
|
|
||||||
onModalClose={onModalClose}
|
|
||||||
/>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthenticationRequiredModal.propTypes = {
|
|
||||||
isOpen: PropTypes.bool.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthenticationRequiredModal;
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import React from 'react';
|
||||||
|
import Modal from 'Components/Modal/Modal';
|
||||||
|
import { sizes } from 'Helpers/Props';
|
||||||
|
import AuthenticationRequiredModalContent from './AuthenticationRequiredModalContent';
|
||||||
|
|
||||||
|
function onModalClose() {
|
||||||
|
// No-op
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AuthenticationRequiredModalProps {
|
||||||
|
isOpen: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AuthenticationRequiredModal({
|
||||||
|
isOpen,
|
||||||
|
}: AuthenticationRequiredModalProps) {
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
size={sizes.MEDIUM}
|
||||||
|
isOpen={isOpen}
|
||||||
|
closeOnBackgroundClick={false}
|
||||||
|
onModalClose={onModalClose}
|
||||||
|
>
|
||||||
|
<AuthenticationRequiredModalContent />
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,170 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { useEffect, useRef } from 'react';
|
|
||||||
import Alert from 'Components/Alert';
|
|
||||||
import FormGroup from 'Components/Form/FormGroup';
|
|
||||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
|
||||||
import FormLabel from 'Components/Form/FormLabel';
|
|
||||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
|
||||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
|
||||||
import ModalBody from 'Components/Modal/ModalBody';
|
|
||||||
import ModalContent from 'Components/Modal/ModalContent';
|
|
||||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
|
||||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
|
||||||
import { inputTypes, kinds } from 'Helpers/Props';
|
|
||||||
import { authenticationMethodOptions, authenticationRequiredOptions } from 'Settings/General/SecuritySettings';
|
|
||||||
import translate from 'Utilities/String/translate';
|
|
||||||
import styles from './AuthenticationRequiredModalContent.css';
|
|
||||||
|
|
||||||
function onModalClose() {
|
|
||||||
// No-op
|
|
||||||
}
|
|
||||||
|
|
||||||
function AuthenticationRequiredModalContent(props) {
|
|
||||||
const {
|
|
||||||
isPopulated,
|
|
||||||
error,
|
|
||||||
isSaving,
|
|
||||||
settings,
|
|
||||||
onInputChange,
|
|
||||||
onSavePress,
|
|
||||||
dispatchFetchStatus
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const {
|
|
||||||
authenticationMethod,
|
|
||||||
authenticationRequired,
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
passwordConfirmation
|
|
||||||
} = settings;
|
|
||||||
|
|
||||||
const authenticationEnabled = authenticationMethod && authenticationMethod.value !== 'none';
|
|
||||||
|
|
||||||
const didMount = useRef(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isSaving && didMount.current) {
|
|
||||||
dispatchFetchStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
didMount.current = true;
|
|
||||||
}, [isSaving, dispatchFetchStatus]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ModalContent
|
|
||||||
showCloseButton={false}
|
|
||||||
onModalClose={onModalClose}
|
|
||||||
>
|
|
||||||
<ModalHeader>
|
|
||||||
{translate('AuthenticationRequired')}
|
|
||||||
</ModalHeader>
|
|
||||||
|
|
||||||
<ModalBody>
|
|
||||||
<Alert
|
|
||||||
className={styles.authRequiredAlert}
|
|
||||||
kind={kinds.WARNING}
|
|
||||||
>
|
|
||||||
{translate('AuthenticationRequiredWarning')}
|
|
||||||
</Alert>
|
|
||||||
|
|
||||||
{
|
|
||||||
isPopulated && !error ?
|
|
||||||
<div>
|
|
||||||
<FormGroup>
|
|
||||||
<FormLabel>{translate('AuthenticationMethod')}</FormLabel>
|
|
||||||
|
|
||||||
<FormInputGroup
|
|
||||||
type={inputTypes.SELECT}
|
|
||||||
name="authenticationMethod"
|
|
||||||
values={authenticationMethodOptions}
|
|
||||||
helpText={translate('AuthenticationMethodHelpText')}
|
|
||||||
helpTextWarning={authenticationMethod.value === 'none' ? translate('AuthenticationMethodHelpTextWarning') : undefined}
|
|
||||||
helpLink="https://wiki.servarr.com/sonarr/faq#forced-authentication"
|
|
||||||
onChange={onInputChange}
|
|
||||||
{...authenticationMethod}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup>
|
|
||||||
<FormLabel>{translate('AuthenticationRequired')}</FormLabel>
|
|
||||||
|
|
||||||
<FormInputGroup
|
|
||||||
type={inputTypes.SELECT}
|
|
||||||
name="authenticationRequired"
|
|
||||||
values={authenticationRequiredOptions}
|
|
||||||
helpText={translate('AuthenticationRequiredHelpText')}
|
|
||||||
onChange={onInputChange}
|
|
||||||
{...authenticationRequired}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup>
|
|
||||||
<FormLabel>{translate('Username')}</FormLabel>
|
|
||||||
|
|
||||||
<FormInputGroup
|
|
||||||
type={inputTypes.TEXT}
|
|
||||||
name="username"
|
|
||||||
onChange={onInputChange}
|
|
||||||
helpTextWarning={username?.value ? undefined : translate('AuthenticationRequiredUsernameHelpTextWarning')}
|
|
||||||
{...username}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup>
|
|
||||||
<FormLabel>{translate('Password')}</FormLabel>
|
|
||||||
|
|
||||||
<FormInputGroup
|
|
||||||
type={inputTypes.PASSWORD}
|
|
||||||
name="password"
|
|
||||||
onChange={onInputChange}
|
|
||||||
helpTextWarning={password?.value ? undefined : translate('AuthenticationRequiredPasswordHelpTextWarning')}
|
|
||||||
{...password}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup>
|
|
||||||
<FormLabel>{translate('PasswordConfirmation')}</FormLabel>
|
|
||||||
|
|
||||||
<FormInputGroup
|
|
||||||
type={inputTypes.PASSWORD}
|
|
||||||
name="passwordConfirmation"
|
|
||||||
onChange={onInputChange}
|
|
||||||
helpTextWarning={passwordConfirmation?.value ? undefined : translate('AuthenticationRequiredPasswordConfirmationHelpTextWarning')}
|
|
||||||
{...passwordConfirmation}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
</div> :
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
!isPopulated && !error ? <LoadingIndicator /> : null
|
|
||||||
}
|
|
||||||
</ModalBody>
|
|
||||||
|
|
||||||
<ModalFooter>
|
|
||||||
<SpinnerButton
|
|
||||||
kind={kinds.PRIMARY}
|
|
||||||
isSpinning={isSaving}
|
|
||||||
isDisabled={!authenticationEnabled}
|
|
||||||
onPress={onSavePress}
|
|
||||||
>
|
|
||||||
{translate('Save')}
|
|
||||||
</SpinnerButton>
|
|
||||||
</ModalFooter>
|
|
||||||
</ModalContent>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthenticationRequiredModalContent.propTypes = {
|
|
||||||
isPopulated: PropTypes.bool.isRequired,
|
|
||||||
error: PropTypes.object,
|
|
||||||
isSaving: PropTypes.bool.isRequired,
|
|
||||||
saveError: PropTypes.object,
|
|
||||||
settings: PropTypes.object.isRequired,
|
|
||||||
onInputChange: PropTypes.func.isRequired,
|
|
||||||
onSavePress: PropTypes.func.isRequired,
|
|
||||||
dispatchFetchStatus: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthenticationRequiredModalContent;
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
import React, { useCallback, useEffect } from 'react';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import Alert from 'Components/Alert';
|
||||||
|
import FormGroup from 'Components/Form/FormGroup';
|
||||||
|
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||||
|
import FormLabel from 'Components/Form/FormLabel';
|
||||||
|
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||||
|
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||||
|
import ModalBody from 'Components/Modal/ModalBody';
|
||||||
|
import ModalContent from 'Components/Modal/ModalContent';
|
||||||
|
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||||
|
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||||
|
import usePrevious from 'Helpers/Hooks/usePrevious';
|
||||||
|
import { inputTypes, kinds } from 'Helpers/Props';
|
||||||
|
import {
|
||||||
|
authenticationMethodOptions,
|
||||||
|
authenticationRequiredOptions,
|
||||||
|
} from 'Settings/General/SecuritySettings';
|
||||||
|
import { clearPendingChanges } from 'Store/Actions/baseActions';
|
||||||
|
import {
|
||||||
|
fetchGeneralSettings,
|
||||||
|
saveGeneralSettings,
|
||||||
|
setGeneralSettingsValue,
|
||||||
|
} from 'Store/Actions/settingsActions';
|
||||||
|
import { fetchStatus } from 'Store/Actions/systemActions';
|
||||||
|
import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector';
|
||||||
|
import { InputChanged } from 'typings/inputs';
|
||||||
|
import translate from 'Utilities/String/translate';
|
||||||
|
import styles from './AuthenticationRequiredModalContent.css';
|
||||||
|
|
||||||
|
const SECTION = 'general';
|
||||||
|
|
||||||
|
const selector = createSettingsSectionSelector(SECTION);
|
||||||
|
|
||||||
|
function onModalClose() {
|
||||||
|
// No-op
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AuthenticationRequiredModalContent() {
|
||||||
|
const { isPopulated, error, isSaving, settings } = useSelector(selector);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const {
|
||||||
|
authenticationMethod,
|
||||||
|
authenticationRequired,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
passwordConfirmation,
|
||||||
|
} = settings;
|
||||||
|
|
||||||
|
const wasSaving = usePrevious(isSaving);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(fetchGeneralSettings());
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
dispatch(clearPendingChanges());
|
||||||
|
};
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const onInputChange = useCallback(
|
||||||
|
(args: InputChanged) => {
|
||||||
|
// @ts-expect-error Actions aren't typed
|
||||||
|
dispatch(setGeneralSettingsValue(args));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
const authenticationEnabled =
|
||||||
|
authenticationMethod && authenticationMethod.value !== 'none';
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isSaving || !wasSaving) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(fetchStatus());
|
||||||
|
}, [isSaving, wasSaving, dispatch]);
|
||||||
|
|
||||||
|
const onPress = useCallback(() => {
|
||||||
|
dispatch(saveGeneralSettings());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalContent showCloseButton={false} onModalClose={onModalClose}>
|
||||||
|
<ModalHeader>{translate('AuthenticationRequired')}</ModalHeader>
|
||||||
|
|
||||||
|
<ModalBody>
|
||||||
|
<Alert className={styles.authRequiredAlert} kind={kinds.WARNING}>
|
||||||
|
{translate('AuthenticationRequiredWarning')}
|
||||||
|
</Alert>
|
||||||
|
|
||||||
|
{isPopulated && !error ? (
|
||||||
|
<div>
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('AuthenticationMethod')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.SELECT}
|
||||||
|
name="authenticationMethod"
|
||||||
|
values={authenticationMethodOptions}
|
||||||
|
helpText={translate('AuthenticationMethodHelpText')}
|
||||||
|
helpTextWarning={
|
||||||
|
authenticationMethod.value === 'none'
|
||||||
|
? translate('AuthenticationMethodHelpTextWarning')
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
helpLink="https://wiki.servarr.com/sonarr/faq#forced-authentication"
|
||||||
|
onChange={onInputChange}
|
||||||
|
{...authenticationMethod}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('AuthenticationRequired')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.SELECT}
|
||||||
|
name="authenticationRequired"
|
||||||
|
values={authenticationRequiredOptions}
|
||||||
|
helpText={translate('AuthenticationRequiredHelpText')}
|
||||||
|
onChange={onInputChange}
|
||||||
|
{...authenticationRequired}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('Username')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.TEXT}
|
||||||
|
name="username"
|
||||||
|
helpTextWarning={
|
||||||
|
username?.value
|
||||||
|
? undefined
|
||||||
|
: translate('AuthenticationRequiredUsernameHelpTextWarning')
|
||||||
|
}
|
||||||
|
onChange={onInputChange}
|
||||||
|
{...username}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('Password')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.PASSWORD}
|
||||||
|
name="password"
|
||||||
|
helpTextWarning={
|
||||||
|
password?.value
|
||||||
|
? undefined
|
||||||
|
: translate('AuthenticationRequiredPasswordHelpTextWarning')
|
||||||
|
}
|
||||||
|
onChange={onInputChange}
|
||||||
|
{...password}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<FormLabel>{translate('PasswordConfirmation')}</FormLabel>
|
||||||
|
|
||||||
|
<FormInputGroup
|
||||||
|
type={inputTypes.PASSWORD}
|
||||||
|
name="passwordConfirmation"
|
||||||
|
helpTextWarning={
|
||||||
|
passwordConfirmation?.value
|
||||||
|
? undefined
|
||||||
|
: translate(
|
||||||
|
'AuthenticationRequiredPasswordConfirmationHelpTextWarning'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onChange={onInputChange}
|
||||||
|
{...passwordConfirmation}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{!isPopulated && !error ? <LoadingIndicator /> : null}
|
||||||
|
</ModalBody>
|
||||||
|
|
||||||
|
<ModalFooter>
|
||||||
|
<SpinnerButton
|
||||||
|
kind={kinds.PRIMARY}
|
||||||
|
isSpinning={isSaving}
|
||||||
|
isDisabled={!authenticationEnabled}
|
||||||
|
onPress={onPress}
|
||||||
|
>
|
||||||
|
{translate('Save')}
|
||||||
|
</SpinnerButton>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,86 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
import { clearPendingChanges } from 'Store/Actions/baseActions';
|
|
||||||
import { fetchGeneralSettings, saveGeneralSettings, setGeneralSettingsValue } from 'Store/Actions/settingsActions';
|
|
||||||
import { fetchStatus } from 'Store/Actions/systemActions';
|
|
||||||
import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector';
|
|
||||||
import AuthenticationRequiredModalContent from './AuthenticationRequiredModalContent';
|
|
||||||
|
|
||||||
const SECTION = 'general';
|
|
||||||
|
|
||||||
function createMapStateToProps() {
|
|
||||||
return createSelector(
|
|
||||||
createSettingsSectionSelector(SECTION),
|
|
||||||
(sectionSettings) => {
|
|
||||||
return {
|
|
||||||
...sectionSettings
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
|
||||||
dispatchClearPendingChanges: clearPendingChanges,
|
|
||||||
dispatchSetGeneralSettingsValue: setGeneralSettingsValue,
|
|
||||||
dispatchSaveGeneralSettings: saveGeneralSettings,
|
|
||||||
dispatchFetchGeneralSettings: fetchGeneralSettings,
|
|
||||||
dispatchFetchStatus: fetchStatus
|
|
||||||
};
|
|
||||||
|
|
||||||
class AuthenticationRequiredModalContentConnector extends Component {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Lifecycle
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.props.dispatchFetchGeneralSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
this.props.dispatchClearPendingChanges({ section: `settings.${SECTION}` });
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Listeners
|
|
||||||
|
|
||||||
onInputChange = ({ name, value }) => {
|
|
||||||
this.props.dispatchSetGeneralSettingsValue({ name, value });
|
|
||||||
};
|
|
||||||
|
|
||||||
onSavePress = () => {
|
|
||||||
this.props.dispatchSaveGeneralSettings();
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Render
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
dispatchClearPendingChanges,
|
|
||||||
dispatchFetchGeneralSettings,
|
|
||||||
dispatchSetGeneralSettingsValue,
|
|
||||||
dispatchSaveGeneralSettings,
|
|
||||||
...otherProps
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AuthenticationRequiredModalContent
|
|
||||||
{...otherProps}
|
|
||||||
onInputChange={this.onInputChange}
|
|
||||||
onSavePress={this.onSavePress}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthenticationRequiredModalContentConnector.propTypes = {
|
|
||||||
dispatchClearPendingChanges: PropTypes.func.isRequired,
|
|
||||||
dispatchFetchGeneralSettings: PropTypes.func.isRequired,
|
|
||||||
dispatchSetGeneralSettingsValue: PropTypes.func.isRequired,
|
|
||||||
dispatchSaveGeneralSettings: PropTypes.func.isRequired,
|
|
||||||
dispatchFetchStatus: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(createMapStateToProps, mapDispatchToProps)(AuthenticationRequiredModalContentConnector);
|
|
|
@ -1,4 +1,6 @@
|
||||||
export type CheckInputChanged = {
|
export type InputChanged<T = unknown> = {
|
||||||
name: string;
|
name: string;
|
||||||
value: boolean;
|
value: T;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CheckInputChanged = InputChanged<boolean>;
|
||||||
|
|
Loading…
Reference in New Issue