RTKQ: Add typing to RTKQ hooks in apiSlice
This commit adds typing to the RTK Query hooks. The hooks have been refactored to be simpler and all custom query functions have been removed.
This commit is contained in:
parent
1b01cfba0b
commit
0fd07f1f74
19 changed files with 237 additions and 242 deletions
|
|
@ -0,0 +1,10 @@
|
|||
import {useGetSourceDetailQuery} from "../../../store/apiSlice";
|
||||
|
||||
type AWSAccountIdProps = {
|
||||
sourceId: string
|
||||
}
|
||||
|
||||
export const AWSAccountId = ({ sourceId }: AWSAccountIdProps) => {
|
||||
const { data } = useGetSourceDetailQuery(sourceId);
|
||||
return <>{data?.aws?.account_id}</>;
|
||||
};
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { FormSpy } from '@data-driven-forms/react-form-renderer';
|
||||
import useFieldApi from '@data-driven-forms/react-form-renderer/use-field-api';
|
||||
import useFormApi from '@data-driven-forms/react-form-renderer/use-form-api';
|
||||
import { Alert } from '@patternfly/react-core';
|
||||
|
|
@ -12,7 +13,10 @@ import {
|
|||
} from '@patternfly/react-core';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useGetAWSSourcesQuery } from '../../../store/apiSlice';
|
||||
import {
|
||||
useGetSourceDetailQuery,
|
||||
useGetSourcesQuery,
|
||||
} from '../../../store/apiSlice';
|
||||
|
||||
export const AWSSourcesSelect = ({
|
||||
label,
|
||||
|
|
@ -33,7 +37,31 @@ export const AWSSourcesSelect = ({
|
|||
isSuccess,
|
||||
isError,
|
||||
refetch,
|
||||
} = useGetAWSSourcesQuery();
|
||||
} = useGetSourcesQuery('aws');
|
||||
|
||||
const {
|
||||
data: sourceDetails,
|
||||
isFetching: isFetchingDetails,
|
||||
isSuccess: isSuccessDetails,
|
||||
isError: isErrorDetails,
|
||||
} = useGetSourceDetailQuery(selectedSourceId, {
|
||||
skip: !selectedSourceId,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (isFetchingDetails || !isSuccessDetails) return;
|
||||
change('aws-associated-account-id', sourceDetails?.aws?.account_id);
|
||||
}, [isFetchingDetails, isSuccessDetails]);
|
||||
|
||||
const onFormChange = ({ values }) => {
|
||||
if (
|
||||
values['aws-target-type'] !== 'aws-target-type-source' ||
|
||||
values[input.name] === undefined
|
||||
) {
|
||||
change(input.name, undefined);
|
||||
change('aws-associated-account-id', undefined);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelect = (_, sourceName) => {
|
||||
const sourceId = sources.find((source) => source.name === sourceName).id;
|
||||
|
|
@ -58,6 +86,7 @@ export const AWSSourcesSelect = ({
|
|||
|
||||
return (
|
||||
<>
|
||||
<FormSpy subscription={{ values: true }} onChange={onFormChange} />
|
||||
<FormGroup
|
||||
isRequired={isRequired}
|
||||
label={label}
|
||||
|
|
@ -82,11 +111,7 @@ export const AWSSourcesSelect = ({
|
|||
>
|
||||
{isSuccess &&
|
||||
sources.map((source) => (
|
||||
<SelectOption
|
||||
key={source.id}
|
||||
value={source.name}
|
||||
description={source.account_id}
|
||||
/>
|
||||
<SelectOption key={source.id} value={source.name} />
|
||||
))}
|
||||
{isFetching && (
|
||||
<SelectOption isNoResultsOption={true}>
|
||||
|
|
@ -107,6 +132,18 @@ export const AWSSourcesSelect = ({
|
|||
ID manually.
|
||||
</Alert>
|
||||
)}
|
||||
{!isError && isErrorDetails && (
|
||||
<Alert
|
||||
variant={'danger'}
|
||||
isPlain
|
||||
isInline
|
||||
title={'AWS details unavailable'}
|
||||
>
|
||||
The AWS account ID for the selected source could not be resolved.
|
||||
There might be a problem with the source. Verify that the source is
|
||||
valid in Sources or select a different source.
|
||||
</Alert>
|
||||
)}
|
||||
</>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
} from '@patternfly/react-core';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useGetAzureSourceDetailQuery } from '../../../store/apiSlice';
|
||||
import { useGetSourceDetailQuery } from '../../../store/apiSlice';
|
||||
|
||||
const AzureResourceGroups = ({ label, isRequired, className, ...props }) => {
|
||||
const { change, getState } = useFormApi();
|
||||
|
|
@ -25,13 +25,14 @@ const AzureResourceGroups = ({ label, isRequired, className, ...props }) => {
|
|||
setSourceId(values['azure-sources-select']);
|
||||
};
|
||||
|
||||
const { data: sourceDetails, isFetching } = useGetAzureSourceDetailQuery(
|
||||
const { data: sourceDetails, isFetching } = useGetSourceDetailQuery(
|
||||
sourceId,
|
||||
{
|
||||
skip: !sourceId,
|
||||
}
|
||||
);
|
||||
const resourceGroups = (sourceId && sourceDetails?.resource_groups) || [];
|
||||
const resourceGroups =
|
||||
(sourceId && sourceDetails?.azure?.resource_groups) || [];
|
||||
|
||||
const setResourceGroup = (_, selection) => {
|
||||
setIsOpen(false);
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import {
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
useGetAzureSourcesQuery,
|
||||
useGetAzureSourceDetailQuery,
|
||||
useGetSourcesQuery,
|
||||
useGetSourceDetailQuery,
|
||||
} from '../../../store/apiSlice';
|
||||
|
||||
const AzureSourcesSelect = ({ label, isRequired, className, ...props }) => {
|
||||
|
|
@ -30,21 +30,21 @@ const AzureSourcesSelect = ({ label, isRequired, className, ...props }) => {
|
|||
isSuccess,
|
||||
isError,
|
||||
refetch,
|
||||
} = useGetAzureSourcesQuery();
|
||||
} = useGetSourcesQuery('azure');
|
||||
|
||||
const {
|
||||
data: sourceDetails,
|
||||
isFetching: isFetchingDetails,
|
||||
isSuccess: isSuccessDetails,
|
||||
isError: isErrorDetails,
|
||||
} = useGetAzureSourceDetailQuery(selectedSourceId, {
|
||||
} = useGetSourceDetailQuery(selectedSourceId, {
|
||||
skip: !selectedSourceId,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (isFetchingDetails || !isSuccessDetails) return;
|
||||
change('azure-tenant-id', sourceDetails.tenant_id);
|
||||
change('azure-subscription-id', sourceDetails.subscription_id);
|
||||
change('azure-tenant-id', sourceDetails?.azure?.tenant_id);
|
||||
change('azure-subscription-id', sourceDetails?.azure?.subscription_id);
|
||||
}, [isFetchingDetails, isSuccessDetails]);
|
||||
|
||||
const onFormChange = ({ values }) => {
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
import React, { useEffect } from 'react';
|
||||
|
||||
import { FormSpy, useFormApi } from '@data-driven-forms/react-form-renderer';
|
||||
|
||||
import { useGetAWSSourcesQuery } from '../../../store/apiSlice';
|
||||
|
||||
const FieldListener = () => {
|
||||
// This listener synchronizes the value of the AWS account ID text field with the
|
||||
// value of the AWS source select field on the AWS target step.
|
||||
// Using a listener to set the value of one field according to the value of another
|
||||
// is a recommended pattern for Data Driven Forms:
|
||||
// https://www.data-driven-forms.org/examples/value-listener
|
||||
const { getState, change } = useFormApi();
|
||||
const awsSourcesSelect = getState().values['aws-sources-select'];
|
||||
const { data: awsSources } = useGetAWSSourcesQuery();
|
||||
|
||||
useEffect(() => {
|
||||
if (awsSourcesSelect) {
|
||||
const awsAccountId = awsSources.find(
|
||||
(source) => source.id === getState()?.values?.['aws-sources-select']
|
||||
)?.account_id;
|
||||
|
||||
change('aws-associated-account-id', awsAccountId);
|
||||
} else {
|
||||
change('aws-associated-account-id', undefined);
|
||||
}
|
||||
}, [awsSourcesSelect]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const FieldListenerWrapper = () => (
|
||||
<FormSpy subcription={{ values: true }}>{() => <FieldListener />}</FormSpy>
|
||||
);
|
||||
|
||||
export default FieldListenerWrapper;
|
||||
|
|
@ -205,21 +205,48 @@ const Repositories = (props) => {
|
|||
const release = getState().values?.release;
|
||||
const version = releaseToVersion(release);
|
||||
|
||||
const firstRequest = useGetRepositoriesQuery(
|
||||
{
|
||||
available_for_arch: 'x86_64',
|
||||
available_for_version: version,
|
||||
limit: 100,
|
||||
offset: 0,
|
||||
},
|
||||
// The cached repos may be incorrect, for now refetch on mount to ensure that
|
||||
// they are accurate when this step loads. Future PR will implement prefetching
|
||||
// and this can be removed.
|
||||
{ refetchOnMountOrArgChange: true }
|
||||
);
|
||||
|
||||
const skip =
|
||||
firstRequest?.data?.meta?.count === undefined ||
|
||||
firstRequest?.data?.meta?.count <= 100;
|
||||
|
||||
// Fetch *all* repositories if there are more than 100 so that typeahead filter works
|
||||
const followupRequest = useGetRepositoriesQuery(
|
||||
{
|
||||
available_for_arch: 'x86_64',
|
||||
available_for_version: version,
|
||||
limit: firstRequest?.data?.meta?.count,
|
||||
offset: 0,
|
||||
},
|
||||
{
|
||||
refetchOnMountOrArgChange: true,
|
||||
skip: skip,
|
||||
}
|
||||
);
|
||||
|
||||
const { data, isError, isFetching, isLoading, isSuccess, refetch } =
|
||||
useGetRepositoriesQuery(
|
||||
{
|
||||
available_for_arch: 'x86_64',
|
||||
available_for_version: version,
|
||||
},
|
||||
// The cached repos may be incorrect, for now refetch on mount to ensure that
|
||||
// they are accurate when this step loads. Future PR will implement prefetching
|
||||
// and this can be removed.
|
||||
{ refetchOnMountOrArgChange: true }
|
||||
);
|
||||
useMemo(() => {
|
||||
if (firstRequest?.data?.meta?.count > 100) {
|
||||
return { ...followupRequest };
|
||||
}
|
||||
return { ...firstRequest };
|
||||
}, [firstRequest, followupRequest]);
|
||||
|
||||
const repositories = useMemo(() => {
|
||||
return data ? initializeRepositories(data.data) : {};
|
||||
}, [data]);
|
||||
}, [firstRequest.data, followupRequest.data]);
|
||||
|
||||
const isRepoSelected = (repoURL) => selected.includes(repoURL);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
import { ExclamationTriangleIcon, HelpIcon } from '@patternfly/react-icons';
|
||||
|
||||
import ActivationKeyInformation from './ActivationKeyInformation';
|
||||
import { AWSAccountId } from './AWSAccountId';
|
||||
import {
|
||||
FSReviewTable,
|
||||
PackagesTable,
|
||||
|
|
@ -24,11 +25,9 @@ import {
|
|||
} from './ReviewStepTables';
|
||||
|
||||
import { RELEASES, UNIT_GIB } from '../../../constants';
|
||||
import {
|
||||
useGetAWSSourcesQuery,
|
||||
useGetAzureSourcesQuery,
|
||||
} from '../../../store/apiSlice';
|
||||
import { useGetSourcesQuery } from '../../../store/apiSlice';
|
||||
import { useGetActivationKeyInformationQuery } from '../../../store/apiSlice';
|
||||
import { useGetEnvironment } from '../../../Utilities/useGetEnvironment';
|
||||
import { googleAccType } from '../steps/googleCloud';
|
||||
|
||||
const ExpirationWarning = () => {
|
||||
|
|
@ -64,8 +63,8 @@ export const ImageOutputList = () => {
|
|||
};
|
||||
|
||||
export const TargetEnvAWSList = () => {
|
||||
const { data: awsSources, isSuccess: isSuccessAWSSources } =
|
||||
useGetAWSSourcesQuery();
|
||||
const { data: awsSources, isSuccess } = useGetSourcesQuery();
|
||||
const { isBeta } = useGetEnvironment();
|
||||
|
||||
const { getState } = useFormApi();
|
||||
return (
|
||||
|
|
@ -87,13 +86,19 @@ export const TargetEnvAWSList = () => {
|
|||
Shared to account
|
||||
</TextListItem>
|
||||
<TextListItem component={TextListItemVariants.dd}>
|
||||
{isSuccessAWSSources &&
|
||||
getState()?.values?.['aws-target-type'] === 'aws-target-type-source'
|
||||
? awsSources.find(
|
||||
(source) =>
|
||||
source.id === getState()?.values?.['aws-sources-select']
|
||||
)?.account_id
|
||||
: getState()?.values?.['aws-account-id']}
|
||||
{!isBeta() && getState()?.values?.['aws-account-id']}
|
||||
{isBeta() &&
|
||||
getState()?.values?.['aws-target-type'] ===
|
||||
'aws-target-type-source' &&
|
||||
isSuccess && (
|
||||
<AWSAccountId
|
||||
sourceId={getState()?.values?.['aws-sources-select']}
|
||||
/>
|
||||
)}
|
||||
{isBeta() &&
|
||||
getState()?.values?.['aws-target-type'] ===
|
||||
'aws-target-type-account-id' &&
|
||||
getState()?.values?.['aws-account-id']}
|
||||
</TextListItem>
|
||||
<TextListItem component={TextListItemVariants.dt}>
|
||||
{getState()?.values?.['aws-target-type'] === 'aws-target-type-source'
|
||||
|
|
@ -101,7 +106,7 @@ export const TargetEnvAWSList = () => {
|
|||
: null}
|
||||
</TextListItem>
|
||||
<TextListItem component={TextListItemVariants.dd}>
|
||||
{isSuccessAWSSources &&
|
||||
{isSuccess &&
|
||||
getState()?.values?.['aws-target-type'] === 'aws-target-type-source'
|
||||
? awsSources.find(
|
||||
(source) =>
|
||||
|
|
@ -163,7 +168,7 @@ export const TargetEnvGCPList = () => {
|
|||
export const TargetEnvAzureList = () => {
|
||||
const { getState } = useFormApi();
|
||||
const { data: azureSources, isSuccess: isSuccessAzureSources } =
|
||||
useGetAzureSourcesQuery();
|
||||
useGetSourcesQuery('azure');
|
||||
return (
|
||||
<TextContent>
|
||||
<Text component={TextVariants.h3}>Microsoft Azure</Text>
|
||||
|
|
|
|||
|
|
@ -24,8 +24,7 @@ const TargetEnvironment = ({ label, isRequired, ...props }) => {
|
|||
'guest-image': false,
|
||||
'image-installer': false,
|
||||
});
|
||||
const prefetchAWSSources = usePrefetch('getAWSSources');
|
||||
const prefetchAzureSources = usePrefetch('getAzureSources');
|
||||
const prefetchSources = usePrefetch('getSources');
|
||||
|
||||
useEffect(() => {
|
||||
if (getState()?.values?.[input.name]) {
|
||||
|
|
@ -73,7 +72,7 @@ const TargetEnvironment = ({ label, isRequired, ...props }) => {
|
|||
}
|
||||
onClick={() => handleSetEnvironment('aws')}
|
||||
onKeyDown={(e) => handleKeyDown(e, 'aws')}
|
||||
onMouseEnter={() => prefetchAWSSources()}
|
||||
onMouseEnter={() => prefetchSources('aws')}
|
||||
isSelected={environment.aws}
|
||||
isStacked
|
||||
isDisplayLarge
|
||||
|
|
@ -110,7 +109,7 @@ const TargetEnvironment = ({ label, isRequired, ...props }) => {
|
|||
}
|
||||
onClick={() => handleSetEnvironment('azure')}
|
||||
onKeyDown={(e) => handleKeyDown(e, 'azure')}
|
||||
onMouseEnter={() => prefetchAzureSources()}
|
||||
onMouseEnter={() => prefetchSources('azure')}
|
||||
isSelected={environment.azure}
|
||||
isStacked
|
||||
isDisplayLarge
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue