Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions Composer/packages/client/src/components/BotConvertDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/** @jsx jsx */
import { jsx, css } from '@emotion/core';
import { OpenConfirmModal } from '@bfc/ui-shared';
import formatMessage from 'format-message';
import { Link } from 'office-ui-fabric-react/lib/Link';

const contentContainer = css`
max-width: 444px;
`;

export const BotConvertConfirmDialog = () => {
return OpenConfirmModal(formatMessage('Convert your project to the latest format'), '', {
confirmText: formatMessage('Convert'),
onRenderContent: () => (
<div css={contentContainer}>
<p>
{formatMessage(
'This project was created in an older version of Composer. To open this project in Composer 2.0, we must copy your project and convert it to the latest format. Your original project will not be changed.'
)}
</p>
<p>
{formatMessage('If you have created custom components, you might need to rebuild them. ')}
Comment thread
lei9444 marked this conversation as resolved.
Outdated
<Link href="https://github.com/microsoft/botframework-components/blob/main/docs/overview.md" target="_blank">
Learn more about custom components.
</Link>
</p>
</div>
),
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@
/** @jsx jsx */
import { jsx } from '@emotion/core';
import React, { useEffect, useState, useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import formatMessage from 'format-message';
import { TeachingBubble } from 'office-ui-fabric-react/lib/TeachingBubble';
import { ScrollablePane } from 'office-ui-fabric-react/lib/ScrollablePane';
import { DisplayMarkdownDialog } from '@bfc/ui-shared';

import TelemetryClient from '../../telemetry/TelemetryClient';
import { localBotsDataSelector } from '../../recoilModel/selectors/project';
import { currentProjectIdState } from '../../recoilModel';
import { currentProjectIdState, schemaDiagnosticsSelectorFamily } from '../../recoilModel';
import { ManageLuis } from '../ManageLuis/ManageLuis';
import { ManageQNA } from '../ManageQNA/ManageQNA';
import { dispatcherState, settingsState } from '../../recoilModel';
import { mergePropertiesManagedByRootBot } from '../../recoilModel/dispatchers/utils/project';
import { rootBotProjectIdSelector } from '../../recoilModel/selectors/project';
import { navigateTo } from '../../utils/navigation';
import { usePVACheck } from '../../hooks/usePVACheck';
import { projectReadmeState } from '../../recoilModel/atoms';
import { debugPanelActiveTabState, debugPanelExpansionState, projectReadmeState } from '../../recoilModel/atoms';

import { GetStartedTask } from './GetStartedTask';
import { NextStep } from './types';
Expand All @@ -42,14 +42,16 @@ export const GetStartedNextSteps: React.FC<GetStartedProps> = (props) => {
const [displayManageQNA, setDisplayManageQNA] = useState<boolean>(false);
const readme = useRecoilValue(projectReadmeState(projectId));
const [readmeHidden, setReadmeHidden] = useState<boolean>(true);

const schemaDiagnostics = useRecoilValue(schemaDiagnosticsSelectorFamily(projectId));
const { setSettings, setQnASettings } = useRecoilValue(dispatcherState);
const rootBotProjectId = useRecoilValue(rootBotProjectIdSelector) || '';
const settings = useRecoilValue(settingsState(projectId));
const mergedSettings = mergePropertiesManagedByRootBot(projectId, rootBotProjectId, settings);
const [requiredNextSteps, setRequiredNextSteps] = useState<NextStep[]>([]);
const [recommendedNextSteps, setRecommendedNextSteps] = useState<NextStep[]>([]);
const [optionalSteps, setOptionalSteps] = useState<NextStep[]>([]);
const setExpansion = useSetRecoilState(debugPanelExpansionState);
const setActiveTab = useSetRecoilState(debugPanelActiveTabState);

const [highlightLUIS, setHighlightLUIS] = useState<boolean>(false);
const [highlightQNA, setHighlightQNA] = useState<boolean>(false);
Expand Down Expand Up @@ -129,6 +131,27 @@ export const GetStartedNextSteps: React.FC<GetStartedProps> = (props) => {
? true
: false;

if (schemaDiagnostics.length) {
newNextSteps.push({
key: 'customActions',
label: formatMessage('Review deactivated custom actions'),
description: formatMessage('We detected {length} custom components that are not support for Composer2.0.', {
Comment thread
lei9444 marked this conversation as resolved.
Outdated
length: schemaDiagnostics.length,
}),
required: true,
checked: false,
onClick: (step) => {
TelemetryClient.track('GettingStartedActionClicked', {
taskName: 'customActionsCheck',
priority: 'required',
});
setExpansion(true);
setActiveTab('Diagnostics');
},
hideFeatureStep: false,
});
}

if (props.requiresLUIS) {
newNextSteps.push({
key: 'luis',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ const tableCell = css`
}
`;

const blodText = css`
font-weight: bold !important;
`;

const content = css`
outline: none;
`;
Expand Down Expand Up @@ -188,7 +192,15 @@ export const DiagnosticList: React.FC<IDiagnosticListProps> = ({ diagnosticItems
css={content}
tabIndex={-1}
>
{item.message}
<span css={blodText}>{item.title ?? ''}</span> <span>{item.message}</span>
Comment thread
lei9444 marked this conversation as resolved.
Outdated
<Link
hidden={!item.learnMore}
href="https://github.com/microsoft/botframework-components/blob/main/docs/overview.md"
target="_blank"
>
{' '}
Comment thread
lei9444 marked this conversation as resolved.
Outdated
{item.learnMore}
</Link>
</div>
</div>
);
Expand Down
11 changes: 11 additions & 0 deletions Composer/packages/client/src/pages/diagnostics/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { createSingleMessage, isDiagnosticWithInRange } from '@bfc/indexers';
import { Diagnostic, DialogInfo, LuFile, LgFile, LgNamePattern } from '@bfc/shared';
import get from 'lodash/get';
import formatMessage from 'format-message';

import { getBaseName } from '../../utils/fileUtil';
import { replaceDialogDiagnosticLabel } from '../../utils/dialogUtil';
Expand Down Expand Up @@ -32,6 +33,8 @@ export interface IDiagnosticInfo {
dialogPath?: string; //the data path in dialog
resourceId: string; // id without locale
getUrl: (hash?: string) => string;
learnMore?: string;
title?: string;
}

export abstract class DiagnosticInfo implements IDiagnosticInfo {
Expand All @@ -46,6 +49,8 @@ export abstract class DiagnosticInfo implements IDiagnosticInfo {
dialogPath?: string;
resourceId: string;
getUrl = () => '';
learnMore?: string;
title?: string;

constructor(rootProjectId: string, projectId: string, id: string, location: string, diagnostic: Diagnostic) {
this.rootProjectId = rootProjectId;
Expand Down Expand Up @@ -97,6 +102,12 @@ export class DialogDiagnostic extends DiagnosticInfo {

export class SchemaDiagnostic extends DialogDiagnostic {
type = DiagnosticType.SCHEMA;
constructor(rootProjectId: string, projectId: string, id: string, location: string, diagnostic: Diagnostic) {
super(rootProjectId, projectId, id, location, diagnostic);
this.message = diagnostic.message;
this.title = formatMessage('Deactivated action.');
this.learnMore = formatMessage('Learn more about custom actions');
}
}

export class SkillSettingDiagnostic extends DiagnosticInfo {
Expand Down
12 changes: 2 additions & 10 deletions Composer/packages/client/src/recoilModel/dispatchers/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import formatMessage from 'format-message';
import findIndex from 'lodash/findIndex';
import { OpenConfirmModal } from '@bfc/ui-shared';
import { PublishTarget, QnABotTemplateId, RootBotManagedProperties } from '@bfc/shared';
import get from 'lodash/get';
import { CallbackInterface, useRecoilCallback } from 'recoil';
Expand Down Expand Up @@ -47,6 +46,7 @@ import { botRuntimeOperationsSelector, rootBotProjectIdSelector } from '../selec
import { mergePropertiesManagedByRootBot, postRootBotCreation } from '../../recoilModel/dispatchers/utils/project';
import { projectDialogsMapSelector, botDisplayNameState } from '../../recoilModel';
import { deleteTrigger as DialogdeleteTrigger } from '../../utils/dialogUtil';
import { BotConvertConfirmDialog } from '../../components/BotConvertDialog';

import { announcementState, boilerplateVersionState, recentProjectsState, templateIdState } from './../atoms';
import { logMessage, setError } from './../dispatchers/shared';
Expand Down Expand Up @@ -246,15 +246,7 @@ export const projectDispatcher = () => {
);

const forceMigrate = useRecoilCallback((callbackHelpers: CallbackInterface) => async (projectId: string) => {
if (
await OpenConfirmModal(
formatMessage('Convert your project to the latest format'),
formatMessage(
'This project was created in an older version of Composer. To open this project in Composer 2.0, we must copy your project and convert it to the latest format. Your original project will not be changed.'
),
{ confirmText: formatMessage('Convert') }
)
) {
if (await BotConvertConfirmDialog()) {
callbackHelpers.set(creationFlowStatusState, CreationFlowStatus.MIGRATE);
navigateTo(`/v2/projects/migrate/${projectId}`);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { BotIndexer, validateSchema } from '@bfc/indexers';
import { selectorFamily, selector } from 'recoil';
import lodashGet from 'lodash/get';
import formatMessage from 'format-message';
import { getFriendlyName } from '@bfc/shared';

import { getReferredLuFiles } from '../../utils/luUtil';
import { INavTreeItem } from '../../components/NavTree';
Expand Down Expand Up @@ -202,7 +203,21 @@ export const schemaDiagnosticsSelectorFamily = selectorFamily({
botAssets.dialogs.forEach((dialog) => {
const diagnostics = validateSchema(dialog.id, dialog.content, sdkSchemaContent);
fullDiagnostics.push(
...diagnostics.map((d) => new SchemaDiagnostic(rootProjectId, projectId, dialog.id, `${dialog.id}.dialog`, d))
...diagnostics.map((d) => {
let location = dialog.id;
if (d.path) {
const list = d.path.split('.');
let path = '';
location = [
location,
...list.map((item) => {
path = `${path}${path ? '.' : ''}${item}`;
return getFriendlyName(lodashGet(dialog.content, path)) || '';
}),
].join('>');
}
return new SchemaDiagnostic(rootProjectId, projectId, dialog.id, location, d);
})
);
});
return fullDiagnostics;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,22 @@ import { BaseSchema, DiagnosticSeverity, SchemaDefinitions } from '@botframework

import { walkAdaptiveDialog } from './walkAdaptiveDialog';

const SCHEMA_NOT_FOUND = formatMessage('Schema definition not found in sdk.schema.');

export const validateSchema = (dialogId: string, dialogData: BaseSchema, schema: SchemaDefinitions): Diagnostic[] => {
const diagnostics: Diagnostic[] = [];
const schemas: any = schema.definitions ?? {};

walkAdaptiveDialog(dialogData, schemas, ($kind, data, path) => {
if (!schemas[$kind]) {
diagnostics.push(
new Diagnostic(`${$kind}: ${SCHEMA_NOT_FOUND}`, `${dialogId}.dialog`, DiagnosticSeverity.Error, path)
new Diagnostic(
formatMessage(
'Components of $kind "{kind}" are not supported. Replace with a different component or create a custom component.',
{ kind: $kind }
),
`${dialogId}.dialog`,
DiagnosticSeverity.Error,
path
)
);
}
return true;
Expand Down