diff --git a/extensions/azurePublish/src/components/api.tsx b/extensions/azurePublish/src/components/api.tsx index 55bf56d9e3..350db893a9 100644 --- a/extensions/azurePublish/src/components/api.tsx +++ b/extensions/azurePublish/src/components/api.tsx @@ -2,6 +2,7 @@ // Licensed under the MIT License. /* eslint-disable no-underscore-dangle */ import axios from 'axios'; +import formatMessage from 'format-message'; import { SubscriptionClient } from '@azure/arm-subscriptions'; import { Subscription } from '@azure/arm-subscriptions/esm/models'; import { ResourceManagementClient } from '@azure/arm-resources'; @@ -27,6 +28,11 @@ import * as Images from './images'; const logger = debug('composer:extension:azureProvision'); +/** + * Retrieves the list of subscriptions from Azure + * @param token The authentication token + * @returns The list of subscriptions or throws + */ export const getSubscriptions = async (token: string): Promise> => { const tokenCredentials = new TokenCredentials(token); try { @@ -37,15 +43,22 @@ export const getSubscriptions = async (token: string): Promise { return { root: { @@ -124,7 +130,7 @@ const onRenderLabel = (props) => { {' '} {props.label}{' '} - + @@ -229,6 +235,7 @@ export const AzureProvisionDialog: React.FC = () => { const extensionState = { ...defaultExtensionState, ...getItem(profileName) }; const [subscriptions, setSubscriptions] = useState(); + const [subscriptionsErrorMessage, setSubscriptionsErrorMessage] = useState(); const [deployLocations, setDeployLocations] = useState([]); const [luisLocations, setLuisLocations] = useState([]); @@ -366,8 +373,10 @@ export const AzureProvisionDialog: React.FC = () => { const getResources = async () => { try { - const resources = await getResourceList(currentProjectId(), publishType); - setExtensionResourceOptions(resources); + if (isMounted.current) { + const resources = await getResourceList(currentProjectId(), publishType); + setExtensionResourceOptions(resources); + } } catch (err) { // todo: how do we handle API errors in this component console.log('ERROR', err); @@ -376,11 +385,26 @@ export const AzureProvisionDialog: React.FC = () => { useEffect(() => { if (token) { - getSubscriptions(token).then((data) => { - if (isMounted.current) { - setSubscriptions(data); - } - }); + setSubscriptionsErrorMessage(undefined); + getSubscriptions(token) + .then((data) => { + if (isMounted.current) { + setSubscriptions(data); + if (data.length === 0) { + setSubscriptionsErrorMessage( + formatMessage( + 'Your subscription list is empty, please add your subscription, or login with another account.' + ) + ); + } + } + }) + .catch((err) => { + if (isMounted.current) { + setSubscriptionsErrorMessage(err.message); + } + }); + getResources(); } }, [token]); @@ -389,14 +413,18 @@ export const AzureProvisionDialog: React.FC = () => { if (token && currentSubscription) { try { const resourceGroups = await getResourceGroups(token, currentSubscription); - setResourceGroups(resourceGroups); + if (isMounted.current) { + setResourceGroups(resourceGroups); - // After the resource groups load, isNewResourceGroupName can be determined - setIsNewResourceGroupName(!resourceGroups?.some((r) => r.name === currentResourceGroupName)); + // After the resource groups load, isNewResourceGroupName can be determined + setIsNewResourceGroupName(!resourceGroups?.some((r) => r.name === currentResourceGroupName)); + } } catch (err) { // todo: how do we handle API errors in this component console.log('ERROR', err); - setResourceGroups(undefined); + if (isMounted.current) { + setResourceGroups(undefined); + } } } else { setResourceGroups(undefined); @@ -407,7 +435,7 @@ export const AzureProvisionDialog: React.FC = () => { loadResourceGroups(); }, [token, currentSubscription]); - const subscriptionOption = useMemo(() => { + const subscriptionOptions = useMemo(() => { return subscriptions?.map((t) => ({ key: t.subscriptionId, text: t.displayName })); }, [subscriptions]); @@ -563,6 +591,7 @@ export const AzureProvisionDialog: React.FC = () => { !currentResourceGroupName || !currentHostName || !currentLocation || + subscriptionsErrorMessage || errorResourceGroupName || errorHostName !== '' ); @@ -599,10 +628,12 @@ export const AzureProvisionDialog: React.FC = () => {
}> - {subscriptionOption?.length > 0 && choice.key === 'create' && ( + {choice.key === 'create' && (
{ onChange={(_e, o) => { setSelectedTenant(o.key as string); }} + onRenderLabel={onRenderLabel} /> { setCurrentSubscription(o.key as string); @@ -766,7 +792,7 @@ export const AzureProvisionDialog: React.FC = () => { items={optionalListItems} selectedKeys={selectedResourceKeys} onSelectionChanged={(keys) => { - const newSelection = listItems.filter((item) => item.required === true || keys.includes(item.key)); + const newSelection = optionalListItems.filter((item) => keys.includes(item.key)); setEnabledResources(newSelection); }} /> @@ -885,7 +911,7 @@ export const AzureProvisionDialog: React.FC = () => { onClick={() => { setPage(PageTypes.ReviewResource); setTitle(DialogTitle.REVIEW); - let selectedResources = enabledResources.slice(); + let selectedResources = requireResources.concat(enabledResources); selectedResources = selectedResources.map((item) => { let region = currentConfig?.region || currentLocation; if (item.key.includes('luis')) {