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 all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
563261c
package and schema update for 4.9-RC1
luhan2017 May 6, 2020
297109e
update trigger wizard (#2917)
liweitian May 6, 2020
1a9a441
rename variable
a-b-r-o-w-n May 6, 2020
b6718f6
update SDKKinds enum
a-b-r-o-w-n May 6, 2020
582c747
Merge branch 'master' into luhan/rc1
a-b-r-o-w-n May 6, 2020
7043b27
fix references to removed kinds
a-b-r-o-w-n May 6, 2020
0eade59
fix schema resolution for property editor
a-b-r-o-w-n May 6, 2020
c0bc0c0
do not title case the schema title
a-b-r-o-w-n May 6, 2020
b86095e
add ability to type custom event name in trigger creation
a-b-r-o-w-n May 6, 2020
5131529
fix autoEndDialog type in samples
a-b-r-o-w-n May 6, 2020
4953447
Merge branch 'master' into luhan/rc1
a-b-r-o-w-n May 6, 2020
a1a937d
Merge branch 'master' into luhan/rc1
luhan2017 May 7, 2020
2751521
Merge branch 'master' into luhan/rc1
a-b-r-o-w-n May 7, 2020
a0598ce
generate sdk enum with all definitions
a-b-r-o-w-n May 7, 2020
10b586b
Revert changes to ui schema and label map
a-b-r-o-w-n May 7, 2020
2161c06
update ActivityTemplate to IActivityTemplate for lg fields
a-b-r-o-w-n May 7, 2020
8f3a944
resolve schema in order to determine stacking
a-b-r-o-w-n May 7, 2020
eda700b
remove test types from sdk enum
a-b-r-o-w-n May 7, 2020
16fc327
fix failing tests
a-b-r-o-w-n May 7, 2020
36bec81
skip failing test
a-b-r-o-w-n May 7, 2020
bf31082
update sdk packages and schema to rc4
a-b-r-o-w-n May 7, 2020
04eea0c
Merge branch 'master' into luhan/rc1
a-b-r-o-w-n May 7, 2020
3eb8df1
update bot start up to not use HostContext
a-b-r-o-w-n May 7, 2020
494e6ff
Merge branch 'master' into luhan/rc1
a-b-r-o-w-n May 7, 2020
87cd210
Update some enum to lower case and removed the recognizerset sample b…
luhan2017 May 8, 2020
c2772e4
Merge branch 'master' into luhan/rc1
a-b-r-o-w-n May 8, 2020
f65ecec
update deprecated method
a-b-r-o-w-n May 8, 2020
6c1e448
Merge branch 'master' into luhan/rc1
cwhitten May 8, 2020
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
5 changes: 2 additions & 3 deletions Composer/cypress/integration/NotificationPage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ context('Notification Page', () => {
cy.findAllByText('__TestToDoBotWithLuisSample').should('exist');
});

it('can show dialog expression error ', () => {
it.skip('can show dialog expression error ', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to leave this test skipped?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Expression validation is broken currently. We decided not to block the PR and do a follow up bug fix.

cy.visitPage('Design Flow');

cy.findByTestId('ProjectTree').within(() => {
Expand All @@ -67,8 +67,7 @@ context('Notification Page', () => {
.should('contain.text', 'expression');
cy.get('#root\\.condition')
.click()
.type('()')
.wait(1000);
.type('()');
});

cy.findByTestId('LeftNav-CommandBarButtonNotifications').click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { PlaceHolderSectionName } from '@bfc/indexers/lib/utils/luUtil';
import get from 'lodash/get';
import { DialogInfo } from '@bfc/shared';
import { LuEditor, inlineModePlaceholder } from '@bfc/code-editor';
import { ComboBox, IComboBoxOption, IComboBox } from 'office-ui-fabric-react/lib/ComboBox';

import {
generateNewDialog,
Expand All @@ -26,10 +27,8 @@ import {
eventTypeKey,
intentTypeKey,
activityTypeKey,
messageTypeKey,
getEventTypes,
getActivityTypes,
getMessageTypes,
regexRecognizerKey,
} from '../../utils/dialogUtil';
import { addIntent } from '../../utils/luUtil';
Expand All @@ -44,18 +43,14 @@ const validateForm = (
regExIntents: [{ intent: string; pattern: string }]
): TriggerFormDataErrors => {
const errors: TriggerFormDataErrors = {};
const { $kind, specifiedType, intent, triggerPhrases, regexEx } = data;
const { $kind, event: eventName, intent, triggerPhrases, regexEx } = data;

if ($kind === eventTypeKey && !specifiedType) {
errors.specifiedType = formatMessage('Please select a event type');
if ($kind === eventTypeKey && !eventName) {
errors.event = formatMessage('Please select a event type');
}

if ($kind === activityTypeKey && !specifiedType) {
errors.specifiedType = formatMessage('Please select an activity type');
}

if ($kind === messageTypeKey && !specifiedType) {
errors.specifiedType = formatMessage('Please select a message type');
if ($kind === activityTypeKey && !eventName) {
errors.event = formatMessage('Please select an activity type');
}

if (!$kind) {
Expand Down Expand Up @@ -108,13 +103,14 @@ export const TriggerCreationModal: React.FC<TriggerCreationModalProps> = props =
const isNone = !get(dialogFile, 'content.recognizer');
const initialFormData: TriggerFormData = {
errors: {},
$kind: isNone ? '' : intentTypeKey,
specifiedType: '',
$kind: '',
event: '',
intent: '',
triggerPhrases: '',
regexEx: '',
};
const [formData, setFormData] = useState(initialFormData);
const [selectedType, setSelectedType] = useState(isNone ? '' : intentTypeKey);

const onClickSubmitButton = e => {
e.preventDefault();
Expand Down Expand Up @@ -144,12 +140,37 @@ export const TriggerCreationModal: React.FC<TriggerCreationModalProps> = props =
onDismiss();
};

const eventTypes: IComboBoxOption[] = getEventTypes();
const activityTypes: IDropdownOption[] = getActivityTypes();
let triggerTypeOptions: IDropdownOption[] = getTriggerTypes();

const onSelectTriggerType = (e, option) => {
setSelectedType(option.key || '');
setFormData({ ...initialFormData, $kind: option.key });
};

const onSelectSpecifiedTypeType = (e, option) => {
setFormData({ ...formData, specifiedType: option.key });
const handleEventChange = (
event: React.FormEvent<IComboBox>,
option?: IComboBoxOption,
index?: number,
value?: string
) => {
if (value) {
// if the custom event is an actual type, use that instead
if (eventTypes.find(o => o.key === value)) {
setFormData({ ...formData, $kind: value, event: '' });
} else {
setFormData({ ...formData, $kind: eventTypeKey, event: value });
}
} else if (option) {
setFormData({ ...formData, $kind: option.key as string, event: '' });
}
};

const onSelectSpecifiedType = (_e: any, option?: IDropdownOption) => {
if (option) {
setFormData({ ...formData, $kind: option.key as string });
}
};

const onNameChange = (e, name) => {
Expand All @@ -168,19 +189,14 @@ export const TriggerCreationModal: React.FC<TriggerCreationModalProps> = props =
setFormData({ ...formData, triggerPhrases: body, errors });
};

const eventTypes: IDropdownOption[] = getEventTypes();
const activityTypes: IDropdownOption[] = getActivityTypes();
const messageTypes: IDropdownOption[] = getMessageTypes();
let triggerTypeOptions: IDropdownOption[] = getTriggerTypes();
if (isNone) {
triggerTypeOptions = triggerTypeOptions.filter(t => t.key !== intentTypeKey);
}
const showIntentName = formData.$kind === intentTypeKey;
const showRegExDropDown = formData.$kind === intentTypeKey && isRegEx;
const showTriggerPhrase = formData.$kind === intentTypeKey && !isRegEx;
const showEventDropDown = formData.$kind === eventTypeKey;
const showActivityDropDown = formData.$kind === activityTypeKey;
const showMessageDropDown = formData.$kind === messageTypeKey;
const showIntentName = selectedType === intentTypeKey;
const showRegExDropDown = selectedType === intentTypeKey && isRegEx;
const showTriggerPhrase = selectedType === intentTypeKey && !isRegEx;
const showEventDropDown = selectedType === eventTypeKey;
const showActivityDropDown = selectedType === activityTypeKey;

return (
<Dialog
Expand All @@ -205,17 +221,21 @@ export const TriggerCreationModal: React.FC<TriggerCreationModalProps> = props =
onChange={onSelectTriggerType}
errorMessage={formData.errors.$kind}
data-testid={'triggerTypeDropDown'}
defaultSelectedKey={formData.$kind}
defaultSelectedKey={selectedType}
/>
{showEventDropDown && (
<Dropdown
placeholder={formatMessage('Select a event type')}
<ComboBox
placeholder={formatMessage('Select an event type or enter a custom event name')}
label={formatMessage('Which event?')}
options={eventTypes}
styles={dropdownStyles}
onChange={onSelectSpecifiedTypeType}
errorMessage={formData.errors.specifiedType}
onChange={handleEventChange}
errorMessage={formData.errors.event}
data-testid={'eventTypeDropDown'}
allowFreeform
useComboBoxAsMenuWidth
autoComplete="off"
text={formData.event || eventTypes.find(e => e.key === formData.$kind)?.text}
/>
)}
{showActivityDropDown && (
Expand All @@ -224,22 +244,11 @@ export const TriggerCreationModal: React.FC<TriggerCreationModalProps> = props =
label={formatMessage('Which activity type')}
options={activityTypes}
styles={dropdownStyles}
onChange={onSelectSpecifiedTypeType}
errorMessage={formData.errors.specifiedType}
onChange={onSelectSpecifiedType}
errorMessage={formData.errors.event}
data-testid={'activityTypeDropDown'}
/>
)}
{showMessageDropDown && (
<Dropdown
placeholder={formatMessage('Select a message type')}
label={formatMessage('Which message type?')}
options={messageTypes}
styles={dropdownStyles}
onChange={onSelectSpecifiedTypeType}
errorMessage={formData.errors.specifiedType}
data-testid={'messageTypeDropDown'}
/>
)}
{showIntentName && (
<TextField
label={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export const dropdownStyles = {
width: '400px',
},
root: {
paddingBottom: '20px',
marginBottom: '20px',
},
};

Expand Down
16 changes: 13 additions & 3 deletions Composer/packages/client/src/pages/design/PropertyEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
/** @jsx jsx */
import { jsx } from '@emotion/core';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import AdaptiveForm, { resolveBaseSchema, getUIOptions, mergePluginConfigs } from '@bfc/adaptive-form';
import Extension, { FormErrors } from '@bfc/extension';
import AdaptiveForm, { resolveRef, getUIOptions, mergePluginConfigs } from '@bfc/adaptive-form';
import Extension, { FormErrors, JSONSchema7 } from '@bfc/extension';
import formatMessage from 'format-message';
import isEqual from 'lodash/isEqual';
import debounce from 'lodash/debounce';
Expand All @@ -17,6 +17,16 @@ import plugins from '../../plugins';

import { formEditor } from './styles';

function resolveBaseSchema(schema: JSONSchema7, $kind: string): JSONSchema7 | undefined {
const defSchema = schema.definitions?.[$kind];
if (defSchema && typeof defSchema === 'object') {
return {
...resolveRef(defSchema, schema.definitions),
definitions: schema.definitions,
};
}
}

const PropertyEditor: React.FC = () => {
const { api: shellApi, data: shellData } = useShell('PropertyEditor');
const { currentDialog, data: formData = {}, focusPath, focusedSteps, schemas } = shellData;
Expand Down Expand Up @@ -48,7 +58,7 @@ const PropertyEditor: React.FC = () => {

const $schema = useMemo(() => {
if (schemas?.sdk?.content && localData) {
return resolveBaseSchema(schemas.sdk.content, localData);
return resolveBaseSchema(schemas.sdk.content, localData.$kind);
}
}, [schemas?.sdk?.content, localData.$kind]);

Expand Down
24 changes: 15 additions & 9 deletions Composer/packages/client/src/utils/dialogUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import set from 'lodash/set';
import cloneDeep from 'lodash/cloneDeep';
import { Expression } from 'adaptive-expressions';
import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { IComboBoxOption } from 'office-ui-fabric-react/lib/ComboBox';
import formatMessage from 'format-message';

import { getFocusPath } from './navigation';
import { upperCaseName } from './fileUtil';
Expand All @@ -18,7 +20,7 @@ interface DialogsMap {
export interface TriggerFormData {
errors: TriggerFormDataErrors;
$kind: string;
specifiedType: string;
event: string;
intent: string;
triggerPhrases: string;
regexEx: string;
Expand All @@ -27,7 +29,7 @@ export interface TriggerFormData {
export interface TriggerFormDataErrors {
$kind?: string;
intent?: string;
specifiedType?: string;
event?: string;
triggerPhrases?: string;
regexEx?: string;
}
Expand All @@ -40,9 +42,7 @@ export function getDialog(dialogs: DialogInfo[], dialogId: string) {
export const eventTypeKey: string = SDKKinds.OnDialogEvent;
export const intentTypeKey: string = SDKKinds.OnIntent;
export const activityTypeKey: string = SDKKinds.OnActivity;
export const messageTypeKey: string = SDKKinds.OnMessageEventActivity;
export const regexRecognizerKey: string = SDKKinds.RegexRecognizer;

function insert(content, path: string, position: number | undefined, data: any) {
const current = get(content, path, []);
const insertAt = typeof position === 'undefined' ? current.length : position;
Expand All @@ -52,13 +52,19 @@ function insert(content, path: string, position: number | undefined, data: any)
}

function generateNewTrigger(data: TriggerFormData, factory: DialogFactory) {
const optionalAttributes: { intent?: string; event?: string } = {};
if (data.specifiedType) {
data.$kind = data.specifiedType;
const optionalAttributes: { intent?: string; event?: string; $designer: { [key: string]: string } } = {
$designer: {},
};

if (data.event) {
optionalAttributes.event = data.event;
optionalAttributes.$designer.name = formatMessage('Custom Event');
}

if (data.intent) {
optionalAttributes.intent = data.intent;
}

const newStep = factory.create(data.$kind as SDKKinds, optionalAttributes);
return newStep;
}
Expand Down Expand Up @@ -163,8 +169,8 @@ export function getTriggerTypes(): IDropdownOption[] {
return triggerTypes;
}

export function getEventTypes(): IDropdownOption[] {
const eventTypes: IDropdownOption[] = [
export function getEventTypes(): IComboBoxOption[] {
const eventTypes: IComboBoxOption[] = [
...dialogGroups[DialogGroup.DIALOG_EVENT_TYPES].types.map(t => {
let name = t as string;
const labelOverrides = ConceptLabels[t];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { FontSizes, NeutralColors, SharedColors } from '@uifabric/fluent-theme';
import formatMessage from 'format-message';
import map from 'lodash/map';

import { getArrayItemProps, getOrderedProperties, useArrayItems } from '../../utils';
import { getArrayItemProps, getOrderedProperties, useArrayItems, resolveRef } from '../../utils';
import { FieldLabel } from '../FieldLabel';

import { objectArrayField } from './styles';
Expand Down Expand Up @@ -92,9 +92,10 @@ const ObjectArrayField: React.FC<FieldProps<any[]>> = props => {

return (
allOrderProps.length > 2 ||
!!Object.entries(properties).filter(
([key, { $role }]: any) => allOrderProps.includes(key) && $role === 'expression'
).length
Object.entries(properties).some(([key, propSchema]) => {
const resolved = resolveRef(propSchema as JSONSchema7, props.definitions);
return allOrderProps.includes(key) && resolved.$role === 'expression';
})
);
}, [itemSchema, orderedProperties]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { UISchema } from '@bfc/extension';
import { SDKKinds } from '@bfc/shared';
import formatMessage from 'format-message';

import { RecognizerField, IntentField } from './components/fields';
import { IntentField, RecognizerField } from './components/fields';

const triggerUiSchema = {
order: ['condition', '*'],
Expand All @@ -23,7 +23,7 @@ const DefaultUISchema: UISchema = {
label: () => formatMessage('Language Understanding'),
description: () =>
formatMessage(
'To understand what the user says, your dialog needs a "IRecognizer"; that includes example words and sentences that users may use.'
'To understand what the user says, your dialog needs a "Recognizer"; that includes example words and sentences that users may use.'
),
},
},
Expand Down Expand Up @@ -116,6 +116,10 @@ const DefaultUISchema: UISchema = {
hidden: ['actions', 'elseActions'],
helpLink: 'https://aka.ms/bfc-controlling-conversation-flow',
},
[SDKKinds.IRecognizer]: {
field: RecognizerField,
helpLink: 'https://aka.ms/BFC-Using-LU',
},
[SDKKinds.LogAction]: {
label: () => formatMessage('Log to console'),
helpLink: 'https://aka.ms/bfc-debugging-bots',
Expand Down Expand Up @@ -153,11 +157,6 @@ const DefaultUISchema: UISchema = {
helpLink:
'https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-conversations?view=azure-bot-service-4.0#conversation-lifetime',
},
[SDKKinds.OnCustomEvent]: {
...triggerUiSchema,
label: () => formatMessage('Handle an Event'),
subtitle: () => formatMessage('Custom event'),
},
[SDKKinds.OnDialogEvent]: {
...triggerUiSchema,
label: () => formatMessage('Dialog events'),
Expand Down Expand Up @@ -238,10 +237,6 @@ const DefaultUISchema: UISchema = {
label: () => formatMessage('QnAMakerDialog'),
helpLink: 'https://aka.ms/bfc-using-QnA',
},
[SDKKinds.IRecognizer]: {
field: RecognizerField,
helpLink: 'https://aka.ms/BFC-Using-LU',
},
[SDKKinds.RegexRecognizer]: {
hidden: ['entities'],
},
Expand Down
Loading