V2Wizard: Create a folder for Azure step and copy needed components
This created a new folder for the Azure step and copies components that will be needed: - AzureAuthButton.tsx - AzureResouceGroups.tsx - AzureSourcesSelect.tsx
This commit is contained in:
parent
47461f9089
commit
fa016c3228
3 changed files with 294 additions and 0 deletions
|
|
@ -0,0 +1,35 @@
|
|||
import React from 'react';
|
||||
|
||||
import useFormApi from '@data-driven-forms/react-form-renderer/use-form-api';
|
||||
import { Button, FormGroup } from '@patternfly/react-core';
|
||||
|
||||
const AzureAuthButton = () => {
|
||||
const { getState } = useFormApi();
|
||||
|
||||
const tenantId = getState()?.values?.['azure-tenant-id'];
|
||||
const guidRegex = new RegExp(
|
||||
'^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$',
|
||||
'i'
|
||||
);
|
||||
|
||||
return (
|
||||
<FormGroup>
|
||||
<Button
|
||||
component="a"
|
||||
target="_blank"
|
||||
variant="secondary"
|
||||
isDisabled={!guidRegex.test(tenantId)}
|
||||
href={
|
||||
'https://login.microsoftonline.com/' +
|
||||
tenantId +
|
||||
'/oauth2/v2.0/authorize?client_id=b94bb246-b02c-4985-9c22-d44e66f657f4&scope=openid&' +
|
||||
'response_type=code&response_mode=query&redirect_uri=https://portal.azure.com'
|
||||
}
|
||||
>
|
||||
Authorize Image Builder
|
||||
</Button>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export default AzureAuthButton;
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
import React, { useState } from 'react';
|
||||
|
||||
import FormSpy from '@data-driven-forms/react-form-renderer/form-spy';
|
||||
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 { FormGroup, Spinner } from '@patternfly/react-core';
|
||||
import {
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from '@patternfly/react-core/deprecated';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { useGetSourceUploadInfoQuery } from '../../../store/provisioningApi';
|
||||
|
||||
const AzureResourceGroups = ({ label, isRequired, className, ...props }) => {
|
||||
const { change, getState } = useFormApi();
|
||||
const { input } = useFieldApi(props);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [sourceId, setSourceId] = useState(
|
||||
getState()?.values?.['azure-sources-select']
|
||||
);
|
||||
const onFormChange = ({ values }) => {
|
||||
setSourceId(values['azure-sources-select']);
|
||||
};
|
||||
|
||||
const { data: sourceDetails, isFetching } = useGetSourceUploadInfoQuery(
|
||||
{ id: sourceId },
|
||||
{
|
||||
skip: !sourceId,
|
||||
}
|
||||
);
|
||||
const resourceGroups =
|
||||
(sourceId && sourceDetails?.azure?.resource_groups) || [];
|
||||
|
||||
const setResourceGroup = (_, selection) => {
|
||||
setIsOpen(false);
|
||||
change(input.name, selection);
|
||||
};
|
||||
|
||||
const handleClear = () => {
|
||||
change(input.name, undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
isRequired={isRequired}
|
||||
label={label}
|
||||
data-testid="azure-resource-groups"
|
||||
>
|
||||
<FormSpy subscription={{ values: true }} onChange={onFormChange} />
|
||||
<Select
|
||||
ouiaId="resource_group_select"
|
||||
variant={SelectVariant.typeahead}
|
||||
className={className}
|
||||
onToggle={() => setIsOpen(!isOpen)}
|
||||
onSelect={setResourceGroup}
|
||||
onClear={handleClear}
|
||||
selections={input.value}
|
||||
isOpen={isOpen}
|
||||
placeholderText="Select resource group"
|
||||
typeAheadAriaLabel="Select resource group"
|
||||
>
|
||||
{isFetching && (
|
||||
<SelectOption
|
||||
isNoResultsOption={true}
|
||||
data-testid="azure-resource-groups-loading"
|
||||
>
|
||||
<Spinner size="lg" />
|
||||
</SelectOption>
|
||||
)}
|
||||
{resourceGroups.map((name, index) => (
|
||||
<SelectOption
|
||||
key={index}
|
||||
value={name}
|
||||
aria-label={`Resource group ${name}`}
|
||||
/>
|
||||
))}
|
||||
</Select>
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
|
||||
AzureResourceGroups.propTypes = {
|
||||
label: PropTypes.node,
|
||||
isRequired: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
AzureResourceGroups.defaultProps = {
|
||||
label: '',
|
||||
isRequired: false,
|
||||
className: '',
|
||||
};
|
||||
|
||||
export default AzureResourceGroups;
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import FormSpy from '@data-driven-forms/react-form-renderer/form-spy';
|
||||
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';
|
||||
import { FormGroup, Spinner } from '@patternfly/react-core';
|
||||
import {
|
||||
Select,
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
} from '@patternfly/react-core/deprecated';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { extractProvisioningList } from '../../../store/helpers';
|
||||
import {
|
||||
useGetSourceListQuery,
|
||||
useGetSourceUploadInfoQuery,
|
||||
} from '../../../store/provisioningApi';
|
||||
|
||||
const AzureSourcesSelect = ({ label, isRequired, className, ...props }) => {
|
||||
const { change } = useFormApi();
|
||||
const { input } = useFieldApi(props);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const selectedSourceId = input.value;
|
||||
|
||||
const {
|
||||
data: rawSources,
|
||||
isFetching,
|
||||
isSuccess,
|
||||
isError,
|
||||
refetch,
|
||||
} = useGetSourceListQuery({ provider: 'azure' });
|
||||
const sources = extractProvisioningList(rawSources);
|
||||
|
||||
const {
|
||||
data: sourceDetails,
|
||||
isFetching: isFetchingDetails,
|
||||
isSuccess: isSuccessDetails,
|
||||
isError: isErrorDetails,
|
||||
} = useGetSourceUploadInfoQuery(
|
||||
{ id: selectedSourceId },
|
||||
{
|
||||
skip: !selectedSourceId,
|
||||
}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isFetchingDetails || !isSuccessDetails) return;
|
||||
change('azure-tenant-id', sourceDetails?.azure?.tenant_id);
|
||||
change('azure-subscription-id', sourceDetails?.azure?.subscription_id);
|
||||
}, [
|
||||
isFetchingDetails,
|
||||
isSuccessDetails,
|
||||
sourceDetails?.azure?.subscription_id,
|
||||
sourceDetails?.azure?.tenant_id,
|
||||
change,
|
||||
]);
|
||||
|
||||
const onFormChange = ({ values }) => {
|
||||
if (
|
||||
values['azure-type'] !== 'azure-type-source' ||
|
||||
values[input.name] === undefined
|
||||
) {
|
||||
change(input.name, undefined);
|
||||
change('azure-tenant-id', undefined);
|
||||
change('azure-subscription-id', undefined);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelect = (_, sourceName) => {
|
||||
const sourceId = sources.find((source) => source.name === sourceName).id;
|
||||
change(input.name, sourceId);
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const handleClear = () => {
|
||||
change(input.name, undefined);
|
||||
};
|
||||
|
||||
const handleToggle = () => {
|
||||
// Refetch upon opening (but not upon closing)
|
||||
if (!isOpen) {
|
||||
refetch();
|
||||
}
|
||||
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FormSpy subscription={{ values: true }} onChange={onFormChange} />
|
||||
<FormGroup
|
||||
isRequired={isRequired}
|
||||
label={label}
|
||||
data-testid="azure-sources"
|
||||
>
|
||||
<Select
|
||||
ouiaId="source_select"
|
||||
variant={SelectVariant.typeahead}
|
||||
className={className}
|
||||
onToggle={handleToggle}
|
||||
onSelect={handleSelect}
|
||||
onClear={handleClear}
|
||||
selections={
|
||||
selectedSourceId
|
||||
? sources.find((source) => source.id === selectedSourceId)?.name
|
||||
: undefined
|
||||
}
|
||||
isOpen={isOpen}
|
||||
placeholderText="Select source"
|
||||
typeAheadAriaLabel="Select source"
|
||||
menuAppendTo="parent"
|
||||
maxHeight="25rem"
|
||||
isDisabled={!isSuccess}
|
||||
>
|
||||
{isSuccess &&
|
||||
sources.map((source) => (
|
||||
<SelectOption key={source.id} value={source.name} />
|
||||
))}
|
||||
{isFetching && (
|
||||
<SelectOption isNoResultsOption={true}>
|
||||
<Spinner size="lg" />
|
||||
</SelectOption>
|
||||
)}
|
||||
</Select>
|
||||
</FormGroup>
|
||||
<>
|
||||
{isError && (
|
||||
<Alert
|
||||
variant={'danger'}
|
||||
isPlain
|
||||
isInline
|
||||
title={'Sources unavailable'}
|
||||
>
|
||||
Sources cannot be reached, try again later or enter an account info
|
||||
for upload manually.
|
||||
</Alert>
|
||||
)}
|
||||
{!isError && isErrorDetails && (
|
||||
<Alert
|
||||
variant={'danger'}
|
||||
isPlain
|
||||
isInline
|
||||
title={'Azure details unavailable'}
|
||||
>
|
||||
Could not fetch Tenant id and Subscription id from Azure for given
|
||||
Source. Check Sources page for the source availability or select a
|
||||
different Source.
|
||||
</Alert>
|
||||
)}
|
||||
</>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
AzureSourcesSelect.propTypes = {
|
||||
className: PropTypes.string,
|
||||
label: PropTypes.node,
|
||||
isRequired: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default AzureSourcesSelect;
|
||||
Loading…
Add table
Add a link
Reference in a new issue