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
59 commits
Select commit Hold shift + click to select a range
197a295
chore: turn RecognizerField to folder
yeze322 Sep 15, 2020
48cf2cc
extract 'useMigrationEffect'
yeze322 Sep 15, 2020
2dd8607
remove dup & no ref file 'defaultRecognizers'
yeze322 Sep 15, 2020
f497f6f
move out complicated selectedType func && var names
yeze322 Sep 15, 2020
b7d6755
use 'dropdownOption' to replace 'isCustomType' which is anti-pattern
yeze322 Sep 15, 2020
43da36d
add 'default' and 'disabled' to RecognizerSchema
yeze322 Sep 15, 2020
a4931f8
set CrossTrain to default, disable Luis
yeze322 Sep 15, 2020
47d1ebb
impl 'getRecognizerDefinition()'
yeze322 Sep 15, 2020
9aa5694
move DefaultRecognizers to separated file
yeze322 Sep 15, 2020
991ba4c
rename: 'editor' -> 'intentEditor'
yeze322 Sep 15, 2020
c0b94a0
impl 'recognizerEditor' in Recognizer schema
yeze322 Sep 15, 2020
6e1918d
adapt to schema's 'disabled' property
yeze322 Sep 15, 2020
de427a8
sort recognizer options
yeze322 Sep 15, 2020
eee273a
make renameIntent optional
yeze322 Sep 15, 2020
c34971d
make handleRecognizerChange optional & impl fallback submit func
yeze322 Sep 15, 2020
19b519e
impl mappers to map among 'schema', 'dropdown', 'value'
yeze322 Sep 15, 2020
fd357e3
provide 'findRecognizer' as hook's buitin func
yeze322 Sep 15, 2020
5d82982
apply findRecognizer to RecognizerField
yeze322 Sep 15, 2020
6ee0b31
mark isSelected optional
yeze322 Sep 15, 2020
aacba7d
Merge branch 'main' into uischema/recognizer
yeze322 Sep 15, 2020
5d4c89f
add a todo
yeze322 Sep 15, 2020
3bf82da
Merge branch 'main' into uischema/recognizer
beyackle Sep 15, 2020
d4de656
Merge branch 'main' into uischema/recognizer
yeze322 Sep 16, 2020
681ebda
merge 'recognizers' to uiSchema
yeze322 Sep 16, 2020
a94cef3
migrate to new RecognizerUISchema
yeze322 Sep 16, 2020
0a1ab40
don't show non-recognizer $kinds as dropdown
yeze322 Sep 16, 2020
0ba8568
adjust dropdown order
yeze322 Sep 16, 2020
2da450e
make the 'Custom Rec' with JSON editor as fallback option
yeze322 Sep 16, 2020
6cde9ca
fix tslint error
yeze322 Sep 16, 2020
32c35b6
omi RegexRecognizer's `isSelected` option
yeze322 Sep 16, 2020
1d82e10
Merge branch 'main' into uischema/recognizer
yeze322 Sep 17, 2020
a0ccd13
resolve intentEditor logic leaks
yeze322 Sep 17, 2020
d00260b
fix UT
yeze322 Sep 17, 2020
87d34bf
fix UT
yeze322 Sep 17, 2020
a510c63
impl getDefaultRecognizer()
yeze322 Sep 17, 2020
bccc372
create default recognizer when seeding new dialog
yeze322 Sep 17, 2020
2165e45
Merge branch 'main' into uischema/recognizer
yeze322 Sep 17, 2020
3272ace
fix UT
yeze322 Sep 17, 2020
d403252
Merge branch 'main' into uischema/recognizer
yeze322 Sep 18, 2020
4726b4c
copyright
yeze322 Sep 18, 2020
aadac7a
del 'default' opt from crosstrain plugin
yeze322 Sep 18, 2020
7ca0e30
migrate handleRecognizerChange to seedNewRecognizer
yeze322 Sep 18, 2020
9075c0b
mark a todo
yeze322 Sep 18, 2020
5c4513d
update `seedNewRecongnizer` interface & apply to dialog modal
yeze322 Sep 18, 2020
5d01f93
Merge branch 'main' into uischema/recognizer
yeze322 Sep 18, 2020
7dd4752
Merge branch 'main' into uischema/recognizer
yeze322 Sep 21, 2020
37e8b42
Fix wording issue in comments
yeze322 Sep 21, 2020
9e39427
minor fixes on code style & comments
yeze322 Sep 21, 2020
ffcfa9a
Merge branch 'uischema/recognizer' of https://github.com/yeze322/BotF…
yeze322 Sep 21, 2020
72f3618
type the 'disabled' field strictly
yeze322 Sep 21, 2020
1ada824
more strict `isSelected()` method in CrossTrainReocognizer shema
yeze322 Sep 21, 2020
0123966
update default recognizer value
yeze322 Sep 21, 2020
b53f24d
provide 'current' and 'default' recognizer schema in useRecognizerCon…
yeze322 Sep 21, 2020
018cb2c
fix UTs
yeze322 Sep 21, 2020
b910d7e
remove custom recognizer template
yeze322 Sep 21, 2020
4769cd3
write `displayName` as function to support multi-locale
yeze322 Sep 22, 2020
eecb027
Merge branch 'main' into uischema/recognizer
yeze322 Sep 23, 2020
7f3c108
Merge branch 'main' into uischema/recognizer
yeze322 Sep 23, 2020
196b3af
Merge branch 'main' into uischema/recognizer
a-b-r-o-w-n Sep 23, 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
2 changes: 1 addition & 1 deletion Composer/packages/adaptive-form/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
const { createConfig } = require('@bfc/test-utils');

module.exports = createConfig('adaptive-form', 'react', {
coveragePathIgnorePatterns: ['defaultRecognizers.ts', 'defaultRoleSchema.ts', 'defaultUiSchema.ts'],
coveragePathIgnorePatterns: ['defaultRoleSchema.ts', 'defaultUiSchema.ts'],
});
17 changes: 8 additions & 9 deletions Composer/packages/adaptive-form/src/components/FormTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,7 @@ interface FormTitleProps {
const FormTitle: React.FC<FormTitleProps> = (props) => {
const { description, schema, formData, uiOptions = {} } = props;
const { shellApi, ...shellData } = useShellApi();
const { currentDialog } = shellData;
const recognizers = useRecognizerConfig();
const selectedRecognizer = recognizers.find((r) => r.isSelected(currentDialog?.content?.recognizer));
const { currentRecognizer: selectedRecognizer } = useRecognizerConfig();
// use a ref because the syncIntentName is debounced and we need the most current version to invoke the api
const shell = useRef({
data: shellData,
Expand All @@ -69,12 +67,13 @@ const FormTitle: React.FC<FormTitleProps> = (props) => {
debounce(async (newIntentName?: string, data?: any) => {
if (newIntentName && selectedRecognizer) {
const normalizedIntentName = newIntentName?.replace(/[^a-zA-Z0-9-_]+/g, '');
await selectedRecognizer.renameIntent(
data?.intent,
normalizedIntentName,
shell.current.data,
shell.current.api
);
typeof selectedRecognizer.renameIntent === 'function' &&
(await selectedRecognizer.renameIntent(
data?.intent,
normalizedIntentName,
shell.current.data,
shell.current.api
));
}
}, 400),
[]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import React from 'react';
import { FieldProps } from '@bfc/extension-client';
import { JsonEditor } from '@bfc/code-editor';

export const CustomRecognizerField: React.FC<FieldProps> = (props) => {
const { value, onChange } = props;
return (
<JsonEditor
key="customRecognizerField"
height={200}
id="customRecognizerField"
value={value as object}
onChange={onChange}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,29 @@
// Licensed under the MIT License.

import React from 'react';
import { FieldProps, useShellApi, useRecognizerConfig, FieldWidget } from '@bfc/extension-client';
import { FieldProps, useRecognizerConfig } from '@bfc/extension-client';
import formatMessage from 'format-message';
import { SDKKinds } from '@bfc/shared';

import { FieldLabel } from '../FieldLabel';

const IntentField: React.FC<FieldProps> = (props) => {
const { id, description, uiOptions, value, required, onChange } = props;
const { currentDialog } = useShellApi();
const recognizers = useRecognizerConfig();
const { currentRecognizer } = useRecognizerConfig();

const Editor = currentRecognizer?.intentEditor;
const label = formatMessage('Trigger phrases (intent: #{intentName})', { intentName: value });

const handleChange = () => {
onChange(value);
};

const recognizer = recognizers.find((r) => r.isSelected(currentDialog?.content?.recognizer));
let Editor: FieldWidget | undefined;
if (recognizer && recognizer.id === SDKKinds.CrossTrainedRecognizerSet) {
Editor = recognizers.find((r) => r.id === SDKKinds.LuisRecognizer)?.editor;
} else {
Editor = recognizer?.editor;
}
const label = formatMessage('Trigger phrases (intent: #{intentName})', { intentName: value });

return (
<React.Fragment>
<FieldLabel description={description} helpLink={uiOptions?.helpLink} id={id} label={label} required={required} />
{Editor ? (
<Editor {...props} onChange={handleChange} />
) : (
formatMessage('No Editor for {type}', { type: recognizer?.id })
formatMessage('No Editor for {type}', { type: currentRecognizer?.id })
)}
</React.Fragment>
);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/** @jsx jsx */
import { jsx } from '@emotion/core';
import React, { useMemo } from 'react';
import { FieldProps, useShellApi, useRecognizerConfig } from '@bfc/extension-client';
import { MicrosoftIRecognizer } from '@bfc/shared';
import { Dropdown, ResponsiveMode, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import formatMessage from 'format-message';

import { FieldLabel } from '../../FieldLabel';

import { useMigrationEffect } from './useMigrationEffect';
import { mapDropdownOptionToRecognizerSchema } from './mappers';
import { getDropdownOptions } from './getDropdownOptions';

export const RecognizerField: React.FC<FieldProps<MicrosoftIRecognizer>> = (props) => {
const { value, id, label, description, uiOptions, required, onChange } = props;
const { shellApi, ...shellData } = useShellApi();

useMigrationEffect(value, onChange);
const { recognizers: recognizerConfigs, currentRecognizer } = useRecognizerConfig();
const dropdownOptions = useMemo(() => getDropdownOptions(recognizerConfigs), [recognizerConfigs]);

const RecognizerEditor = currentRecognizer?.recognizerEditor;
const widget = RecognizerEditor ? <RecognizerEditor {...props} /> : null;

const submit = (_, option?: IDropdownOption): void => {
if (!option) return;

const recognizerDefinition = mapDropdownOptionToRecognizerSchema(option, recognizerConfigs);

const seedNewRecognizer = recognizerDefinition?.seedNewRecognizer;
const recognizerInstance =
typeof seedNewRecognizer === 'function'
? seedNewRecognizer(shellData, shellApi)
: { $kind: option.key as string, intents: [] }; // fallback to default Recognizer instance;
onChange(recognizerInstance);
};

return (
<React.Fragment>
<FieldLabel description={description} helpLink={uiOptions?.helpLink} id={id} label={label} required={required} />
<Dropdown
data-testid="recognizerTypeDropdown"
label={formatMessage('Recognizer Type')}
options={dropdownOptions}
responsiveMode={ResponsiveMode.large}
selectedKey={currentRecognizer?.id}
onChange={submit}
/>
{widget}
</React.Fragment>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { SDKKinds } from '@bfc/shared';

export const defaultRecognizerOrder = [SDKKinds.CrossTrainedRecognizerSet, SDKKinds.RegexRecognizer];

export const recognizerOrderMap: { [$kind: string]: number } = defaultRecognizerOrder.reduce((result, $kind, index) => {
result[$kind] = index;
return result;
}, {});
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { RecognizerSchema, FallbackRecognizerKey } from '@bfc/extension-client';

import { recognizerOrderMap } from './defaultRecognizerOrder';
import { mapRecognizerSchemaToDropdownOption } from './mappers';

const getRankScore = (r: RecognizerSchema) => {
// Always put disabled recognizer behind. Handle 'disabled' before 'default'.
if (r.disabled) return Number.MAX_VALUE;
// Always put default recognzier ahead.
if (r.default) return -1;
// Put fallback recognizer behind.
if (r.id === FallbackRecognizerKey) return Number.MAX_VALUE - 1;
return recognizerOrderMap[r.id] ?? Number.MAX_VALUE - 1;
};

export const getDropdownOptions = (recognizerConfigs: RecognizerSchema[]) => {
return recognizerConfigs
.filter((r) => !r.disabled)
.sort((r1, r2) => {
return getRankScore(r1) - getRankScore(r2);
})
.map(mapRecognizerSchemaToDropdownOption);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

export { RecognizerField } from './RecognizerField';
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { RecognizerSchema } from '@bfc/extension-client';
import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';

export const mapDropdownOptionToRecognizerSchema = (option: IDropdownOption, recognizerConfigs: RecognizerSchema[]) => {
return recognizerConfigs.find((r) => r.id === option.key);
};

export const mapRecognizerSchemaToDropdownOption = (recognizerSchema: RecognizerSchema): IDropdownOption => {
const { id, displayName } = recognizerSchema;
const recognizerName = typeof displayName === 'function' ? displayName({}) : displayName;
return { key: id, text: recognizerName || id };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { useShellApi, ChangeHandler } from '@bfc/extension-client';
import { useEffect } from 'react';
import { MicrosoftIRecognizer } from '@bfc/shared';

export const useMigrationEffect = (
recognizer: MicrosoftIRecognizer | undefined,
onChangeRecognizer: ChangeHandler<MicrosoftIRecognizer>
) => {
const { qnaFiles, luFiles, currentDialog, locale } = useShellApi();

useEffect(() => {
// this logic is for handling old bot with `recognizer = undefined'
if (recognizer === undefined) {
const qnaFile = qnaFiles.find((f) => f.id === `${currentDialog.id}.${locale}`);
const luFile = luFiles.find((f) => f.id === `${currentDialog.id}.${locale}`);
if (qnaFile && luFile) {
onChangeRecognizer(`${currentDialog.id}.lu.qna`);
}
}

// transform lu recognizer to crosstrained for old bot
if (recognizer === `${currentDialog.id}.lu`) {
onChangeRecognizer(`${currentDialog.id}.lu.qna`);
}
}, [recognizer]);
};
Loading