Skip to content

Commit

Permalink
feat: add adaptive-form and extension packages (#2118)
Browse files Browse the repository at this point in the history
* extract visual editor from design page

* bump shared packages

* add botframework-ui dependencies

* extract property editor from design page

* don't pass rootPath as a prop

* [wip] use adaptive form package

* don't hoist botframework-ui packages

* start stubbing out sync based new shell api

* bump prompts plugin

* revert to using shell extension container to render new form

* add extension and adaptive form packages

* update jest config to include display name

* import json and prompts plugins

* convert code editor to @monaco-editor package

* render string field for expressions

* remove height transition when there is an error

* feat: Added select dialog ui plugin (#1)

* feat: Added select dialog ui plugin

* Apply suggestions from code review

* Added tests

* Clean up

* Updated tests

* renamed directory to select-dialog

Co-authored-by: Andy Brown <asbrown002@gmail.com>

* enable json ui plugin

* allow customization of $role and $kind fields

* [wip] begin lg editor field

* fix height calculation

* fix: Set default value in StringField to an empty string (#2)

* use field name for lg fields

* ignore lg lib

* refactor plugin config

add roleSchema and kindSchema

* clean up lg plugin dependencies

* drop ui prefix for ui options

* bump @types/react and @types/react-dom

* initial support of recognizers in plugin config

* initial lu ui plugin

* fix: Fixed object array border conflict (#3)

* fix: Fixed object array border conflict

* Modified getUISchema function

* Resolve build errors

* Fixed uiOptions in SchemaField

* Reverted changes to getUISchema

* [wip] start work on rendering better descriptions and help links

* finish rendering description and help links

* re-renable custom keybinding

* clean up old bfcomposer monaco editor bits

* fix build errors

* do not enable minimap by default

* feat: Add Select Dialog Plugin

* Updated defaultUiSchema

* Added select dialog plugin

* fixed issue in uiSchema

* Fixed luIntentOptions

* Added help link

* Modified tests

* Fixed tests

* move shared types from indexers to shared

* fix merge issue

* fix lint error

* do not compile with test files

* move prompt settings to 'Other' tab

* fix: Moved prompt settings to 'Other' tab

* fix: prompt settings styling and description

* wrap labels in formatMessage

Co-authored-by: Andy Brown <asbrown002@gmail.com>

* move globally hidden fields to getOrderedProperties

* [wip] add ability to have multi field rows

* make sure to pass value to form rows

* use json schema version 7 for base typings

* add one of field

* begin work on expression editor

* update prompt plugin to use json schema v 7

* feat: Updated FormRow to support multiple fields in a row

* feat: Updated FormRow to support multiple fields in a row

* Updated FormRow

* Updated FormRow

* fix problem with yarn install

* bump react versions

* fix merge conflicts

* correctly hide placeholder in code editor

* remove inline recognizer editor

* remove select intent plugin

* add key to editor to force remounting

* handle type and oneOf expression schemas

* port inline luis intent editor

* memoize initial value

* rename lu plugin to luis

* port regex intent editor

* fix: Moved type selector to be inline with label (#7)

* fix: Fixed warning related to link navigation styling (#8)

* rename handleChange to handleRecognizerChange

* add method to recognizer config to determine if selected

* refactor code editors to not have dependency on monaco-editor package directly

* downgrade monaco-languageclient

There is an error initializing the language services

* export OnInit type

* clean up monaco dependencies

* update sample schema

* render all other fields on single row

sets up support for defaultValue exression editor

* render json editor with selected schema for complex types

* feat: Added custom array field for set properties

* feat: Added stackArrayItems to UiOptions

* fix: Fixed array item borders

* add designerId to ShellData

formContext.dialogId is actually data.$designer.id which is confusing when there is dialogId in the ShellData.

* feat: Updated ObjectArrayField to display complex arrays in a stacked layout

* fix: Filtered object array properties to reflect ui order

* removed console.log

* fix: Fixed ExpressionField flicker

* feat: Added add button for stacked array items

* add schema prop to json editor

* updated defautUiSchema.ts

* register schemas on a per-model basis

* fix merge build issue

* trigger intent field change when editor changes

* fix: Added 'expression' to expression type dropdown.

* add disabled item actions for new array item

* reduce height of lg field

* pass raw errors to schema field child

* plumb errors through the prompt form

* fix array item styles when an error is present

* use label overrides from ConceptLabels in form title

* pass project id to lg editor

* fix: Added 'expression' to type selector

* implement arrayitem wrapper for array fields

* fix: Added helpLinks to defaultUiSchema

* add useArrayItems hook for array fields

* fix: Added 'expression' to type selector

* fix: added 'expression' to type dropdown

* fix: combined 'selectedSchema' and 'selectedKey' into 'selectedOption'

* feat: Added inline lu to prompts

* do not override descriptions for prompt fields

* fix array item usage

* support expression fields with object properties

* add subtitle to uiSchema

* add titles to choices and confirmChoices

* do not use label overrides in form title

* [wip] use schema field to render all input fields

* update ui schema

* correctly set selected option

* fix: fixed array item styles

* feat: added formatData to uiOptions

* fix: Added formatData to ObjectArrayField

* default to correct type in expression editor

* start case the fallback labels

* allow labels for objects with properties

* combine choice input and confirm input components

* handle enum expressions

* feat: Removed formatData in favor of serializer

* fix: Fixed serializer labeling

* Updated jest.config.js

* fix: fixed recognizer in prompts

* fix: fixed getSelectedOption returning expression option for strings

* fix unit tests

* Removed select intent

* Fixed luis handleRecognizerChange method

* fix merge issue

* fixed error message displaying next to field in an array

* removed kindSchema comments

* update error message when recognizer can't be determined

* add testid to expression dropdown

* fix todo spec

* fix notifications page spec

* remove obiformeditor package

* fix new LGTM alerts

* incorporate locale when setting lg file name

* fix selecting correct lu file with locale

* sync data with shell to support undo/redo

* update oneOf field to handle array of types

* do not use transparent border for one of fields

* do not have transparent border for expression editor

It looks weird with the prefix icon

* fix: Fixed dropdownWidth in expressions

* fix: Fixed inline array styling

* fix: removed unused variable

* fix: Fixed lint issue

* get localize lu file for inline intent editor

* fix: Fixed error rendering issue

* fix: Fixed schema field styles

Co-authored-by: TJ Durnford <tjdford@gmail.com>
  • Loading branch information
a-b-r-o-w-n and tdurnford authored Mar 26, 2020
1 parent 23a84cb commit 0a9a9ea
Show file tree
Hide file tree
Showing 330 changed files with 7,250 additions and 8,199 deletions.
2 changes: 1 addition & 1 deletion Composer/.eslintrc.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module.exports = {
plugins: ['react-hooks', 'format-message', 'emotion'],
settings: {
react: {
version: '16.9.0',
version: '16.9.16',
},
},
parserOptions: {
Expand Down
2 changes: 1 addition & 1 deletion Composer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Composer is managed via yarn workspaces, producing such a folder layout.
|- server // composer api server
|- extensions
|- package.json // put all extension as one package
|- obiformeditor // dialog property editor
|- adaptive-form // dialog property editor
|- lib
|- shared // shared code
```
Expand Down
8 changes: 7 additions & 1 deletion Composer/cypress/integration/NotificationPage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,13 @@ context('Notification Page', () => {

cy.withinEditor('FormEditor', () => {
cy.findByText('Condition').should('exist');
cy.get('.ObjectItem input').type('()');
cy.findByTestId('expression-type-dropdown-Condition')
.focus()
.type('{downarrow}')
.should('contain.text', 'expression');
cy.get('#root\\.condition')
.click()
.type('()');
});

cy.get('[data-testid="notifications-info-button"]').click();
Expand Down
1 change: 1 addition & 0 deletions Composer/cypress/integration/ToDoBot.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ context('ToDo Bot', () => {
before(() => {
cy.visit(Cypress.env('COMPOSER_URL'));
cy.createBot('TodoSample');
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(5000);
});

Expand Down
1 change: 1 addition & 0 deletions Composer/cypress/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ beforeEach(() => {
});

after(() => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(500);
cy.exec('yarn test:integration:clean');
});
11 changes: 9 additions & 2 deletions Composer/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,18 @@ module.exports = {
testPathIgnorePatterns: ['/node_modules/', '/scripts/', '/jestMocks/', '__tests__/setup.(j|t)s', '/cypress/'],
projects: [
'<rootDir>/packages/client',
'<rootDir>/packages/server',
'<rootDir>/packages/extensions/obiformeditor',
'<rootDir>/packages/extensions/adaptive-form',
'<rootDir>/packages/extensions/extension',
'<rootDir>/packages/extensions/visual-designer',
'<rootDir>/packages/lib/code-editor',
'<rootDir>/packages/lib/shared',
'<rootDir>/packages/server',
'<rootDir>/packages/tools/language-servers/language-generation',
'<rootDir>/packages/ui-plugins/expressions',
'<rootDir>/packages/ui-plugins/json',
'<rootDir>/packages/ui-plugins/lg',
'<rootDir>/packages/ui-plugins/luis',
'<rootDir>/packages/ui-plugins/prompts',
'<rootDir>/packages/ui-plugins/select-dialog',
],
};
8 changes: 5 additions & 3 deletions Composer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"license": "MIT",
"private": true,
"resolutions": {
"@types/react": "16.9.0"
"@types/react": "16.9.23"
},
"engines": {
"node": ">=12"
Expand All @@ -17,14 +17,15 @@
"packages/lib/*",
"packages/tools",
"packages/tools/language-servers",
"packages/tools/language-servers/*"
"packages/tools/language-servers/*",
"packages/ui-plugins/*"
],
"scripts": {
"build": "node scripts/update.js && node scripts/begin.js && yarn build:prod && yarn build:plugins",
"build:prod": "yarn build:dev && yarn build:server && yarn build:client",
"build:dev": "yarn build:lib && yarn build:tools && yarn build:extensions && yarn build:plugins",
"build:lib": "yarn workspace @bfc/libs build:all",
"build:extensions": "yarn workspace @bfc/extensions build:all",
"build:extensions": "wsrun -lt -p @bfc/extension @bfc/adaptive-form @bfc/visual-designer @bfc/ui-plugin-* -c build",
"build:server": "yarn workspace @bfc/server build",
"build:client": "yarn workspace @bfc/client build",
"build:tools": "yarn workspace @bfc/tools build:all",
Expand Down Expand Up @@ -71,6 +72,7 @@
"@cypress/webpack-preprocessor": "^4.1.1",
"@emotion/babel-preset-css-prop": "^10.0.17",
"@testing-library/cypress": "^5.2.1",
"@types/jest": "^25.1.3",
"@typescript-eslint/eslint-plugin": "2.10.0",
"@typescript-eslint/parser": "2.10.0",
"babel-jest": "24.0.0",
Expand Down
5 changes: 0 additions & 5 deletions Composer/packages/client/config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeM
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const MonacoWebpackPlugin = require('@bfcomposer/monaco-editor-webpack-plugin');

const getClientEnvironment = require('./env');
const paths = require('./paths');
Expand Down Expand Up @@ -404,10 +403,6 @@ module.exports = function(webpackEnv) {
],
},
plugins: [
new MonacoWebpackPlugin({
// available options are documented at https://github.com/Microsoft/monaco-editor-webpack-plugin#options
languages: ['markdown', 'json'],
}),
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
Expand Down
10 changes: 9 additions & 1 deletion Composer/packages/client/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// eslint-disable-next-line
const path = require('path');
module.exports = {
displayName: 'client',
preset: 'ts-jest/presets/js-with-ts',
// transform: {
// '^.+\\.tsx?$': 'ts-jest',
Expand All @@ -19,7 +20,14 @@ module.exports = {

'^@src/(.*)$': '<rootDir>/src/$1',
},
testPathIgnorePatterns: ['/node_modules/', '/jestMocks/', '/testUtils/', '__tests__/setupTests.ts', '.*\\.d\\.ts'],
testPathIgnorePatterns: [
'/node_modules/',
'/jestMocks/',
'__mocks__',
'/testUtils/',
'__tests__/setupTests.ts',
'.*\\.d\\.ts',
],
// Some node modules are packaged and distributed in a non-transpiled form
// (ex. contain import & export statements); and Jest won't be able to
// understand them because node_modules aren't transformed by default. So
Expand Down
24 changes: 17 additions & 7 deletions Composer/packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,24 @@
},
"proxy": "http://localhost:5000",
"dependencies": {
"@bfc/adaptive-form": "*",
"@bfc/code-editor": "*",
"@bfc/extensions": "*",
"@bfc/extension": "*",
"@bfc/indexers": "*",
"@bfc/shared": "*",
"@bfc/ui-plugin-expressions": "*",
"@bfc/ui-plugin-json": "*",
"@bfc/ui-plugin-lg": "*",
"@bfc/ui-plugin-luis": "*",
"@bfc/ui-plugin-prompts": "*",
"@bfc/ui-plugin-select-dialog": "*",
"@bfc/visual-designer": "*",
"@emotion/core": "^10.0.7",
"@microsoft/bf-lu": "^4.9.0-preview.115707",
"@reach/router": "^1.2.1",
"@uifabric/fluent-theme": "^7.1.13",
"@uifabric/icons": "^7.3.4",
"@uifabric/styling": "^7.10.4",
"adaptive-expressions": "^4.8.0-preview-110700",
"axios": "^0.18.0",
"botbuilder-lg": "^4.8.0-preview-109324",
Expand All @@ -31,13 +42,13 @@
"jwt-decode": "^2.2.0",
"lodash": "^4.17.15",
"nanoid": "^2.1.6",
"office-ui-fabric-react": "7.37.1",
"office-ui-fabric-react": "^7.88.1",
"prop-types": "^15.7.2",
"query-string": "^6.8.2",
"react": "16.9.0",
"react": "16.13.0",
"react-app-polyfill": "^0.2.1",
"react-dev-utils": "^7.0.3",
"react-dom": "16.9.0",
"react-dom": "16.13.0",
"react-frame-component": "^4.0.2",
"react-timeago": "^4.4.0",
"styled-components": "^4.1.3"
Expand All @@ -56,15 +67,14 @@
"@babel/preset-env": "7.3.0",
"@babel/preset-react": "7.0.0",
"@babel/runtime": "7.3.4",
"@bfcomposer/monaco-editor-webpack-plugin": "^1.7.2",
"@emotion/babel-preset-css-prop": "^10.0.14",
"@svgr/webpack": "4.1.0",
"@types/jest": "^24.0.16",
"@types/jwt-decode": "^2.2.1",
"@types/lodash": "^4.14.146",
"@types/reach__router": "^1.2.4",
"@types/react": "16.9.0",
"@types/react-dom": "16.9.0",
"@types/react": "16.9.23",
"@types/react-dom": "16.9.5",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "9.0.0",
"babel-jest": "24.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const dropdown: Partial<IDropdownStyles> = {
subComponentStyles: {
label: textFieldlabel,
panel: {},
multiSelectItem: {},
},
// root: [
// {
Expand Down
4 changes: 3 additions & 1 deletion Composer/packages/client/src/ShellApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@ export const ShellApi: React.FC = () => {
return {} as ShellData;
}

const data = getData(sourceWindow);
return {
data: getData(sourceWindow),
data,
locale,
botName,
projectId,
Expand All @@ -108,6 +109,7 @@ export const ShellApi: React.FC = () => {
luFiles,
currentDialog,
dialogId,
designerId: get(data, '$designer.id'),
focusedEvent: selected,
focusedActions: focused ? [focused] : [],
focusedSteps: focused ? [focused] : selected ? [selected] : [],
Expand Down
2 changes: 1 addition & 1 deletion Composer/packages/client/src/TestController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner';
import { Callout } from 'office-ui-fabric-react/lib/Callout';
import { Stack } from 'office-ui-fabric-react/lib/Stack';
import formatMessage from 'format-message';
import { DiagnosticSeverity, Diagnostic } from '@bfc/indexers';
import { DiagnosticSeverity, Diagnostic } from '@bfc/shared';

import settingsStorage from './utils/dialogSettingStorage';
import { StoreContext } from './store';
Expand Down
17 changes: 8 additions & 9 deletions Composer/packages/client/src/components/NavItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

/** @jsx jsx */
import { jsx } from '@emotion/core';
import { useCallback, useContext, useState } from 'react';
import { Link, LinkGetProps } from '@reach/router';
import { useCallback, useContext } from 'react';
import { Link } from '@reach/router';
import { CommandBarButton } from 'office-ui-fabric-react/lib/Button';

import { StoreContext } from '../../store';
import { useLocation } from '../../utils/hooks';

import { link, outer, commandBarButton } from './styles';

Expand All @@ -31,20 +32,18 @@ export const NavItem: React.FC<INavItemProps> = props => {
actions: { onboardingAddCoachMarkRef },
} = useContext(StoreContext);

const { to, exact, iconName, labelName, disabled } = props;
const [active, setActive] = useState(false);
const { to, iconName, labelName, disabled } = props;
const {
location: { pathname },
} = useLocation();
const active = pathname.startsWith(to);

const addRef = useCallback(ref => onboardingAddCoachMarkRef({ [`nav${labelName.replace(' ', '')}`]: ref }), []);

return (
<Link
to={to}
css={link(active, disabled)}
getProps={(props: LinkGetProps) => {
const isActive = exact ? props.isCurrent : props.isPartiallyCurrent;
setActive(isActive);
return {};
}}
data-testid={'LeftNav-CommandBarButton' + labelName}
aria-disabled={disabled}
aria-label={labelName}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ import { Stack } from 'office-ui-fabric-react/lib/Stack';
import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
import { Dropdown } from 'office-ui-fabric-react/lib/Dropdown';
import { TextField } from 'office-ui-fabric-react/lib/TextField';
import { DialogInfo, luIndexer, combineMessage } from '@bfc/indexers';
import { luIndexer, combineMessage } from '@bfc/indexers';
import get from 'lodash/get';
import { DialogInfo } from '@bfc/shared';
import { LuEditor } from '@bfc/code-editor';

import {
Expand Down Expand Up @@ -265,7 +266,7 @@ export const TriggerCreationModal: React.FC<TriggerCreationModalProps> = props =
<LuEditor
onChange={onTriggerPhrasesChange}
value={formData.triggerPhrases}
errorMsg={formData.errors.triggerPhrases}
errorMessage={formData.errors.triggerPhrases}
hidePlaceholder={true}
luOption={{
projectId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { SearchBox } from 'office-ui-fabric-react/lib/SearchBox';
import { IIconProps } from 'office-ui-fabric-react/lib/Icon';
import cloneDeep from 'lodash/cloneDeep';
import formatMessage from 'format-message';
import { DialogInfo, ITrigger } from '@bfc/indexers';
import { DialogInfo, ITrigger } from '@bfc/shared';

import { StoreContext } from '../../store';
import { createSelectedPath, getFriendlyName } from '../../utils';
Expand Down
8 changes: 4 additions & 4 deletions Composer/packages/client/src/extension-container/EditorMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// Licensed under the MIT License.

// this is currently hard-coded here
import FormEditor from '@bfc/extensions/obiformeditor';
import VisualDesigner from '@bfc/extensions/visual-designer';
import VisualDesigner from '@bfc/visual-designer';
import AdaptiveForm from '@bfc/adaptive-form';

const getEditor = (): typeof VisualDesigner | typeof FormEditor | null => {
const getEditor = (): typeof VisualDesigner | typeof AdaptiveForm | null => {
// i'm now more towarding pick editor based on name, not data
// because we want shell to totally control file read/save
// which means each editor cann't be differiante by data
Expand All @@ -14,7 +14,7 @@ const getEditor = (): typeof VisualDesigner | typeof FormEditor | null => {
}

if (window.name === 'FormEditor') {
return FormEditor;
return AdaptiveForm;
}
return null;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import React, { useState, useEffect } from 'react';
import { initializeIcons } from '@uifabric/icons';
import { ShellData, ShellApi } from '@bfc/shared';
import Extension from '@bfc/extension';

import ApiClient from '../messenger/ApiClient';

import getEditor from './EditorMap';
import plugins from './plugins';

import './extensionContainer.css';

Expand Down Expand Up @@ -181,7 +183,21 @@ function ExtensionContainer() {

const RealEditor = shellData.data ? getEditor() : null;

return RealEditor && <RealEditor {...shellData} onChange={shellApi.saveData} shellApi={shellApi} />;
return (
RealEditor && (
<Extension shell={shellApi} shellData={shellData}>
<RealEditor
key={shellData.focusPath}
{...shellData}
onChange={shellApi.saveData}
shellApi={shellApi}
formData={shellData.data}
plugins={plugins}
schema={shellData.schemas?.sdk?.content}
/>
</Extension>
)
);
}

export default ExtensionContainer;
10 changes: 10 additions & 0 deletions Composer/packages/client/src/extension-container/plugins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import json from '@bfc/ui-plugin-json';
import expressions from '@bfc/ui-plugin-expressions';
import prompts from '@bfc/ui-plugin-prompts';
import selectDialog from '@bfc/ui-plugin-select-dialog';
import lg from '@bfc/ui-plugin-lg';
import lu from '@bfc/ui-plugin-luis';

export default [json, prompts, selectDialog, lg, lu, expressions];
Loading

0 comments on commit 0a9a9ea

Please sign in to comment.