From 997a34dbf5feffe056bee547bb0d68b337b53b6f Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Thu, 15 Apr 2021 17:43:48 -0700 Subject: [PATCH 01/12] Runtime log for skills Signed-off-by: Srinaath Ravichandran --- .../pages/botProject/BotProjectSettings.tsx | 2 +- .../RuntimeOutputLog/OutputTabContent.tsx | 89 ++++++++++++++++++- .../RuntimeOutputLog/RuntimeOutputLog.tsx | 67 +------------- ...Log.test.tsx => OutputTabContent.test.tsx} | 40 +++++++-- .../electron-server/locales/en-US.json | 6 +- 5 files changed, 124 insertions(+), 80 deletions(-) rename Composer/packages/client/src/pages/design/__tests__/{RuntimeOutputLog.test.tsx => OutputTabContent.test.tsx} (71%) diff --git a/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx b/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx index 933163cade..9704ff69a2 100644 --- a/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx +++ b/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx @@ -153,7 +153,7 @@ const BotProjectSettings: React.FC { return formatMessage( - 'This Page contains detailed information about your bot. For security reasons, they are hidden by default. To test your bot or publish to Azure, you may need to provide these settings' + 'This Page contains detailed information about your bot. For security reasons, they are hidden by default. To test your bot or publish to Azure, you may need to provide these settings.' ); }; diff --git a/Composer/packages/client/src/pages/design/DebugPanel/TabExtensions/RuntimeOutputLog/OutputTabContent.tsx b/Composer/packages/client/src/pages/design/DebugPanel/TabExtensions/RuntimeOutputLog/OutputTabContent.tsx index dca52c42de..ec34d8c558 100644 --- a/Composer/packages/client/src/pages/design/DebugPanel/TabExtensions/RuntimeOutputLog/OutputTabContent.tsx +++ b/Composer/packages/client/src/pages/design/DebugPanel/TabExtensions/RuntimeOutputLog/OutputTabContent.tsx @@ -6,19 +6,102 @@ /** @jsx jsx */ import { jsx } from '@emotion/core'; import { Split } from '@geoffcox/react-splitter'; -import { useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { useRecoilValue } from 'recoil'; +import formatMessage from 'format-message'; import { renderThinSplitter } from '../../../../../components/Split/ThinSplitter'; -import { rootBotProjectIdSelector } from '../../../../../recoilModel'; +import { + botProjectIdsState, + botProjectSpaceLoadedState, + dispatcherState, + rootBotProjectIdSelector, +} from '../../../../../recoilModel'; import { DebugPanelTabHeaderProps } from '../types'; +import httpClient from '../../../../../utils/httpUtil'; +import { checkIfDotnetVersionMissing, missingDotnetVersionError } from '../../../../../utils/runtimeErrors'; +import { BotStartError } from '../../../../../recoilModel/types'; +import { Text } from '../../../../../constants'; -import { BotProjectsFilter } from './BotProjectsFilter'; import { RuntimeOutputLog } from './RuntimeOutputLog'; +import { BotProjectsFilter } from './BotProjectsFilter'; + +const genericErrorMessage = () => { + return { + message: 'Runtime Log', + summary: formatMessage('Error occurred trying to fetch runtime standard output'), + }; +}; export const OutputsTabContent: React.FC = ({ isActive }) => { const rootBotId = useRecoilValue(rootBotProjectIdSelector); const [currentProjectId, setProjectId] = useState(rootBotId ?? ''); + const runtimeTrafficChannel = useRef | null>(null); + const projectIds = useRecoilValue(botProjectIdsState); + const { setRuntimeStandardOutputData, setApplicationLevelError } = useRecoilValue(dispatcherState); + const botProjectSolutionLoaded = useRecoilValue(botProjectSpaceLoadedState); + + useEffect(() => { + const setupLogConnection = async () => { + projectIds.forEach(async (projectId) => { + try { + const runtimeStreamUrl = await httpClient.get(`/publish/runtimeLogUrl/${projectId}`); + + const socket = new WebSocket(runtimeStreamUrl.data); + + if (socket) { + socket.onmessage = (event) => { + const data: { standardError: string; standardOutput: string } = JSON.parse(event.data); + + let standardError: BotStartError | null = null; + if (data.standardError) { + const isDotnetError = checkIfDotnetVersionMissing({ + message: data.standardError ?? '', + }); + + if (isDotnetError) { + standardError = { + title: Text.DOTNETFAILURE, + ...missingDotnetVersionError, + }; + } else { + standardError = { + title: Text.BOTRUNTIMEERROR, + message: data.standardError, + }; + } + } + + setRuntimeStandardOutputData(projectId, { + standardError, + standardOutput: data.standardOutput, + }); + }; + runtimeTrafficChannel.current = { + ...runtimeTrafficChannel.current, + [projectId]: socket, + }; + } + } catch (ex) { + setApplicationLevelError(genericErrorMessage()); + } + }); + }; + + if (!runtimeTrafficChannel.current && botProjectSolutionLoaded) { + setupLogConnection(); + } + + return () => { + if (runtimeTrafficChannel.current) { + for (const projectId in runtimeTrafficChannel.current) { + runtimeTrafficChannel.current[projectId].close(); + } + } + runtimeTrafficChannel.current = null; + }; + }, [botProjectSolutionLoaded]); + return (
{ - return { - message: 'Runtime Log', - summary: formatMessage('Error occurred trying to fetch runtime standard output'), - }; -}; const ansiUp = new AnsiUp(); const DEFAULT_FONT_SETTINGS = getDefaultFontSettings(); @@ -35,68 +23,15 @@ const createMarkup = (txt: string) => { export const RuntimeOutputLog: React.FC<{ projectId: string }> = ({ projectId }) => { const runtimeData = useRecoilValue(runtimeStandardOutputDataState(projectId)); const botBuildErrors = useRecoilValue(botBuildTimeErrorState(projectId)); - const { setRuntimeStandardOutputData, setApplicationLevelError } = useRecoilValue(dispatcherState); const runtimeLogsContainerRef = useRef(null); - const runtimeTrafficChannel = useRef(null); - useEffect(() => { if (runtimeLogsContainerRef?.current) { runtimeLogsContainerRef.current.scrollTop = runtimeLogsContainerRef.current.scrollHeight; } }, [runtimeData]); - useEffect(() => { - const setupLogConnection = async () => { - try { - const runtimeStreamUrl = await httpClient.get(`/publish/runtimeLogUrl/${projectId}`); - - runtimeTrafficChannel.current = new WebSocket(runtimeStreamUrl.data); - - if (runtimeTrafficChannel.current) { - runtimeTrafficChannel.current.onmessage = (event) => { - const data: { standardError: string; standardOutput: string } = JSON.parse(event.data); - - let standardError: BotStartError | null = null; - if (data.standardError) { - const isDotnetError = checkIfDotnetVersionMissing({ - message: data.standardError ?? '', - }); - - if (isDotnetError) { - standardError = { - title: Text.DOTNETFAILURE, - ...missingDotnetVersionError, - }; - } else { - standardError = { - title: Text.BOTRUNTIMEERROR, - message: data.standardError, - }; - } - } - setRuntimeStandardOutputData(projectId, { - standardError, - standardOutput: data.standardOutput, - }); - }; - } - } catch (ex) { - setApplicationLevelError(genericErrorMessage()); - } - }; - - if (!runtimeTrafficChannel.current) { - setupLogConnection(); - } - - return () => { - runtimeTrafficChannel.current?.close(); - runtimeTrafficChannel.current = null; - }; - }, []); - return (
', () => { +describe('', () => { let mockWSServer; beforeAll(() => { const url = `ws://localhost:1234/test/${projectId}`; @@ -38,9 +43,17 @@ describe('', () => { mockWSServer = null; }); - describe('', () => { + describe('', () => { it('should render Runtime logs', async () => { - const { findByTestId } = renderWithRecoil(); + const { findByTestId } = renderWithRecoil(, ({ set }) => { + set(botProjectIdsState, [projectId]); + set(projectMetaDataState(projectId), { + isRootBot: true, + isRemote: false, + }); + set(botProjectSpaceLoadedState, true); + }); + await mockWSServer.connected; act(() => { const stringified = JSON.stringify({ @@ -53,7 +66,14 @@ describe('', () => { }); it('should render Runtime standard errors', async () => { - const { findByText } = renderWithRecoil(); + const { findByText } = renderWithRecoil(, ({ set }) => { + set(botProjectIdsState, [projectId]); + set(projectMetaDataState(projectId), { + isRootBot: true, + isRemote: false, + }); + set(botProjectSpaceLoadedState, true); + }); await mockWSServer.connected; act(() => { const stringified = JSON.stringify({ @@ -66,7 +86,13 @@ describe('', () => { }); it('should render Runtime errors', async () => { - const { findByText } = renderWithRecoil(, ({ set }) => { + const { findByText } = renderWithRecoil(, ({ set }) => { + set(botProjectIdsState, [projectId]); + set(projectMetaDataState(projectId), { + isRootBot: true, + isRemote: false, + }); + set(botProjectSpaceLoadedState, true); set(botBuildTimeErrorState(projectId), { message: '.NET 3.1 needs to be installed', title: '.NET runtime error', diff --git a/Composer/packages/electron-server/locales/en-US.json b/Composer/packages/electron-server/locales/en-US.json index fae3220af4..7203f8cfa2 100644 --- a/Composer/packages/electron-server/locales/en-US.json +++ b/Composer/packages/electron-server/locales/en-US.json @@ -53,8 +53,8 @@ "initializing_4e34f7d": { "message": "Initializing..." }, - "learn_more_about_bot_framework_2daca065": { - "message": "Learn More About Bot Framework" + "learn_more_about_bot_framework_f5fe280b": { + "message": "Learn more about Bot Framework" }, "minimize_4f999e30": { "message": "Minimize" @@ -122,4 +122,4 @@ "zoom_out_dc7d60d2": { "message": "Zoom Out" } -} \ No newline at end of file +} From 73f92cda4e1f7bc6b6dfe79a51b3ff58369687d8 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 10:20:29 -0700 Subject: [PATCH 02/12] PVa disabler Signed-off-by: Srinaath Ravichandran --- .../BotRuntimeController/BotController.tsx | 109 ++++++++++-------- .../packages/client/src/components/Header.tsx | 5 +- .../client/src/components/PVADisabler.tsx | 46 ++++++++ .../botProject/BotProjectsSettingsTabView.tsx | 27 ++++- 4 files changed, 130 insertions(+), 57 deletions(-) create mode 100644 Composer/packages/client/src/components/PVADisabler.tsx diff --git a/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx b/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx index 2be2e72540..e4463f0d74 100644 --- a/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx +++ b/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx @@ -12,6 +12,7 @@ import { css } from '@emotion/core'; import { NeutralColors, CommunicationColors } from '@uifabric/fluent-theme'; import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner'; +import { PVADisabler } from '../PVADisabler'; import TelemetryClient from '../../telemetry/TelemetryClient'; import { buildConfigurationSelector, @@ -209,60 +210,66 @@ const BotController: React.FC = ({ onHideController, isContr return ; })}
- null} - styles={{ - root: { - backgroundColor: CommunicationColors.tint10, - display: 'flex', - alignItems: 'center', - minWidth: '229px', - height: '36px', - flexDirection: 'row', - padding: '0 7px', - border: `1px solid ${CommunicationColors.tint10}`, - width: '100%', - }, - rootHovered: { - background: transparentBackground, - }, - rootDisabled: { - opacity: 0.6, - backgroundColor: CommunicationColors.tint10, - color: `${NeutralColors.white}`, - border: 'none', - font: '62px', - }, - }} - title={startPanelButtonText} - onClick={handleClick} + - {areBotsStarting && ( - - )} - {startPanelButtonText} - + }, + }} + id={'startbot'} + menuAs={() => null} + styles={{ + root: { + backgroundColor: CommunicationColors.tint10, + display: 'flex', + alignItems: 'center', + minWidth: '229px', + height: '36px', + flexDirection: 'row', + padding: '0 7px', + border: `1px solid ${CommunicationColors.tint10}`, + width: '100%', + }, + rootHovered: { + background: transparentBackground, + }, + rootDisabled: { + opacity: 0.6, + backgroundColor: CommunicationColors.tint10, + color: `${NeutralColors.white}`, + border: 'none', + font: '62px', + }, + }} + title={startPanelButtonText} + onClick={handleClick} + > + {areBotsStarting && ( + + )} + {startPanelButtonText} + +
{ const [teachingBubbleVisibility, setTeachingBubbleVisibility] = useState(); const [showGetStartedTeachingBubble, setshowGetStartedTeachingBubble] = useState(false); const settings = useRecoilValue(settingsState(projectId)); - const schemas = useRecoilValue(schemasState(projectId)); const isWebChatPanelVisible = useRecoilValue(isWebChatPanelVisibleState); const botProjectSolutionLoaded = useRecoilValue(botProjectSpaceLoadedState); @@ -291,7 +288,7 @@ export const Header = () => {
- {isShow && !checkForPVASchema(schemas.sdk) && ( + {isShow && (
= { root: { display: 'inline-block' } }; + +const genericDisableMessage = () => { + return formatMessage('PVA bots cannot use this functionality at this time.'); +}; + +export const PVADisabler: React.FC<{ content?: string }> = (props) => { + const rootBotId = useRecoilValue(rootBotProjectIdSelector); + const schema = useRecoilValue(schemasState(rootBotId ?? '')); + const [isPVABot, setIsPVABot] = useState(false); + + useEffect(() => { + setIsPVABot(checkForPVASchema(schema.sdk)); + }, [rootBotId]); + + const tooltipId = useId('tooltip'); + + if (!isPVABot) { + return <>{props.children}; + } + + return ( + + {props.children} + + ); +}; diff --git a/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx b/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx index ed5657ae8e..a6402d08cc 100644 --- a/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx +++ b/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx @@ -8,8 +8,11 @@ import React, { useEffect, useState } from 'react'; import { RouteComponentProps } from '@reach/router'; import { Pivot, PivotItem } from 'office-ui-fabric-react/lib/components/Pivot'; import formatMessage from 'format-message'; +import { Label } from 'office-ui-fabric-react/lib/Label'; +import { IButtonProps } from 'office-ui-fabric-react/lib/Button'; import { localBotsDataSelector } from '../../recoilModel/selectors/project'; +import { PVADisabler } from '../../components/PVADisabler'; import { BotSkillConfiguration } from './BotSkillConfiguration'; import { BotProjectInfo } from './BotProjectInfo'; @@ -28,6 +31,11 @@ const container = css` height: 100%; `; +const disabledPivotStyle: IButtonProps = { + disabled: true, + style: { pointerEvents: 'unset', cursor: 'no-drop' }, +}; + const idsInTab: Record = { Basics: ['runtimeSettings'], LuisQna: ['luisKey', 'qnaKey', 'luisRegion'], @@ -80,7 +88,17 @@ export const BotProjectSettingsTabView: React.FC - + ( + + + + )} + > ( + + + + )} > {isRootBot && } From 310842d64c480c6e9c07698cad3d26910780203c Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 14:59:04 -0700 Subject: [PATCH 03/12] Disable functionalities for PVA Signed-off-by: Srinaath Ravichandran --- .../RecognizerField/getDropdownOptions.ts | 11 ++++- .../src/components/AppComponents/SideBar.tsx | 10 ++++- .../BotRuntimeController/BotController.tsx | 10 ++--- ...{PVADisabler.tsx => PVADisableFeature.tsx} | 4 +- .../components/ProjectTree/ProjectHeader.tsx | 14 ++++++- .../packages/client/src/hooks/usePVACheck.ts | 13 ++++++ .../botProject/BotProjectsSettingsTabView.tsx | 42 ++++++++++++------- .../runtime-settings/RuntimeSettings.tsx | 18 +++++--- .../src/recoilModel/selectors/project.ts | 10 ++++- .../packages/client/src/utils/pageLinks.ts | 24 +++++++---- 10 files changed, 114 insertions(+), 42 deletions(-) rename Composer/packages/client/src/components/{PVADisabler.tsx => PVADisableFeature.tsx} (88%) create mode 100644 Composer/packages/client/src/hooks/usePVACheck.ts diff --git a/Composer/packages/adaptive-form/src/components/fields/RecognizerField/getDropdownOptions.ts b/Composer/packages/adaptive-form/src/components/fields/RecognizerField/getDropdownOptions.ts index 8279009426..e5c0c51ff4 100644 --- a/Composer/packages/adaptive-form/src/components/fields/RecognizerField/getDropdownOptions.ts +++ b/Composer/packages/adaptive-form/src/components/fields/RecognizerField/getDropdownOptions.ts @@ -2,6 +2,7 @@ // Licensed under the MIT License. import { RecognizerSchema, FallbackRecognizerKey, ShellApi, ShellData } from '@bfc/extension-client'; +import { checkForPVASchema } from '@bfc/shared'; import { recognizerOrderMap } from './defaultRecognizerOrder'; import { mapRecognizerSchemaToDropdownOption } from './mappers'; @@ -16,7 +17,15 @@ const getRankScore = (r: RecognizerSchema, shellData: ShellData, shellApi: Shell return recognizerOrderMap[r.id] ?? Number.MAX_VALUE - 1; }; -export const getDropdownOptions = (recognizerConfigs: RecognizerSchema[], shellData: ShellData, shellApi: ShellApi) => { +export const getDropdownOptions = (configs: RecognizerSchema[], shellData: ShellData, shellApi: ShellApi) => { + const isPVASchema = checkForPVASchema(shellData.schemas.sdk); + let recognizerConfigs: RecognizerSchema[] = configs; + if (isPVASchema) { + recognizerConfigs = recognizerConfigs.filter((config) => { + return config.id !== FallbackRecognizerKey; + }); + } + return recognizerConfigs .filter((r) => (typeof r.disabled === 'function' && !r.disabled(shellData, shellApi)) || !r.disabled) .sort((r1, r2) => { diff --git a/Composer/packages/client/src/components/AppComponents/SideBar.tsx b/Composer/packages/client/src/components/AppComponents/SideBar.tsx index c0028aeb86..858fd10f74 100644 --- a/Composer/packages/client/src/components/AppComponents/SideBar.tsx +++ b/Composer/packages/client/src/components/AppComponents/SideBar.tsx @@ -16,6 +16,7 @@ import { BASEPATH } from '../../constants'; import { NavItem } from '../NavItem'; import TelemetryClient from '../../telemetry/TelemetryClient'; import { PageLink } from '../../utils/pageLinks'; +import { PVADisableFeature } from '../PVADisableFeature'; import { useLinks } from './../../utils/hooks'; @@ -92,10 +93,10 @@ export const SideBar: React.FC = () => {
{' '} {topLinks.map((link, index) => { - return ( + const navItem = ( = () => { to={mapNavItemTo(link.to)} /> ); + + if (link.isDisabledForPVA) { + return {navItem}; + } + return navItem; })}
diff --git a/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx b/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx index e4463f0d74..6fd7e1161f 100644 --- a/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx +++ b/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx @@ -12,7 +12,7 @@ import { css } from '@emotion/core'; import { NeutralColors, CommunicationColors } from '@uifabric/fluent-theme'; import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner'; -import { PVADisabler } from '../PVADisabler'; +import { PVADisableFeature } from '../PVADisableFeature'; import TelemetryClient from '../../telemetry/TelemetryClient'; import { buildConfigurationSelector, @@ -210,10 +210,8 @@ const BotController: React.FC = ({ onHideController, isContr return ; })}
- = ({ onHideController, isContr )} {startPanelButtonText} - +
{ return formatMessage('PVA bots cannot use this functionality at this time.'); }; -export const PVADisabler: React.FC<{ content?: string }> = (props) => { +export const PVADisableFeature: React.FC<{ content?: string; projectId?: string }> = (props) => { const rootBotId = useRecoilValue(rootBotProjectIdSelector); - const schema = useRecoilValue(schemasState(rootBotId ?? '')); + const schema = useRecoilValue(schemasState(props.projectId ?? rootBotId ?? '')); const [isPVABot, setIsPVABot] = useState(false); useEffect(() => { diff --git a/Composer/packages/client/src/components/ProjectTree/ProjectHeader.tsx b/Composer/packages/client/src/components/ProjectTree/ProjectHeader.tsx index 6a17eb65ad..cfe6f44c08 100644 --- a/Composer/packages/client/src/components/ProjectTree/ProjectHeader.tsx +++ b/Composer/packages/client/src/components/ProjectTree/ProjectHeader.tsx @@ -13,6 +13,7 @@ import { BotStatus } from '../../constants'; import { perProjectDiagnosticsSelectorFamily, botStatusState, rootBotProjectIdSelector } from '../../recoilModel'; import TelemetryClient from '../../telemetry/TelemetryClient'; import { createBotSettingUrl, navigateTo } from '../../utils/navigation'; +import { usePVACheck } from '../../hooks/usePVACheck'; import { isChildDialogLinkSelected, doesLinkMatch } from './helpers'; import { TreeItem } from './treeItem'; @@ -71,6 +72,7 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { const rootProjectId = useRecoilValue(rootBotProjectIdSelector) || ''; const status = useRecoilValue(botStatusState(projectId)); const diagnostics = useRecoilValue(perProjectDiagnosticsSelectorFamily(projectId)); + const isPVABot = usePVACheck(projectId); const isRunning = status === BotStatus.connected; const displayName = `${name} ${rootProjectId !== projectId ? `(${formatMessage('Skill')})` : ''}`; @@ -87,7 +89,7 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { }; const generateMenuItems = useCallback(() => { - const menuItems = [ + let menuItems = [ { label: formatMessage('Add a dialog'), icon: 'Add', @@ -95,6 +97,7 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { onBotCreateDialog(projectId); TelemetryClient.track('AddNewDialogStarted'); }, + isDisableForPVA: false, }, { label: isRunning ? formatMessage('Stop bot') : formatMessage('Start bot'), @@ -107,6 +110,7 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { isRoot: projectId === rootProjectId, }); }, + isDisableForPVA: true, }, { label: '', @@ -117,18 +121,21 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { onClick: () => { onBotEditManifest(projectId); }, + isDisableForPVA: true, }, { label: formatMessage('Export this bot as .zip'), onClick: () => { onBotExportZip(projectId); }, + isDisableForPVA: false, }, { label: formatMessage('Settings'), onClick: () => { navigateTo(createBotSettingUrl(link.projectId, link.skillId)); }, + isDisableForPVA: false, }, ]; @@ -138,6 +145,7 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { onBotRemoveSkill(projectId); }, }; + if (isRemote || botError) { return [removeSkillItem]; } @@ -145,6 +153,10 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { if (!isRootBot) { menuItems.splice(3, 0, removeSkillItem); } + + if (isPVABot) { + menuItems = menuItems.filter((item) => !item.isDisableForPVA); + } return menuItems; }, [projectId, isRunning]); diff --git a/Composer/packages/client/src/hooks/usePVACheck.ts b/Composer/packages/client/src/hooks/usePVACheck.ts new file mode 100644 index 0000000000..4423297715 --- /dev/null +++ b/Composer/packages/client/src/hooks/usePVACheck.ts @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { checkForPVASchema } from '@bfc/shared'; +import { useRecoilValue } from 'recoil'; + +import { schemasState } from '../recoilModel'; + +export const usePVACheck = (projectId: string) => { + const schema = useRecoilValue(schemasState(projectId)); + const isPVASchema = checkForPVASchema(schema.sdk); + return isPVASchema; +}; diff --git a/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx b/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx index a6402d08cc..935181fe66 100644 --- a/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx +++ b/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx @@ -4,15 +4,16 @@ /** @jsx jsx */ import { jsx, css } from '@emotion/core'; import { useRecoilValue } from 'recoil'; -import React, { useEffect, useState } from 'react'; +import React, { Fragment, useEffect, useState } from 'react'; import { RouteComponentProps } from '@reach/router'; import { Pivot, PivotItem } from 'office-ui-fabric-react/lib/components/Pivot'; import formatMessage from 'format-message'; -import { Label } from 'office-ui-fabric-react/lib/Label'; import { IButtonProps } from 'office-ui-fabric-react/lib/Button'; +import { NeutralColors } from '@uifabric/fluent-theme'; import { localBotsDataSelector } from '../../recoilModel/selectors/project'; -import { PVADisabler } from '../../components/PVADisabler'; +import { PVADisableFeature } from '../../components/PVADisableFeature'; +import { usePVACheck } from '../../hooks/usePVACheck'; import { BotSkillConfiguration } from './BotSkillConfiguration'; import { BotProjectInfo } from './BotProjectInfo'; @@ -33,7 +34,11 @@ const container = css` const disabledPivotStyle: IButtonProps = { disabled: true, - style: { pointerEvents: 'unset', cursor: 'no-drop' }, + style: { + pointerEvents: 'unset', + cursor: 'not-allowed', + color: `${NeutralColors.gray100}`, + }, }; const idsInTab: Record = { @@ -63,6 +68,7 @@ export const BotProjectSettingsTabView: React.FC b.projectId === projectId); const isRootBot = !!botProject?.isRootBot; const [selectedKey, setSelectedKey] = useState(PivotItemKey.Basics); + const isPVABot = usePVACheck(projectId); useEffect(() => { if (scrollToSectionId) { @@ -91,13 +97,15 @@ export const BotProjectSettingsTabView: React.FC ( - - - - )} + onRenderItemLink={() => { + if (isPVABot) { + return {formatMessage('LUIS and QnA')}; + } else { + return {formatMessage('LUIS and QnA')}; + } + }} > @@ -112,11 +120,15 @@ export const BotProjectSettingsTabView: React.FC ( - - - - )} + onRenderItemLink={() => { + if (isPVABot) { + return ( + {formatMessage('Skill Configuration')} + ); + } else { + return {formatMessage('Skill Configuration')}; + } + }} > {isRootBot && } diff --git a/Composer/packages/client/src/pages/botProject/runtime-settings/RuntimeSettings.tsx b/Composer/packages/client/src/pages/botProject/runtime-settings/RuntimeSettings.tsx index 1abbf8f85b..4e9cb260e0 100644 --- a/Composer/packages/client/src/pages/botProject/runtime-settings/RuntimeSettings.tsx +++ b/Composer/packages/client/src/pages/botProject/runtime-settings/RuntimeSettings.tsx @@ -29,6 +29,8 @@ import { import { LoadingSpinner } from '../../../components/LoadingSpinner'; import TelemetryClient from '../../../telemetry/TelemetryClient'; import { subtitle, errorContainer, errorTextStyle, errorIcon, customError } from '../styles'; +import { PVADisableFeature } from '../../../components/PVADisableFeature'; +import { usePVACheck } from '../../../hooks/usePVACheck'; import { EjectModal } from './ejectModal'; import { WorkingModal } from './workingModal'; @@ -50,6 +52,7 @@ export const RuntimeSettings: React.FC (
- + + +
); diff --git a/Composer/packages/client/src/recoilModel/selectors/project.ts b/Composer/packages/client/src/recoilModel/selectors/project.ts index c5d50e11e4..6d79fe2141 100644 --- a/Composer/packages/client/src/recoilModel/selectors/project.ts +++ b/Composer/packages/client/src/recoilModel/selectors/project.ts @@ -424,8 +424,14 @@ export const outputsDebugPanelSelector = selector({ key: 'outputsDebugPanelSelector', get: ({ get }) => { const projectIds: string[] = get(botProjectIdsState); - return projectIds.map((projectId) => { - return get(webChatEssentialsSelector(projectId)); + const filteredProjects: WebChatEssentials[] = []; + projectIds.forEach((projectId: string) => { + const { isRemote } = get(projectMetaDataState(projectId)); + if (!isRemote) { + const data = get(webChatEssentialsSelector(projectId)); + filteredProjects.push(data); + } }); + return filteredProjects; }, }); diff --git a/Composer/packages/client/src/utils/pageLinks.ts b/Composer/packages/client/src/utils/pageLinks.ts index 9ee6598b75..0cd4f0dc17 100644 --- a/Composer/packages/client/src/utils/pageLinks.ts +++ b/Composer/packages/client/src/utils/pageLinks.ts @@ -2,7 +2,6 @@ // Licensed under the MIT License. import formatMessage from 'format-message'; import { ExtensionPageContribution } from '@bfc/extension-client'; -import { checkForPVASchema } from '@bfc/shared'; export type ExtensionPageConfig = ExtensionPageContribution & { id: string }; @@ -12,6 +11,7 @@ export type PageLink = { labelName: string; disabled: boolean; match?: RegExp; + isDisabledForPVA: boolean; }; export const topLinks = ( @@ -28,12 +28,13 @@ export const topLinks = ( ? `/bot/${projectId}/` : `/bot/${rootProjectId}/skill/${projectId}/`; - let links: PageLink[] = [ + const links: PageLink[] = [ { to: '/home', iconName: 'Home', labelName: formatMessage('Home'), disabled: false, + isDisabledForPVA: false, }, { to: linkBase + `dialogs/${openedDialogId}`, @@ -41,6 +42,7 @@ export const topLinks = ( labelName: formatMessage('Design'), disabled: !botLoaded, match: /(bot\/[0-9.]+)$|(bot\/[0-9.]+\/skill\/[0-9.]+)$/, + isDisabledForPVA: false, }, { to: linkBase + `language-generation/${openedDialogId}`, @@ -48,6 +50,7 @@ export const topLinks = ( labelName: formatMessage('Bot responses'), disabled: !botLoaded, match: /language-generation\/[a-zA-Z0-9_-]+$/, + isDisabledForPVA: false, }, { to: linkBase + `language-understanding/${openedDialogId}`, @@ -55,6 +58,7 @@ export const topLinks = ( labelName: formatMessage('User input'), disabled: !botLoaded, match: /language-understanding\/[a-zA-Z0-9_-]+$/, + isDisabledForPVA: false, }, { to: linkBase + `knowledge-base/${openedDialogId}`, @@ -62,6 +66,7 @@ export const topLinks = ( labelName: formatMessage('QnA'), disabled: !botLoaded, match: /knowledge-base\/[a-zA-Z0-9_-]+$/, + isDisabledForPVA: true, }, { to: `/bot/${rootProjectId || projectId}/diagnostics`, @@ -69,12 +74,14 @@ export const topLinks = ( labelName: formatMessage('Diagnostics'), disabled: !botLoaded, match: /diagnostics/, + isDisabledForPVA: false, }, { to: `/bot/${rootProjectId || projectId}/publish`, iconName: 'CloudUpload', labelName: formatMessage('Publish'), disabled: !botLoaded, + isDisabledForPVA: false, }, { to: `/bot/${rootProjectId || projectId}/botProjectsSettings`, @@ -82,6 +89,7 @@ export const topLinks = ( labelName: formatMessage('Project settings'), disabled: !botLoaded, match: /botProjectsSettings/, + isDisabledForPVA: false, }, ...(showFormDialog ? [ @@ -90,23 +98,24 @@ export const topLinks = ( iconName: 'Table', labelName: formatMessage('Forms (preview)'), disabled: !botLoaded, + isDisabledForPVA: false, }, ] : []), ]; - // TODO: refactor when Composer can better model the left nav based on schema - if (schema && checkForPVASchema(schema)) { - links = links.filter((link) => link.to.indexOf('/knowledge-base') == -1 && link.to.indexOf('/skills') == -1); - } - if (pluginPages.length > 0) { pluginPages.forEach((p) => { + let disablePluginForPva = false; + if (p.bundleId === 'package-manager') { + disablePluginForPva = true; + } links.push({ to: `/bot/${projectId}/plugin/${p.id}/${p.bundleId}`, iconName: p.icon ?? 'StatusCircleQuestionMark', labelName: p.label, disabled: !projectId, + isDisabledForPVA: disablePluginForPva, }); }); } @@ -120,6 +129,7 @@ export const bottomLinks: PageLink[] = [ iconName: 'Settings', labelName: formatMessage('Composer settings'), disabled: false, + isDisabledForPVA: false, }, // { // to: `/extensions`, From 71969d24d9b8684c10befa11c9dc0b6e8022f183 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 15:32:15 -0700 Subject: [PATCH 04/12] Updated tests Signed-off-by: Srinaath Ravichandran --- .../BotRuntimeController/BotController.tsx | 1 - .../src/components/PVADisableFeature.tsx | 4 +- .../__tests__/PVADisableFeature.test.tsx | 54 +++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 Composer/packages/client/src/components/__tests__/PVADisableFeature.test.tsx diff --git a/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx b/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx index 6fd7e1161f..1832732404 100644 --- a/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx +++ b/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx @@ -227,7 +227,6 @@ const BotController: React.FC = ({ onHideController, isContr }, }, }} - id={'startbot'} menuAs={() => null} styles={{ root: { diff --git a/Composer/packages/client/src/components/PVADisableFeature.tsx b/Composer/packages/client/src/components/PVADisableFeature.tsx index 55e17633d0..8701bcd927 100644 --- a/Composer/packages/client/src/components/PVADisableFeature.tsx +++ b/Composer/packages/client/src/components/PVADisableFeature.tsx @@ -25,7 +25,7 @@ export const PVADisableFeature: React.FC<{ content?: string; projectId?: string setIsPVABot(checkForPVASchema(schema.sdk)); }, [rootBotId]); - const tooltipId = useId('tooltip'); + const tooltipId = useId('pva-disable-tooltip'); if (!isPVABot) { return <>{props.children}; @@ -35,8 +35,6 @@ export const PVADisableFeature: React.FC<{ content?: string; projectId?: string diff --git a/Composer/packages/client/src/components/__tests__/PVADisableFeature.test.tsx b/Composer/packages/client/src/components/__tests__/PVADisableFeature.test.tsx new file mode 100644 index 0000000000..346293c171 --- /dev/null +++ b/Composer/packages/client/src/components/__tests__/PVADisableFeature.test.tsx @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import * as React from 'react'; + +import { renderWithRecoil } from '../../../__tests__/testUtils/renderWithRecoil'; +import { PVADisableFeature } from '../PVADisableFeature'; +import { schemasState } from '../../recoilModel'; + +describe('', () => { + const projectId = '123a.324'; + + it('should wrap the element with a tooltip for PVA bot', async () => { + const { container } = renderWithRecoil( + + Test element + , + ({ set }) => { + set(schemasState(projectId), { + sdk: { + content: { + definitions: { + 'Microsoft.VirtualAgents.Recognizer': true, + }, + }, + }, + }); + } + ); + const tooltipElement = container.querySelector('#pva-disable-tooltip0'); + expect(tooltipElement).toBeDefined(); + }); + + it('should not wrap the element with a tooltip for non PVA bot', async () => { + const { container } = renderWithRecoil( + + Test element + , + ({ set }) => { + set(schemasState(projectId), { + sdk: { + content: { + definitions: { + 'Microsoft.VirtualAgents.OrchestratorRecognizer': true, + }, + }, + }, + }); + } + ); + const tooltipElement = container.querySelector('#pva-disable-tooltip0'); + expect(tooltipElement).toBeNull(); + }); +}); From 4978bc07af8293ee2a5fd241bc70ed5539e65608 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 16:47:20 -0700 Subject: [PATCH 05/12] Remove inline block Signed-off-by: Srinaath Ravichandran --- .../client/src/components/PVADisableFeature.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Composer/packages/client/src/components/PVADisableFeature.tsx b/Composer/packages/client/src/components/PVADisableFeature.tsx index 8701bcd927..0900e435d2 100644 --- a/Composer/packages/client/src/components/PVADisableFeature.tsx +++ b/Composer/packages/client/src/components/PVADisableFeature.tsx @@ -3,14 +3,13 @@ import { checkForPVASchema } from '@bfc/shared'; import { useId } from '@uifabric/react-hooks'; import formatMessage from 'format-message'; -import { TooltipHost, ITooltipHostStyles } from 'office-ui-fabric-react/lib/Tooltip'; +import { TooltipHost } from 'office-ui-fabric-react/lib/Tooltip'; import React, { useEffect, useState } from 'react'; import { useRecoilValue } from 'recoil'; import { rootBotProjectIdSelector, schemasState } from '../recoilModel'; const calloutProps = { gapSpace: 0 }; -const hostStyles: Partial = { root: { display: 'inline-block' } }; const genericDisableMessage = () => { return formatMessage('PVA bots cannot use this functionality at this time.'); @@ -32,12 +31,7 @@ export const PVADisableFeature: React.FC<{ content?: string; projectId?: string } return ( - + {props.children} ); From 688801ebb7f8e9233d8c770660c9fa1944ba8106 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 17:35:04 -0700 Subject: [PATCH 06/12] Updated pagelinks Signed-off-by: Srinaath Ravichandran --- .../pages/botProject/BotProjectsSettingsTabView.tsx | 12 ++++++++++-- Composer/packages/client/src/utils/pageLinks.ts | 6 ++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx b/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx index 3baa3b523c..32c070aebe 100644 --- a/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx +++ b/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx @@ -100,7 +100,7 @@ export const BotProjectSettingsTabView: React.FC { @@ -115,14 +115,22 @@ export const BotProjectSettingsTabView: React.FC { + if (isPVABot) { + return {formatMessage('Connections')}; + } else { + return {formatMessage('Connections')}; + } + }} > {isRootBot && } { if (isPVABot) { diff --git a/Composer/packages/client/src/utils/pageLinks.ts b/Composer/packages/client/src/utils/pageLinks.ts index 0cd4f0dc17..a3d550d315 100644 --- a/Composer/packages/client/src/utils/pageLinks.ts +++ b/Composer/packages/client/src/utils/pageLinks.ts @@ -2,6 +2,7 @@ // Licensed under the MIT License. import formatMessage from 'format-message'; import { ExtensionPageContribution } from '@bfc/extension-client'; +import { checkForPVASchema } from '@bfc/shared'; export type ExtensionPageConfig = ExtensionPageContribution & { id: string }; @@ -22,6 +23,7 @@ export const topLinks = ( schema: any, rootProjectId?: string ) => { + const isPVASchema = checkForPVASchema(schema); const botLoaded = !!projectId; const linkBase = projectId === rootProjectId || rootProjectId == null @@ -66,7 +68,7 @@ export const topLinks = ( labelName: formatMessage('QnA'), disabled: !botLoaded, match: /knowledge-base\/[a-zA-Z0-9_-]+$/, - isDisabledForPVA: true, + isDisabledForPVA: isPVASchema, }, { to: `/bot/${rootProjectId || projectId}/diagnostics`, @@ -107,7 +109,7 @@ export const topLinks = ( if (pluginPages.length > 0) { pluginPages.forEach((p) => { let disablePluginForPva = false; - if (p.bundleId === 'package-manager') { + if (p.bundleId === 'package-manager' && isPVASchema) { disablePluginForPva = true; } links.push({ From b98d9b64244c2e5f0ae5b2bfd14cc57736702f89 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 17:48:48 -0700 Subject: [PATCH 07/12] Hide manage connections Signed-off-by: Srinaath Ravichandran --- .../pages/botProject/BotProjectSettings.tsx | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx b/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx index 9704ff69a2..665fd2869d 100644 --- a/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx +++ b/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx @@ -21,6 +21,7 @@ import { settingsState, userSettingsState } from '../../recoilModel/atoms'; import { localBotsDataSelector, rootBotProjectIdSelector } from '../../recoilModel/selectors/project'; import { createBotSettingUrl, navigateTo } from '../../utils/navigation'; import { mergePropertiesManagedByRootBot } from '../../recoilModel/dispatchers/utils/project'; +import { usePVACheck } from '../../hooks/usePVACheck'; import { openDeleteBotModal } from './DeleteBotButton'; import { BotProjectSettingsTabView } from './BotProjectsSettingsTabView'; @@ -53,6 +54,8 @@ const BotProjectSettings: React.FC b.projectId === currentProjectId); const { deleteBot } = useRecoilValue(dispatcherState); + const isPVABot = usePVACheck(currentProjectId); + console.log(isPVABot); const settings = useRecoilValue(settingsState(currentProjectId)); const mergedSettings = mergePropertiesManagedByRootBot(currentProjectId, rootBotProjectId, settings); @@ -103,16 +106,20 @@ const BotProjectSettings: React.FC buttonClick(linkToConnections), - styles: defaultToolbarButtonStyles, - }, - align: 'left', - }, + ...(!isPVABot + ? [ + { + text: formatMessage('Manage connections'), + type: 'action', + buttonProps: { + iconProps: { iconName: 'PlugConnected' }, + onClick: () => buttonClick(linkToConnections), + styles: defaultToolbarButtonStyles, + }, + align: 'left', + }, + ] + : []), { text: formatMessage('Delete bot'), type: 'action', From a9371b866f50f1d79db87bdc6ec99e74f62ceed7 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 18:02:10 -0700 Subject: [PATCH 08/12] Disable add skill button Signed-off-by: Srinaath Ravichandran --- .../src/components/PVADisableFeature.tsx | 11 ++--- .../ProjectTree/ProjectTreeHeader.tsx | 48 ++++++++++++------- .../client/src/pages/design/SideBar.tsx | 1 + 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/Composer/packages/client/src/components/PVADisableFeature.tsx b/Composer/packages/client/src/components/PVADisableFeature.tsx index 0900e435d2..f079c2c3f1 100644 --- a/Composer/packages/client/src/components/PVADisableFeature.tsx +++ b/Composer/packages/client/src/components/PVADisableFeature.tsx @@ -7,7 +7,8 @@ import { TooltipHost } from 'office-ui-fabric-react/lib/Tooltip'; import React, { useEffect, useState } from 'react'; import { useRecoilValue } from 'recoil'; -import { rootBotProjectIdSelector, schemasState } from '../recoilModel'; +import { usePVACheck } from '../hooks/usePVACheck'; +import { rootBotProjectIdSelector } from '../recoilModel'; const calloutProps = { gapSpace: 0 }; @@ -17,12 +18,8 @@ const genericDisableMessage = () => { export const PVADisableFeature: React.FC<{ content?: string; projectId?: string }> = (props) => { const rootBotId = useRecoilValue(rootBotProjectIdSelector); - const schema = useRecoilValue(schemasState(props.projectId ?? rootBotId ?? '')); - const [isPVABot, setIsPVABot] = useState(false); - - useEffect(() => { - setIsPVABot(checkForPVASchema(schema.sdk)); - }, [rootBotId]); + const currentProjectId = props.projectId ?? rootBotId ?? ''; + const isPVABot = usePVACheck(currentProjectId); const tooltipId = useId('pva-disable-tooltip'); diff --git a/Composer/packages/client/src/components/ProjectTree/ProjectTreeHeader.tsx b/Composer/packages/client/src/components/ProjectTree/ProjectTreeHeader.tsx index c1ba488426..b45ad4d173 100644 --- a/Composer/packages/client/src/components/ProjectTree/ProjectTreeHeader.tsx +++ b/Composer/packages/client/src/components/ProjectTree/ProjectTreeHeader.tsx @@ -9,6 +9,11 @@ import formatMessage from 'format-message'; import { CommandButton } from 'office-ui-fabric-react/lib/Button'; import { IOverflowSetItemProps } from 'office-ui-fabric-react/lib/OverflowSet'; import { ISearchBox, ISearchBoxStyles, SearchBox } from 'office-ui-fabric-react/lib/SearchBox'; +import { useRecoilValue } from 'recoil'; + +import { PVADisableFeature } from '../PVADisableFeature'; +import { usePVACheck } from '../../hooks/usePVACheck'; +import { rootBotProjectIdSelector } from '../../recoilModel'; const searchBox: ISearchBoxStyles = { root: { @@ -64,6 +69,8 @@ export const ProjectTreeHeader: React.FC = ({ }) => { const [showFilter, setShowFilter] = useState(false); const searchBoxRef = useRef(null); + const rootBotId = useRecoilValue(rootBotProjectIdSelector) ?? ''; + const isPVABot = usePVACheck(rootBotId); useEffect(() => { if (showFilter && searchBoxRef.current) { @@ -90,6 +97,26 @@ export const ProjectTreeHeader: React.FC = ({ setShowFilter(false); }; + const addCommandBtn = ( + { + if (e.key === 'Enter') { + e.stopPropagation(); + } + }} + /> + ); + return (
{showFilter ? ( @@ -106,22 +133,11 @@ export const ProjectTreeHeader: React.FC = ({ ) : (
{overflowMenu.length ? ( - { - if (e.key === 'Enter') { - e.stopPropagation(); - } - }} - /> + isPVABot ? ( + {addCommandBtn} + ) : ( + addCommandBtn + ) ) : null} = React.memo(({ projectId }) => { updateZoomRate, deleteTrigger, } = useRecoilValue(dispatcherState); + const skillUsedInBotsMap = useRecoilValue(skillUsedInBotsSelector); const selected = decodeDesignerPathToArrayPath( dialogs.find((x) => x.id === dialogId)?.content, From d8a733854e1a3f90c42c8d4372bba82b579ee843 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 18:05:12 -0700 Subject: [PATCH 09/12] Disable add a package header Signed-off-by: Srinaath Ravichandran --- .../pages/botProject/BotProjectSettings.tsx | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx b/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx index 665fd2869d..3df36e2426 100644 --- a/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx +++ b/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx @@ -55,7 +55,6 @@ const BotProjectSettings: React.FC b.projectId === currentProjectId); const { deleteBot } = useRecoilValue(dispatcherState); const isPVABot = usePVACheck(currentProjectId); - console.log(isPVABot); const settings = useRecoilValue(settingsState(currentProjectId)); const mergedSettings = mergePropertiesManagedByRootBot(currentProjectId, rootBotProjectId, settings); @@ -76,16 +75,20 @@ const BotProjectSettings: React.FC buttonClick(linkToPackageManager), - styles: defaultToolbarButtonStyles, - }, - align: 'left', - }, + ...(!isPVABot + ? [ + { + text: formatMessage('Add a package'), + type: 'action', + buttonProps: { + iconProps: { iconName: 'Package' }, + onClick: () => buttonClick(linkToPackageManager), + styles: defaultToolbarButtonStyles, + }, + align: 'left', + }, + ] + : []), { text: formatMessage('Edit LG'), type: 'action', From 56a177ece998ede0c102a645ee11798d6d47147e Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 18:09:45 -0700 Subject: [PATCH 10/12] Remove unused refs Signed-off-by: Srinaath Ravichandran --- Composer/packages/client/src/components/PVADisableFeature.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Composer/packages/client/src/components/PVADisableFeature.tsx b/Composer/packages/client/src/components/PVADisableFeature.tsx index f079c2c3f1..769c21d74c 100644 --- a/Composer/packages/client/src/components/PVADisableFeature.tsx +++ b/Composer/packages/client/src/components/PVADisableFeature.tsx @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { checkForPVASchema } from '@bfc/shared'; + import { useId } from '@uifabric/react-hooks'; import formatMessage from 'format-message'; import { TooltipHost } from 'office-ui-fabric-react/lib/Tooltip'; -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { useRecoilValue } from 'recoil'; import { usePVACheck } from '../hooks/usePVACheck'; From 8a719eb0b67b77a793e6b87df2906da48fe90f08 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 20:58:16 -0700 Subject: [PATCH 11/12] Rename component Signed-off-by: Srinaath Ravichandran --- .../fields/RecognizerField/getDropdownOptions.ts | 2 +- .../client/src/components/AppComponents/SideBar.tsx | 9 +++++++-- .../BotRuntimeController/BotController.tsx | 9 ++++++--- ...DisableFeature.tsx => DisableFeatureToolTip.tsx} | 13 +++---------- .../components/ProjectTree/ProjectTreeHeader.tsx | 8 ++------ ...ture.test.tsx => DisableFeatureToolTip.test.tsx} | 12 ++++++------ .../pages/botProject/BotProjectsSettingsTabView.tsx | 10 ++++++---- .../botProject/runtime-settings/RuntimeSettings.tsx | 6 +++--- 8 files changed, 34 insertions(+), 35 deletions(-) rename Composer/packages/client/src/components/{PVADisableFeature.tsx => DisableFeatureToolTip.tsx} (52%) rename Composer/packages/client/src/components/__tests__/{PVADisableFeature.test.tsx => DisableFeatureToolTip.test.tsx} (83%) diff --git a/Composer/packages/adaptive-form/src/components/fields/RecognizerField/getDropdownOptions.ts b/Composer/packages/adaptive-form/src/components/fields/RecognizerField/getDropdownOptions.ts index e5c0c51ff4..09fad911d5 100644 --- a/Composer/packages/adaptive-form/src/components/fields/RecognizerField/getDropdownOptions.ts +++ b/Composer/packages/adaptive-form/src/components/fields/RecognizerField/getDropdownOptions.ts @@ -18,7 +18,7 @@ const getRankScore = (r: RecognizerSchema, shellData: ShellData, shellApi: Shell }; export const getDropdownOptions = (configs: RecognizerSchema[], shellData: ShellData, shellApi: ShellApi) => { - const isPVASchema = checkForPVASchema(shellData.schemas.sdk); + const isPVASchema = checkForPVASchema(shellData.schemas?.sdk); let recognizerConfigs: RecognizerSchema[] = configs; if (isPVASchema) { recognizerConfigs = recognizerConfigs.filter((config) => { diff --git a/Composer/packages/client/src/components/AppComponents/SideBar.tsx b/Composer/packages/client/src/components/AppComponents/SideBar.tsx index 858fd10f74..1f55ab2e76 100644 --- a/Composer/packages/client/src/components/AppComponents/SideBar.tsx +++ b/Composer/packages/client/src/components/AppComponents/SideBar.tsx @@ -10,13 +10,16 @@ import { IconButton } from 'office-ui-fabric-react/lib/Button'; import { FocusZone } from 'office-ui-fabric-react/lib/FocusZone'; import { TooltipHost, DirectionalHint } from 'office-ui-fabric-react/lib/Tooltip'; import { RouteComponentProps } from '@reach/router'; +import { useRecoilValue } from 'recoil'; import { resolveToBasePath } from '../../utils/fileUtil'; import { BASEPATH } from '../../constants'; import { NavItem } from '../NavItem'; import TelemetryClient from '../../telemetry/TelemetryClient'; import { PageLink } from '../../utils/pageLinks'; -import { PVADisableFeature } from '../PVADisableFeature'; +import { DisableFeatureToolTip } from '../DisableFeatureToolTip'; +import { currentProjectIdState } from '../../recoilModel'; +import { usePVACheck } from '../../hooks/usePVACheck'; import { useLinks } from './../../utils/hooks'; @@ -67,6 +70,8 @@ const divider = (isExpand: boolean) => css` // -------------------- SideBar -------------------- // export const SideBar: React.FC = () => { + const projectId = useRecoilValue(currentProjectIdState); + const isPVABot = usePVACheck(projectId); const [sideBarExpand, setSideBarExpand] = useState(false); const { topLinks, bottomLinks } = useLinks(); @@ -106,7 +111,7 @@ export const SideBar: React.FC = () => { ); if (link.isDisabledForPVA) { - return {navItem}; + return {navItem}; } return navItem; })} diff --git a/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx b/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx index 1832732404..e68921813b 100644 --- a/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx +++ b/Composer/packages/client/src/components/BotRuntimeController/BotController.tsx @@ -12,7 +12,7 @@ import { css } from '@emotion/core'; import { NeutralColors, CommunicationColors } from '@uifabric/fluent-theme'; import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner'; -import { PVADisableFeature } from '../PVADisableFeature'; +import { DisableFeatureToolTip } from '../DisableFeatureToolTip'; import TelemetryClient from '../../telemetry/TelemetryClient'; import { buildConfigurationSelector, @@ -23,6 +23,7 @@ import { } from '../../recoilModel'; import { BotStatus } from '../../constants'; import { useClickOutsideOutsideTarget } from '../../utils/hooks'; +import { usePVACheck } from '../../hooks/usePVACheck'; import { BotControllerMenu } from './BotControllerMenu'; import { useBotOperations } from './useBotOperations'; @@ -77,6 +78,7 @@ const BotController: React.FC = ({ onHideController, isContr const { startAllBots, stopAllBots } = useBotOperations(); const builderEssentials = useRecoilValue(buildConfigurationSelector); const rootBotId = useRecoilValue(rootBotProjectIdSelector); + const isPVABot = usePVACheck(rootBotId ?? ''); const startPanelTarget = useRef(null); const botControllerMenuTarget = useRef(null); @@ -210,8 +212,9 @@ const BotController: React.FC = ({ onHideController, isContr return ; })}
- = ({ onHideController, isContr )} {startPanelButtonText} - +
{ return formatMessage('PVA bots cannot use this functionality at this time.'); }; -export const PVADisableFeature: React.FC<{ content?: string; projectId?: string }> = (props) => { - const rootBotId = useRecoilValue(rootBotProjectIdSelector); - const currentProjectId = props.projectId ?? rootBotId ?? ''; - const isPVABot = usePVACheck(currentProjectId); - +export const DisableFeatureToolTip: React.FC<{ content?: string; isPVABot: boolean }> = (props) => { + const { isPVABot, content } = props; const tooltipId = useId('pva-disable-tooltip'); if (!isPVABot) { @@ -28,7 +21,7 @@ export const PVADisableFeature: React.FC<{ content?: string; projectId?: string } return ( - + {props.children} ); diff --git a/Composer/packages/client/src/components/ProjectTree/ProjectTreeHeader.tsx b/Composer/packages/client/src/components/ProjectTree/ProjectTreeHeader.tsx index b45ad4d173..d036cdd70b 100644 --- a/Composer/packages/client/src/components/ProjectTree/ProjectTreeHeader.tsx +++ b/Composer/packages/client/src/components/ProjectTree/ProjectTreeHeader.tsx @@ -11,7 +11,7 @@ import { IOverflowSetItemProps } from 'office-ui-fabric-react/lib/OverflowSet'; import { ISearchBox, ISearchBoxStyles, SearchBox } from 'office-ui-fabric-react/lib/SearchBox'; import { useRecoilValue } from 'recoil'; -import { PVADisableFeature } from '../PVADisableFeature'; +import { DisableFeatureToolTip } from '../DisableFeatureToolTip'; import { usePVACheck } from '../../hooks/usePVACheck'; import { rootBotProjectIdSelector } from '../../recoilModel'; @@ -133,11 +133,7 @@ export const ProjectTreeHeader: React.FC = ({ ) : (
{overflowMenu.length ? ( - isPVABot ? ( - {addCommandBtn} - ) : ( - addCommandBtn - ) + {addCommandBtn} ) : null} ', () => { +describe('', () => { const projectId = '123a.324'; it('should wrap the element with a tooltip for PVA bot', async () => { const { container } = renderWithRecoil( - + Test element - , + , ({ set }) => { set(schemasState(projectId), { sdk: { @@ -33,9 +33,9 @@ describe('', () => { it('should not wrap the element with a tooltip for non PVA bot', async () => { const { container } = renderWithRecoil( - + Test element - , + , ({ set }) => { set(schemasState(projectId), { sdk: { diff --git a/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx b/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx index 32c070aebe..b3e7fb2836 100644 --- a/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx +++ b/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx @@ -12,7 +12,7 @@ import { IButtonProps } from 'office-ui-fabric-react/lib/Button'; import { NeutralColors } from '@uifabric/fluent-theme'; import { localBotsDataSelector } from '../../recoilModel/selectors/project'; -import { PVADisableFeature } from '../../components/PVADisableFeature'; +import { DisableFeatureToolTip } from '../../components/DisableFeatureToolTip'; import { usePVACheck } from '../../hooks/usePVACheck'; import { navigateTo } from '../../utils/navigation'; @@ -105,7 +105,7 @@ export const BotProjectSettingsTabView: React.FC { if (isPVABot) { - return {formatMessage('LUIS and QnA')}; + return {formatMessage('LUIS and QnA')}; } else { return {formatMessage('LUIS and QnA')}; } @@ -120,7 +120,7 @@ export const BotProjectSettingsTabView: React.FC { if (isPVABot) { - return {formatMessage('Connections')}; + return {formatMessage('Connections')}; } else { return {formatMessage('Connections')}; } @@ -135,7 +135,9 @@ export const BotProjectSettingsTabView: React.FC { if (isPVABot) { return ( - {formatMessage('Skill Configuration')} + + {formatMessage('Skill Configuration')} + ); } else { return {formatMessage('Skill Configuration')}; diff --git a/Composer/packages/client/src/pages/botProject/runtime-settings/RuntimeSettings.tsx b/Composer/packages/client/src/pages/botProject/runtime-settings/RuntimeSettings.tsx index 4e9cb260e0..e17503b679 100644 --- a/Composer/packages/client/src/pages/botProject/runtime-settings/RuntimeSettings.tsx +++ b/Composer/packages/client/src/pages/botProject/runtime-settings/RuntimeSettings.tsx @@ -29,7 +29,7 @@ import { import { LoadingSpinner } from '../../../components/LoadingSpinner'; import TelemetryClient from '../../../telemetry/TelemetryClient'; import { subtitle, errorContainer, errorTextStyle, errorIcon, customError } from '../styles'; -import { PVADisableFeature } from '../../../components/PVADisableFeature'; +import { DisableFeatureToolTip } from '../../../components/DisableFeatureToolTip'; import { usePVACheck } from '../../../hooks/usePVACheck'; import { EjectModal } from './ejectModal'; @@ -149,7 +149,7 @@ export const RuntimeSettings: React.FC (
- + - +
); From b8ac858bec17eadbafb0cf125289a65731e44137 Mon Sep 17 00:00:00 2001 From: Srinaath Ravichandran Date: Mon, 19 Apr 2021 21:39:52 -0700 Subject: [PATCH 12/12] test name update Signed-off-by: Srinaath Ravichandran --- .../src/components/__tests__/DisableFeatureToolTip.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Composer/packages/client/src/components/__tests__/DisableFeatureToolTip.test.tsx b/Composer/packages/client/src/components/__tests__/DisableFeatureToolTip.test.tsx index 80b8c1a02a..5a0db8ab66 100644 --- a/Composer/packages/client/src/components/__tests__/DisableFeatureToolTip.test.tsx +++ b/Composer/packages/client/src/components/__tests__/DisableFeatureToolTip.test.tsx @@ -7,7 +7,7 @@ import { renderWithRecoil } from '../../../__tests__/testUtils/renderWithRecoil' import { DisableFeatureToolTip } from '../DisableFeatureToolTip'; import { schemasState } from '../../recoilModel'; -describe('', () => { +describe('', () => { const projectId = '123a.324'; it('should wrap the element with a tooltip for PVA bot', async () => {