diff --git a/Composer/packages/client/src/shell/useShell.ts b/Composer/packages/client/src/shell/useShell.ts index de01dcbee3..cbb8b68da1 100644 --- a/Composer/packages/client/src/shell/useShell.ts +++ b/Composer/packages/client/src/shell/useShell.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import { useMemo, useRef } from 'react'; -import { ShellApi, ShellData, Shell, fetchFromSettings, DialogSchemaFile, SkillSetting } from '@bfc/shared'; +import { ShellApi, ShellData, Shell, DialogSchemaFile } from '@bfc/shared'; import { useRecoilValue } from 'recoil'; import formatMessage from 'format-message'; @@ -203,10 +203,7 @@ export function useShell(source: EventSource, projectId: string): Shell { updateDialogSchema: async (dialogSchema: DialogSchemaFile) => { updateDialogSchema(dialogSchema, projectId); }, - skillsSettings: { - get: (path: string) => fetchFromSettings(path, settings), - set: (id: string, skill: SkillSetting) => updateSkill(projectId, id, skill), - }, + updateSkillSetting: (...params) => updateSkill(projectId, ...params), }; const currentDialog = useMemo(() => dialogs.find((d) => d.id === dialogId), [dialogs, dialogId]); @@ -240,6 +237,7 @@ export function useShell(source: EventSource, projectId: string): Shell { clipboardActions, hosted: !!isAbsHosted(), skills, + skillsSettings: settings.skill || {}, } : ({} as ShellData); diff --git a/Composer/packages/lib/shared/src/types/shell.ts b/Composer/packages/lib/shared/src/types/shell.ts index acfb580fb0..03c5753076 100644 --- a/Composer/packages/lib/shared/src/types/shell.ts +++ b/Composer/packages/lib/shared/src/types/shell.ts @@ -58,6 +58,7 @@ export interface ShellData { qnaFiles: QnAFile[]; userSettings: UserSettings; skills: any[]; + skillsSettings: Record; // TODO: remove schemas: BotSchemas; } @@ -100,10 +101,7 @@ export interface ShellApi { displayManifestModal: (manifestId: string) => void; updateDialogSchema: (_: DialogSchemaFile) => Promise; createTrigger: (id: string, formData, url?: string) => void; - skillsSettings: { - get: (path: string) => any; - set: (skillId: string, skillsData: SkillSetting) => Promise; - }; + updateSkillSetting: (skillId: string, skillsData: SkillSetting) => Promise; } export interface Shell { diff --git a/Composer/packages/ui-plugins/select-skill-dialog/src/BeginSkillDialogField.tsx b/Composer/packages/ui-plugins/select-skill-dialog/src/BeginSkillDialogField.tsx index 5e46060a83..a2b919c38e 100644 --- a/Composer/packages/ui-plugins/select-skill-dialog/src/BeginSkillDialogField.tsx +++ b/Composer/packages/ui-plugins/select-skill-dialog/src/BeginSkillDialogField.tsx @@ -1,147 +1,18 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import React, { useMemo, useState, useEffect } from 'react'; -import { FieldProps, JSONSchema7, useShellApi } from '@bfc/extension-client'; -import { Link } from 'office-ui-fabric-react/lib/Link'; +import React from 'react'; +import { FieldProps } from '@bfc/extension-client'; import { ObjectField } from '@bfc/adaptive-form'; -import formatMessage from 'format-message'; -import { Skill, getSkillNameFromSetting } from '@bfc/shared'; -import { IComboBoxOption } from 'office-ui-fabric-react/lib/ComboBox'; import { SelectSkillDialog } from './SelectSkillDialogField'; -import { SkillEndpointField } from './SkillEndpointField'; - -const referBySettings = (skillName: string, property: string) => { - return `=settings.skill['${skillName}'].${property}`; -}; - -const settingReferences = (skillName: string) => ({ - skillEndpoint: referBySettings(skillName, 'endpointUrl'), - skillAppId: referBySettings(skillName, 'msAppId'), -}); - -const handleBackwardCompatibility = (skills: Skill[], value): { name: string; endpointName: string } | undefined => { - const { skillEndpoint } = value; - const foundSkill = skills.find(({ manifestUrl }) => manifestUrl === value.id); - if (foundSkill) { - const matchedEndpoint: any = foundSkill.endpoints.find(({ endpointUrl }) => endpointUrl === skillEndpoint); - return { - name: foundSkill?.name, - endpointName: matchedEndpoint ? matchedEndpoint.name : '', - }; - } -}; export const BeginSkillDialogField: React.FC = (props) => { - const { depth, id, schema, uiOptions, value, onChange, definitions } = props; - const { projectId, shellApi, skills = [] } = useShellApi(); - const { displayManifestModal, skillsSettings } = shellApi; - const [selectedSkill, setSelectedSkill] = useState(''); - const [oldEndpoint, loadEndpointForOldBots] = useState(''); - - useEffect(() => { - const { skillEndpoint } = value; - const skill = skills.find(({ name }) => name === getSkillNameFromSetting(skillEndpoint)); - - if (skill) { - setSelectedSkill(skill.name); - } else { - const result = handleBackwardCompatibility(skills, value); - if (result) { - setSelectedSkill(result.name); - if (result.endpointName) { - loadEndpointForOldBots(result.endpointName); - } - } - } - }, []); - - const matchedSkill = useMemo(() => { - return skills.find(({ id }) => id === selectedSkill) || ({} as Skill); - }, [skills, selectedSkill]); - - const endpointOptions = useMemo(() => { - return (matchedSkill.endpoints || []).map(({ name }) => name); - }, [matchedSkill]); - - const handleEndpointChange = async (skillEndpoint) => { - if (matchedSkill.id) { - const { msAppId, endpointUrl } = - (matchedSkill.endpoints || []).find(({ name }) => name === skillEndpoint) || ({} as any); - const schemaUpdate: any = {}; - const settingsUpdate: any = { ...matchedSkill }; - if (endpointUrl) { - schemaUpdate.skillEndpoint = referBySettings(matchedSkill.name, 'endpointUrl'); - settingsUpdate.endpointUrl = endpointUrl; - } - if (msAppId) { - schemaUpdate.skillAppId = referBySettings(matchedSkill.name, 'msAppId'); - settingsUpdate.msAppId = msAppId; - } - skillsSettings.set(matchedSkill.id, { ...settingsUpdate }); - onChange({ - ...value, - ...schemaUpdate, - }); - } - }; - - useEffect(() => { - if (oldEndpoint) { - handleEndpointChange(oldEndpoint); - } - }, [oldEndpoint]); - - const handleShowManifestClick = () => { - matchedSkill && displayManifestModal(matchedSkill.manifestUrl); - }; - - const skillEndpointUiSchema = uiOptions.properties?.skillEndpoint || {}; - skillEndpointUiSchema.serializer = { - get: (value) => { - const url: any = skillsSettings.get(value); - const endpoint = (matchedSkill?.endpoints || []).find(({ endpointUrl }) => endpointUrl === url); - return endpoint?.name; - }, - set: (value) => { - const endpoint = (matchedSkill?.endpoints || []).find(({ name }) => name === value); - return endpoint?.endpointUrl; - }, - }; - - const onSkillSelectionChange = (option: IComboBoxOption | null) => { - if (option?.text) { - setSelectedSkill(option.text); - onChange({ ...value, ...settingReferences(option.text) }); - } - }; + const { value, onChange } = props; return ( - - - {formatMessage('Show skill manifest')} - - - - {formatMessage('Open Skills page for configuration details')} - + ); diff --git a/Composer/packages/ui-plugins/select-skill-dialog/src/SelectSkillDialogField.tsx b/Composer/packages/ui-plugins/select-skill-dialog/src/SelectSkillDialogField.tsx index c7b2159041..ef0cca7244 100644 --- a/Composer/packages/ui-plugins/select-skill-dialog/src/SelectSkillDialogField.tsx +++ b/Composer/packages/ui-plugins/select-skill-dialog/src/SelectSkillDialogField.tsx @@ -8,24 +8,39 @@ import { IComboBoxOption, SelectableOptionMenuItemType } from 'office-ui-fabric- import { useShellApi } from '@bfc/extension-client'; import formatMessage from 'format-message'; import { schemaField } from '@bfc/adaptive-form'; +import { getSkillNameFromSetting, Skill } from '@bfc/shared'; +import { Link } from 'office-ui-fabric-react/lib/components/Link/Link'; import { ComboBoxField } from './ComboBoxField'; const ADD_DIALOG = 'ADD_DIALOG'; +const referBySettings = (skillName: string, property: string) => { + return `=settings.skill['${skillName}'].${property}`; +}; + +export const settingReferences = (skillName: string) => ({ + skillEndpoint: referBySettings(skillName, 'endpointUrl'), + skillAppId: referBySettings(skillName, 'msAppId'), +}); + export const SelectSkillDialog: React.FC<{ - value: string; - onChange: (option: IComboBoxOption | null) => void; + value: any; + onChange: (value: any) => void; }> = (props) => { const { value, onChange } = props; const { shellApi, skills = [] } = useShellApi(); - const { addSkillDialog } = shellApi; + const { addSkillDialog, displayManifestModal } = shellApi; const [comboboxTitle, setComboboxTitle] = useState(null); - const options: IComboBoxOption[] = skills.map(({ name }) => ({ + const skillId = getSkillNameFromSetting(value.skillEndpoint); + const { content, manifestUrl, name } = skills.find(({ id }) => id === skillId) || ({} as Skill); + + const options: IComboBoxOption[] = skills.map(({ id, name }) => ({ key: name, text: name, - isSelected: value === name, + data: settingReferences(id), + isSelected: id === skillId, })); options.push( @@ -41,21 +56,19 @@ export const SelectSkillDialog: React.FC<{ options.push({ key: 'customTitle', text: comboboxTitle }); } - const handleChange = (_, option) => { + const handleChange = (_, option: IComboBoxOption) => { if (option) { if (option.key === ADD_DIALOG) { setComboboxTitle(formatMessage('Add a new Skill Dialog')); addSkillDialog().then((skill) => { if (skill?.manifestUrl && skill?.name) { - onChange({ key: skill?.manifestUrl, text: skill?.name }); + onChange({ ...value, ...settingReferences(skill.name) }); } setComboboxTitle(null); }); } else { - onChange(option); + onChange({ ...value, ...option.data }); } - } else { - onChange(null); } }; @@ -67,9 +80,16 @@ export const SelectSkillDialog: React.FC<{ id={'SkillDialogName'} label={formatMessage('Skill Dialog Name')} options={options} - value={value} + value={skillId} onChange={handleChange} /> + manifestUrl && displayManifestModal(manifestUrl)} + > + {formatMessage('Show skill manifest')} + ); }; diff --git a/Composer/packages/ui-plugins/select-skill-dialog/src/SkillEndpointField.tsx b/Composer/packages/ui-plugins/select-skill-dialog/src/SkillEndpointField.tsx index 0787695d5e..3e21d71a9a 100644 --- a/Composer/packages/ui-plugins/select-skill-dialog/src/SkillEndpointField.tsx +++ b/Composer/packages/ui-plugins/select-skill-dialog/src/SkillEndpointField.tsx @@ -3,50 +3,48 @@ /** @jsx jsx */ import { jsx } from '@emotion/core'; -import React from 'react'; -import { FieldProps, useFormConfig } from '@bfc/extension-client'; -import { - getUiLabel, - getUIOptions, - getUiPlaceholder, - getUiDescription, - schemaField, - SelectField, -} from '@bfc/adaptive-form'; +import React, { useMemo } from 'react'; +import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; +import { FieldProps, useShellApi } from '@bfc/extension-client'; +import { FieldLabel } from '@bfc/adaptive-form'; +import { getSkillNameFromSetting, Skill } from '@bfc/shared'; export const SkillEndpointField: React.FC = (props) => { - const { depth, schema, uiOptions: baseUIOptions, value, onChange } = props; - const formUIOptions = useFormConfig(); + const { description, label, required, uiOptions, value } = props; + const { shellApi, skillsSettings, skills = [] } = useShellApi(); + const { updateSkillSetting } = shellApi; - const uiOptions = { - ...getUIOptions(schema, formUIOptions), - ...baseUIOptions, - }; + const id = getSkillNameFromSetting(value); + const skill = skills.find(({ id: skillId }) => skillId === id) || ({} as Skill); + const { endpointUrl, msAppId } = skillsSettings[id] || {}; + + const { endpoints = [] } = skill; - const deserializedValue = typeof uiOptions?.serializer?.get === 'function' ? uiOptions.serializer.get(value) : value; + const options = useMemo( + () => + endpoints.map(({ name, endpointUrl, msAppId }, key) => ({ + key, + text: name, + data: { + endpointUrl, + msAppId, + }, + })), + [endpoints] + ); - const handleChange = (newValue: any) => { - const serializedValue = newValue; - if (typeof uiOptions?.serializer?.set === 'function') { - uiOptions.serializer.set(newValue); + const { key } = options.find(({ data }) => data.endpointUrl === endpointUrl && data.msAppId === msAppId) || {}; + + const handleChange = (_: React.FormEvent, option?: IDropdownOption) => { + if (option) { + updateSkillSetting(skill.id, { ...skill, ...option.data }); } - onChange(serializedValue); }; - const label = getUiLabel({ ...props, uiOptions }); - const placeholder = getUiPlaceholder({ ...props, uiOptions }); - const description = getUiDescription({ ...props, uiOptions }); - return ( -
- -
+ + + + ); }; diff --git a/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/BeginSkillDialogField.test.tsx b/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/BeginSkillDialogField.test.tsx deleted file mode 100644 index 3caaab819c..0000000000 --- a/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/BeginSkillDialogField.test.tsx +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -/* eslint-disable @typescript-eslint/no-explicit-any */ - -import React from 'react'; -import { fireEvent, getAllByRole, render } from '@bfc/test-utils'; -import { EditorExtension, JSONSchema7 } from '@bfc/extension-client'; -import { SDKKinds, convertSkillsToDictionary, fetchFromSettings } from '@bfc/shared'; -import { act } from '@bfc/test-utils/lib/hooks'; - -import { BeginSkillDialogField } from '../BeginSkillDialogField'; -import pluginConfig from '..'; - -import { schema } from './constants'; - -const skills: any = [ - { - id: 'yuesuemailskill0207', - content: {}, - manifestUrl: 'https://yuesuemailskill0207-gjvga67.azurewebsites.net/manifest/manifest-1.0.json', - name: 'yuesuemailskill0207', - endpoints: [ - { - name: 'production', - protocol: 'BotFrameworkV3', - description: 'Production endpoint for the Email Skill', - endpointUrl: 'https://yuesuemailskill0207-gjvga67.azurewebsites.net/api/messages', - msAppId: '79432da8-0f7e-4a16-8c23-ddbba30ae85d', - }, - ], - }, -]; - -const renderBeginSkillDialog = ({ value = {}, onChange = jest.fn() } = {}) => { - const addSkillDialog = jest.fn().mockResolvedValue({ manifestUrl: 'https://' }); - - const props = { - depth: 1, - id: 'select.skillDialog', - schema: (schema?.[SDKKinds.BeginSkill] || {}) as JSONSchema7, - uiOptions: pluginConfig.uiSchema?.[SDKKinds.BeginSkill]?.form || {}, - value, - onChange, - definitions: {}, - name: 'select.skillDialog', - }; - - const shellData: any = { - skills, - }; - const setting: any = { - skill: convertSkillsToDictionary(skills), - }; - - const shell: any = { - addSkillDialog, - skillsSettings: { - get: (path: string) => fetchFromSettings(path, setting), - set: () => {}, - }, - }; - - return render( - - - - ); -}; - -describe('Begin Skill Dialog', () => { - beforeEach(() => { - jest.useFakeTimers(); - }); - - it('should add a new skill', async () => { - const onChange = jest.fn(); - const value = { skillEndpoint: `=settings.skill['yuesuemailskill0207'].endpointUrl` }; - const { baseElement, findByRole } = renderBeginSkillDialog({ value, onChange }); - - const listbox = await findByRole('listbox'); - fireEvent.click(listbox); - - const endpoints = getAllByRole(baseElement, 'option'); - act(() => { - fireEvent.click(endpoints[endpoints.length - 1]); - }); - - expect(onChange).toHaveBeenCalledWith({ - skillAppId: "=settings.skill['yuesuemailskill0207'].msAppId", - skillEndpoint: "=settings.skill['yuesuemailskill0207'].endpointUrl", - }); - }); - - it('should be backwards compatible', async () => { - const onChange = jest.fn(); - const value = { - id: `https://yuesuemailskill0207-gjvga67.azurewebsites.net/manifest/manifest-1.0.json`, - skillEndpoint: 'https://yuesuemailskill0207-gjvga67.azurewebsites.net/api/messages', - }; - renderBeginSkillDialog({ value, onChange }); - - expect(onChange).toHaveBeenCalledWith({ - id: `https://yuesuemailskill0207-gjvga67.azurewebsites.net/manifest/manifest-1.0.json`, - skillAppId: "=settings.skill['yuesuemailskill0207'].msAppId", - skillEndpoint: "=settings.skill['yuesuemailskill0207'].endpointUrl", - }); - }); -}); diff --git a/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/SelectSkillDialog.test.tsx b/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/SelectSkillDialog.test.tsx index 09db7f078d..f30715afc5 100644 --- a/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/SelectSkillDialog.test.tsx +++ b/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/SelectSkillDialog.test.tsx @@ -1,61 +1,22 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -// @ts-nocheck - import React from 'react'; -import { fireEvent, getAllByRole, render } from '@bfc/test-utils'; +import { act, fireEvent, getAllByRole, render } from '@bfc/test-utils'; import { EditorExtension } from '@bfc/extension-client'; -import { fetchFromSettings, convertSkillsToDictionary } from '@bfc/shared'; -import { SelectSkillDialog } from '../SelectSkillDialogField'; +import { SelectSkillDialog, settingReferences } from '../SelectSkillDialogField'; -const skills = [ - { - manifestUrl: 'https://yuesuemailskill0207-gjvga67.azurewebsites.net/manifest/manifest-1.0.json', - name: 'Email Skill', - endpoints: [ - { - name: 'production', - protocol: 'BotFrameworkV3', - description: 'Production endpoint for the Email Skill', - endpointUrl: 'https://yuesuemailskill0207-gjvga67.azurewebsites.net/api/messages', - msAppId: '79432da8-0f7e-4a16-8c23-ddbba30ae85d', - }, - ], - }, - { - manifestUrl: 'https://ericv3skillssimplesandwichbot.azurewebsites.net/wwwroot/sandwich-bot-manifest.json', - name: 'Sandwich Skill Bot', - endpoints: [ - { - name: 'YourSandwichBotName', - protocol: 'BotFrameworkV3', - description: 'Default endpoint for the skill', - endpointUrl: 'https://ericv3skillssimplesandwichbot.azurewebsites.net/api/messages', - msAppId: '94e29d0f-3f0d-46f0-aa78-00aed83698cf', - }, - ], - }, -]; +import { skills } from './constants'; -const renderSelectSkillDialog = ({ addSkillDialog, onChange } = {}) => { +const renderSelectSkillDialog = ({ addSkillDialog = jest.fn(), onChange = jest.fn() } = {}) => { const props = { - description: 'Name of the skill to call.', - id: 'select.skillDialog', - label: 'Skill Dialog Name', + value: {}, onChange, }; const shell = { addSkillDialog, - skillsSettings: { - get: (path: string) => - fetchFromSettings(path, { - skill: convertSkillsToDictionary(skills), - }), - set: () => {}, - }, }; const shellData = { @@ -74,7 +35,12 @@ describe('Select Skill Dialog', () => { const addSkillDialog = jest.fn().mockImplementation(() => { return { then: (cb) => { - cb({ manifestUrl: 'https://', name: 'test-skill' }); + cb({ + manifestUrl: 'https://skill', + name: 'test-skill', + msAppId: '0000-0000', + endpointUrl: 'https://skill/api/messafes', + }); }, }; }); @@ -82,31 +48,17 @@ describe('Select Skill Dialog', () => { const { baseElement, findByRole } = renderSelectSkillDialog({ addSkillDialog, onChange }); const combobox = await findByRole('combobox'); - fireEvent.click(combobox); + act(() => { + fireEvent.click(combobox); + }); const dialogs = getAllByRole(baseElement, 'option'); - fireEvent.click(dialogs[dialogs.length - 1]); + act(() => { + fireEvent.click(dialogs[dialogs.length - 1]); + }); expect(addSkillDialog).toHaveBeenCalled(); - expect(onChange).toHaveBeenCalledWith({ key: 'https://', text: 'test-skill' }); - }); - - it('should select skill', async () => { - const onChange = jest.fn(); - - const { baseElement, findByRole } = renderSelectSkillDialog({ onChange }); - const combobox = await findByRole('combobox'); - fireEvent.click(combobox); - - const [skill] = getAllByRole(baseElement, 'option'); - fireEvent.click(skill); - - expect(onChange).toHaveBeenCalledWith({ - index: 0, - isSelected: false, - key: 'Email Skill', - text: 'Email Skill', - }); + expect(onChange).toHaveBeenCalledWith({ ...settingReferences('test-skill') }); }); it('should display label', async () => { diff --git a/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/SkillEndpointField.test.tsx b/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/SkillEndpointField.test.tsx new file mode 100644 index 0000000000..05a21d8cce --- /dev/null +++ b/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/SkillEndpointField.test.tsx @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import React from 'react'; +import { fireEvent, getAllByRole, render } from '@bfc/test-utils'; +import { EditorExtension } from '@bfc/extension-client'; +import { convertSkillsToDictionary, Skill } from '@bfc/shared'; +import { act } from '@bfc/test-utils/lib/hooks'; + +import { SkillEndpointField } from '../SkillEndpointField'; + +import { skills } from './constants'; + +const projectId = '123.abc'; + +const renderSkillEndpointField = ({ value = '', updateSkillSetting = jest.fn() } = {}) => { + const props = { + label: 'Skill endpoint', + value, + } as any; + + const shellData: any = { + skillsSettings: convertSkillsToDictionary(skills as Skill[]), + skills, + }; + + const shell: any = { + updateSkillSetting, + }; + + return render( + + + + ); +}; + +describe('Begin Skill Dialog', () => { + it('should update the skill settings', async () => { + const updateSkillSetting = jest.fn(); + const { baseElement, findByRole } = renderSkillEndpointField({ + updateSkillSetting, + value: `=settings.skill['${skills[0].id}'].endpointUrl`, + }); + + const listbox = await findByRole('listbox'); + act(() => { + fireEvent.click(listbox); + }); + + const endpoints = getAllByRole(baseElement, 'option'); + act(() => { + fireEvent.click(endpoints[endpoints.length - 1]); + }); + + expect(updateSkillSetting).toHaveBeenCalledWith( + skills[0].id, + expect.objectContaining({ + endpointUrl: skills[0].endpoints[0].endpointUrl, + msAppId: skills[0].endpoints[0].msAppId, + }) + ); + }); +}); diff --git a/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/constants.ts b/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/constants.ts index 2202c4bf12..7b8d4f479f 100644 --- a/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/constants.ts +++ b/Composer/packages/ui-plugins/select-skill-dialog/src/__tests__/constants.ts @@ -3,8 +3,8 @@ export const skills = [ { + id: 'yuesuemailskill0207', manifestUrl: 'https://yuesuemailskill0207-gjvga67.azurewebsites.net/manifest/manifest-1.0.json', - name: 'Email Skill', endpoints: [ { name: 'production', @@ -14,8 +14,12 @@ export const skills = [ msAppId: '79432da8-0f7e-4a16-8c23-ddbba30ae85d', }, ], + name: 'Email Skill', + description: 'Production endpoint for the Email Skill', + content: {}, }, { + id: 'sandwich', manifestUrl: 'https://ericv3skillssimplesandwichbot.azurewebsites.net/wwwroot/sandwich-bot-manifest.json', name: 'Sandwich Skill Bot', endpoints: [ @@ -27,40 +31,7 @@ export const skills = [ msAppId: '94e29d0f-3f0d-46f0-aa78-00aed83698cf', }, ], + description: 'Default endpoint for the skill', + content: {}, }, ]; - -export const schema = { - 'Microsoft.BeginSkill': { - $role: 'implements(Microsoft.IDialog)', - title: 'Begin a skill dialog', - description: 'Begin a remote skill dialog.', - type: 'object', - properties: { - $kind: { - title: '$kind', - description: 'Defines the valid properties for the component you are configuring (from a dialog .schema file)', - type: 'string', - pattern: '^[a-zA-Z][a-zA-Z0-9.]*$', - const: 'Microsoft.BeginSkill', - }, - id: { - type: 'string', - title: 'Id', - description: 'Optional id for the skill dialog', - }, - skillAppId: { - $role: 'expression', - type: 'string', - title: 'Skill App ID', - description: 'The Microsoft App ID for the skill.', - }, - skillEndpoint: { - type: 'string', - title: 'Skill endpoint ', - description: 'The /api/messages endpoint for the skill.', - examples: ['https://myskill.contoso.com/api/messages/'], - }, - }, - }, -}; diff --git a/Composer/packages/ui-plugins/select-skill-dialog/src/index.ts b/Composer/packages/ui-plugins/select-skill-dialog/src/index.ts index 6dcd1ca222..3240a8bf28 100644 --- a/Composer/packages/ui-plugins/select-skill-dialog/src/index.ts +++ b/Composer/packages/ui-plugins/select-skill-dialog/src/index.ts @@ -5,14 +5,20 @@ import { PluginConfig } from '@bfc/extension-client'; import { SDKKinds } from '@bfc/shared'; import { BeginSkillDialogField } from './BeginSkillDialogField'; +import { SkillEndpointField } from './SkillEndpointField'; const config: PluginConfig = { uiSchema: { [SDKKinds.BeginSkill]: { form: { - order: ['skillAppId', '*', 'resultProperty', 'disabled', 'activityProcessed'], - hidden: ['botId', 'skillEndpoint', 'skillAppId', 'skillHostEndpoint'], + order: ['skillEndpoint', '*', 'resultProperty', 'activityProcessed'], + hidden: ['botId', 'skillAppId', 'skillHostEndpoint'], field: BeginSkillDialogField, + properties: { + skillEndpoint: { + field: SkillEndpointField, + }, + }, }, }, },