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..09fad911d5 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..1f55ab2e76 100644 --- a/Composer/packages/client/src/components/AppComponents/SideBar.tsx +++ b/Composer/packages/client/src/components/AppComponents/SideBar.tsx @@ -10,12 +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 { DisableFeatureToolTip } from '../DisableFeatureToolTip'; +import { currentProjectIdState } from '../../recoilModel'; +import { usePVACheck } from '../../hooks/usePVACheck'; import { useLinks } from './../../utils/hooks'; @@ -66,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(); @@ -92,10 +98,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 2be2e72540..e68921813b 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 { DisableFeatureToolTip } from '../DisableFeatureToolTip'; import TelemetryClient from '../../telemetry/TelemetryClient'; import { buildConfigurationSelector, @@ -22,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'; @@ -76,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); @@ -209,60 +212,64 @@ 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} - + }, + }} + 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} + +
{ + return formatMessage('PVA bots cannot use this functionality at this time.'); +}; + +export const DisableFeatureToolTip: React.FC<{ content?: string; isPVABot: boolean }> = (props) => { + const { isPVABot, content } = props; + const tooltipId = useId('pva-disable-tooltip'); + + if (!isPVABot) { + return <>{props.children}; + } + + return ( + + {props.children} + + ); +}; diff --git a/Composer/packages/client/src/components/Header.tsx b/Composer/packages/client/src/components/Header.tsx index cae3140192..2f4b4ccfd6 100644 --- a/Composer/packages/client/src/components/Header.tsx +++ b/Composer/packages/client/src/components/Header.tsx @@ -8,7 +8,6 @@ import { IconButton, IButtonStyles } from 'office-ui-fabric-react/lib/Button'; import { Callout, DirectionalHint } from 'office-ui-fabric-react/lib/Callout'; import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; import { FocusTrapZone } from 'office-ui-fabric-react/lib/FocusTrapZone'; -import { checkForPVASchema } from '@bfc/shared'; import { useCallback, useState, Fragment, useMemo, useEffect } from 'react'; import { NeutralColors, SharedColors, FontSizes, CommunicationColors } from '@uifabric/fluent-theme'; import { useRecoilValue } from 'recoil'; @@ -18,7 +17,6 @@ import { TeachingBubble } from 'office-ui-fabric-react/lib/TeachingBubble'; import { useLocation } from '../utils/hooks'; import { BASEPATH } from '../constants'; -import { schemasState } from '../recoilModel/atoms'; import { dispatcherState, appUpdateState, @@ -162,7 +160,6 @@ export const Header = () => { 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 && (
{ 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')})` : ''}`; @@ -85,7 +87,7 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { }; const generateMenuItems = useCallback(() => { - const menuItems = [ + let menuItems = [ { label: formatMessage('Add a dialog'), icon: 'Add', @@ -93,6 +95,7 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { onBotCreateDialog(projectId); TelemetryClient.track('AddNewDialogStarted'); }, + isDisableForPVA: false, }, { label: isRunning ? formatMessage('Stop bot') : formatMessage('Start bot'), @@ -105,6 +108,7 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { isRoot: projectId === rootProjectId, }); }, + isDisableForPVA: true, }, { label: '', @@ -115,18 +119,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, }, ]; @@ -136,6 +143,7 @@ export const ProjectHeader = (props: ProjectHeaderProps) => { onBotRemoveSkill(projectId); }, }; + if (isRemote || botError) { return [removeSkillItem]; } @@ -143,6 +151,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/components/ProjectTree/ProjectTreeHeader.tsx b/Composer/packages/client/src/components/ProjectTree/ProjectTreeHeader.tsx index c1ba488426..d036cdd70b 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 { DisableFeatureToolTip } from '../DisableFeatureToolTip'; +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,7 @@ export const ProjectTreeHeader: React.FC = ({ ) : (
{overflowMenu.length ? ( - { - if (e.key === 'Enter') { - e.stopPropagation(); - } - }} - /> + {addCommandBtn} ) : null} ', () => { + 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(); + }); +}); 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/BotProjectSettings.tsx b/Composer/packages/client/src/pages/botProject/BotProjectSettings.tsx index 9704ff69a2..3df36e2426 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,7 @@ const BotProjectSettings: React.FC b.projectId === currentProjectId); const { deleteBot } = useRecoilValue(dispatcherState); + const isPVABot = usePVACheck(currentProjectId); const settings = useRecoilValue(settingsState(currentProjectId)); const mergedSettings = mergePropertiesManagedByRootBot(currentProjectId, rootBotProjectId, settings); @@ -73,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', @@ -103,16 +109,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', diff --git a/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx b/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx index 7facf877a0..b3e7fb2836 100644 --- a/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx +++ b/Composer/packages/client/src/pages/botProject/BotProjectsSettingsTabView.tsx @@ -4,12 +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 { IButtonProps } from 'office-ui-fabric-react/lib/Button'; +import { NeutralColors } from '@uifabric/fluent-theme'; import { localBotsDataSelector } from '../../recoilModel/selectors/project'; +import { DisableFeatureToolTip } from '../../components/DisableFeatureToolTip'; +import { usePVACheck } from '../../hooks/usePVACheck'; import { navigateTo } from '../../utils/navigation'; import { BotSkillConfiguration } from './BotSkillConfiguration'; @@ -29,6 +33,15 @@ const container = css` height: 100%; `; +const disabledPivotStyle: IButtonProps = { + disabled: true, + style: { + pointerEvents: 'unset', + cursor: 'not-allowed', + color: `${NeutralColors.gray100}`, + }, +}; + const idsInTab: Record = { Basics: ['runtimeSettings'], LuisQna: ['luisKey', 'qnaKey', 'luisRegion'], @@ -56,6 +69,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) { @@ -84,20 +98,51 @@ export const BotProjectSettingsTabView: React.FC - + { + if (isPVABot) { + return {formatMessage('LUIS and QnA')}; + } else { + return {formatMessage('LUIS and QnA')}; + } + }} + > { + if (isPVABot) { + return {formatMessage('Connections')}; + } else { + return {formatMessage('Connections')}; + } + }} > {isRootBot && } { + 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..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,6 +29,8 @@ import { import { LoadingSpinner } from '../../../components/LoadingSpinner'; import TelemetryClient from '../../../telemetry/TelemetryClient'; import { subtitle, errorContainer, errorTextStyle, errorIcon, customError } from '../styles'; +import { DisableFeatureToolTip } from '../../../components/DisableFeatureToolTip'; +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/pages/design/SideBar.tsx b/Composer/packages/client/src/pages/design/SideBar.tsx index 452d86ef31..414ee0022c 100644 --- a/Composer/packages/client/src/pages/design/SideBar.tsx +++ b/Composer/packages/client/src/pages/design/SideBar.tsx @@ -90,6 +90,7 @@ const SideBar: React.FC = React.memo(({ projectId }) => { updateZoomRate, deleteTrigger, } = useRecoilValue(dispatcherState); + const skillUsedInBotsMap = useRecoilValue(skillUsedInBotsSelector); const selected = decodeDesignerPathToArrayPath( dialogs.find((x) => x.id === dialogId)?.content, diff --git a/Composer/packages/client/src/recoilModel/selectors/project.ts b/Composer/packages/client/src/recoilModel/selectors/project.ts index 761ca12338..290a98b0ee 100644 --- a/Composer/packages/client/src/recoilModel/selectors/project.ts +++ b/Composer/packages/client/src/recoilModel/selectors/project.ts @@ -425,8 +425,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..a3d550d315 100644 --- a/Composer/packages/client/src/utils/pageLinks.ts +++ b/Composer/packages/client/src/utils/pageLinks.ts @@ -12,6 +12,7 @@ export type PageLink = { labelName: string; disabled: boolean; match?: RegExp; + isDisabledForPVA: boolean; }; export const topLinks = ( @@ -22,18 +23,20 @@ export const topLinks = ( schema: any, rootProjectId?: string ) => { + const isPVASchema = checkForPVASchema(schema); const botLoaded = !!projectId; const linkBase = projectId === rootProjectId || rootProjectId == null ? `/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 +44,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 +52,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 +60,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 +68,7 @@ export const topLinks = ( labelName: formatMessage('QnA'), disabled: !botLoaded, match: /knowledge-base\/[a-zA-Z0-9_-]+$/, + isDisabledForPVA: isPVASchema, }, { to: `/bot/${rootProjectId || projectId}/diagnostics`, @@ -69,12 +76,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 +91,7 @@ export const topLinks = ( labelName: formatMessage('Project settings'), disabled: !botLoaded, match: /botProjectsSettings/, + isDisabledForPVA: false, }, ...(showFormDialog ? [ @@ -90,23 +100,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' && isPVASchema) { + 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 +131,7 @@ export const bottomLinks: PageLink[] = [ iconName: 'Settings', labelName: formatMessage('Composer settings'), disabled: false, + isDisabledForPVA: false, }, // { // to: `/extensions`,