From 41e61cc9fb9662574614aa7063989559222bf933 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Fri, 5 Feb 2021 00:16:40 +0800 Subject: [PATCH 01/44] change edit dialog page 1 --- .../AddProfileDialog.tsx | 8 +- .../PublishProfileDialog.tsx | 90 +++++++++---------- 2 files changed, 45 insertions(+), 53 deletions(-) diff --git a/Composer/packages/client/src/pages/botProject/create-publish-profile/AddProfileDialog.tsx b/Composer/packages/client/src/pages/botProject/create-publish-profile/AddProfileDialog.tsx index 05a7fb252f..8721d2f764 100644 --- a/Composer/packages/client/src/pages/botProject/create-publish-profile/AddProfileDialog.tsx +++ b/Composer/packages/client/src/pages/botProject/create-publish-profile/AddProfileDialog.tsx @@ -34,6 +34,7 @@ type AddProfileDialogProps = { updateSettings: (name: string, type: string, configuration: string) => Promise; projectId: string; setType: (value) => void; + current?: { index: number; item: PublishTarget } | null; }; const labelContainer = css` display: flex; @@ -73,10 +74,10 @@ const onRenderLabel = (props) => { }; export const AddProfileDialog: React.FC = (props) => { - const { onDismiss, targets, types, onNext, updateSettings, projectId, setType } = props; - const [name, setName] = useState(''); + const { onDismiss, targets, types, onNext, updateSettings, projectId, setType, current } = props; + const [name, setName] = useState(current?.item.name || ''); const [errorMessage, setErrorMsg] = useState(''); - const [targetType, setTargetType] = useState(''); + const [targetType, setTargetType] = useState(current?.item.type || ''); const [showAuthDialog, setShowAuthDialog] = useState(false); const { provisionToTarget } = useRecoilValue(dispatcherState); @@ -168,6 +169,7 @@ export const AddProfileDialog: React.FC = (props) => { required ariaLabel={formatMessage('The name of your publishing file')} defaultValue={name} + disabled={current?.item.name ? true : false} errorMessage={errorMessage} label={formatMessage('Name')} placeholder={formatMessage('e.g. AzureBot')} diff --git a/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx b/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx index 03968c68d5..e166e6e0af 100644 --- a/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx +++ b/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx @@ -16,7 +16,6 @@ import { PluginHost } from '../../../components/PluginHost/PluginHost'; import { defaultPublishSurface, pvaPublishSurface, azurePublishSurface } from '../../publish/styles'; import TelemetryClient from '../../../telemetry/TelemetryClient'; -import { EditProfileDialog } from './EditProfileDialog'; import { AddProfileDialog } from './AddProfileDialog'; type PublishProfileDialogProps = { @@ -40,7 +39,7 @@ export const PublishProfileDialog: React.FC = (props) const [publishSurfaceStyles, setStyles] = useState(defaultPublishSurface); const [dialogTitle, setTitle] = useState({ - title: formatMessage('Add a publishing profile'), + title: current ? formatMessage('Edit a publishing profile') : formatMessage('Add a publishing profile'), subText: formatMessage('A publishing profile provides the secure connectivity required to publish your bot. '), }); @@ -125,55 +124,46 @@ export const PublishProfileDialog: React.FC = (props) return ( - {page === Page.EditProfile && ( - - )} - {page != Page.EditProfile && ( - ); }; From ff0cc0acc13723e97e9bf31d62407ff52e35894c Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 8 Feb 2021 17:51:33 +0800 Subject: [PATCH 02/44] change add and edit page one --- .../EditProfileDialog.tsx | 115 ------------------ ...rofileDialog.tsx => ProfileFormDialog.tsx} | 4 +- .../PublishProfileDialog.tsx | 41 ++----- Composer/packages/client/src/plugins/api.ts | 2 +- .../extension-client/src/publish/index.ts | 2 +- .../src/client/publish/main.tsx | 2 +- 6 files changed, 18 insertions(+), 148 deletions(-) delete mode 100644 Composer/packages/client/src/pages/botProject/create-publish-profile/EditProfileDialog.tsx rename Composer/packages/client/src/pages/botProject/create-publish-profile/{AddProfileDialog.tsx => ProfileFormDialog.tsx} (98%) diff --git a/Composer/packages/client/src/pages/botProject/create-publish-profile/EditProfileDialog.tsx b/Composer/packages/client/src/pages/botProject/create-publish-profile/EditProfileDialog.tsx deleted file mode 100644 index 77d1d585a1..0000000000 --- a/Composer/packages/client/src/pages/botProject/create-publish-profile/EditProfileDialog.tsx +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -/** @jsx jsx */ -import { jsx } from '@emotion/core'; -import formatMessage from 'format-message'; -import { useState, useCallback, useMemo } from 'react'; -import { DialogWrapper, DialogTypes } from '@bfc/ui-shared'; -import { Separator } from 'office-ui-fabric-react/lib/Separator'; -import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; -import { TextField } from 'office-ui-fabric-react/lib/TextField'; -import { PublishTarget } from '@bfc/shared'; -import { JsonEditor } from '@bfc/code-editor'; -import { DialogFooter } from 'office-ui-fabric-react/lib/Dialog'; -import { PrimaryButton, DefaultButton } from 'office-ui-fabric-react/lib/Button'; -import { useRecoilValue } from 'recoil'; - -import { PublishType } from '../../../recoilModel/types'; -import { label, separator } from '../../publish/styles'; -import { userSettingsState } from '../../../recoilModel'; - -type EditProfileDialogProps = { - onDismiss: () => void; - current: { index: number; item: PublishTarget } | null; - types: PublishType[]; - updateSettings: (name: string, type: string, configuration: string, editTarget: any) => Promise; -}; - -export const EditProfileDialog: React.FC = (props) => { - const { current, onDismiss, types, updateSettings } = props; - const [targetType, setTargetType] = useState(current?.item.type || ''); - const userSettings = useRecoilValue(userSettingsState); - const [config, setConfig] = useState(current ? JSON.parse(current.item.configuration) : undefined); - - const targetTypes = useMemo(() => { - return types.map((t) => ({ key: t.name, text: t.description })); - }, [types]); - - const updateType = useCallback( - (_e, option?: IDropdownOption) => { - const type = targetTypes.find((t) => t.key === option?.key); - - if (type) { - setTargetType(type.key); - } - }, - [targetTypes] - ); - - const selectedType = useMemo(() => { - return types.find((t) => t.name === targetType); - }, [types, targetType]); - - const submit = useCallback( - (_e) => { - if (targetType) { - updateSettings(current?.item.name || '', targetType, JSON.stringify(config) || '{}', current); - onDismiss(); - } - }, - [targetType, config, current, updateSettings] - ); - - return ( - -
-
- - - - {selectedType?.instructions &&

{selectedType.instructions}

} -
{formatMessage('Publish Configuration')}
- -
- - - - - -
- ); -}; diff --git a/Composer/packages/client/src/pages/botProject/create-publish-profile/AddProfileDialog.tsx b/Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx similarity index 98% rename from Composer/packages/client/src/pages/botProject/create-publish-profile/AddProfileDialog.tsx rename to Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx index 8721d2f764..ac49843fea 100644 --- a/Composer/packages/client/src/pages/botProject/create-publish-profile/AddProfileDialog.tsx +++ b/Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx @@ -26,7 +26,7 @@ import { dispatcherState } from '../../../recoilModel'; import { AuthClient } from '../../../utils/authClient'; import { getTokenFromCache, isGetTokenFromUser } from '../../../utils/auth'; -type AddProfileDialogProps = { +type ProfileFormDialogProps = { onDismiss: () => void; targets: PublishTarget[]; types: PublishType[]; @@ -73,7 +73,7 @@ const onRenderLabel = (props) => { ); }; -export const AddProfileDialog: React.FC = (props) => { +export const ProfileFormDialog: React.FC = (props) => { const { onDismiss, targets, types, onNext, updateSettings, projectId, setType, current } = props; const [name, setName] = useState(current?.item.name || ''); const [errorMessage, setErrorMsg] = useState(''); diff --git a/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx b/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx index e166e6e0af..1642e2aed2 100644 --- a/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx +++ b/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx @@ -16,7 +16,7 @@ import { PluginHost } from '../../../components/PluginHost/PluginHost'; import { defaultPublishSurface, pvaPublishSurface, azurePublishSurface } from '../../publish/styles'; import TelemetryClient from '../../../telemetry/TelemetryClient'; -import { AddProfileDialog } from './AddProfileDialog'; +import { ProfileFormDialog } from './ProfileFormDialog'; type PublishProfileDialogProps = { closeDialog: () => void; @@ -27,15 +27,14 @@ type PublishProfileDialogProps = { setPublishTargets: (targets: PublishTarget[], projectId: string) => Promise; }; -enum Page { - AddProfile = 'add', - EditProfile = 'edit', - ConfigProvision = 'config', -} +const Page = { + ProfileForm: Symbol('form'), + ConfigProvision: Symbol('config'), +}; export const PublishProfileDialog: React.FC = (props) => { const { current, types, projectId, closeDialog, targets, setPublishTargets } = props; - const [page, setPage] = useState(current ? Page.EditProfile : Page.AddProfile); + const [page, setPage] = useState(Page.ProfileForm); const [publishSurfaceStyles, setStyles] = useState(defaultPublishSurface); const [dialogTitle, setTitle] = useState({ @@ -71,7 +70,11 @@ export const PublishProfileDialog: React.FC = (props) useEffect(() => { PluginAPI.publish.closeDialog = closeDialog; PluginAPI.publish.onBack = () => { - setPage(Page.AddProfile); + setPage(Page.ProfileForm); + setTitle({ + title: current ? formatMessage('Edit a publishing profile') : formatMessage('Add a publishing profile'), + subText: formatMessage('A publishing profile provides the secure connectivity required to publish your bot. '), + }); }; PluginAPI.publish.getTokenFromCache = () => { return { @@ -89,30 +92,12 @@ export const PublishProfileDialog: React.FC = (props) // setup plugin APIs so that the provisioning plugin can initiate the process from inside the iframe useEffect(() => { - PluginAPI.publish.useConfigBeingEdited = () => [current ? JSON.parse(current.item.configuration) : undefined]; + PluginAPI.publish.useConfigBeingEdited = () => (current ? JSON.parse(current.item.configuration) : undefined); PluginAPI.publish.currentProjectId = () => { return projectId; }; }, [current, projectId]); - const updatePublishTarget = useCallback( - async (name: string, type: string, configuration: string, editTarget: any) => { - if (!editTarget) { - return; - } - - const newTargets = targets ? [...targets] : []; - newTargets[editTarget.index] = { - name, - type, - configuration, - }; - - await setPublishTargets(newTargets, projectId); - }, - [targets, projectId] - ); - const savePublishTarget = useCallback( async (name: string, type: string, configuration: string) => { const newTargets = [...(targets || []), { name, type, configuration }]; @@ -144,7 +129,7 @@ export const PublishProfileDialog: React.FC = (props) {formatMessage('Learn More.')} - PublishConfig[]) | (() => void); + useConfigBeingEdited?: (() => PublishConfig) | (() => void); startProvision?: (config: any) => void; currentProjectId?: () => string; closeDialog?: () => void; diff --git a/Composer/packages/extension-client/src/publish/index.ts b/Composer/packages/extension-client/src/publish/index.ts index cb864cf362..db5a70cd4c 100644 --- a/Composer/packages/extension-client/src/publish/index.ts +++ b/Composer/packages/extension-client/src/publish/index.ts @@ -5,7 +5,7 @@ import { ComposerGlobalName } from '../common/constants'; import { PublishConfig } from './types'; -export function useConfigBeingEdited(): PublishConfig[] | undefined[] { +export function useConfigBeingEdited(): PublishConfig | undefined { return window[ComposerGlobalName].useConfigBeingEdited(); } diff --git a/extensions/sample-ui-plugin/src/client/publish/main.tsx b/extensions/sample-ui-plugin/src/client/publish/main.tsx index 19343e9782..a8e9495d16 100644 --- a/extensions/sample-ui-plugin/src/client/publish/main.tsx +++ b/extensions/sample-ui-plugin/src/client/publish/main.tsx @@ -7,7 +7,7 @@ import { closeDialog, onBack, savePublishConfig, useConfigBeingEdited } from '@b import { backButton, buttonBar, column, label, publishRoot, saveButton, textField, title } from '../styles'; export const Main: React.FC<{ title: string }> = (props) => { - const [configBeingEdited] = useConfigBeingEdited(); + const configBeingEdited = useConfigBeingEdited(); const [val1, setVal1] = useState(configBeingEdited ? configBeingEdited.val1 : ''); const [val2, setVal2] = useState(configBeingEdited ? configBeingEdited.val2 : ''); const [val3, setVal3] = useState(configBeingEdited ? configBeingEdited.val3 : ''); From 722ae73ddba0ec0afc6498e611be81fe97b3c803 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Tue, 9 Feb 2021 12:01:41 +0800 Subject: [PATCH 03/44] add review page and enable provision resources in current provision --- .../PublishProfileDialog.tsx | 9 +- extensions/azurePublish/src/node/index.ts | 1 - extensions/azurePublish/src/node/provision.ts | 4 +- extensions/azurePublish/src/node/schema.ts | 4 +- extensions/azurePublish/src/types/index.ts | 14 + .../src/ui/azureProvisionDialog.tsx | 351 ++++++++++++++---- 6 files changed, 296 insertions(+), 87 deletions(-) diff --git a/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx b/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx index 1642e2aed2..673bc44234 100644 --- a/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx +++ b/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx @@ -100,7 +100,14 @@ export const PublishProfileDialog: React.FC = (props) const savePublishTarget = useCallback( async (name: string, type: string, configuration: string) => { - const newTargets = [...(targets || []), { name, type, configuration }]; + // check exist + const newTargets = [...targets] || []; + const index = targets.findIndex((item) => item.name === name); + if (index >= 0) { + newTargets.splice(index, 1, { name, type, configuration }); + } else { + newTargets.push({ name, type, configuration }); + } await setPublishTargets(newTargets, projectId); TelemetryClient.track('NewPublishingProfileSaved', { type }); }, diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index b4a4d26afd..dc939bbf61 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -369,7 +369,6 @@ export default async (composer: IExtensionRegistration): Promise => { this.logger(msg); BackgroundProcessManager.updateProcess(jobId, 202, msg.message); }, - tenantId: subscription.tenantId, // does the tenantId ever come back from the subscription API we use? it does not appear in my tests. }); // perform the provision using azureProvisioner.create. diff --git a/extensions/azurePublish/src/node/provision.ts b/extensions/azurePublish/src/node/provision.ts index 61cf729597..93987d5247 100644 --- a/extensions/azurePublish/src/node/provision.ts +++ b/extensions/azurePublish/src/node/provision.ts @@ -18,7 +18,7 @@ export interface ProvisionConfig { externalResources: ResourceType[]; location: { id: string; name: string; displayName: string }; luisLocation: string; - subscription: { subscriptionId: string; tenantId: string; displayName: string }; + subscription: string; logger?: (string) => any; name: string; // profile name type: string; // webapp or function @@ -42,7 +42,7 @@ export class BotProjectProvision { private tenantId = ''; constructor(config: ProvisionConfig) { - this.subscriptionId = config.subscription.subscriptionId; + this.subscriptionId = config.subscription; this.logger = config.logger; this.accessToken = config.accessToken; this.graphToken = config.graphToken; diff --git a/extensions/azurePublish/src/node/schema.ts b/extensions/azurePublish/src/node/schema.ts index 89cfffc597..7ea04cd53c 100644 --- a/extensions/azurePublish/src/node/schema.ts +++ b/extensions/azurePublish/src/node/schema.ts @@ -123,9 +123,9 @@ const schema: JSONSchema7 = { container: '', }, luis: { - authoringKey: '', + authoringKey: '', authoringEndpoint: '', - endpointKey: '', + endpointKey: '', endpoint: '', region: 'westus', }, diff --git a/extensions/azurePublish/src/types/index.ts b/extensions/azurePublish/src/types/index.ts index 02cf77ad26..409374815e 100644 --- a/extensions/azurePublish/src/types/index.ts +++ b/extensions/azurePublish/src/types/index.ts @@ -37,6 +37,20 @@ export enum AzureAPIStatus { ERROR = 'ERROR', } +export const AzureResourceTypes = { + APP_REGISTRATION: 'appRegistration', + BOT_REGISTRATION: 'botRegistration', + WEBAPP: 'webApp', + AZUREFUNCTIONS: 'azureFunctions', + COSMOSDB: 'cosmosDb', + APPINSIGHTS: 'applicationInsights', + LUIS_AUTHORING: 'luisAuthoring', + LUIS_PREDICTION: 'luisPrediction', + BLOBSTORAGE: 'blobStorage', + QNA: 'qna', + SERVICE_PLAN: 'servicePlan', +}; + export enum AzureResourceProviderType { QnA = 'Microsoft.CognitiveServices', Luis = 'Microsoft.CognitiveServices', diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index cf7004f342..4c87aee093 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -18,6 +18,7 @@ import { getType, getTokenFromCache, isGetTokenFromUser, + useConfigBeingEdited } from '@bfc/extension-client'; import { Subscription } from '@azure/arm-subscriptions/esm/models'; import { ResourceGroup } from '@azure/arm-resources/esm/models'; @@ -51,6 +52,9 @@ import { SharedColors } from '@uifabric/fluent-theme'; import { JsonEditor } from '@bfc/code-editor'; import jwtDecode from 'jwt-decode'; import { getResourceList, getSubscriptions, getResourceGroups, getDeployLocations, getPreview, getLuisAuthoringRegions, CheckWebAppNameAvailability } from './api'; +import { AzureResourceTypes } from '../types'; +import { Item } from '@azure/cosmos'; +import { hostname } from 'os'; const choiceOptions: IChoiceGroupOption[] = [ { key: 'create', text: 'Create new Azure resources' }, @@ -58,6 +62,7 @@ const choiceOptions: IChoiceGroupOption[] = [ ]; const PageTypes = { ConfigProvision: 'config', + AddResources: 'add', ReviewResource: 'review', }; const DialogTitle = { @@ -67,6 +72,10 @@ const DialogTitle = { 'How you would like to provision your Azure resources to publish your bot?' ), }, + ADD_RESOURCES: { + title: formatMessage('Add resources'), + subText: formatMessage('Your bot needs the following resources based on its capabilities. Select resources that you want to provision in your publishing profile.') + }, REVIEW: { title: formatMessage('Review & create'), subText: formatMessage( @@ -128,6 +137,128 @@ const onRenderLabel = (props) => { ); }; +const columns: IColumn[] = [ + { + key: 'Icon', + name: 'File Type', + isIconOnly: true, + fieldName: 'name', + minWidth: 16, + maxWidth: 16, + onRender: (item: ResourcesItem & {name,icon}) => { + return ; + }, + }, + { + key: 'Name', + name: formatMessage('Name'), + className: 'name', + fieldName: 'name', + minWidth: 300, + isRowHeader: true, + data: 'string', + onRender: (item: ResourcesItem & {name,icon}) => { + return
+
{item.name}
+
{item.text} | {item.tier}
+
; + }, + isPadded: true, + }, + { + key: 'Description', + name: formatMessage('Description'), + className: 'description', + fieldName: 'description', + minWidth: 380, + isRowHeader: true, + data: 'string', + onRender: (item: ResourcesItem & {name,icon}) => { + return
{item.description}
; + }, + isPadded: true, + } +]; + +const reviewCols: IColumn[] = [ + { + key: 'Icon', + name: 'File Type', + isIconOnly: true, + fieldName: 'name', + minWidth: 16, + maxWidth: 16, + onRender: (item: ResourcesItem & {name,icon}) => { + return ; + }, + }, + { + key: 'Resource Type', + name: formatMessage('Resource Type'), + className: 'Resource Type', + fieldName: 'Resource Type', + minWidth: 150, + isRowHeader: true, + data: 'string', + onRender: (item: ResourcesItem) => { + return
{item.text}
; + }, + isPadded: true, + }, + { + key: 'Status', + name: formatMessage('Status'), + className: 'Status', + fieldName: 'Status', + minWidth: 100, + isRowHeader: true, + data: 'string', + onRender: (item: ResourcesItem) => { + return
Ready
; + }, + isPadded: true, + }, + { + key: 'resourceGroup', + name: formatMessage('Resource Group'), + className: 'resourceGroup', + fieldName: 'resourceGroup', + minWidth: 100, + isRowHeader: true, + data: 'string', + onRender: (item: ResourcesItem) => { + return
{item.resourceGroup}
; + }, + isPadded: true, + }, + { + key: 'Name', + name: formatMessage('Name'), + className: 'name', + fieldName: 'name', + minWidth: 150, + isRowHeader: true, + data: 'string', + onRender: (item: ResourcesItem & {name,icon}) => { + return
{item.name}
; + }, + isPadded: true, + }, + { + key: 'Region', + name: formatMessage('Region'), + className: 'region', + fieldName: 'region', + minWidth: 100, + isRowHeader: true, + data: 'string', + onRender: (item: ResourcesItem & {name,icon}) => { + return
{item.region.displayName}
; + }, + isPadded: true, + }, +]; + export const AzureProvisionDialog: React.FC = () => { const [subscriptions, setSubscriptions] = useState([]); const [resourceGroups, setResourceGroups] = useState([]); @@ -138,7 +269,7 @@ export const AzureProvisionDialog: React.FC = () => { const [currentUser, setCurrentUser] = useState(); const [choice, setChoice] = useState(choiceOptions[0]); - const [currentSubscription, setSubscription] = useState(); + const [currentSubscription, setSubscription] = useState(''); const [currentHostName, setHostName] = useState(''); const [errorHostName, setErrorHostName] = useState(''); const [currentLocation, setLocation] = useState(); @@ -148,57 +279,16 @@ export const AzureProvisionDialog: React.FC = () => { const [requireResources, setRequireResources] = useState([]); const [isEditorError, setEditorError] = useState(false); - const [importConfig, setImportConfig] = useState(); + const [importConfig, setImportConfig] = useState(); const [page, setPage] = useState(PageTypes.ConfigProvision); const [group, setGroup] = useState(); const [listItems, setListItem] = useState<(ResourcesItem & {name,icon})[]>(); + const [reviewListItems, setReviewListItems] = useState([]); // set type of publish - azurePublish or azureFunctionsPublish const publishType = getType(); - - const columns: IColumn[] = [ - { - key: 'Icon', - name: 'File Type', - isIconOnly: true, - fieldName: 'name', - minWidth: 16, - maxWidth: 16, - onRender: (item: ResourcesItem & {name,icon}) => { - return ; - }, - }, - { - key: 'Name', - name: formatMessage('Name'), - className: 'name', - fieldName: 'name', - minWidth: 300, - isRowHeader: true, - data: 'string', - onRender: (item: ResourcesItem & {name,icon}) => { - return
-
{item.name}
-
{item.text} | {item.tier}
-
; - }, - isPadded: true, - }, - { - key: 'Description', - name: formatMessage('Description'), - className: 'description', - fieldName: 'description', - minWidth: 380, - isRowHeader: true, - data: 'string', - onRender: (item: ResourcesItem & {name,icon}) => { - return
{item.description}
; - }, - isPadded: true, - } - ]; + const currentConfig = useConfigBeingEdited(); useEffect(() => { setTitle(DialogTitle.CONFIG_RESOURCES); @@ -236,6 +326,17 @@ export const AzureProvisionDialog: React.FC = () => { }, []); + useEffect(()=>{ + if(currentConfig){ + if(currentConfig?.subscriptionId){ + setSubscription(currentConfig?.subscriptionId); + } + if(currentConfig?.hostname){ + setHostName(currentConfig?.hostname); + } + } + },[currentConfig]); + useEffect(()=> { if(token){ getSubscriptions(token).then(setSubscriptions); @@ -267,17 +368,17 @@ export const AzureProvisionDialog: React.FC = () => { const updateCurrentSubscription = useMemo( () => (_e, option?: IDropdownOption) => { - const sub = subscriptions.find((t) => t.subscriptionId === option?.key); + const sub = subscriptionOption.find((t) => t.key === option?.key); if (sub) { - setSubscription(sub); + setSubscription(sub.key); } }, - [subscriptions] + [subscriptionOption] ); const checkNameAvailability = useMemo(()=>(newName: string)=>{ - if(currentSubscription){ + if(!currentConfig?.subscriptionId && currentSubscription){ // get preview list const names = getPreview(newName); let app = ''; @@ -287,7 +388,7 @@ export const AzureProvisionDialog: React.FC = () => { app = names.find(item=>item.key === 'webApp').name; } // check app name whether exist or not - CheckWebAppNameAvailability(token, app, currentSubscription.subscriptionId).then(value=>{ + CheckWebAppNameAvailability(token, app, currentSubscription).then(value=>{ if(!value.nameAvailable){ setErrorHostName(value.message); } else { @@ -297,17 +398,19 @@ export const AzureProvisionDialog: React.FC = () => { } else { setErrorHostName(''); } - }, [publishType, currentSubscription, token]); + }, [currentConfig, publishType, currentSubscription, token]); const newResourceGroup = useMemo( () => (e, newName) => { setHostName(newName); - // validate existed or not - const existed = resourceGroups.find((t) => t.name === newName); - if (existed) { - setErrorHostName('this resource group already exist'); - } else { - checkNameAvailability(newName); + if(!currentConfig?.hostname){ + // validate existed or not + const existed = resourceGroups.find((t) => t.name === newName); + if (existed) { + setErrorHostName('this resource group already exist'); + } else { + checkNameAvailability(newName); + } } }, [resourceGroups, checkNameAvailability] @@ -337,28 +440,57 @@ export const AzureProvisionDialog: React.FC = () => { useEffect(() => { if (currentSubscription) { // get resource group under subscription - getResourceGroups(token, currentSubscription.subscriptionId).then(setResourceGroups); - getDeployLocations(token, currentSubscription.subscriptionId).then(setDeployLocations); + getResourceGroups(token, currentSubscription).then(setResourceGroups); + getDeployLocations(token, currentSubscription).then(setDeployLocations); setLuisLocations(getLuisAuthoringRegions()); - if(currentHostName){ - // check its hostname availability - checkNameAvailability(currentHostName); - } + // if(currentHostName){ + // // check its hostname availability + // checkNameAvailability(currentHostName); + // } } }, [currentSubscription]); + const getExistResources = ()=>{ + const result = []; + if(currentConfig){ + if(currentConfig.hostname){ + result.push(AzureResourceTypes.WEBAPP); + result.push(AzureResourceTypes.APP_REGISTRATION); + } + if(currentConfig.settings?.MicrosoftAppId){ + result.push(AzureResourceTypes.BOT_REGISTRATION); + } + if(currentConfig.settings?.luis?.authoringKey){ + result.push(AzureResourceTypes.LUIS_AUTHORING); + } + if(currentConfig.settings?.luis?.endpointKey){ + result.push(AzureResourceTypes.LUIS_PREDICTION); + } + return result; + } else return []; + } + const onNext = useMemo( () => (hostname) => { + // get resources already have + const alreadyHave = getExistResources(); + console.log(alreadyHave); + const names = getPreview(hostname); - const result = extensionResourceOptions.map((resource) => { + const result = []; + for(let resource of extensionResourceOptions){ + if(alreadyHave.find(item => item === resource.key)){ + continue; + } const previewObject = names.find((n) => n.key === resource.key); - return { + result.push({ ...resource, name: previewObject ? previewObject.name : `UNKNOWN NAME FOR ${resource.key}`, icon: previewObject ? previewObject.icon : undefined, - }; - }); + }); + } + console.log(result); // set review list const groups: IGroup[] = []; @@ -382,8 +514,8 @@ export const AzureProvisionDialog: React.FC = () => { setGroup(groups); setListItem(items); - setPage(PageTypes.ReviewResource); - setTitle(DialogTitle.REVIEW); + setPage(PageTypes.AddResources); + setTitle(DialogTitle.ADD_RESOURCES); }, [extensionResourceOptions] ); @@ -391,9 +523,10 @@ export const AzureProvisionDialog: React.FC = () => { const onSubmit = useMemo( () => async (options) => { // call back to the main Composer API to begin this process... - startProvision(options); + // startProvision(options); + console.log(options); // TODO: close window - closeDialog(); + // closeDialog(); }, [] ); @@ -421,8 +554,8 @@ export const AzureProvisionDialog: React.FC = () => { ); const isDisAble = useMemo(() => { - return !currentSubscription || !currentHostName || errorHostName !== ''; - }, [currentSubscription, currentHostName, errorHostName]); + return !currentSubscription || !currentHostName || errorHostName !== '' || !currentLocation; + }, [currentSubscription, currentHostName, errorHostName, currentLocation]); const PageFormConfig = ( @@ -431,7 +564,8 @@ export const AzureProvisionDialog: React.FC = () => {
{ styles={{ root: { paddingBottom: '8px' } }} onRenderLabel={onRenderLabel} /> + {currentConfig?.resourceGroup && } { { setEditorError(false); setImportConfig(value); @@ -514,7 +659,7 @@ export const AzureProvisionDialog: React.FC = () => { return s; }, [listItems]); - const PageReview = useMemo(() => { + const PageAddResources = useMemo(() => { return ( @@ -535,6 +680,23 @@ export const AzureProvisionDialog: React.FC = () => { ); }, [group, listItems, selection]); + + const PageReview = ( + + + item.key} + items={reviewListItems} + layoutMode={DetailsListLayoutMode.justified} + setKey="none" + /> + + + ); + const PageFooter = useMemo(() => { if (page === PageTypes.ConfigProvision) { return ( @@ -557,7 +719,7 @@ export const AzureProvisionDialog: React.FC = () => { ); - } else { + } else if(page === PageTypes.AddResources){ return (
{currentUser? : null} @@ -572,7 +734,32 @@ export const AzureProvisionDialog: React.FC = () => { /> { + setPage(PageTypes.ReviewResource); + setTitle(DialogTitle.REVIEW); + let selectedResources = requireResources.concat(enabledResources); + selectedResources = selectedResources.map(item=>({...item, region: currentLocation, resourceGroup:currentConfig.resourceGroup || currentHostName})) + console.log(selectedResources); + setReviewListItems(selectedResources); + }} + style={{margin: '0 4px'}} + /> +
+ + ); + } else { + return ( +
+ {currentUser? : null} +
+ { + setPage(PageTypes.AddResources); + setTitle(DialogTitle.ADD_RESOURCES); + }} style={{margin: '0 4px'}} /> + { const selectedResources = requireResources.concat(enabledResources); await onSubmit({ @@ -588,7 +775,7 @@ export const AzureProvisionDialog: React.FC = () => { />
- ); + ) } }, [ onSave, @@ -609,7 +796,9 @@ export const AzureProvisionDialog: React.FC = () => { return (
- {page === PageTypes.ConfigProvision ? PageFormConfig : PageReview} + {page === PageTypes.ConfigProvision && PageFormConfig} + {page === PageTypes.AddResources && PageAddResources} + {page === PageTypes.ReviewResource && PageReview}
Date: Tue, 9 Feb 2021 12:11:07 +0800 Subject: [PATCH 04/44] add some log --- .../ProfileFormDialog.tsx | 2 +- .../src/recoilModel/dispatchers/provision.ts | 7 +++-- .../packages/server/src/locales/en-US.json | 31 ++++++++++++------- extensions/azurePublish/src/node/index.ts | 2 +- .../src/ui/azureProvisionDialog.tsx | 4 +-- 5 files changed, 29 insertions(+), 17 deletions(-) diff --git a/Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx b/Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx index ac49843fea..2980048267 100644 --- a/Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx +++ b/Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx @@ -145,7 +145,7 @@ export const ProfileFormDialog: React.FC = (props) => { arm = getTokenFromCache('accessToken'); graph = getTokenFromCache('graphToken'); } - provisionToTarget(fullConfig, config.type, projectId, arm, graph); + provisionToTarget(fullConfig, config.type, projectId, arm, graph, current?.item); }; }, [name, targetType]); diff --git a/Composer/packages/client/src/recoilModel/dispatchers/provision.ts b/Composer/packages/client/src/recoilModel/dispatchers/provision.ts index 5c1e917711..37e4c9eada 100644 --- a/Composer/packages/client/src/recoilModel/dispatchers/provision.ts +++ b/Composer/packages/client/src/recoilModel/dispatchers/provision.ts @@ -3,6 +3,7 @@ /* eslint-disable react-hooks/rules-of-hooks */ import formatMessage from 'format-message'; import { CallbackInterface, useRecoilCallback } from 'recoil'; +import { PublishTarget } from '@bfc/shared'; import { provisionStatusState, settingsState } from '../atoms/botState'; import { CardProps } from '../../components/Notifications/NotificationCard'; @@ -40,13 +41,15 @@ export const provisionDispatcher = () => { type: string, projectId: string, armToken = '', - graphToken = '' + graphToken = '', + currentProfile: PublishTarget | undefined = undefined ) => { try { TelemetryClient.track('NewPublishingProfileStarted'); + console.log(currentProfile); const result = await httpClient.post( `/provision/${projectId}/${type}`, - { ...config, graphToken: graphToken }, + { ...config, graphToken: graphToken, currentProfile }, { headers: { Authorization: `Bearer ${armToken}` }, } diff --git a/Composer/packages/server/src/locales/en-US.json b/Composer/packages/server/src/locales/en-US.json index b33e287d59..3c146be348 100644 --- a/Composer/packages/server/src/locales/en-US.json +++ b/Composer/packages/server/src/locales/en-US.json @@ -482,9 +482,6 @@ "choose_how_to_create_your_bot_a97f7b3e": { "message": "Choose how to create your bot" }, - "choose_one_2c4277df": { - "message": "Choose One" - }, "chris_whitten_11df1f35": { "message": "Chris Whitten" }, @@ -983,8 +980,8 @@ "early_adopters_e8db7999": { "message": "Early adopters" }, - "edit_a_publish_profile_30ebab3e": { - "message": "Edit a publish profile" + "edit_a_publishing_profile_705e87e3": { + "message": "Edit a publishing profile" }, "edit_a_skill_5665d9ac": { "message": "Edit a skill" @@ -1217,6 +1214,9 @@ "extracting_qna_pairs_from_url_b0331bba": { "message": "Extracting QNA pairs from { url }" }, + "fail_to_save_bot_578fa8aa": { + "message": "Fail to save bot" + }, "failed_to_start_1edb0dbe": { "message": "Failed to start" }, @@ -1637,6 +1637,9 @@ "local_skill_6ce0d311": { "message": "Local Skill." }, + "locale_locale_is_not_supported_by_luis_a3a72047": { + "message": "locale \"{ locale }\" is not supported by LUIS" + }, "locate_the_bot_file_and_repair_the_link_202045b1": { "message": "Locate the bot file and repair the link" }, @@ -1703,6 +1706,9 @@ "luis_authoring_region_b142f97b": { "message": "Luis Authoring Region" }, + "luis_build_warning_320e4ee2": { + "message": "Luis build warning" + }, "luis_endpoint_key_c685e219": { "message": "LUIS endpoint key" }, @@ -1859,9 +1865,6 @@ "must_have_a_name_d5c5c464": { "message": "Must have a name" }, - "my_staging_environment_2b92d0aa": { - "message": "My Staging Environment" - }, "name_1aed4a1b": { "message": "Name" }, @@ -2246,9 +2249,6 @@ "publish_5211dca3": { "message": "Publish" }, - "publish_configuration_d759a4e3": { - "message": "Publish Configuration" - }, "publish_models_9a36752a": { "message": "Publish models" }, @@ -2801,6 +2801,9 @@ "the_root_bot_is_not_a_bot_project_d1495cf6": { "message": "The root bot is not a bot project" }, + "the_skill_you_tried_to_remove_from_the_project_is__2c0bd965": { + "message": "The skill you tried to remove from the project is currently used in the below bot(s). Removing this skill won’t delete the files, but it will cause your Bot to malfunction without additional action." + }, "the_target_where_you_publish_your_bot_3132ef47": { "message": "The target where you publish your bot" }, @@ -3134,6 +3137,9 @@ "warning_53c98b03": { "message": "Warning!" }, + "warning_aacb8c24": { + "message": "Warning" + }, "warning_the_action_you_are_about_to_take_cannot_be_1071a3c3": { "message": "Warning: the action you are about to take cannot be undone. Going further will delete this bot and any related files in the bot project folder." }, @@ -3224,6 +3230,9 @@ "you_are_about_to_pull_project_files_from_the_selec_15786351": { "message": "You are about to pull project files from the selected publish profiles. The current project will be overwritten by the pulled files, and will be saved as a backup automatically. You will be able to retrieve the backup anytime in the future." }, + "you_are_about_to_remove_the_skill_from_this_projec_2ba31a6d": { + "message": "You are about to remove the skill from this project. Removing this skill won’t delete the files." + }, "you_can_create_a_new_bot_from_scratch_with_compose_1486288c": { "message": "You can create a new bot from scratch with Composer, or start with a template." }, diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index dc939bbf61..e7aa0ad23e 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -522,7 +522,7 @@ export default async (composer: IExtensionRegistration): Promise => { *************************************************************************************************/ provision = async (config: any, project: IBotProject, user, getAccessToken): Promise => { const jobId = BackgroundProcessManager.startProcess(202, project.id, config.name, 'Creating Azure resources...'); - + console.log(config); this.asyncProvision(jobId, config, project, user); return BackgroundProcessManager.getStatus(jobId); }; diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index 4c87aee093..a1de27f086 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -523,10 +523,10 @@ export const AzureProvisionDialog: React.FC = () => { const onSubmit = useMemo( () => async (options) => { // call back to the main Composer API to begin this process... - // startProvision(options); + startProvision(options); console.log(options); // TODO: close window - // closeDialog(); + closeDialog(); }, [] ); From 863c34a9a8990b82d6f87c7dbd274931cffd7e3f Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Tue, 9 Feb 2021 14:56:11 +0800 Subject: [PATCH 05/44] fix test --- extensions/azurePublish/src/node/provision.test.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/extensions/azurePublish/src/node/provision.test.ts b/extensions/azurePublish/src/node/provision.test.ts index 846a24d495..1493723405 100644 --- a/extensions/azurePublish/src/node/provision.test.ts +++ b/extensions/azurePublish/src/node/provision.test.ts @@ -14,11 +14,7 @@ const mockConfig = { luisLocation: '', name: 'profileName', type: 'azurepublish', - subscription: { - subscriptionId: 'subscriptionId', - tenantId: 'tenant', - displayName: 'test' - }, + subscription: 'test', } as ProvisionConfig; const azProvision = new BotProjectProvision(mockConfig); From 52bd3f6598af16b3b3a0e4f5def92eb19cba57a1 Mon Sep 17 00:00:00 2001 From: Qi Kang Date: Tue, 9 Feb 2021 16:25:39 +0800 Subject: [PATCH 06/44] add profile merge logic --- extensions/azurePublish/src/node/index.ts | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index e7aa0ad23e..8d66b61a24 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -378,6 +378,7 @@ export default async (composer: IExtensionRegistration): Promise => { const provisionResults = await azureProvisioner.create(config); // GOT PROVISION RESULTS! // cast this into the right form for a publish profile + const currentSettings = JSON.parse(config.currentProfile.configuration).settings; const publishProfile = { name: config.hostname, environment: 'composer', @@ -386,19 +387,19 @@ export default async (composer: IExtensionRegistration): Promise => { runtimeIdentifier: 'win-x64', settings: { applicationInsights: { - InstrumentationKey: provisionResults.appInsights?.instrumentationKey, + InstrumentationKey: currentSettings.applicationInsights.InstrumentationKey ?? provisionResults.appInsights?.instrumentationKey, }, - cosmosDb: provisionResults.cosmosDB, - blobStorage: provisionResults.blobStorage, + cosmosDb: currentSettings?.cosmosDb?.authKey?.startsWith('<') ? provisionResults.cosmosDB : currentSettings?.cosmosDb, + blobStorage: currentSettings?.blobStorage?.connectionString?.startsWith('<') ? provisionResults.blobStorage : currentSettings?.blobStorage, luis: { - authoringKey: provisionResults.luisAuthoring?.authoringKey, - authoringEndpoint: provisionResults.luisAuthoring?.authoringEndpoint, - endpointKey: provisionResults.luisPrediction?.endpointKey, - endpoint: provisionResults.luisPrediction?.endpoint, - region: provisionResults.resourceGroup.location, + authoringKey: currentSettings?.luis?.authoringKey ?? provisionResults.luisAuthoring?.authoringKey, + authoringEndpoint: currentSettings?.luis?.authoringEndpoint ?? provisionResults.luisAuthoring?.authoringEndpoint, + endpointKey: currentSettings?.luis?.endpointKey ?? provisionResults.luisPrediction?.endpointKey, + endpoint: currentSettings?.luis?.endpoint ?? provisionResults.luisPrediction?.endpoint, + region: currentSettings?.luis?.region ?? provisionResults.resourceGroup.location, }, - MicrosoftAppId: provisionResults.appId, - MicrosoftAppPassword: provisionResults.appPassword, + MicrosoftAppId: currentSettings?.settings.MicrosoftAppId ?? provisionResults.appId, + MicrosoftAppPassword: currentSettings?.settings.MicrosoftAppPassword ?? provisionResults.appPassword, }, }; From ff6dd1f54898c05aa0d88d25e5640ac1576e81cc Mon Sep 17 00:00:00 2001 From: Qi Kang Date: Tue, 9 Feb 2021 16:36:12 +0800 Subject: [PATCH 07/44] add retry logic judging --- extensions/azurePublish/src/node/index.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index 8d66b61a24..c012f6b925 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -387,19 +387,19 @@ export default async (composer: IExtensionRegistration): Promise => { runtimeIdentifier: 'win-x64', settings: { applicationInsights: { - InstrumentationKey: currentSettings.applicationInsights.InstrumentationKey ?? provisionResults.appInsights?.instrumentationKey, + InstrumentationKey: currentSettings?.applicationInsights?.InstrumentationKey?.startsWith('<') ? provisionResults.appInsights?.instrumentationKey : currentSettings?.applicationInsights?.InstrumentationKey, }, cosmosDb: currentSettings?.cosmosDb?.authKey?.startsWith('<') ? provisionResults.cosmosDB : currentSettings?.cosmosDb, blobStorage: currentSettings?.blobStorage?.connectionString?.startsWith('<') ? provisionResults.blobStorage : currentSettings?.blobStorage, luis: { - authoringKey: currentSettings?.luis?.authoringKey ?? provisionResults.luisAuthoring?.authoringKey, - authoringEndpoint: currentSettings?.luis?.authoringEndpoint ?? provisionResults.luisAuthoring?.authoringEndpoint, - endpointKey: currentSettings?.luis?.endpointKey ?? provisionResults.luisPrediction?.endpointKey, - endpoint: currentSettings?.luis?.endpoint ?? provisionResults.luisPrediction?.endpoint, - region: currentSettings?.luis?.region ?? provisionResults.resourceGroup.location, + authoringKey: currentSettings?.luis?.authoringKey?.startsWith('<') ? provisionResults.luisAuthoring?.authoringKey : currentSettings?.luis?.authoringKey, + authoringEndpoint: currentSettings?.luis?.authoringEndpoint?.startsWith('<') ? provisionResults.luisAuthoring?.authoringEndpoint: currentSettings?.luis?.authoringEndpoint, + endpointKey: currentSettings?.luis?.endpointKey?.startsWith('<') ? provisionResults.luisPrediction?.endpointKey : currentSettings?.luis?.endpointKey, + endpoint: currentSettings?.luis?.endpoint?.startsWith('<') ? provisionResults.luisPrediction?.endpoint : currentSettings?.luis?.endpoint, + region: currentSettings?.luis?.region?.startsWith('<') ? provisionResults.resourceGroup.location : currentSettings?.luis?.region, }, - MicrosoftAppId: currentSettings?.settings.MicrosoftAppId ?? provisionResults.appId, - MicrosoftAppPassword: currentSettings?.settings.MicrosoftAppPassword ?? provisionResults.appPassword, + MicrosoftAppId: currentSettings?.settings?.MicrosoftAppId?.startsWith('<') ? provisionResults.appId : currentSettings?.settings.MicrosoftAppId, + MicrosoftAppPassword: currentSettings?.settings?.MicrosoftAppPassword?.startsWith('<') ? provisionResults.appPassword : currentSettings?.settings.MicrosoftAppPassword, }, }; From d8855a3969d2132da31441029a7c06e86a21b5c4 Mon Sep 17 00:00:00 2001 From: Qi Kang Date: Tue, 9 Feb 2021 17:44:09 +0800 Subject: [PATCH 08/44] remove settings --- extensions/azurePublish/src/node/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index c012f6b925..2990f8b501 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -398,8 +398,8 @@ export default async (composer: IExtensionRegistration): Promise => { endpoint: currentSettings?.luis?.endpoint?.startsWith('<') ? provisionResults.luisPrediction?.endpoint : currentSettings?.luis?.endpoint, region: currentSettings?.luis?.region?.startsWith('<') ? provisionResults.resourceGroup.location : currentSettings?.luis?.region, }, - MicrosoftAppId: currentSettings?.settings?.MicrosoftAppId?.startsWith('<') ? provisionResults.appId : currentSettings?.settings.MicrosoftAppId, - MicrosoftAppPassword: currentSettings?.settings?.MicrosoftAppPassword?.startsWith('<') ? provisionResults.appPassword : currentSettings?.settings.MicrosoftAppPassword, + MicrosoftAppId: currentSettings?.MicrosoftAppId?.startsWith('<') ? provisionResults.appId : currentSettings?.settings.MicrosoftAppId, + MicrosoftAppPassword: currentSettings?.MicrosoftAppPassword?.startsWith('<') ? provisionResults.appPassword : currentSettings?.settings.MicrosoftAppPassword, }, }; From 205dc993f222587803ca4655e86400f4fa9ed633 Mon Sep 17 00:00:00 2001 From: Qi Kang Date: Tue, 9 Feb 2021 17:45:18 +0800 Subject: [PATCH 09/44] remove settings --- extensions/azurePublish/src/node/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index 2990f8b501..9074828463 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -398,8 +398,8 @@ export default async (composer: IExtensionRegistration): Promise => { endpoint: currentSettings?.luis?.endpoint?.startsWith('<') ? provisionResults.luisPrediction?.endpoint : currentSettings?.luis?.endpoint, region: currentSettings?.luis?.region?.startsWith('<') ? provisionResults.resourceGroup.location : currentSettings?.luis?.region, }, - MicrosoftAppId: currentSettings?.MicrosoftAppId?.startsWith('<') ? provisionResults.appId : currentSettings?.settings.MicrosoftAppId, - MicrosoftAppPassword: currentSettings?.MicrosoftAppPassword?.startsWith('<') ? provisionResults.appPassword : currentSettings?.settings.MicrosoftAppPassword, + MicrosoftAppId: currentSettings?.MicrosoftAppId?.startsWith('<') ? provisionResults.appId : currentSettings?.MicrosoftAppId, + MicrosoftAppPassword: currentSettings?.MicrosoftAppPassword?.startsWith('<') ? provisionResults.appPassword : currentSettings?.MicrosoftAppPassword, }, }; From c86c8e258336342fa715e93cdc26d8b75891b61b Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Tue, 9 Feb 2021 20:14:01 +0800 Subject: [PATCH 10/44] fix review page display error --- .../src/ui/azureProvisionDialog.tsx | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index a1de27f086..8c39e81747 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -47,6 +47,7 @@ import { Selection, SelectionMode, DetailsRow, + setRTL, } from 'office-ui-fabric-react'; import { SharedColors } from '@uifabric/fluent-theme'; import { JsonEditor } from '@bfc/code-editor'; @@ -451,22 +452,49 @@ export const AzureProvisionDialog: React.FC = () => { } }, [currentSubscription]); + // const removePlaceholder = React.useCallback((config:any)=>{ + // if(config){ + // let str = JSON.stringify(config); + // str = str.replace(/<.*>/g,''); + // console.log(str); + // const newConfig = JSON.parse(str); + // console.log(newConfig); + // return newConfig; + // } else { + // return undefined; + // } + // },[]); + const getExistResources = ()=>{ const result = []; - if(currentConfig){ - if(currentConfig.hostname){ + // let config = removePlaceholder(currentConfig); + const config = currentConfig; + // const str = JSON.stringify(config).replace(/<.*>/g, ''); + // console.log(JSON.parse(str)); + console.log(config); + if(config){ + if(config.hostname){ result.push(AzureResourceTypes.WEBAPP); result.push(AzureResourceTypes.APP_REGISTRATION); } - if(currentConfig.settings?.MicrosoftAppId){ + if(config.settings?.MicrosoftAppId){ result.push(AzureResourceTypes.BOT_REGISTRATION); } - if(currentConfig.settings?.luis?.authoringKey){ + if(config.settings?.luis?.authoringKey){ result.push(AzureResourceTypes.LUIS_AUTHORING); } - if(currentConfig.settings?.luis?.endpointKey){ + if(config.settings?.luis?.endpointKey){ result.push(AzureResourceTypes.LUIS_PREDICTION); } + if(config.settings?.applicationInsights?.InstrumentationKey){ + result.push(AzureResourceTypes.APPINSIGHTS); + } + if(config.settings?.cosmosDb?.authKey){ + result.push(AzureResourceTypes.COSMOSDB); + } + if(config.settings?.blobStorage?.connectionString){ + result.push(AzureResourceTypes.BLOBSTORAGE); + } return result; } else return []; } @@ -733,13 +761,12 @@ export const AzureProvisionDialog: React.FC = () => { style={{margin: '0 4px'}} /> { setPage(PageTypes.ReviewResource); setTitle(DialogTitle.REVIEW); let selectedResources = requireResources.concat(enabledResources); - selectedResources = selectedResources.map(item=>({...item, region: currentLocation, resourceGroup:currentConfig.resourceGroup || currentHostName})) + selectedResources = selectedResources.map(item=>({...item, region: currentLocation, resourceGroup:currentConfig?.resourceGroup || currentHostName})) console.log(selectedResources); setReviewListItems(selectedResources); }} From 5daccf34670fd1e64d5469629d86d46c27132629 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Tue, 9 Feb 2021 21:00:12 +0800 Subject: [PATCH 11/44] fix profile update in edit --- .../src/recoilModel/dispatchers/provision.ts | 22 +++++++++++++--- .../src/ui/azureProvisionDialog.tsx | 26 ++++++++++--------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/Composer/packages/client/src/recoilModel/dispatchers/provision.ts b/Composer/packages/client/src/recoilModel/dispatchers/provision.ts index 37e4c9eada..8bc9816e13 100644 --- a/Composer/packages/client/src/recoilModel/dispatchers/provision.ts +++ b/Composer/packages/client/src/recoilModel/dispatchers/provision.ts @@ -3,7 +3,7 @@ /* eslint-disable react-hooks/rules-of-hooks */ import formatMessage from 'format-message'; import { CallbackInterface, useRecoilCallback } from 'recoil'; -import { PublishTarget } from '@bfc/shared'; +import { DialogSetting, PublishTarget } from '@bfc/shared'; import { provisionStatusState, settingsState } from '../atoms/botState'; import { CardProps } from '../../components/Notifications/NotificationCard'; @@ -35,6 +35,21 @@ export const provisionDispatcher = () => { }; }; + const updatePublishTargets = (settings: DialogSetting, profile: PublishTarget) => { + const index = settings.publishTargets?.findIndex((item) => item.name === profile.name); + if (index && index >= 0) { + return settings.publishTargets?.map((item) => { + if (item.name === profile.name) { + return profile; + } else { + return item; + } + }); + } else { + return (settings.publishTargets || []).concat([profile]); + } + }; + const provisionToTarget = useRecoilCallback( (callbackHelpers: CallbackInterface) => async ( config: any, @@ -46,7 +61,6 @@ export const provisionDispatcher = () => { ) => { try { TelemetryClient.track('NewPublishingProfileStarted'); - console.log(currentProfile); const result = await httpClient.post( `/provision/${projectId}/${type}`, { ...config, graphToken: graphToken, currentProfile }, @@ -117,10 +131,10 @@ export const provisionDispatcher = () => { name: targetName, type: targetType, }; - const targetlist = (settings.publishTargets || []).concat([profile]); + const targetList = updatePublishTargets(settings, profile); return { ...settings, - publishTargets: targetlist, + publishTargets: targetList, }; }); diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index 8c39e81747..537fa78287 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -453,25 +453,27 @@ export const AzureProvisionDialog: React.FC = () => { }, [currentSubscription]); // const removePlaceholder = React.useCallback((config:any)=>{ - // if(config){ - // let str = JSON.stringify(config); - // str = str.replace(/<.*>/g,''); - // console.log(str); - // const newConfig = JSON.parse(str); - // console.log(newConfig); - // return newConfig; - // } else { - // return undefined; + // try{ + // if(config){ + // let str = JSON.stringify(config); + // str = str.replace(/<.*>/g,null); + // console.log(str); + // const newConfig = JSON.parse(str); + // console.log(newConfig); + // return newConfig; + // } else { + // return undefined; + // } + // }catch(e){ + // console.log(e); // } + // },[]); const getExistResources = ()=>{ const result = []; // let config = removePlaceholder(currentConfig); const config = currentConfig; - // const str = JSON.stringify(config).replace(/<.*>/g, ''); - // console.log(JSON.parse(str)); - console.log(config); if(config){ if(config.hostname){ result.push(AzureResourceTypes.WEBAPP); From f5104ceab9199685e31abb19a307b793f4796311 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Wed, 10 Feb 2021 00:21:46 +0800 Subject: [PATCH 12/44] remove status and fix provision update --- .../src/recoilModel/dispatchers/provision.ts | 3 +- .../src/ui/azureProvisionDialog.tsx | 58 ++++++------------- 2 files changed, 20 insertions(+), 41 deletions(-) diff --git a/Composer/packages/client/src/recoilModel/dispatchers/provision.ts b/Composer/packages/client/src/recoilModel/dispatchers/provision.ts index 8bc9816e13..d342c805b9 100644 --- a/Composer/packages/client/src/recoilModel/dispatchers/provision.ts +++ b/Composer/packages/client/src/recoilModel/dispatchers/provision.ts @@ -37,7 +37,7 @@ export const provisionDispatcher = () => { const updatePublishTargets = (settings: DialogSetting, profile: PublishTarget) => { const index = settings.publishTargets?.findIndex((item) => item.name === profile.name); - if (index && index >= 0) { + if (typeof index === 'number' && index >= 0) { return settings.publishTargets?.map((item) => { if (item.name === profile.name) { return profile; @@ -132,6 +132,7 @@ export const provisionDispatcher = () => { type: targetType, }; const targetList = updatePublishTargets(settings, profile); + console.log(targetList); return { ...settings, publishTargets: targetList, diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index 537fa78287..ebb222bde8 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -206,19 +206,6 @@ const reviewCols: IColumn[] = [ }, isPadded: true, }, - { - key: 'Status', - name: formatMessage('Status'), - className: 'Status', - fieldName: 'Status', - minWidth: 100, - isRowHeader: true, - data: 'string', - onRender: (item: ResourcesItem) => { - return
Ready
; - }, - isPadded: true, - }, { key: 'resourceGroup', name: formatMessage('Resource Group'), @@ -405,13 +392,7 @@ export const AzureProvisionDialog: React.FC = () => { () => (e, newName) => { setHostName(newName); if(!currentConfig?.hostname){ - // validate existed or not - const existed = resourceGroups.find((t) => t.name === newName); - if (existed) { - setErrorHostName('this resource group already exist'); - } else { - checkNameAvailability(newName); - } + checkNameAvailability(newName); } }, [resourceGroups, checkNameAvailability] @@ -452,28 +433,26 @@ export const AzureProvisionDialog: React.FC = () => { } }, [currentSubscription]); - // const removePlaceholder = React.useCallback((config:any)=>{ - // try{ - // if(config){ - // let str = JSON.stringify(config); - // str = str.replace(/<.*>/g,null); - // console.log(str); - // const newConfig = JSON.parse(str); - // console.log(newConfig); - // return newConfig; - // } else { - // return undefined; - // } - // }catch(e){ - // console.log(e); - // } - - // },[]); + const removePlaceholder = React.useCallback((config:any)=>{ + try{ + if(config){ + let str = JSON.stringify(config); + str = str.replace(/<[.^>]*>/g, null); + const newConfig = JSON.parse(str); + return newConfig; + } else { + return undefined; + } + }catch(e){ + console.log(e); + } + + },[]); const getExistResources = ()=>{ const result = []; - // let config = removePlaceholder(currentConfig); - const config = currentConfig; + const config = removePlaceholder(currentConfig); + console.log(config); if(config){ if(config.hostname){ result.push(AzureResourceTypes.WEBAPP); @@ -554,7 +533,6 @@ export const AzureProvisionDialog: React.FC = () => { () => async (options) => { // call back to the main Composer API to begin this process... startProvision(options); - console.log(options); // TODO: close window closeDialog(); }, From ec03934255bda8852823116d32a53b39ea9ad4f8 Mon Sep 17 00:00:00 2001 From: Qi Kang Date: Wed, 10 Feb 2021 15:50:39 +0800 Subject: [PATCH 13/44] add missed field in current settings --- extensions/azurePublish/src/node/index.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index 9074828463..ca0bff41bb 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -402,6 +402,11 @@ export default async (composer: IExtensionRegistration): Promise => { MicrosoftAppPassword: currentSettings?.MicrosoftAppPassword?.startsWith('<') ? provisionResults.appPassword : currentSettings?.MicrosoftAppPassword, }, }; + for (let configUnit in currentSettings) { + if (!(configUnit in publishProfile)) { + publishProfile[configUnit] = currentSettings[configUnit]; + } + } this.logger(publishProfile); From 19f6cdbf86f1c42cf44fcf6c8fe3b5fc5f4a7060 Mon Sep 17 00:00:00 2001 From: Lu Han <32191031+luhan2017@users.noreply.github.com> Date: Thu, 18 Feb 2021 16:30:56 +0800 Subject: [PATCH 14/44] Fix some issues 1. fix the logic of merging existing profile with new provisioned configurations. 2. when hostname or name exist, don't provision new webapp. 3. add subscriptionId and resourceGroup in the publish profile. --- extensions/azurePublish/src/node/index.ts | 40 +++++++++++++------ extensions/azurePublish/src/node/provision.ts | 3 ++ .../src/ui/azureProvisionDialog.tsx | 5 ++- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index ca0bff41bb..5f95a81aae 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -17,6 +17,7 @@ import schema from './schema'; import { stringifyError, AzurePublishErrors, createCustomizeError } from './utils/errorHandler'; import { ProcessStatus } from './types'; import { authConfig, ResourcesItem } from '../types'; +import { ResourceGroup } from '@azure/arm-resources/esm/models/mappers'; // This option controls whether the history is serialized to a file between sessions with Composer // set to TRUE for history to be saved to disk @@ -378,31 +379,44 @@ export default async (composer: IExtensionRegistration): Promise => { const provisionResults = await azureProvisioner.create(config); // GOT PROVISION RESULTS! // cast this into the right form for a publish profile - const currentSettings = JSON.parse(config.currentProfile.configuration).settings; + + var currentProfile = null; + if (config.currentProfile) + { + currentProfile = JSON.parse(config.currentProfile.configuration); + } + const currentSettings = currentProfile?.settings; + const publishProfile = { name: config.hostname, environment: 'composer', + subscriptionId: provisionResults.subscriptionId, + resourceGroup: provisionResults.resourceGroup.name, hostname: config.hostname, luisResource: `${config.hostname}-luis`, runtimeIdentifier: 'win-x64', settings: { applicationInsights: { - InstrumentationKey: currentSettings?.applicationInsights?.InstrumentationKey?.startsWith('<') ? provisionResults.appInsights?.instrumentationKey : currentSettings?.applicationInsights?.InstrumentationKey, + InstrumentationKey: provisionResults.appInsights?.instrumentationKey ?? currentSettings?.applicationInsights?.InstrumentationKey, }, - cosmosDb: currentSettings?.cosmosDb?.authKey?.startsWith('<') ? provisionResults.cosmosDB : currentSettings?.cosmosDb, - blobStorage: currentSettings?.blobStorage?.connectionString?.startsWith('<') ? provisionResults.blobStorage : currentSettings?.blobStorage, + cosmosDb: provisionResults.cosmosDB ?? currentSettings?.cosmosDb, + blobStorage: provisionResults.blobStorage ?? currentSettings?.blobStorage, luis: { - authoringKey: currentSettings?.luis?.authoringKey?.startsWith('<') ? provisionResults.luisAuthoring?.authoringKey : currentSettings?.luis?.authoringKey, - authoringEndpoint: currentSettings?.luis?.authoringEndpoint?.startsWith('<') ? provisionResults.luisAuthoring?.authoringEndpoint: currentSettings?.luis?.authoringEndpoint, - endpointKey: currentSettings?.luis?.endpointKey?.startsWith('<') ? provisionResults.luisPrediction?.endpointKey : currentSettings?.luis?.endpointKey, - endpoint: currentSettings?.luis?.endpoint?.startsWith('<') ? provisionResults.luisPrediction?.endpoint : currentSettings?.luis?.endpoint, - region: currentSettings?.luis?.region?.startsWith('<') ? provisionResults.resourceGroup.location : currentSettings?.luis?.region, + authoringKey: provisionResults.luisAuthoring?.authoringKey ?? currentSettings?.luis?.authoringKey, + authoringEndpoint: provisionResults.luisAuthoring?.authoringEndpoint ?? currentSettings?.luis?.authoringEndpoint, + endpointKey: provisionResults.luisPrediction?.endpointKey ?? currentSettings?.luis?.endpointKey, + endpoint: provisionResults.luisPrediction?.endpoint ?? currentSettings?.luis?.endpoint, + region: provisionResults.luisPrediction?.location ?? currentSettings?.luis?.region, }, - MicrosoftAppId: currentSettings?.MicrosoftAppId?.startsWith('<') ? provisionResults.appId : currentSettings?.MicrosoftAppId, - MicrosoftAppPassword: currentSettings?.MicrosoftAppPassword?.startsWith('<') ? provisionResults.appPassword : currentSettings?.MicrosoftAppPassword, - }, + qna: { + subscriptionKey: provisionResults.qna?.subscriptionKey ?? currentSettings?.qna?.subscriptionKey, + qnaRegion: provisionResults.qna?.region ?? currentSettings?.qna?.qnaRegion, + }, + MicrosoftAppId: provisionResults.appId ?? currentSettings?.MicrosoftAppId, + MicrosoftAppPassword: provisionResults.appPassword ?? currentSettings?.MicrosoftAppPassword, + } }; - for (let configUnit in currentSettings) { + for (let configUnit in currentProfile) { if (!(configUnit in publishProfile)) { publishProfile[configUnit] = currentSettings[configUnit]; } diff --git a/extensions/azurePublish/src/node/provision.ts b/extensions/azurePublish/src/node/provision.ts index 93987d5247..e14a621aab 100644 --- a/extensions/azurePublish/src/node/provision.ts +++ b/extensions/azurePublish/src/node/provision.ts @@ -195,6 +195,7 @@ export class BotProjectProvision { // this object collects all of the various configuration output const provisionResults = { + subscriptionId: null, appId: null, appPassword: null, resourceGroup: null, @@ -216,6 +217,8 @@ export class BotProjectProvision { logger: this.logger, } as AzureResourceManangerConfig; + provisionResults.subscriptionId = this.subscriptionId; + // This object is used to actually make the calls to Azure... this.azureResourceManagementClient = new AzureResourceMananger(armConfig); diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index ebb222bde8..48e3517898 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -454,12 +454,13 @@ export const AzureProvisionDialog: React.FC = () => { const config = removePlaceholder(currentConfig); console.log(config); if(config){ - if(config.hostname){ + // If name or hostname is configured, it means the webapp is already created. + if(config.hostname || config.name){ result.push(AzureResourceTypes.WEBAPP); - result.push(AzureResourceTypes.APP_REGISTRATION); } if(config.settings?.MicrosoftAppId){ result.push(AzureResourceTypes.BOT_REGISTRATION); + result.push(AzureResourceTypes.APP_REGISTRATION); } if(config.settings?.luis?.authoringKey){ result.push(AzureResourceTypes.LUIS_AUTHORING); From 296193937ffc2a630f07e6c080ac8ea8dda19b95 Mon Sep 17 00:00:00 2001 From: Lu Han <32191031+luhan2017@users.noreply.github.com> Date: Fri, 19 Feb 2021 17:51:41 +0800 Subject: [PATCH 15/44] remove the dependency between webapp and bot channel registration in provision --- .../azureResourceManager.ts | 18 +----------------- extensions/azurePublish/src/node/index.ts | 15 ++++++++------- extensions/azurePublish/src/node/provision.ts | 10 +++------- .../src/ui/azureProvisionDialog.tsx | 3 +++ 4 files changed, 15 insertions(+), 31 deletions(-) diff --git a/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts b/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts index b2c1b30b3e..8e66de128c 100644 --- a/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts +++ b/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts @@ -785,15 +785,7 @@ export class AzureResourceMananger { { name: 'WEBSITE_NODE_DEFAULT_VERSION', value: '10.14.1', - }, - { - name: 'MicrosoftAppId', - value: config.appId, - }, - { - name: 'MicrosoftAppPassword', - value: config.appPwd, - }, + } ], cors: { allowedOrigins: ['https://botservice.hosting.portal.azure.net', 'https://hosting.onecloud.azure-test.net/'], @@ -839,14 +831,6 @@ export class AzureResourceMananger { httpsOnly: true, siteConfig: { appSettings: [ - { - name: 'MicrosoftAppId', - value: config.appId, - }, - { - name: 'MicrosoftAppPassword', - value: config.appPwd, - }, { name: 'FUNCTIONS_EXTENSION_VERSION', value: '~3' diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index 86de1af98c..a70a3dfff3 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -18,6 +18,7 @@ import { stringifyError, AzurePublishErrors, createCustomizeError } from './util import { ProcessStatus } from './types'; import { authConfig, ResourcesItem } from '../types'; import { ResourceGroup } from '@azure/arm-resources/esm/models/mappers'; +import { LuisApp } from '@azure/cognitiveservices-luis-authoring/esm/models/mappers'; // This option controls whether the history is serialized to a file between sessions with Composer // set to TRUE for history to be saved to disk @@ -399,13 +400,13 @@ export default async (composer: IExtensionRegistration): Promise => { const currentSettings = currentProfile?.settings; const publishProfile = { - name: config.hostname, - environment: 'composer', - subscriptionId: provisionResults.subscriptionId, - resourceGroup: provisionResults.resourceGroup.name, - hostname: config.hostname, - luisResource: `${config.hostname}-luis`, - runtimeIdentifier: 'win-x64', + name: currentProfile?.name ?? config.hostname, + environment: currentProfile?.environment ?? 'composer', + subscriptionId: provisionResults.subscriptionId ?? currentProfile?.subscriptionId, + resourceGroup: provisionResults.resourceGroup?.name ?? currentProfile?.resourceGroup, + hostname: config.hostname ?? currentProfile?.hostname, + luisResource: provisionResults.luisPrediction? `${config.hostname}-luis` : currentProfile?.luisResource, + runtimeIdentifier: currentProfile?.runtimeIdentifier ?? 'win-x64', settings: { applicationInsights: { InstrumentationKey: provisionResults.appInsights?.instrumentationKey ?? currentSettings?.applicationInsights?.InstrumentationKey, diff --git a/extensions/azurePublish/src/node/provision.ts b/extensions/azurePublish/src/node/provision.ts index e14a621aab..8253ae4108 100644 --- a/extensions/azurePublish/src/node/provision.ts +++ b/extensions/azurePublish/src/node/provision.ts @@ -254,9 +254,7 @@ export class BotProjectProvision { const hostname = await this.azureResourceManagementClient.deployWebAppResource({ resourceGroupName: resourceGroupName, location: provisionResults.resourceGroup.location, - name: config.hostname, - appId: provisionResults.appId, - appPwd: provisionResults.appPassword, + name: config.hostname }); provisionResults.webApp = { hostname: hostname, @@ -271,7 +269,7 @@ export class BotProjectProvision { location: provisionResults.resourceGroup.location, name: config.hostname, // come back to this! displayName: config.hostname, // todo: this may be wrong! - endpoint: `https://${provisionResults.webApp.hostname}/api/messages`, + endpoint: `https://${provisionResults.webApp?.hostname ?? (config.hostname + ".azurewebsites.net")}/api/messages`, appId: provisionResults.appId, }); break; @@ -282,9 +280,7 @@ export class BotProjectProvision { const functionsHostName = await this.azureResourceManagementClient.deployAzureFunctions({ resourceGroupName: resourceGroupName, location: provisionResults.resourceGroup.location, - name: config.hostname, - appId: provisionResults.appId, - appPwd: provisionResults.appPassword, + name: config.hostname }); provisionResults.webApp = { hostname: functionsHostName, diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index 48e3517898..82e876ee06 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -468,6 +468,9 @@ export const AzureProvisionDialog: React.FC = () => { if(config.settings?.luis?.endpointKey){ result.push(AzureResourceTypes.LUIS_PREDICTION); } + if(config.settings?.qna?.subscriptionKey){ + result.push(AzureResourceTypes.QNA); + } if(config.settings?.applicationInsights?.InstrumentationKey){ result.push(AzureResourceTypes.APPINSIGHTS); } From f93987c90fb8cf3baf96f2668f7c364c588a53cf Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Fri, 19 Feb 2021 22:15:38 +0800 Subject: [PATCH 16/44] fix luis region always westus --- .../packages/server/src/locales/en-US.json | 43 +++++++----- .../src/ui/azureProvisionDialog.tsx | 66 ++++++++++++------- 2 files changed, 67 insertions(+), 42 deletions(-) diff --git a/Composer/packages/server/src/locales/en-US.json b/Composer/packages/server/src/locales/en-US.json index 104bc739a1..62c44c4f70 100644 --- a/Composer/packages/server/src/locales/en-US.json +++ b/Composer/packages/server/src/locales/en-US.json @@ -545,6 +545,9 @@ "collapse_34080b4d": { "message": "Collapse" }, + "collapse_debug_panel_6f1c5869": { + "message": "Collapse debug panel" + }, "collapse_navigation_17228b95": { "message": "Collapse Navigation" }, @@ -653,12 +656,6 @@ "conversation_invoked_invoke_activity_71efde42": { "message": "Conversation invoked (Invoke activity)" }, - "conversational_core_preview_template_is_available__ba9b43b8": { - "message": "Conversational Core preview template is available since you have that feature turned on." - }, - "conversational_core_template_899e3082": { - "message": "Conversational Core Template" - }, "conversationupdate_activity_9e94bff5": { "message": "ConversationUpdate activity" }, @@ -824,6 +821,9 @@ "debug_break_870a75df": { "message": "Debug break" }, + "debug_panel_header_2ee4d70c": { + "message": "Debug Panel Header" + }, "debugging_options_20e2e9da": { "message": "Debugging options" }, @@ -1097,9 +1097,6 @@ "enable_multi_turn_extraction_8a168892": { "message": "Enable multi-turn extraction" }, - "enable_the_new_conversational_core_template_built__df338773": { - "message": "Enable the new conversational core template built on the component model" - }, "enabled_ba7cab66": { "message": "Enabled" }, @@ -1304,8 +1301,11 @@ "file_type_fd1ba7ee": { "message": "File Type" }, - "filter_dialog_de3ce43f": { - "message": "Filter Dialog" + "filter_by_dialog_or_trigger_name_784ee5b0": { + "message": "Filter by dialog or trigger name" + }, + "filter_by_file_name_fa3d33b5": { + "message": "Filter by file name" }, "firstselector_a3daca5d": { "message": "FirstSelector" @@ -1577,6 +1577,9 @@ "is_missing_or_empty_a551462e": { "message": "is missing or empty" }, + "issues_4680a499": { + "message": "Issues" + }, "it_s_not_a_built_in_function_or_a_custom_function_1527ed83": { "message": "it''s not a built-in function or a custom function." }, @@ -2153,6 +2156,12 @@ "open_start_bots_panel_f7f87200": { "message": "Open start bots panel" }, + "open_web_chat_23601990": { + "message": "Open Web Chat" + }, + "open_web_chat_7a24d4f8": { + "message": "Open web chat" + }, "optional_221bcc9d": { "message": "Optional" }, @@ -2549,6 +2558,12 @@ "responses_12d6df1d": { "message": "Responses" }, + "restart_conversation_new_user_id_9c024543": { + "message": "Restart Conversation - new user ID" + }, + "restart_conversation_same_user_id_a0188cca": { + "message": "Restart Conversation - same user ID" + }, "review_and_generate_63dec712": { "message": "Review and generate" }, @@ -3161,9 +3176,6 @@ "type_could_not_be_loaded_65ebaf86": { "message": "{ type } could not be loaded" }, - "type_dialog_name_14a50769": { - "message": "Type dialog name" - }, "type_form_dialog_schema_name_b767985c": { "message": "Type form dialog schema name" }, @@ -3445,8 +3457,5 @@ }, "your_knowledge_base_is_ready_6ecc1871": { "message": "Your knowledge base is ready!" - }, - "your_project_2a42631c": { - "message": "your project" } } \ No newline at end of file diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index 82e876ee06..55e94a0d45 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -85,16 +85,16 @@ const DialogTitle = { }, }; -function onRenderDetailsHeader(props, defaultRender) { - return ( - - {defaultRender({ - ...props, - onRenderColumnHeaderTooltip: (tooltipHostProps) => , - })} - - ); -} +// function onRenderDetailsHeader(props, defaultRender) { +// return ( +// +// {defaultRender({ +// ...props, +// onRenderColumnHeaderTooltip: (tooltipHostProps) => , +// })} +// +// ); +// } function decodeToken(token: string) { try { @@ -241,7 +241,11 @@ const reviewCols: IColumn[] = [ isRowHeader: true, data: 'string', onRender: (item: ResourcesItem & {name,icon}) => { - return
{item.region.displayName}
; + // if(item.key.includes('luis')){ + // return
{item.}
+ // }else{ + return
{item.region.displayName}
; + // } }, isPadded: true, }, @@ -251,7 +255,7 @@ export const AzureProvisionDialog: React.FC = () => { const [subscriptions, setSubscriptions] = useState([]); const [resourceGroups, setResourceGroups] = useState([]); const [deployLocations, setDeployLocations] = useState([]); - const [luisLocations, setLuisLocations] = useState([]); + const [luisLocations, setLuisLocations] = useState([]); const [token, setToken] = useState(); const [currentUser, setCurrentUser] = useState(); @@ -261,7 +265,7 @@ export const AzureProvisionDialog: React.FC = () => { const [currentHostName, setHostName] = useState(''); const [errorHostName, setErrorHostName] = useState(''); const [currentLocation, setLocation] = useState(); - const [currentLuisLocation, setCurrentLuisLocation] = useState(); + const [currentLuisLocation, setCurrentLuisLocation] = useState(); const [extensionResourceOptions, setExtensionResourceOptions] = useState([]); const [enabledResources, setEnabledResources] = useState([]); // create from optional list const [requireResources, setRequireResources] = useState([]); @@ -351,7 +355,7 @@ export const AzureProvisionDialog: React.FC = () => { }, [deployLocations]); const luisLocationsOption = useMemo((): IDropdownOption[] => { - return luisLocations.map((t) => ({ key: t, text: t })); + return luisLocations.map((t) => ({ key: t.id, text: t.displayName })); }, [luisLocations]); const updateCurrentSubscription = useMemo( @@ -411,7 +415,7 @@ export const AzureProvisionDialog: React.FC = () => { const updateLuisLocation = useMemo( () => (_e, option?: IDropdownOption) => { - const location = luisLocations.find((t) => t === option?.key); + const location = luisLocations.find((t) => t.id === option?.key); if (location) { setCurrentLuisLocation(location); } @@ -423,8 +427,14 @@ export const AzureProvisionDialog: React.FC = () => { if (currentSubscription) { // get resource group under subscription getResourceGroups(token, currentSubscription).then(setResourceGroups); - getDeployLocations(token, currentSubscription).then(setDeployLocations); - setLuisLocations(getLuisAuthoringRegions()); + getDeployLocations(token, currentSubscription).then((data:DeployLocation[])=> { + setDeployLocations(data); + const luRegions = getLuisAuthoringRegions(); + const region = data.filter(item=> luRegions.includes(item.name)); + console.log(region); + setLuisLocations(region); + }); + // if(currentHostName){ // // check its hostname availability @@ -437,7 +447,8 @@ export const AzureProvisionDialog: React.FC = () => { try{ if(config){ let str = JSON.stringify(config); - str = str.replace(/<[.^>]*>/g, null); + str = str.replace(/<[.^>]*>/g, ''); + console.log(str); const newConfig = JSON.parse(str); return newConfig; } else { @@ -536,9 +547,9 @@ export const AzureProvisionDialog: React.FC = () => { const onSubmit = useMemo( () => async (options) => { // call back to the main Composer API to begin this process... - startProvision(options); - // TODO: close window - closeDialog(); + console.log(options); + // startProvision(options); + // closeDialog(); }, [] ); @@ -617,7 +628,7 @@ export const AzureProvisionDialog: React.FC = () => { styles={{ root: { paddingBottom: '8px' } }} onChange={updateCurrentLocation} /> - {currentLocation && luisLocations.length>0 && !luisLocations.includes(currentLocation.name) ? + {currentLocation && luisLocations.length>0 && !luisLocations.find(item=> item.name === currentLocation.name) ? { setPage(PageTypes.ReviewResource); setTitle(DialogTitle.REVIEW); let selectedResources = requireResources.concat(enabledResources); - selectedResources = selectedResources.map(item=>({...item, region: currentLocation, resourceGroup:currentConfig?.resourceGroup || currentHostName})) - console.log(selectedResources); + selectedResources = selectedResources.map(item=>{ + let region = currentLocation; + if(item.key.includes('luis')){ + region = currentLuisLocation; + } + return {...item, region: region, resourceGroup:currentConfig?.resourceGroup || currentHostName}; + }); setReviewListItems(selectedResources); }} style={{margin: '0 4px'}} @@ -777,7 +793,7 @@ export const AzureProvisionDialog: React.FC = () => { subscription: currentSubscription, hostname: currentHostName, location: currentLocation, - luisLocation: currentLuisLocation || currentLocation.name, + luisLocation: currentLuisLocation.name || currentLocation.name, type: publishType, externalResources: selectedResources, }); From 93b00b301cdfa636d59fcbfc97f19244490f3995 Mon Sep 17 00:00:00 2001 From: Lu Han <32191031+luhan2017@users.noreply.github.com> Date: Sat, 20 Feb 2021 13:09:51 +0800 Subject: [PATCH 17/44] decouple resourceGroup and hostName, fix regex --- extensions/azurePublish/src/node/index.ts | 2 +- extensions/azurePublish/src/node/provision.ts | 3 +- .../src/ui/azureProvisionDialog.tsx | 28 ++++++++++++++----- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index a70a3dfff3..68907ea3bb 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -403,7 +403,7 @@ export default async (composer: IExtensionRegistration): Promise => { name: currentProfile?.name ?? config.hostname, environment: currentProfile?.environment ?? 'composer', subscriptionId: provisionResults.subscriptionId ?? currentProfile?.subscriptionId, - resourceGroup: provisionResults.resourceGroup?.name ?? currentProfile?.resourceGroup, + resourceGroup: currentProfile?.resourceGroup ?? provisionResults.resourceGroup?.name, hostname: config.hostname ?? currentProfile?.hostname, luisResource: provisionResults.luisPrediction? `${config.hostname}-luis` : currentProfile?.luisResource, runtimeIdentifier: currentProfile?.runtimeIdentifier ?? 'win-x64', diff --git a/extensions/azurePublish/src/node/provision.ts b/extensions/azurePublish/src/node/provision.ts index 8253ae4108..051e60a773 100644 --- a/extensions/azurePublish/src/node/provision.ts +++ b/extensions/azurePublish/src/node/provision.ts @@ -19,6 +19,7 @@ export interface ProvisionConfig { location: { id: string; name: string; displayName: string }; luisLocation: string; subscription: string; + resourceGroup?: string; logger?: (string) => any; name: string; // profile name type: string; // webapp or function @@ -208,7 +209,7 @@ export class BotProjectProvision { qna: null, }; - const resourceGroupName = `${config.hostname}`; + const resourceGroupName = config.resourceGroup ?? config.hostname; // azure resource manager class config const armConfig = { diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index 55e94a0d45..8e4557f6c4 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -262,6 +262,7 @@ export const AzureProvisionDialog: React.FC = () => { const [choice, setChoice] = useState(choiceOptions[0]); const [currentSubscription, setSubscription] = useState(''); + const [currentResourceGroup, setResourceGroup] = useState(''); const [currentHostName, setHostName] = useState(''); const [errorHostName, setErrorHostName] = useState(''); const [currentLocation, setLocation] = useState(); @@ -323,6 +324,9 @@ export const AzureProvisionDialog: React.FC = () => { if(currentConfig?.subscriptionId){ setSubscription(currentConfig?.subscriptionId); } + if(currentConfig?.resourceGroup){ + setResourceGroup(currentConfig?.resourceGroup); + } if(currentConfig?.hostname){ setHostName(currentConfig?.hostname); } @@ -393,6 +397,13 @@ export const AzureProvisionDialog: React.FC = () => { }, [currentConfig, publishType, currentSubscription, token]); const newResourceGroup = useMemo( + () => (e, newName) => { + setResourceGroup(newName); + }, + [resourceGroups, checkNameAvailability] + ); + + const newHostName = useMemo( () => (e, newName) => { setHostName(newName); if(!currentConfig?.hostname){ @@ -447,7 +458,7 @@ export const AzureProvisionDialog: React.FC = () => { try{ if(config){ let str = JSON.stringify(config); - str = str.replace(/<[.^>]*>/g, ''); + str = str.replace(/<.*>/g, ''); console.log(str); const newConfig = JSON.parse(str); return newConfig; @@ -548,8 +559,8 @@ export const AzureProvisionDialog: React.FC = () => { () => async (options) => { // call back to the main Composer API to begin this process... console.log(options); - // startProvision(options); - // closeDialog(); + startProvision(options); + closeDialog(); }, [] ); @@ -604,6 +615,7 @@ export const AzureProvisionDialog: React.FC = () => { label={formatMessage('Resource group name')} ariaLabel={formatMessage('A resource group is a collection of resources that share the same lifecycle, permissions, and policies')} placeholder={'Name of your new resource group'} + onChange={newResourceGroup} styles={{ root: { paddingBottom: '8px' } }} onRenderLabel={onRenderLabel} />} @@ -613,9 +625,9 @@ export const AzureProvisionDialog: React.FC = () => { defaultValue={currentHostName} errorMessage={errorHostName} label={currentConfig?.resourceGroup? formatMessage('Hostname') : formatMessage('Resource group name')} - ariaLabel={formatMessage('A resource group is a collection of resources that share the same lifecycle, permissions, and policies')} - placeholder={'Name of your new resource group'} - onChange={newResourceGroup} + ariaLabel={formatMessage('A hostname which is used to make up the provisoned services names')} + placeholder={'Name of your services'} + onChange={newHostName} styles={{ root: { paddingBottom: '8px' } }} onRenderLabel={onRenderLabel} /> @@ -791,9 +803,10 @@ export const AzureProvisionDialog: React.FC = () => { const selectedResources = requireResources.concat(enabledResources); await onSubmit({ subscription: currentSubscription, + resourceGroup: currentResourceGroup, hostname: currentHostName, location: currentLocation, - luisLocation: currentLuisLocation.name || currentLocation.name, + luisLocation: currentLuisLocation?.name || currentLocation.name, type: publishType, externalResources: selectedResources, }); @@ -811,6 +824,7 @@ export const AzureProvisionDialog: React.FC = () => { isEditorError, isDisAble, currentSubscription, + currentResourceGroup, currentHostName, currentLocation, publishType, From 74ea3ef7b95de4c8e0da3e5dda95924e329e47bf Mon Sep 17 00:00:00 2001 From: Lu Han <32191031+luhan2017@users.noreply.github.com> Date: Sat, 20 Feb 2021 14:55:12 +0800 Subject: [PATCH 18/44] Add a botName field for channel service --- .../src/node/azureResourceManager/azureResourceManager.ts | 2 +- extensions/azurePublish/src/node/provision.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts b/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts index 8e66de128c..311893722f 100644 --- a/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts +++ b/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts @@ -903,7 +903,7 @@ export class AzureResourceMananger { }); throw createCustomizeError(ProvisionErrors.BOT_REGISTRATION_ERROR, botResult._response?.bodyAsText); } - + return config.name; } catch (err) { this.logger({ status: BotProjectDeployLoggerType.PROVISION_ERROR, diff --git a/extensions/azurePublish/src/node/provision.ts b/extensions/azurePublish/src/node/provision.ts index 051e60a773..9729fc0fd5 100644 --- a/extensions/azurePublish/src/node/provision.ts +++ b/extensions/azurePublish/src/node/provision.ts @@ -207,6 +207,7 @@ export class BotProjectProvision { cosmosDB: null, appInsights: null, qna: null, + botName: null, }; const resourceGroupName = config.resourceGroup ?? config.hostname; @@ -265,7 +266,7 @@ export class BotProjectProvision { /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ // Create the Azure Bot Service registration case AzureResourceTypes.BOT_REGISTRATION: - await this.azureResourceManagementClient.deployBotResource({ + const botName = await this.azureResourceManagementClient.deployBotResource({ resourceGroupName: resourceGroupName, location: provisionResults.resourceGroup.location, name: config.hostname, // come back to this! @@ -273,6 +274,7 @@ export class BotProjectProvision { endpoint: `https://${provisionResults.webApp?.hostname ?? (config.hostname + ".azurewebsites.net")}/api/messages`, appId: provisionResults.appId, }); + provisionResults.botName = botName; break; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ From 9ee1a8a258881c54c4a96fc9df2b1fd64e1842c4 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 22 Feb 2021 11:49:05 +0800 Subject: [PATCH 19/44] fix bug when select luis resource but not select the luis region --- extensions/azurePublish/src/ui/azureProvisionDialog.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index 8e4557f6c4..3fc649c608 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -241,11 +241,7 @@ const reviewCols: IColumn[] = [ isRowHeader: true, data: 'string', onRender: (item: ResourcesItem & {name,icon}) => { - // if(item.key.includes('luis')){ - // return
{item.}
- // }else{ - return
{item.region.displayName}
; - // } + return
{item.region?.displayName}
; }, isPadded: true, }, @@ -444,9 +440,9 @@ export const AzureProvisionDialog: React.FC = () => { const region = data.filter(item=> luRegions.includes(item.name)); console.log(region); setLuisLocations(region); + setCurrentLuisLocation(region[0]); }); - // if(currentHostName){ // // check its hostname availability // checkNameAvailability(currentHostName); @@ -778,6 +774,7 @@ export const AzureProvisionDialog: React.FC = () => { if(item.key.includes('luis')){ region = currentLuisLocation; } + console.log(region); return {...item, region: region, resourceGroup:currentConfig?.resourceGroup || currentHostName}; }); setReviewListItems(selectedResources); From c18406e7bb94800ab4e53bd3610b61fbaa77f9ab Mon Sep 17 00:00:00 2001 From: Lu Han <32191031+luhan2017@users.noreply.github.com> Date: Mon, 22 Feb 2021 11:51:25 +0800 Subject: [PATCH 20/44] add botName to publish profile --- extensions/azurePublish/src/node/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index 68907ea3bb..6a5d39ab83 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -404,6 +404,7 @@ export default async (composer: IExtensionRegistration): Promise => { environment: currentProfile?.environment ?? 'composer', subscriptionId: provisionResults.subscriptionId ?? currentProfile?.subscriptionId, resourceGroup: currentProfile?.resourceGroup ?? provisionResults.resourceGroup?.name, + botName: currentProfile?.botName ?? provisionResults.botName, hostname: config.hostname ?? currentProfile?.hostname, luisResource: provisionResults.luisPrediction? `${config.hostname}-luis` : currentProfile?.luisResource, runtimeIdentifier: currentProfile?.runtimeIdentifier ?? 'win-x64', From 52f462373130955873cb23fa7037f36dc44beb42 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 22 Feb 2021 15:30:18 +0800 Subject: [PATCH 21/44] make hostname disable if name or hostname already have --- .../src/ui/azureProvisionDialog.tsx | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index 3fc649c608..60ea3456b7 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -35,8 +35,6 @@ import { IColumn, IGroup, CheckboxVisibility, - Sticky, - StickyPositionType, TooltipHost, Icon, TextField, @@ -46,16 +44,12 @@ import { PersonaSize, Selection, SelectionMode, - DetailsRow, - setRTL, } from 'office-ui-fabric-react'; import { SharedColors } from '@uifabric/fluent-theme'; import { JsonEditor } from '@bfc/code-editor'; import jwtDecode from 'jwt-decode'; import { getResourceList, getSubscriptions, getResourceGroups, getDeployLocations, getPreview, getLuisAuthoringRegions, CheckWebAppNameAvailability } from './api'; import { AzureResourceTypes } from '../types'; -import { Item } from '@azure/cosmos'; -import { hostname } from 'os'; const choiceOptions: IChoiceGroupOption[] = [ { key: 'create', text: 'Create new Azure resources' }, @@ -325,6 +319,8 @@ export const AzureProvisionDialog: React.FC = () => { } if(currentConfig?.hostname){ setHostName(currentConfig?.hostname); + } else if(currentConfig?.name){ + setHostName(currentConfig?.environment? `${currentConfig?.name}-${currentConfig?.environment}`: currentConfig?.name); } } },[currentConfig]); @@ -392,21 +388,16 @@ export const AzureProvisionDialog: React.FC = () => { } }, [currentConfig, publishType, currentSubscription, token]); - const newResourceGroup = useMemo( - () => (e, newName) => { - setResourceGroup(newName); - }, - [resourceGroups, checkNameAvailability] - ); + const updateCurrentResourceGroup = useMemo(()=>(e,newGroup)=>{ + setResourceGroup(newGroup); + },[]); const newHostName = useMemo( () => (e, newName) => { setHostName(newName); - if(!currentConfig?.hostname){ - checkNameAvailability(newName); - } + checkNameAvailability(newName); }, - [resourceGroups, checkNameAvailability] + [checkNameAvailability] ); const updateCurrentLocation = useMemo( @@ -604,23 +595,25 @@ export const AzureProvisionDialog: React.FC = () => { styles={{ root: { paddingBottom: '8px' } }} onRenderLabel={onRenderLabel} /> - {currentConfig?.resourceGroup && } + /> Date: Mon, 22 Feb 2021 16:56:14 +0800 Subject: [PATCH 22/44] fix resourceGroup display error in review page --- .../src/ui/azureProvisionDialog.tsx | 40 ++++++------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index 60ea3456b7..7aee885ba9 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -79,17 +79,6 @@ const DialogTitle = { }, }; -// function onRenderDetailsHeader(props, defaultRender) { -// return ( -// -// {defaultRender({ -// ...props, -// onRenderColumnHeaderTooltip: (tooltipHostProps) => , -// })} -// -// ); -// } - function decodeToken(token: string) { try { return jwtDecode(token); @@ -243,7 +232,6 @@ const reviewCols: IColumn[] = [ export const AzureProvisionDialog: React.FC = () => { const [subscriptions, setSubscriptions] = useState([]); - const [resourceGroups, setResourceGroups] = useState([]); const [deployLocations, setDeployLocations] = useState([]); const [luisLocations, setLuisLocations] = useState([]); @@ -406,9 +394,15 @@ export const AzureProvisionDialog: React.FC = () => { if (location) { setLocation(location); + const region = luisLocations.find(item=> item.name === location.name) + if(region){ + setCurrentLuisLocation(region); + } else { + setCurrentLuisLocation(luisLocations[0]); + } } }, - [deployLocations] + [deployLocations, luisLocations] ); const updateLuisLocation = useMemo( @@ -424,20 +418,13 @@ export const AzureProvisionDialog: React.FC = () => { useEffect(() => { if (currentSubscription) { // get resource group under subscription - getResourceGroups(token, currentSubscription).then(setResourceGroups); + // getResourceGroups(token, currentSubscription).then(setResourceGroups); getDeployLocations(token, currentSubscription).then((data:DeployLocation[])=> { setDeployLocations(data); const luRegions = getLuisAuthoringRegions(); const region = data.filter(item=> luRegions.includes(item.name)); - console.log(region); setLuisLocations(region); - setCurrentLuisLocation(region[0]); }); - - // if(currentHostName){ - // // check its hostname availability - // checkNameAvailability(currentHostName); - // } } }, [currentSubscription]); @@ -595,11 +582,10 @@ export const AzureProvisionDialog: React.FC = () => { styles={{ root: { paddingBottom: '8px' } }} onRenderLabel={onRenderLabel} /> - {/* {currentConfig?.resourceGroup && */} { disabled={currentConfig?.hostname || currentConfig?.name} defaultValue={currentHostName} errorMessage={errorHostName} - // label={currentConfig?.resourceGroup? formatMessage('Hostname') : formatMessage('Resource group name')} label={formatMessage('Hostname')} ariaLabel={formatMessage('A hostname which is used to make up the provisoned services names')} placeholder={'Name of your services'} @@ -629,14 +614,15 @@ export const AzureProvisionDialog: React.FC = () => { styles={{ root: { paddingBottom: '8px' } }} onChange={updateCurrentLocation} /> - {currentLocation && luisLocations.length>0 && !luisLocations.find(item=> item.name === currentLocation.name) ? + {currentLocation && currentLuisLocation && currentLocation.name !== currentLuisLocation.name && //luisLocations.length>0 && !luisLocations.find(item=> item.name === currentLocation.name) ? : null} + />} )} {choice.key === 'create' && subscriptionOption.length < 1 && } @@ -768,7 +754,7 @@ export const AzureProvisionDialog: React.FC = () => { region = currentLuisLocation; } console.log(region); - return {...item, region: region, resourceGroup:currentConfig?.resourceGroup || currentHostName}; + return {...item, region: region, resourceGroup: currentConfig?.resourceGroup || currentResourceGroup}; }); setReviewListItems(selectedResources); }} From 0f74d2e52a43f8dad387e3e197b248403009ac0f Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 22 Feb 2021 18:00:51 +0800 Subject: [PATCH 23/44] remove annotation --- .../src/node/azureResourceManager/azureResourceManager.ts | 2 +- extensions/azurePublish/src/ui/azureProvisionDialog.tsx | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts b/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts index 311893722f..1af2f0f563 100644 --- a/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts +++ b/extensions/azurePublish/src/node/azureResourceManager/azureResourceManager.ts @@ -27,7 +27,7 @@ import { AzureFuntionsConfig, } from './azureResourceManagerConfig'; import { createCustomizeError, ProvisionErrors, stringifyError } from '../utils/errorHandler'; -import { LuisAuthoringSupportLocation, LuisPublishSupportLocation } from '../../types'; +import { LuisAuthoringSupportLocation } from '../../types'; export class AzureResourceMananger { // Logger diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index 7aee885ba9..c52c5d8376 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -433,14 +433,13 @@ export const AzureProvisionDialog: React.FC = () => { if(config){ let str = JSON.stringify(config); str = str.replace(/<.*>/g, ''); - console.log(str); const newConfig = JSON.parse(str); return newConfig; } else { return undefined; } }catch(e){ - console.log(e); + console.error(e); } },[]); @@ -448,7 +447,6 @@ export const AzureProvisionDialog: React.FC = () => { const getExistResources = ()=>{ const result = []; const config = removePlaceholder(currentConfig); - console.log(config); if(config){ // If name or hostname is configured, it means the webapp is already created. if(config.hostname || config.name){ @@ -484,7 +482,6 @@ export const AzureProvisionDialog: React.FC = () => { () => (hostname) => { // get resources already have const alreadyHave = getExistResources(); - console.log(alreadyHave); const names = getPreview(hostname); const result = []; @@ -499,7 +496,6 @@ export const AzureProvisionDialog: React.FC = () => { icon: previewObject ? previewObject.icon : undefined, }); } - console.log(result); // set review list const groups: IGroup[] = []; @@ -532,7 +528,6 @@ export const AzureProvisionDialog: React.FC = () => { const onSubmit = useMemo( () => async (options) => { // call back to the main Composer API to begin this process... - console.log(options); startProvision(options); closeDialog(); }, @@ -753,7 +748,6 @@ export const AzureProvisionDialog: React.FC = () => { if(item.key.includes('luis')){ region = currentLuisLocation; } - console.log(region); return {...item, region: region, resourceGroup: currentConfig?.resourceGroup || currentResourceGroup}; }); setReviewListItems(selectedResources); From 076aeba8e1199b1ed061977d006a7c872aaab348 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Tue, 23 Feb 2021 11:44:06 +0800 Subject: [PATCH 24/44] fix regex issue and get location issue --- extensions/azurePublish/src/ui/azureProvisionDialog.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx index c52c5d8376..46cbf44a2e 100644 --- a/extensions/azurePublish/src/ui/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/ui/azureProvisionDialog.tsx @@ -416,9 +416,8 @@ export const AzureProvisionDialog: React.FC = () => { ); useEffect(() => { - if (currentSubscription) { + if (currentSubscription && token) { // get resource group under subscription - // getResourceGroups(token, currentSubscription).then(setResourceGroups); getDeployLocations(token, currentSubscription).then((data:DeployLocation[])=> { setDeployLocations(data); const luRegions = getLuisAuthoringRegions(); @@ -426,13 +425,13 @@ export const AzureProvisionDialog: React.FC = () => { setLuisLocations(region); }); } - }, [currentSubscription]); + }, [currentSubscription, token]); const removePlaceholder = React.useCallback((config:any)=>{ try{ if(config){ let str = JSON.stringify(config); - str = str.replace(/<.*>/g, ''); + str = str.replace(/<[^>]*>/g, ''); const newConfig = JSON.parse(str); return newConfig; } else { @@ -474,6 +473,7 @@ export const AzureProvisionDialog: React.FC = () => { if(config.settings?.blobStorage?.connectionString){ result.push(AzureResourceTypes.BLOBSTORAGE); } + console.log(result); return result; } else return []; } From 61c696577392f73cc3750379e5b3a58868e753b7 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Tue, 23 Feb 2021 16:15:54 +0800 Subject: [PATCH 25/44] update publish function getPublishConfig --- .../packages/server/src/locales/en-US.json | 84 +++++++++++++++++-- .../src/components/azureProvisionDialog.tsx | 4 +- extensions/azurePublish/yarn.lock | 10 +-- 3 files changed, 85 insertions(+), 13 deletions(-) diff --git a/Composer/packages/server/src/locales/en-US.json b/Composer/packages/server/src/locales/en-US.json index db73bf80e7..8a6659123c 100644 --- a/Composer/packages/server/src/locales/en-US.json +++ b/Composer/packages/server/src/locales/en-US.json @@ -227,6 +227,33 @@ "an_authoring_key_is_created_automatically_when_you_21cf77aa": { "message": "An authoring key is created automatically when you create a LUIS account." }, + "an_error_occured_connecting_initializing_the_direc_980f809": { + "message": "An error occured connecting initializing the DirectLine server" + }, + "an_error_occured_receiving_an_activity_from_the_bo_addcc879": { + "message": "An error occured receiving an activity from the bot." + }, + "an_error_occured_saving_the_transcript_to_disk_a36615df": { + "message": "An error occured saving the transcript to disk." + }, + "an_error_occured_saving_transcripts_25581129": { + "message": "An error occured saving transcripts" + }, + "an_error_occured_sending_conversation_update_activ_55c000": { + "message": "An error occured sending conversation update activity to the bot" + }, + "an_error_occured_starting_a_new_conversation_da8779c": { + "message": "An error occured starting a new conversation" + }, + "an_error_occured_trying_to_save_the_transcript_to__dfb5d862": { + "message": "An error occured trying to save the transcript to disk" + }, + "an_error_occured_validating_the_microsoft_app_id_a_e8698163": { + "message": "An error occured validating the Microsoft App Id and Microsoft App Password." + }, + "an_error_occurred_parsing_the_transcript_for_a_con_a47395c3": { + "message": "An error occurred parsing the transcript for a conversation" + }, "animation_card_1a7d75ff": { "message": "Animation card" }, @@ -401,6 +428,9 @@ "bot_controller_319b408d": { "message": "Bot Controller" }, + "bot_endpoint_not_available_in_the_request_43c381f8": { + "message": "Bot endpoint not available in the request" + }, "bot_files_created_986109df": { "message": "Bot files created" }, @@ -500,6 +530,18 @@ "cancel_dialog_event_cc671dee": { "message": "Cancel dialog event" }, + "cannot_find_a_matching_conversation_d6344e4a": { + "message": "Cannot find a matching conversation." + }, + "cannot_parse_attachment_c3e552a5": { + "message": "Cannot parse attachment." + }, + "cannot_post_activity_conversation_not_found_c1e26d2d": { + "message": "Cannot post activity. Conversation not found." + }, + "cannot_upload_file_conversation_not_found_8a983504": { + "message": "Cannot upload file. Conversation not found." + }, "carousal_c65edfcd": { "message": "Carousal" }, @@ -650,6 +692,9 @@ "conversation_ended_endofconversation_activity_41d0c83f": { "message": "Conversation ended (EndOfConversation activity)" }, + "conversation_id_cannot_be_updated_2a973f13": { + "message": "Conversation ID cannot be updated." + }, "conversation_invoked_e960884e": { "message": "Conversation invoked" }, @@ -1085,6 +1130,9 @@ "emit_event_32aa6583": { "message": "Emit Event" }, + "empty_bot_template_that_routes_to_qna_configuratio_21531414": { + "message": "Empty bot template that routes to qna configuration" + }, "empty_qna_icon_34c180c6": { "message": "Empty QnA Icon" }, @@ -1160,6 +1208,9 @@ "entities_ef09392c": { "message": "Entities" }, + "entity_defined_in_lu_files_entity_1812c172": { + "message": "Entity defined in lu files: { entity }" + }, "environment_68aed6d3": { "message": "Environment" }, @@ -1253,9 +1304,6 @@ "extension_settings_899ccb55": { "message": "Extension Settings" }, - "extensions_7250a0bb": { - "message": "Extensions" - }, "external_resources_will_not_be_changed_c08b0009": { "message": "External resources will not be changed." }, @@ -1574,15 +1622,15 @@ "introduction_of_key_concepts_and_user_experience_e_971b32e9": { "message": "Introduction of key concepts and user experience elements for Composer." }, + "invalid_file_path_to_save_the_transcript_54c92a51": { + "message": "Invalid file path to save the transcript." + }, "invoke_activity_87df4903": { "message": "Invoke activity" }, "is_missing_or_empty_a551462e": { "message": "is missing or empty" }, - "issues_4680a499": { - "message": "Issues" - }, "it_s_not_a_built_in_function_or_a_custom_function_1527ed83": { "message": "it''s not a built-in function or a custom function." }, @@ -2066,6 +2114,9 @@ "no_updates_available_cecd904d": { "message": "No updates available" }, + "no_uploads_were_attached_as_a_part_of_the_request_63e92f54": { + "message": "No uploads were attached as a part of the request." + }, "no_wildcard_ff439e76": { "message": "no wildcard" }, @@ -2105,6 +2156,9 @@ "number_or_expression_55c7f9f": { "message": "Number or expression" }, + "oauth_activities_are_not_available_for_testing_in__2207dcef": { + "message": "OAuth activities are not available for testing in Composer yet. Please continue using Bot Framework Emulator for testing OAuth actions." + }, "oauth_login_b6aa9534": { "message": "OAuth login" }, @@ -2288,6 +2342,9 @@ "privacy_statement_da69ebc6": { "message": "Privacy statement" }, + "problems_31833f8c": { + "message": "Problems" + }, "progress_of_total_87de8616": { "message": "{ progress }% of { total }" }, @@ -2912,6 +2969,12 @@ "suggested_actions_94d06bfa": { "message": "Suggested Actions" }, + "suggested_propertiy_u_in_cardtype_ca80f69": { + "message": "Suggested propertiy { u } in { cardType }" + }, + "suggestion_for_card_or_activity_type_b257066a": { + "message": "Suggestion for Card or Activity: { type }" + }, "switch_to_code_editor_3dcbe16f": { "message": "switch to code editor" }, @@ -3002,6 +3065,12 @@ "there_are_no_preview_features_at_this_time_a5c40953": { "message": "There are no preview features at this time." }, + "there_is_no_original_view_63a2eaed": { + "message": "There is no original view" + }, + "there_is_no_thumbnail_view_908fe5cc": { + "message": "There is no thumbnail view" + }, "there_was_an_error_74ed3c58": { "message": "There was an error" }, @@ -3344,6 +3413,9 @@ "weather_bot_c38920cd": { "message": "Weather Bot" }, + "webchat_inspector_4d0dfeb7": { + "message": "Webchat Inspector" + }, "welcome_73d18b4d": { "message": "Welcome!" }, diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index 884455cdbd..8cf976e807 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -233,7 +233,7 @@ const reviewCols: IColumn[] = [ export const AzureProvisionDialog: React.FC = () => { const { currentProjectId, - getPublishConfig, + publishConfig, startProvision, closeDialog, onBack, @@ -272,7 +272,7 @@ export const AzureProvisionDialog: React.FC = () => { // set type of publish - azurePublish or azureFunctionsPublish const publishType = getType(); - const currentConfig = getPublishConfig(); + const currentConfig = publishConfig; useEffect(() => { setTitle(DialogTitle.CONFIG_RESOURCES); diff --git a/extensions/azurePublish/yarn.lock b/extensions/azurePublish/yarn.lock index abff02c2db..d530400a67 100644 --- a/extensions/azurePublish/yarn.lock +++ b/extensions/azurePublish/yarn.lock @@ -1181,7 +1181,7 @@ "@bfc/indexers@../../Composer/packages/lib/indexers": version "0.0.0" dependencies: - "@microsoft/bf-lu" "^4.12.0-dev.20210129.82760de" + "@microsoft/bf-lu" "4.12.0-rc0" adaptive-expressions "4.12.0-rc1" botbuilder-lg "4.12.0-rc1" lodash "^4.17.19" @@ -1649,10 +1649,10 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@microsoft/bf-lu@^4.12.0-dev.20210129.82760de": - version "4.12.0-dev.20210202.c622c6f" - resolved "https://registry.yarnpkg.com/@microsoft/bf-lu/-/bf-lu-4.12.0-dev.20210202.c622c6f.tgz#a19a9ffd2bd09c783f8f254c58eeda45bbbebcee" - integrity sha512-Bi1mLKJuAqrKpp2svqSq/p4fvweHf3ie7EiSyfAaWmcmFdWES9N/z5T6xKSlY0BT41vOEvu0BpYfTFz0lNnZwA== +"@microsoft/bf-lu@4.12.0-rc0": + version "4.12.0-rc0" + resolved "https://registry.yarnpkg.com/@microsoft/bf-lu/-/bf-lu-4.12.0-rc0.tgz#9c1aa4cb7d22a0a49d4c16eb1bce5d5e222c40b1" + integrity sha512-bz5BPQsIh+BwXZ+YAMG15wTndF/Ug3EviSjOs0GtryRSkgJkmAqAhdpU0SRjVAVuy7XzTRpltxbMmSoiYVnHtA== dependencies: "@azure/cognitiveservices-luis-authoring" "4.0.0-preview.1" "@azure/ms-rest-azure-js" "2.0.1" From c0529a1ac23fa13dd7ce8155590886fcc02c0eff Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Wed, 24 Feb 2021 11:55:15 +0800 Subject: [PATCH 26/44] fix hostname check issue --- .../src/components/azureProvisionDialog.tsx | 124 ++++++++---------- 1 file changed, 56 insertions(+), 68 deletions(-) diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index 8cf976e807..92767f75e9 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -81,6 +81,55 @@ function decodeToken(token: string) { } } +function removePlaceholder(config:any){ + try{ + if(config){ + let str = JSON.stringify(config); + str = str.replace(/<[^>]*>/g, ''); + const newConfig = JSON.parse(str); + return newConfig; + } else { + return undefined; + } + }catch(e){ + console.error(e); + } +}; + +function getExistResources (config){ + const result = []; + if(config){ + // If name or hostname is configured, it means the webapp is already created. + if(config.hostname || config.name){ + result.push(AzureResourceTypes.WEBAPP); + } + if(config.settings?.MicrosoftAppId){ + result.push(AzureResourceTypes.BOT_REGISTRATION); + result.push(AzureResourceTypes.APP_REGISTRATION); + } + if(config.settings?.luis?.authoringKey){ + result.push(AzureResourceTypes.LUIS_AUTHORING); + } + if(config.settings?.luis?.endpointKey){ + result.push(AzureResourceTypes.LUIS_PREDICTION); + } + if(config.settings?.qna?.subscriptionKey){ + result.push(AzureResourceTypes.QNA); + } + if(config.settings?.applicationInsights?.InstrumentationKey){ + result.push(AzureResourceTypes.APPINSIGHTS); + } + if(config.settings?.cosmosDb?.authKey){ + result.push(AzureResourceTypes.COSMOSDB); + } + if(config.settings?.blobStorage?.connectionString){ + result.push(AzureResourceTypes.BLOBSTORAGE); + } + console.log(result); + return result; + } else return []; +} + const iconStyle = (required) => { return { root: { @@ -272,7 +321,7 @@ export const AzureProvisionDialog: React.FC = () => { // set type of publish - azurePublish or azureFunctionsPublish const publishType = getType(); - const currentConfig = publishConfig; + const currentConfig = removePlaceholder(publishConfig); useEffect(() => { setTitle(DialogTitle.CONFIG_RESOURCES); @@ -366,27 +415,17 @@ export const AzureProvisionDialog: React.FC = () => { ); const checkNameAvailability = useMemo(()=>(newName: string)=>{ - if(!currentConfig?.subscriptionId && currentSubscription){ - // get preview list - const names = getPreview(newName); - let app = ''; - if(publishType.includes('Function')) { - app = names.find(item=>item.key.includes('Function')).name; - } else { - app = names.find(item=>item.key === 'webApp').name; - } + setErrorHostName(''); + console.log(publishType); + if(currentSubscription && publishType === 'azurePublish'){ // check app name whether exist or not - CheckWebAppNameAvailability(token, app, currentSubscription).then(value=>{ + CheckWebAppNameAvailability(token, newName, currentSubscription).then(value=>{ if(!value.nameAvailable){ setErrorHostName(value.message); - } else { - app = names.find((item) => item.key === 'webApp').name; } }); - } else { - setErrorHostName(''); } - }, [currentConfig, publishType, currentSubscription, token]); + }, [publishType, currentSubscription, token]); const updateCurrentResourceGroup = useMemo(()=>(e,newGroup)=>{ setResourceGroup(newGroup); @@ -439,61 +478,10 @@ export const AzureProvisionDialog: React.FC = () => { } }, [currentSubscription, token]); - const removePlaceholder = React.useCallback((config:any)=>{ - try{ - if(config){ - let str = JSON.stringify(config); - str = str.replace(/<[^>]*>/g, ''); - const newConfig = JSON.parse(str); - return newConfig; - } else { - return undefined; - } - }catch(e){ - console.error(e); - } - - },[]); - - const getExistResources = ()=>{ - const result = []; - const config = removePlaceholder(currentConfig); - if(config){ - // If name or hostname is configured, it means the webapp is already created. - if(config.hostname || config.name){ - result.push(AzureResourceTypes.WEBAPP); - } - if(config.settings?.MicrosoftAppId){ - result.push(AzureResourceTypes.BOT_REGISTRATION); - result.push(AzureResourceTypes.APP_REGISTRATION); - } - if(config.settings?.luis?.authoringKey){ - result.push(AzureResourceTypes.LUIS_AUTHORING); - } - if(config.settings?.luis?.endpointKey){ - result.push(AzureResourceTypes.LUIS_PREDICTION); - } - if(config.settings?.qna?.subscriptionKey){ - result.push(AzureResourceTypes.QNA); - } - if(config.settings?.applicationInsights?.InstrumentationKey){ - result.push(AzureResourceTypes.APPINSIGHTS); - } - if(config.settings?.cosmosDb?.authKey){ - result.push(AzureResourceTypes.COSMOSDB); - } - if(config.settings?.blobStorage?.connectionString){ - result.push(AzureResourceTypes.BLOBSTORAGE); - } - console.log(result); - return result; - } else return []; - } - const onNext = useMemo( () => (hostname) => { // get resources already have - const alreadyHave = getExistResources(); + const alreadyHave = getExistResources(currentConfig); const names = getPreview(hostname); const result = []; From ddda758d9614b0ef0a00478aba8f14059eaef3e6 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Wed, 24 Feb 2021 14:50:16 +0800 Subject: [PATCH 27/44] fix UI in add resource page --- .../azurePublish/src/components/azureProvisionDialog.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index 92767f75e9..ebb313f6dd 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -192,8 +192,8 @@ const columns: IColumn[] = [ data: 'string', onRender: (item: ResourcesItem & {name,icon}) => { return
-
{item.name}
-
{item.text} | {item.tier}
+
{item.text}
+
{item.tier}
; }, isPadded: true, From 2f79a3c276a0d996f7a45b63e7edcfc049c0d831 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Wed, 24 Feb 2021 17:34:11 +0800 Subject: [PATCH 28/44] fix UI issue --- .../azurePublish/src/components/azureProvisionDialog.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index ebb313f6dd..b4f86776b4 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -247,7 +247,7 @@ const reviewCols: IColumn[] = [ isRowHeader: true, data: 'string', onRender: (item: ResourcesItem) => { - return
{item.resourceGroup}
; + return
{item.resourceGroup}
; }, isPadded: true, }, @@ -260,7 +260,7 @@ const reviewCols: IColumn[] = [ isRowHeader: true, data: 'string', onRender: (item: ResourcesItem & {name,icon}) => { - return
{item.name}
; + return
{item.name}
; }, isPadded: true, }, @@ -273,7 +273,7 @@ const reviewCols: IColumn[] = [ isRowHeader: true, data: 'string', onRender: (item: ResourcesItem & {name,icon}) => { - return
{item.region?.displayName}
; + return
{item.region?.displayName}
; }, isPadded: true, }, From a1b35195adc3c124d735507faf46af256075a404 Mon Sep 17 00:00:00 2001 From: Lu Han <32191031+luhan2017@users.noreply.github.com> Date: Thu, 25 Feb 2021 11:19:33 +0800 Subject: [PATCH 29/44] Fix the config missing issue --- extensions/azurePublish/src/node/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index 0a3b65c074..21a27e8e06 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -444,7 +444,7 @@ export default async (composer: IExtensionRegistration): Promise => { }; for (let configUnit in currentProfile) { if (!(configUnit in publishProfile)) { - publishProfile[configUnit] = currentSettings[configUnit]; + publishProfile[configUnit] = currentProfile[configUnit]; } } From b1551768b6b48637d4b59b5573ac88e25fbb4b2e Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Fri, 26 Feb 2021 18:22:36 +0800 Subject: [PATCH 30/44] update qna image and resource group check --- .../azurePublish/src/components/api.tsx | 2 +- .../src/components/azureProvisionDialog.tsx | 56 +++++++++++++------ .../src/components/images/Qna-Maker.svg | 3 + .../src/components/images/index.ts | 2 + 4 files changed, 44 insertions(+), 19 deletions(-) create mode 100644 extensions/azurePublish/src/components/images/Qna-Maker.svg diff --git a/extensions/azurePublish/src/components/api.tsx b/extensions/azurePublish/src/components/api.tsx index 66984ad7ed..9ae2c9769d 100644 --- a/extensions/azurePublish/src/components/api.tsx +++ b/extensions/azurePublish/src/components/api.tsx @@ -450,7 +450,7 @@ export const getPreview = (hostname: string) => { }, { name: qnaAccountName, - icon: Images.CognitiveServices, + icon: Images.QNAMaker, key: 'qna', }, { diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index b4f86776b4..c4a0c4df54 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -2,7 +2,7 @@ // Licensed under the MIT License. import formatMessage from 'format-message'; import * as React from 'react'; -import { useState, useMemo, useEffect, Fragment } from 'react'; +import { useState, useMemo, useEffect, Fragment, useCallback, useRef } from 'react'; import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; import { DefaultButton, PrimaryButton } from 'office-ui-fabric-react/lib/Button'; import { getAccessToken, logOut, usePublishApi } from '@bfc/extension-client'; @@ -278,7 +278,6 @@ const reviewCols: IColumn[] = [ isPadded: true, }, ]; - export const AzureProvisionDialog: React.FC = () => { const { currentProjectId, @@ -305,6 +304,7 @@ export const AzureProvisionDialog: React.FC = () => { const [currentResourceGroup, setResourceGroup] = useState(''); const [currentHostName, setHostName] = useState(''); const [errorHostName, setErrorHostName] = useState(''); + const [errorResourceGroupName, setErrorResourceGroupName] = useState(''); const [currentLocation, setLocation] = useState(); const [currentLuisLocation, setCurrentLuisLocation] = useState(); const [extensionResourceOptions, setExtensionResourceOptions] = useState([]); @@ -319,6 +319,7 @@ export const AzureProvisionDialog: React.FC = () => { const [listItems, setListItem] = useState<(ResourcesItem & {name,icon})[]>(); const [reviewListItems, setReviewListItems] = useState([]); + const timerRef = useRef(); // set type of publish - azurePublish or azureFunctionsPublish const publishType = getType(); const currentConfig = removePlaceholder(publishConfig); @@ -414,27 +415,45 @@ export const AzureProvisionDialog: React.FC = () => { [subscriptionOption] ); - const checkNameAvailability = useMemo(()=>(newName: string)=>{ - setErrorHostName(''); - console.log(publishType); - if(currentSubscription && publishType === 'azurePublish'){ - // check app name whether exist or not - CheckWebAppNameAvailability(token, newName, currentSubscription).then(value=>{ - if(!value.nameAvailable){ - setErrorHostName(value.message); - } - }); + + const checkNameAvailability = useCallback((newName: string)=>{ + if(timerRef.current){ + clearTimeout(timerRef.current); } + timerRef.current = setTimeout(()=>{ + if(currentSubscription && publishType === 'azurePublish'){ + // check app name whether exist or not + CheckWebAppNameAvailability(token, newName, currentSubscription).then(value=>{ + if(!value.nameAvailable){ + setErrorHostName(value.message); + } else { + setErrorHostName(''); + } + }); + } + }, 500); }, [publishType, currentSubscription, token]); + + const checkResourceGroupName = useCallback((group: string) => { + if(group.match(/^[-\w\._\(\)]+$/)){ + setErrorResourceGroupName(''); + } else { + setErrorResourceGroupName('Resource group names only allow alphanumeric characters, periods, underscores, hyphens and parenthesis and cannot end in a period.'); + } + },[]); + const updateCurrentResourceGroup = useMemo(()=>(e,newGroup)=>{ setResourceGroup(newGroup); - },[]); + // check resource group name + checkResourceGroupName(newGroup); + },[checkResourceGroupName]); - const newHostName = useMemo( - () => (e, newName) => { + const newHostName = useCallback( + (e, newName) => { setHostName(newName); - checkNameAvailability(newName); + // debounce name check + checkNameAvailability(newName) }, [checkNameAvailability] ); @@ -567,8 +586,8 @@ export const AzureProvisionDialog: React.FC = () => { ); const isDisAble = useMemo(() => { - return !currentSubscription || !currentHostName || errorHostName !== '' || !currentLocation; - }, [currentSubscription, currentHostName, errorHostName, currentLocation]); + return !currentSubscription || !currentHostName || errorHostName!== '' || errorResourceGroupName !== '' || !currentLocation; + }, [currentSubscription, currentHostName, errorHostName, currentLocation, errorResourceGroupName]); const PageFormConfig = ( @@ -591,6 +610,7 @@ export const AzureProvisionDialog: React.FC = () => { required disabled={currentConfig?.resourceGroup} defaultValue={currentResourceGroup} + errorMessage={errorResourceGroupName} label={formatMessage('Resource group name')} placeholder={'Name of your new resource group'} onChange={updateCurrentResourceGroup} diff --git a/extensions/azurePublish/src/components/images/Qna-Maker.svg b/extensions/azurePublish/src/components/images/Qna-Maker.svg new file mode 100644 index 0000000000..27f1f60e66 --- /dev/null +++ b/extensions/azurePublish/src/components/images/Qna-Maker.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/azurePublish/src/components/images/index.ts b/extensions/azurePublish/src/components/images/index.ts index adad3007e9..da87d88f83 100644 --- a/extensions/azurePublish/src/components/images/index.ts +++ b/extensions/azurePublish/src/components/images/index.ts @@ -10,6 +10,7 @@ import AppInsights from './Application-Insights.svg'; import BlobStorage from './Storage-Accounts.svg'; import FunctionApp from './Function-Apps.svg'; import AppRegistration from './App-Registrations.svg'; +import QNAMaker from './Qna-Maker.svg'; export { AppServicePlan, @@ -21,4 +22,5 @@ export { BlobStorage, FunctionApp, AppRegistration, + QNAMaker, }; From 85dfda36941af2bc529659d15ee78133bcc9142c Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 12:20:23 +0800 Subject: [PATCH 31/44] add region to profile and show the profile region as default in edit mode --- .../src/components/azureProvisionDialog.tsx | 27 +++++++++---------- extensions/azurePublish/src/node/index.ts | 1 + 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index c4a0c4df54..e909595f8a 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -361,16 +361,16 @@ export const AzureProvisionDialog: React.FC = () => { useEffect(()=>{ if(currentConfig){ - if(currentConfig?.subscriptionId){ - setSubscription(currentConfig?.subscriptionId); + if(currentConfig.subscriptionId){ + setSubscription(currentConfig.subscriptionId); } - if(currentConfig?.resourceGroup){ - setResourceGroup(currentConfig?.resourceGroup); + if(currentConfig.resourceGroup){ + setResourceGroup(currentConfig.resourceGroup); } - if(currentConfig?.hostname){ - setHostName(currentConfig?.hostname); - } else if(currentConfig?.name){ - setHostName(currentConfig?.environment? `${currentConfig?.name}-${currentConfig?.environment}`: currentConfig?.name); + if(currentConfig.hostname){ + setHostName(currentConfig.hostname); + } else if(currentConfig.name){ + setHostName(currentConfig.environment? `${currentConfig.name}-${currentConfig.environment}`: currentConfig.name); } } },[currentConfig]); @@ -397,7 +397,7 @@ export const AzureProvisionDialog: React.FC = () => { }, [subscriptions]); const deployLocationsOption = useMemo((): IDropdownOption[] => { - return deployLocations.map((t) => ({ key: t.id, text: t.displayName })); + return deployLocations.map((t) => ({ key: t.name, text: t.displayName })); }, [deployLocations]); const luisLocationsOption = useMemo((): IDropdownOption[] => { @@ -460,8 +460,7 @@ export const AzureProvisionDialog: React.FC = () => { const updateCurrentLocation = useMemo( () => (_e, option?: IDropdownOption) => { - const location = deployLocations.find((t) => t.id === option?.key); - + const location = deployLocations.find((t) => t.name === option?.key); if (location) { setLocation(location); const region = luisLocations.find(item=> item.name === location.name) @@ -625,8 +624,8 @@ export const AzureProvisionDialog: React.FC = () => { disabled={currentConfig?.hostname || currentConfig?.name} defaultValue={currentHostName} errorMessage={errorHostName} - label={formatMessage('Hostname')} - ariaLabel={formatMessage('A hostname which is used to make up the provisoned services names')} + label={formatMessage('Resource name')} + ariaLabel={formatMessage('This name will be assigned to all your new resources. For eg-test-web app, test-luis-prediction')} placeholder={'Name of your services'} onChange={newHostName} styles={{ root: { paddingBottom: '8px' } }} @@ -634,7 +633,7 @@ export const AzureProvisionDialog: React.FC = () => { /> => { hostname: config.hostname ?? currentProfile?.hostname, luisResource: provisionResults.luisPrediction? `${config.hostname}-luis` : currentProfile?.luisResource, runtimeIdentifier: currentProfile?.runtimeIdentifier ?? 'win-x64', + region: config.location.name, settings: { applicationInsights: { InstrumentationKey: provisionResults.appInsights?.instrumentationKey ?? currentSettings?.applicationInsights?.InstrumentationKey, From e0f68a27b12e96d17e2dc4fde06a1e3d2c76ce27 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 15:11:51 +0800 Subject: [PATCH 32/44] add display name for app registration --- extensions/azurePublish/src/components/api.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/azurePublish/src/components/api.tsx b/extensions/azurePublish/src/components/api.tsx index 9ae2c9769d..c6c49910c2 100644 --- a/extensions/azurePublish/src/components/api.tsx +++ b/extensions/azurePublish/src/components/api.tsx @@ -409,7 +409,7 @@ export const getPreview = (hostname: string) => { key: 'webApp', }, { - name: 'Microsoft Application Registration', + name: azureWebAppName, icon: Images.AppRegistration, key: 'appRegistration', }, From 159575dcec6287e33d2f293850e6cfe41f0808ce Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 16:57:49 +0800 Subject: [PATCH 33/44] remove form page if type already have --- .../src/pages/botProject/PublishTargets.tsx | 28 +++++++++++++- .../ProfileFormDialog.tsx | 22 +---------- .../PublishProfileDialog.tsx | 38 +++++++++++++++++++ .../azurePublish/src/components/api.tsx | 24 ++++++------ 4 files changed, 78 insertions(+), 34 deletions(-) diff --git a/Composer/packages/client/src/pages/botProject/PublishTargets.tsx b/Composer/packages/client/src/pages/botProject/PublishTargets.tsx index 119d74c267..5ef11cb45f 100644 --- a/Composer/packages/client/src/pages/botProject/PublishTargets.tsx +++ b/Composer/packages/client/src/pages/botProject/PublishTargets.tsx @@ -13,6 +13,8 @@ import { NeutralColors, SharedColors } from '@uifabric/fluent-theme'; import { dispatcherState, settingsState, publishTypesState } from '../../recoilModel'; import { CollapsableWrapper } from '../../components/CollapsableWrapper'; +import { AuthDialog } from '../../components/Auth/AuthDialog'; +import { isShowAuthDialog } from '../../utils/auth'; import { PublishProfileDialog } from './create-publish-profile/PublishProfileDialog'; @@ -106,6 +108,7 @@ export const PublishTargets: React.FC = (props) => { const publishTypes = useRecoilValue(publishTypesState(projectId)); const [dialogHidden, setDialogHidden] = useState(true); + const [showAuthDialog, setShowAuthDialog] = useState(isShowAuthDialog(true)); const publishTargetsRef = React.useRef(null); const [current, setCurrent] = useState<{ index: number; item: PublishTarget } | null>(null); @@ -145,7 +148,11 @@ export const PublishTargets: React.FC = (props) => { styles={editPublishProfile} onClick={() => { setCurrent({ item: p, index: index }); - setDialogHidden(false); + if (isShowAuthDialog(true)) { + setShowAuthDialog(true); + } else { + setDialogHidden(false); + } }} > {formatMessage('Edit')} @@ -157,12 +164,29 @@ export const PublishTargets: React.FC = (props) => { setDialogHidden(false)} + onClick={() => { + if (isShowAuthDialog(true)) { + setShowAuthDialog(true); + } else { + setDialogHidden(false); + } + }} > {formatMessage('Add new')}
+ {showAuthDialog && ( + { + setDialogHidden(false); + }} + onDismiss={() => { + setShowAuthDialog(false); + }} + /> + )} {!dialogHidden ? ( { diff --git a/Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx b/Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx index 2980048267..69351c8b63 100644 --- a/Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx +++ b/Composer/packages/client/src/pages/botProject/create-publish-profile/ProfileFormDialog.tsx @@ -19,8 +19,6 @@ import { Icon } from 'office-ui-fabric-react/lib/Icon'; import { separator } from '../../publish/styles'; import { armScopes, graphScopes } from '../../../constants'; import { PublishType } from '../../../recoilModel/types'; -import { isShowAuthDialog } from '../../../utils/auth'; -import { AuthDialog } from '../../../components/Auth/AuthDialog'; import { PluginAPI } from '../../../plugins/api'; import { dispatcherState } from '../../../recoilModel'; import { AuthClient } from '../../../utils/authClient'; @@ -78,7 +76,6 @@ export const ProfileFormDialog: React.FC = (props) => { const [name, setName] = useState(current?.item.name || ''); const [errorMessage, setErrorMsg] = useState(''); const [targetType, setTargetType] = useState(current?.item.type || ''); - const [showAuthDialog, setShowAuthDialog] = useState(false); const { provisionToTarget } = useRecoilValue(dispatcherState); const updateName = (e, newName) => { @@ -151,17 +148,6 @@ export const ProfileFormDialog: React.FC = (props) => { return ( - {showAuthDialog && ( - { - onNext(); - }} - onDismiss={() => { - setShowAuthDialog(false); - }} - /> - )}
@@ -195,12 +181,8 @@ export const ProfileFormDialog: React.FC = (props) => { { - if (isShowAuthDialog(true)) { - setShowAuthDialog(true); - } else { - onNext(); - } + onClick={() => { + onNext(); }} /> diff --git a/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx b/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx index 37af42cf82..9193cc9375 100644 --- a/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx +++ b/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx @@ -8,6 +8,7 @@ import { PublishTarget } from '@bfc/shared'; import formatMessage from 'format-message'; import { Dialog } from 'office-ui-fabric-react/lib/Dialog'; import { Link } from 'office-ui-fabric-react/lib/Link'; +import { useRecoilValue } from 'recoil'; import { getTokenFromCache, isGetTokenFromUser } from '../../../utils/auth'; import { PublishType } from '../../../recoilModel/types'; @@ -15,6 +16,9 @@ import { PluginAPI } from '../../../plugins/api'; import { PluginHost } from '../../../components/PluginHost/PluginHost'; import { defaultPublishSurface, pvaPublishSurface, azurePublishSurface } from '../../publish/styles'; import TelemetryClient from '../../../telemetry/TelemetryClient'; +import { AuthClient } from '../../../utils/authClient'; +import { armScopes, graphScopes } from '../../../constants'; +import { dispatcherState } from '../../../recoilModel'; import { ProfileFormDialog } from './ProfileFormDialog'; @@ -36,6 +40,7 @@ export const PublishProfileDialog: React.FC = (props) const { current, types, projectId, closeDialog, targets, setPublishTargets } = props; const [page, setPage] = useState(Page.ProfileForm); const [publishSurfaceStyles, setStyles] = useState(defaultPublishSurface); + const { provisionToTarget } = useRecoilValue(dispatcherState); const [dialogTitle, setTitle] = useState({ title: current ? formatMessage('Edit a publishing profile') : formatMessage('Add a publishing profile'), @@ -96,6 +101,11 @@ export const PublishProfileDialog: React.FC = (props) PluginAPI.publish.currentProjectId = () => { return projectId; }; + if (current?.item.type) { + setPage(Page.ConfigProvision); + } else { + setPage(Page.ProfileForm); + } }, [current, projectId]); const savePublishTarget = useCallback( @@ -114,6 +124,34 @@ export const PublishProfileDialog: React.FC = (props) [targets, projectId] ); + useEffect(() => { + if (current?.item?.type) { + PluginAPI.publish.getType = () => { + return current?.item?.type; + }; + PluginAPI.publish.getSchema = () => { + return types.find((t) => t.name === current?.item?.type)?.schema; + }; + PluginAPI.publish.savePublishConfig = (config) => { + savePublishTarget(name, current?.item?.type, JSON.stringify(config) || '{}'); + }; + PluginAPI.publish.startProvision = async (config) => { + const fullConfig = { ...config, name: current.item.name, type: current.item.type }; + let arm, graph; + if (!isGetTokenFromUser()) { + // login or get token implicit + arm = await AuthClient.getAccessToken(armScopes); + graph = await AuthClient.getAccessToken(graphScopes); + } else { + // get token from cache + arm = getTokenFromCache('accessToken'); + graph = getTokenFromCache('graphToken'); + } + provisionToTarget(fullConfig, config.type, projectId, arm, graph, current?.item); + }; + } + }, [current, types, savePublishTarget]); + return ( { { name: azureWebAppName, icon: Images.AppService, - key: 'webApp', + key: AzureResourceTypes.WEBAPP, }, { name: azureWebAppName, icon: Images.AppRegistration, - key: 'appRegistration', + key: AzureResourceTypes.APP_REGISTRATION, }, { name: botServiceName, icon: Images.BotServices, - key: 'botRegistration', + key: AzureResourceTypes.BOT_REGISTRATION, }, { name: azureWebAppName, icon: Images.FunctionApp, - key: 'azureFunctions', + key: AzureResourceTypes.AZUREFUNCTIONS, }, { name: cosmosDbName, icon: Images.AzureCosmosDb, - key: 'cosmosDb', + key: AzureResourceTypes.COSMOSDB, }, { name: blobStorageName, icon: Images.BlobStorage, - key: 'blobStorage', + key: AzureResourceTypes.BLOBSTORAGE, }, { name: applicationInsightsName, icon: Images.AppInsights, - key: 'applicationInsights', + key: AzureResourceTypes.APPINSIGHTS, }, { name: luisAuthoringName, icon: Images.CognitiveServices, - key: 'luisAuthoring', + key: AzureResourceTypes.LUIS_AUTHORING, }, { name: luisResourceName, icon: Images.CognitiveServices, - key: 'luisPrediction', + key: AzureResourceTypes.LUIS_PREDICTION, }, { name: qnaAccountName, icon: Images.QNAMaker, - key: 'qna', + key: AzureResourceTypes.QNA, }, { name: azureServicePlanName, icon: Images.AppServicePlan, - key: 'servicePlan', + key: AzureResourceTypes.SERVICE_PLAN, }, ]; From 625a706a3b942f13e0242457be2ee30602cb3001 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 17:02:58 +0800 Subject: [PATCH 34/44] fix bug --- .../src/components/azureProvisionDialog.tsx | 42 +++++++++++++------ .../src/components/images/Qna-Maker.svg | 20 +++++++-- .../src/components/images/index.ts | 2 +- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index e909595f8a..17aced3f0a 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -273,7 +273,9 @@ const reviewCols: IColumn[] = [ isRowHeader: true, data: 'string', onRender: (item: ResourcesItem & {name,icon}) => { - return
{item.region?.displayName}
; + return
+ {item.key === AzureResourceTypes.APP_REGISTRATION ? 'global': item.region?.displayName} +
; }, isPadded: true, }, @@ -546,6 +548,7 @@ export const AzureProvisionDialog: React.FC = () => { const onSubmit = useMemo( () => async (options) => { // call back to the main Composer API to begin this process... + console.log(options); startProvision(options); closeDialog(); }, @@ -585,8 +588,12 @@ export const AzureProvisionDialog: React.FC = () => { ); const isDisAble = useMemo(() => { - return !currentSubscription || !currentHostName || errorHostName!== '' || errorResourceGroupName !== '' || !currentLocation; - }, [currentSubscription, currentHostName, errorHostName, currentLocation, errorResourceGroupName]); + return !currentSubscription || !currentHostName || errorHostName!== '' || errorResourceGroupName !== '' || (!currentConfig?.region && !currentLocation); + }, [currentSubscription, currentHostName, errorHostName, currentLocation, errorResourceGroupName, currentConfig]); + + const isSelectAddResources = useMemo(()=>{ + return enabledResources.length>0; + },[enabledResources]); const PageFormConfig = ( @@ -631,15 +638,23 @@ export const AzureProvisionDialog: React.FC = () => { styles={{ root: { paddingBottom: '8px' } }} onRenderLabel={onRenderLabel} /> - + {currentConfig?.region ? + : + } {currentLocation && currentLuisLocation && currentLocation.name !== currentLuisLocation.name && { /> { setPage(PageTypes.ReviewResource); setTitle(DialogTitle.REVIEW); @@ -825,7 +841,7 @@ export const AzureProvisionDialog: React.FC = () => { subscription: currentSubscription, resourceGroup: currentResourceGroup, hostname: currentHostName, - location: currentLocation, + location: currentConfig?.region || currentLocation, luisLocation: currentLuisLocation?.name || currentLocation.name, type: publishType, externalResources: selectedResources, diff --git a/extensions/azurePublish/src/components/images/Qna-Maker.svg b/extensions/azurePublish/src/components/images/Qna-Maker.svg index 27f1f60e66..60469407ef 100644 --- a/extensions/azurePublish/src/components/images/Qna-Maker.svg +++ b/extensions/azurePublish/src/components/images/Qna-Maker.svg @@ -1,3 +1,17 @@ - - - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extensions/azurePublish/src/components/images/index.ts b/extensions/azurePublish/src/components/images/index.ts index da87d88f83..24c9750558 100644 --- a/extensions/azurePublish/src/components/images/index.ts +++ b/extensions/azurePublish/src/components/images/index.ts @@ -10,7 +10,7 @@ import AppInsights from './Application-Insights.svg'; import BlobStorage from './Storage-Accounts.svg'; import FunctionApp from './Function-Apps.svg'; import AppRegistration from './App-Registrations.svg'; -import QNAMaker from './Qna-Maker.svg'; +import QNAMaker from './QnA-Maker.svg'; export { AppServicePlan, From 22653bd13b9ec2a089f033e4b443b9b7b8963ebd Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 17:32:35 +0800 Subject: [PATCH 35/44] fix bug --- extensions/azurePublish/src/components/azureProvisionDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index 17aced3f0a..14e87405db 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -592,7 +592,7 @@ export const AzureProvisionDialog: React.FC = () => { }, [currentSubscription, currentHostName, errorHostName, currentLocation, errorResourceGroupName, currentConfig]); const isSelectAddResources = useMemo(()=>{ - return enabledResources.length>0; + return enabledResources.length>0 || requireResources.length>0; },[enabledResources]); const PageFormConfig = ( From 41b5ee5263a9d896e692ab99f0c7e8e78730378b Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 18:00:50 +0800 Subject: [PATCH 36/44] remove image --- .../PublishProfileDialog.tsx | 2 +- .../src/components/images/Qna-Maker.svg | 17 ----------------- .../azurePublish/src/components/images/index.ts | 2 +- 3 files changed, 2 insertions(+), 19 deletions(-) delete mode 100644 extensions/azurePublish/src/components/images/Qna-Maker.svg diff --git a/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx b/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx index 9193cc9375..d90430a80b 100644 --- a/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx +++ b/Composer/packages/client/src/pages/botProject/create-publish-profile/PublishProfileDialog.tsx @@ -133,7 +133,7 @@ export const PublishProfileDialog: React.FC = (props) return types.find((t) => t.name === current?.item?.type)?.schema; }; PluginAPI.publish.savePublishConfig = (config) => { - savePublishTarget(name, current?.item?.type, JSON.stringify(config) || '{}'); + savePublishTarget(current?.item.name, current?.item?.type, JSON.stringify(config) || '{}'); }; PluginAPI.publish.startProvision = async (config) => { const fullConfig = { ...config, name: current.item.name, type: current.item.type }; diff --git a/extensions/azurePublish/src/components/images/Qna-Maker.svg b/extensions/azurePublish/src/components/images/Qna-Maker.svg deleted file mode 100644 index 60469407ef..0000000000 --- a/extensions/azurePublish/src/components/images/Qna-Maker.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/extensions/azurePublish/src/components/images/index.ts b/extensions/azurePublish/src/components/images/index.ts index 24c9750558..da87d88f83 100644 --- a/extensions/azurePublish/src/components/images/index.ts +++ b/extensions/azurePublish/src/components/images/index.ts @@ -10,7 +10,7 @@ import AppInsights from './Application-Insights.svg'; import BlobStorage from './Storage-Accounts.svg'; import FunctionApp from './Function-Apps.svg'; import AppRegistration from './App-Registrations.svg'; -import QNAMaker from './QnA-Maker.svg'; +import QNAMaker from './Qna-Maker.svg'; export { AppServicePlan, From de0b25d0adc4260e50e9626075836a195acc8ae6 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 18:01:22 +0800 Subject: [PATCH 37/44] add image --- .../src/components/images/QnA-Maker.svg | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 extensions/azurePublish/src/components/images/QnA-Maker.svg diff --git a/extensions/azurePublish/src/components/images/QnA-Maker.svg b/extensions/azurePublish/src/components/images/QnA-Maker.svg new file mode 100644 index 0000000000..60469407ef --- /dev/null +++ b/extensions/azurePublish/src/components/images/QnA-Maker.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file From 621b8ac0ccf916fbcfcf0ef195cb32134784937e Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 18:03:18 +0800 Subject: [PATCH 38/44] fix bugs --- .../azurePublish/src/components/azureProvisionDialog.tsx | 9 ++++----- extensions/azurePublish/src/components/images/index.ts | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index 14e87405db..8654ee0c8a 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -125,7 +125,6 @@ function getExistResources (config){ if(config.settings?.blobStorage?.connectionString){ result.push(AzureResourceTypes.BLOBSTORAGE); } - console.log(result); return result; } else return []; } @@ -274,7 +273,7 @@ const reviewCols: IColumn[] = [ data: 'string', onRender: (item: ResourcesItem & {name,icon}) => { return
- {item.key === AzureResourceTypes.APP_REGISTRATION ? 'global': item.region?.displayName} + {item.key === AzureResourceTypes.APP_REGISTRATION ? 'global': (item.region?.displayName || item)}
; }, isPadded: true, @@ -548,7 +547,6 @@ export const AzureProvisionDialog: React.FC = () => { const onSubmit = useMemo( () => async (options) => { // call back to the main Composer API to begin this process... - console.log(options); startProvision(options); closeDialog(); }, @@ -557,6 +555,7 @@ export const AzureProvisionDialog: React.FC = () => { const onSave = useMemo( () => () => { + savePublishConfig(importConfig); closeDialog(); }, @@ -809,7 +808,7 @@ export const AzureProvisionDialog: React.FC = () => { setTitle(DialogTitle.REVIEW); let selectedResources = requireResources.concat(enabledResources); selectedResources = selectedResources.map(item=>{ - let region = currentLocation; + let region = currentConfig?.region ? {displayName: currentConfig?.region} : currentLocation; if(item.key.includes('luis')){ region = currentLuisLocation; } @@ -841,7 +840,7 @@ export const AzureProvisionDialog: React.FC = () => { subscription: currentSubscription, resourceGroup: currentResourceGroup, hostname: currentHostName, - location: currentConfig?.region || currentLocation, + location: {name: currentConfig?.region} || currentLocation, luisLocation: currentLuisLocation?.name || currentLocation.name, type: publishType, externalResources: selectedResources, diff --git a/extensions/azurePublish/src/components/images/index.ts b/extensions/azurePublish/src/components/images/index.ts index da87d88f83..24c9750558 100644 --- a/extensions/azurePublish/src/components/images/index.ts +++ b/extensions/azurePublish/src/components/images/index.ts @@ -10,7 +10,7 @@ import AppInsights from './Application-Insights.svg'; import BlobStorage from './Storage-Accounts.svg'; import FunctionApp from './Function-Apps.svg'; import AppRegistration from './App-Registrations.svg'; -import QNAMaker from './Qna-Maker.svg'; +import QNAMaker from './QnA-Maker.svg'; export { AppServicePlan, From 582285b91c9306047a7eaad5af4e360fdfec7b7e Mon Sep 17 00:00:00 2001 From: Long Alan Date: Mon, 1 Mar 2021 18:26:09 +0800 Subject: [PATCH 39/44] fix: provision process shown in publish list (#6044) * add jobId for filter publish process * lint * delete un-use value * ut * refactor --- .../src/recoilModel/dispatchers/publisher.ts | 23 ++++++++++++++++++- .../src/utils/publishStatusPollingUpdater.ts | 10 +++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Composer/packages/client/src/recoilModel/dispatchers/publisher.ts b/Composer/packages/client/src/recoilModel/dispatchers/publisher.ts index fb83da97f7..13251e5c37 100644 --- a/Composer/packages/client/src/recoilModel/dispatchers/publisher.ts +++ b/Composer/packages/client/src/recoilModel/dispatchers/publisher.ts @@ -21,6 +21,7 @@ import { openInEmulator } from '../../utils/navigation'; import { botEndpointsState } from '../atoms'; import { rootBotProjectIdSelector, dialogsSelectorFamily } from '../selectors'; import * as luUtil from '../../utils/luUtil'; +import { ClientStorage } from '../../utils/storage'; import { BotStatus, Text } from './../../constants'; import httpClient from './../../utils/httpUtil'; @@ -47,6 +48,8 @@ const checkIfDotnetVersionMissing = (err: any) => { return /(Command failed: dotnet user-secrets)|(install[\w\r\s\S\t\n]*\.NET Core SDK)/.test(err.message as string); }; +export const publishStorage = new ClientStorage(window.sessionStorage, 'publish'); + export const publisherDispatcher = () => { const publishFailure = async ({ set }: CallbackInterface, title: string, error, target, projectId: string) => { if (target.name === defaultPublishConfig.name) { @@ -99,6 +102,13 @@ export const publisherDispatcher = () => { if (data == null) return; const { set, snapshot } = callbackHelpers; const { endpointURL, status } = data; + + // remove job id in publish storage if published + if (status === PUBLISH_SUCCESS || status === PUBLISH_FAILED) { + const publishJobIds = publishStorage.get('jobIds') || {}; + delete publishJobIds[`${projectId}-${target.name}`]; + publishStorage.set('jobIds', publishJobIds); + } // the action below only applies to when a bot is being started using the "start bot" button // a check should be added to this that ensures this ONLY applies to the "default" profile. if (target.name === defaultPublishConfig.name) { @@ -189,6 +199,12 @@ export const publisherDispatcher = () => { }, sensitiveSettings, }); + + // add job id to storage + const publishJobIds = publishStorage.get('jobIds') || {}; + publishJobIds[`${projectId}-${target.name}`] = response.data.id; + publishStorage.set('jobIds', publishJobIds); + await publishSuccess(callbackHelpers, projectId, response.data, target); } catch (err) { // special case to handle dotnet issues @@ -226,7 +242,12 @@ export const publisherDispatcher = () => { const getPublishStatus = useRecoilCallback( (callbackHelpers: CallbackInterface) => async (projectId: string, target: any, jobId?: string) => { try { - const response = await httpClient.get(`/publish/${projectId}/status/${target.name}${jobId ? '/' + jobId : ''}`); + const currentJobId = + jobId ?? + (publishStorage.get('jobIds') ? publishStorage.get('jobIds')[`${projectId}-${target.name}`] : undefined); + const response = await httpClient.get( + `/publish/${projectId}/status/${target.name}/${currentJobId ? '/' + currentJobId : ''}` + ); updatePublishStatus(callbackHelpers, projectId, target, response.data); } catch (err) { updatePublishStatus(callbackHelpers, projectId, target, err.response?.data); diff --git a/Composer/packages/client/src/utils/publishStatusPollingUpdater.ts b/Composer/packages/client/src/utils/publishStatusPollingUpdater.ts index 8b90e40932..083ae09e0d 100644 --- a/Composer/packages/client/src/utils/publishStatusPollingUpdater.ts +++ b/Composer/packages/client/src/utils/publishStatusPollingUpdater.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +import { publishStorage } from '../recoilModel/dispatchers/publisher'; + import httpClient from './httpUtil'; enum PollingStateEnum { @@ -39,8 +41,14 @@ export class PublishStatusPollingUpdater { private async fetchPublishStatusData(botProjectId: string, publishTargetName: string, onData: OnDataHandler) { // TODO: DONT set HTTP Status code with 500 404 directly! + const currentJobId = publishStorage.get('jobIds') + ? publishStorage.get('jobIds')[`${botProjectId}-${publishTargetName}`] + : undefined; + if (!currentJobId) { + return; + } const response = await httpClient - .get(`/publish/${this.botProjectId}/status/${this.publishTargetName}`) + .get(`/publish/${this.botProjectId}/status/${this.publishTargetName}/${currentJobId}`) .catch((reason) => reason.response); onData({ From c021d278eb4d285687ef65fc4033070191664416 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 18:34:04 +0800 Subject: [PATCH 40/44] fix region --- .../packages/client/src/recoilModel/dispatchers/provision.ts | 1 - .../azurePublish/src/components/azureProvisionDialog.tsx | 5 +++-- extensions/azurePublish/src/node/index.ts | 2 +- extensions/azurePublish/src/node/provision.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Composer/packages/client/src/recoilModel/dispatchers/provision.ts b/Composer/packages/client/src/recoilModel/dispatchers/provision.ts index d342c805b9..8451fc0c1d 100644 --- a/Composer/packages/client/src/recoilModel/dispatchers/provision.ts +++ b/Composer/packages/client/src/recoilModel/dispatchers/provision.ts @@ -132,7 +132,6 @@ export const provisionDispatcher = () => { type: targetType, }; const targetList = updatePublishTargets(settings, profile); - console.log(targetList); return { ...settings, publishTargets: targetList, diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index 8654ee0c8a..86922814c1 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -644,6 +644,7 @@ export const AzureProvisionDialog: React.FC = () => { defaultValue={currentConfig?.region} label={formatMessage('Region')} styles={{ root: { paddingBottom: '8px' } }} + onRenderLabel={onRenderLabel} /> : { subscription: currentSubscription, resourceGroup: currentResourceGroup, hostname: currentHostName, - location: {name: currentConfig?.region} || currentLocation, - luisLocation: currentLuisLocation?.name || currentLocation.name, + location: currentConfig?.region || currentLocation.name, + luisLocation: currentLuisLocation?.name || currentConfig?.region || currentLocation.name, type: publishType, externalResources: selectedResources, }); diff --git a/extensions/azurePublish/src/node/index.ts b/extensions/azurePublish/src/node/index.ts index 9f703a682c..a2b3ec4af6 100644 --- a/extensions/azurePublish/src/node/index.ts +++ b/extensions/azurePublish/src/node/index.ts @@ -418,7 +418,7 @@ export default async (composer: IExtensionRegistration): Promise => { hostname: config.hostname ?? currentProfile?.hostname, luisResource: provisionResults.luisPrediction? `${config.hostname}-luis` : currentProfile?.luisResource, runtimeIdentifier: currentProfile?.runtimeIdentifier ?? 'win-x64', - region: config.location.name, + region: config.location, settings: { applicationInsights: { InstrumentationKey: provisionResults.appInsights?.instrumentationKey ?? currentSettings?.applicationInsights?.InstrumentationKey, diff --git a/extensions/azurePublish/src/node/provision.ts b/extensions/azurePublish/src/node/provision.ts index e8d30a69b2..b09dad772f 100644 --- a/extensions/azurePublish/src/node/provision.ts +++ b/extensions/azurePublish/src/node/provision.ts @@ -16,7 +16,7 @@ export interface ProvisionConfig { tenantId?: string; hostname: string; // for previous bot, it's ${name}-${environment} externalResources: ResourceType[]; - location: { id: string; name: string; displayName: string }; + location: string; luisLocation: string; subscription: string; resourceGroup?: string; @@ -234,7 +234,7 @@ export class BotProjectProvision { // Ensure the resource group is ready provisionResults.resourceGroup = await this.azureResourceManagementClient.createResourceGroup({ name: resourceGroupName, - location: config.location.name, + location: config.location, }); // SOME OF THESE MUST HAPPEN IN THE RIGHT ORDER! From f6b88eb561daf5172385b8e42db0204a68579900 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 19:18:19 +0800 Subject: [PATCH 41/44] go to edit page if no resources can be added --- .../src/components/azureProvisionDialog.tsx | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index 86922814c1..f96bf3787b 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -54,6 +54,7 @@ const PageTypes = { ConfigProvision: 'config', AddResources: 'add', ReviewResource: 'review', + EditJson: 'edit', }; const DialogTitle = { CONFIG_RESOURCES: { @@ -70,6 +71,10 @@ const DialogTitle = { 'Please review the resources that will be created for your bot. Once these resources are provisioned, they will be available in your Azure portal.' ), }, + EDIT:{ + title: formatMessage('Configure resources'), + subText: formatMessage('How you would like to provision your Azure resources to publish your bot?'), + } }; function decodeToken(token: string) { @@ -697,6 +702,14 @@ export const AzureProvisionDialog: React.FC = () => {
); + useEffect(()=>{ + console.log(listItems); + if(listItems?.length === 0) { + setTitle(DialogTitle.EDIT); + setPage(PageTypes.EditJson); + } + },[listItems]); + const selection = useMemo(() => { const s = new Selection({ onSelectionChanged: () => { @@ -822,7 +835,7 @@ export const AzureProvisionDialog: React.FC = () => {
); - } else { + } else if(page === PageTypes.ReviewResource){ return (
{currentUser? : null} @@ -851,6 +864,18 @@ export const AzureProvisionDialog: React.FC = () => {
) + } else { + return ( + <> + { + closeDialog(); + }} + /> + + ); } }, [ onSave, @@ -875,6 +900,21 @@ export const AzureProvisionDialog: React.FC = () => { {page === PageTypes.ConfigProvision && PageFormConfig} {page === PageTypes.AddResources && PageAddResources} {page === PageTypes.ReviewResource && PageReview} + {page === PageTypes.EditJson && ( + { + setEditorError(false); + setImportConfig(value); + }} + onError={() => { + setEditorError(true); + }} + /> + )}
Date: Mon, 1 Mar 2021 21:12:26 +0800 Subject: [PATCH 42/44] fix the region issue --- extensions/azurePublish/src/node/provision.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extensions/azurePublish/src/node/provision.ts b/extensions/azurePublish/src/node/provision.ts index b09dad772f..6995868a65 100644 --- a/extensions/azurePublish/src/node/provision.ts +++ b/extensions/azurePublish/src/node/provision.ts @@ -262,7 +262,7 @@ export class BotProjectProvision { // eslint-disable-next-line no-case-declarations const hostname = await this.azureResourceManagementClient.deployWebAppResource({ resourceGroupName: resourceGroupName, - location: provisionResults.resourceGroup.location, + location: config.location ?? provisionResults.resourceGroup.location, name: config.hostname }); provisionResults.webApp = { @@ -275,7 +275,7 @@ export class BotProjectProvision { case AzureResourceTypes.BOT_REGISTRATION: const botName = await this.azureResourceManagementClient.deployBotResource({ resourceGroupName: resourceGroupName, - location: provisionResults.resourceGroup.location, + location: config.location ?? provisionResults.resourceGroup.location, name: config.hostname, // come back to this! displayName: config.hostname, // todo: this may be wrong! endpoint: `https://${provisionResults.webApp?.hostname ?? (config.hostname + ".azurewebsites.net")}/api/messages`, @@ -290,7 +290,7 @@ export class BotProjectProvision { case AzureResourceTypes.AZUREFUNCTIONS: { const functionsHostName = await this.azureResourceManagementClient.deployAzureFunctions({ resourceGroupName: resourceGroupName, - location: provisionResults.resourceGroup.location, + location: config.location ?? provisionResults.resourceGroup.location, name: config.hostname }); provisionResults.webApp = { @@ -304,7 +304,7 @@ export class BotProjectProvision { case AzureResourceTypes.COSMOSDB: provisionResults.cosmosDB = await this.azureResourceManagementClient.deployCosmosDBResource({ resourceGroupName: resourceGroupName, - location: provisionResults.resourceGroup.location, + location: config.location ?? provisionResults.resourceGroup.location, name: config.hostname.replace(/_/g, '').substr(0, 31).toLowerCase(), databaseName: `botstate-db`, containerName: `botstate-container`, @@ -316,7 +316,7 @@ export class BotProjectProvision { case AzureResourceTypes.APPINSIGHTS: provisionResults.appInsights = await this.azureResourceManagementClient.deployAppInsightsResource({ resourceGroupName: resourceGroupName, - location: provisionResults.resourceGroup.location, + location: config.location ?? provisionResults.resourceGroup.location, name: config.hostname, }); @@ -358,7 +358,7 @@ export class BotProjectProvision { // eslint-disable-next-line no-case-declarations provisionResults.blobStorage = await this.azureResourceManagementClient.deployBlobStorageResource({ resourceGroupName: resourceGroupName, - location: provisionResults.resourceGroup.location, + location: config.location ?? provisionResults.resourceGroup.location, name: config.hostname.toLowerCase().replace(/-/g, '').replace(/_/g, ''), containerName: 'transcripts', }); @@ -369,7 +369,7 @@ export class BotProjectProvision { case AzureResourceTypes.QNA: provisionResults.qna = await this.azureResourceManagementClient.deployQnAReource({ resourceGroupName: resourceGroupName, - location: provisionResults.resourceGroup.location, + location: config.location ?? provisionResults.resourceGroup.location, name: `${config.hostname}-qna`, }); break; From cde52aa4f0e26677f3525e6a390c395736e5d1e4 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 21:40:02 +0800 Subject: [PATCH 43/44] fix ut --- .../botProjectsSettings/PublishTarget.test.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Composer/packages/client/__tests__/pages/botProjectsSettings/PublishTarget.test.tsx b/Composer/packages/client/__tests__/pages/botProjectsSettings/PublishTarget.test.tsx index 9cd6e37076..6b485c057f 100644 --- a/Composer/packages/client/__tests__/pages/botProjectsSettings/PublishTarget.test.tsx +++ b/Composer/packages/client/__tests__/pages/botProjectsSettings/PublishTarget.test.tsx @@ -8,11 +8,23 @@ import { act, fireEvent } from '@botframework-composer/test-utils'; import { PublishTargets } from '../../../src/pages/botProject/PublishTargets'; import { renderWithRecoilAndCustomDispatchers } from '../../testUtils'; import { dispatcherState, publishTypesState } from '../../../src/recoilModel'; +import { isShowAuthDialog } from '../../../src/utils/auth'; + +jest.mock('../../../src/utils/auth', () => ({ + isShowAuthDialog: jest.fn(), + getTokenFromCache: jest.fn(), + isGetTokenFromUser: jest.fn(), +})); + const state = { projectId: 'test', publishTypes: [{ name: 'azureFunctionsPublish', description: 'Publish bot to Azure Functions (Preview)' }], }; + describe('Publish Target', () => { + beforeEach(() => { + (isShowAuthDialog as jest.Mock).mockReturnValue(false); + }); const setPublishTargetsMock = jest.fn(); const initRecoilState = ({ set }) => { set(dispatcherState, { @@ -28,6 +40,7 @@ describe('Publish Target', () => { , initRecoilState ); + const addNewPublishProfile = getByTestId('addNewPublishProfile'); act(() => { fireEvent.click(addNewPublishProfile); From c1b4dd8c4dd6e848e54fe6fa363108d804570231 Mon Sep 17 00:00:00 2001 From: Wenyi Luo Date: Mon, 1 Mar 2021 22:02:21 +0800 Subject: [PATCH 44/44] fix auth dialog popup everytime --- .../packages/client/src/pages/botProject/PublishTargets.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Composer/packages/client/src/pages/botProject/PublishTargets.tsx b/Composer/packages/client/src/pages/botProject/PublishTargets.tsx index 5ef11cb45f..2a017df3b4 100644 --- a/Composer/packages/client/src/pages/botProject/PublishTargets.tsx +++ b/Composer/packages/client/src/pages/botProject/PublishTargets.tsx @@ -108,7 +108,7 @@ export const PublishTargets: React.FC = (props) => { const publishTypes = useRecoilValue(publishTypesState(projectId)); const [dialogHidden, setDialogHidden] = useState(true); - const [showAuthDialog, setShowAuthDialog] = useState(isShowAuthDialog(true)); + const [showAuthDialog, setShowAuthDialog] = useState(false); const publishTargetsRef = React.useRef(null); const [current, setCurrent] = useState<{ index: number; item: PublishTarget } | null>(null);