diff --git a/Composer/package.json b/Composer/package.json index f2e93589c4..04ad660b95 100644 --- a/Composer/package.json +++ b/Composer/package.json @@ -27,27 +27,21 @@ "packages/extension-client", "packages/form-dialogs", "packages/intellisense", - "packages/lib", "packages/lib/*", "packages/server", "packages/test-utils", - "packages/tools", "packages/tools/built-in-functions", - "packages/tools/language-servers", "packages/tools/language-servers/*", + "packages/types", "packages/ui-plugins/*" ], "scripts": { - "build": "node scripts/begin.js && yarn build:prod", - "build:prod": "yarn build:dev && yarn build:server && yarn build:client && yarn build:electron", - "build:dev": "yarn build:test && yarn build:lib && yarn build:tools && yarn build:extensions && yarn build:plugins && yarn l10n", - "build:test": "yarn workspace @bfc/test-utils build", - "build:lib": "yarn workspace @bfc/libs build:all", + "build": "node scripts/begin.js && yarn build:prod && yarn l10n", + "build:prod": "yarn build:dev && yarn build:client && yarn build:server && yarn build:electron", + "build:dev": "wsrun -ltm -x @bfc/electron-server -x @bfc/client -x @bfc/server -p @bfc/* -c build && yarn build:plugins", "build:electron": "yarn workspace @bfc/electron-server build && yarn workspace @bfc/electron-server l10n", - "build:extensions": "wsrun -lt -p @bfc/extension @bfc/intellisense @bfc/extension-client @bfc/adaptive-form @bfc/adaptive-flow @bfc/ui-plugin-* @bfc/form-dialogs -c build", "build:server": "yarn workspace @bfc/server build", "build:client": "yarn workspace @bfc/client build", - "build:tools": "yarn workspace @bfc/tools build:all", "build:plugins": "yarn build:plugins:localpublish && yarn build:plugins:samples && yarn build:plugins:azurePublish && yarn build:plugins:runtimes", "build:plugins:localpublish": "cd plugins/localPublish && yarn install && yarn build", "build:plugins:samples": "cd plugins/samples && yarn install && yarn build", diff --git a/Composer/packages/adaptive-flow/__tests__/adaptive-flow-editor/utils/getCustomSchema.test.ts b/Composer/packages/adaptive-flow/__tests__/adaptive-flow-editor/utils/getCustomSchema.test.ts index cd7e39d8be..320800e809 100644 --- a/Composer/packages/adaptive-flow/__tests__/adaptive-flow-editor/utils/getCustomSchema.test.ts +++ b/Composer/packages/adaptive-flow/__tests__/adaptive-flow-editor/utils/getCustomSchema.test.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { OBISchema } from '@bfc/shared'; +import { JSONSchema7 } from '@bfc/shared'; import { getCustomSchema } from '../../../src/adaptive-flow-editor/utils/getCustomSchema'; @@ -23,7 +23,7 @@ describe('getCustomSchema', () => { description: 'Send an activity.', }, }, - } as OBISchema; + } as JSONSchema7; expect(getCustomSchema({ oneOf: [], definitions: {} }, ejected)).toEqual({ actions: { oneOf: [ @@ -59,7 +59,7 @@ describe('getCustomSchema', () => { description: 'My Trigger.', }, }, - } as OBISchema; + } as JSONSchema7; expect(getCustomSchema({ oneOf: [], definitions: {} }, ejected)).toEqual({ actions: { oneOf: [ diff --git a/Composer/packages/adaptive-flow/src/adaptive-flow-editor/AdaptiveFlowEditor.tsx b/Composer/packages/adaptive-flow/src/adaptive-flow-editor/AdaptiveFlowEditor.tsx index 61c04ec80c..5377920e93 100644 --- a/Composer/packages/adaptive-flow/src/adaptive-flow-editor/AdaptiveFlowEditor.tsx +++ b/Composer/packages/adaptive-flow/src/adaptive-flow-editor/AdaptiveFlowEditor.tsx @@ -105,7 +105,7 @@ const VisualDesigner: React.FC = ({ onFocus, onBlur, schema }; const customFlowSchema: FlowUISchema = nodeContext.customSchemas.reduce((result, s) => { - const definitionKeys: string[] = Object.keys(s.definitions); + const definitionKeys = Object.keys(s.definitions ?? {}); definitionKeys.forEach(($kind) => { result[$kind] = { widget: 'ActionHeader', diff --git a/Composer/packages/adaptive-flow/src/adaptive-flow-editor/contexts/NodeRendererContext.ts b/Composer/packages/adaptive-flow/src/adaptive-flow-editor/contexts/NodeRendererContext.ts index d78c9e64e5..8f2f5f703c 100644 --- a/Composer/packages/adaptive-flow/src/adaptive-flow-editor/contexts/NodeRendererContext.ts +++ b/Composer/packages/adaptive-flow/src/adaptive-flow-editor/contexts/NodeRendererContext.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. import React from 'react'; -import { DialogFactory, OBISchema } from '@bfc/shared'; +import { DialogFactory, JSONSchema7 } from '@bfc/shared'; export interface NodeRendererContextValue { focusedId?: string; @@ -10,7 +10,7 @@ export interface NodeRendererContextValue { focusedTab?: string; clipboardActions: any[]; dialogFactory: DialogFactory; - customSchemas: OBISchema[]; + customSchemas: JSONSchema7[]; } export const defaultRendererContextValue = { diff --git a/Composer/packages/adaptive-flow/src/adaptive-flow-editor/utils/getCustomSchema.ts b/Composer/packages/adaptive-flow/src/adaptive-flow-editor/utils/getCustomSchema.ts index 959cec5e7f..e88810fef8 100644 --- a/Composer/packages/adaptive-flow/src/adaptive-flow-editor/utils/getCustomSchema.ts +++ b/Composer/packages/adaptive-flow/src/adaptive-flow-editor/utils/getCustomSchema.ts @@ -1,24 +1,24 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { OBISchema, SDKKinds } from '@bfc/shared'; +import { JSONSchema7, SDKKinds } from '@bfc/shared'; import pickBy from 'lodash/pickBy'; interface CustomSchemaSet { - actions?: OBISchema; - triggers?: OBISchema; - recognizers?: OBISchema; + actions?: JSONSchema7; + triggers?: JSONSchema7; + recognizers?: JSONSchema7; } -const pickSchema = ( - picked$kinds: SDKKinds[], - sourceSchema: { [key in SDKKinds]: OBISchema } -): OBISchema | undefined => { +type SourceSchema = { [key in SDKKinds]: JSONSchema7 }; + +const pickSchema = (picked$kinds: SDKKinds[], sourceSchema: SourceSchema): JSONSchema7 | undefined => { if (!Array.isArray(picked$kinds) || picked$kinds.length === 0) return undefined; const pickedSchema = picked$kinds.reduce( (schema, $kind) => { const definition = sourceSchema[$kind]; + schema.definitions = schema.definitions ?? {}; schema.definitions[$kind] = definition; schema.oneOf?.push({ title: definition.title || $kind, @@ -30,11 +30,13 @@ const pickSchema = ( { oneOf: [], definitions: {}, - } as OBISchema + } as JSONSchema7 ); // Sort `oneOf` list alphabetically - pickedSchema.oneOf?.sort((a, b) => (a.$ref < b.$ref ? -1 : 1)); + pickedSchema.oneOf?.sort((a, b) => { + return (a.$ref ?? '') < (b.$ref ?? '') ? -1 : 1; + }); return pickedSchema; }; @@ -47,18 +49,18 @@ const roleImplementsInterface = (interfaceName: SDKKinds, $role?: SchemaRole): b return false; }; -const isActionSchema = (schema: OBISchema) => roleImplementsInterface(SDKKinds.IDialog, schema.$role); -const isTriggerSchema = (schema: OBISchema) => roleImplementsInterface(SDKKinds.ITrigger, schema.$role); -const isRecognizerSchema = (schema: OBISchema) => +const isActionSchema = (schema: JSONSchema7) => roleImplementsInterface(SDKKinds.IDialog, schema.$role); +const isTriggerSchema = (schema: JSONSchema7) => roleImplementsInterface(SDKKinds.ITrigger, schema.$role); +const isRecognizerSchema = (schema: JSONSchema7) => roleImplementsInterface(SDKKinds.IRecognizer, schema.$role) || roleImplementsInterface(SDKKinds.IEntityRecognizer, schema.$role); -export const getCustomSchema = (baseSchema?: OBISchema, ejectedSchema?: OBISchema): CustomSchemaSet => { +export const getCustomSchema = (baseSchema?: JSONSchema7, ejectedSchema?: JSONSchema7): CustomSchemaSet => { if (!baseSchema || !ejectedSchema) return {}; if (typeof baseSchema.definitions !== 'object' || typeof ejectedSchema.definitions !== 'object') return {}; const baseDefinitions = baseSchema.definitions; - const ejectedDefinitions = ejectedSchema.definitions; + const ejectedDefinitions = ejectedSchema.definitions ?? {}; const baseKindHash = Object.keys(baseDefinitions).reduce((hash, $kind) => { hash[$kind] = true; @@ -75,9 +77,9 @@ export const getCustomSchema = (baseSchema?: OBISchema, ejectedSchema?: OBISchem return pickBy( { - actions: pickSchema(actionKinds, ejectedDefinitions), - triggers: pickSchema(triggerKinds, ejectedDefinitions), - recognizers: pickSchema(recognizerKinds, ejectedDefinitions), + actions: pickSchema(actionKinds, ejectedDefinitions as SourceSchema), + triggers: pickSchema(triggerKinds, ejectedDefinitions as SourceSchema), + recognizers: pickSchema(recognizerKinds, ejectedDefinitions as SourceSchema), }, (v) => v !== undefined ); diff --git a/Composer/packages/adaptive-form/src/components/fields/ExpressionField/utils.ts b/Composer/packages/adaptive-form/src/components/fields/ExpressionField/utils.ts index 1bf98d71f2..5a4448fcf7 100644 --- a/Composer/packages/adaptive-form/src/components/fields/ExpressionField/utils.ts +++ b/Composer/packages/adaptive-form/src/components/fields/ExpressionField/utils.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { JSONSchema7, JSONSchema7Definition, SchemaDefinitions } from '@bfc/extension-client'; +import { JSONSchema7, SchemaDefinitions } from '@bfc/extension-client'; import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; import { resolveRef, getValueType } from '../../../utils'; @@ -43,7 +43,7 @@ function getOptionLabel(schema: JSONSchema7, parent: JSONSchema7): string { } export function getOneOfOptions( - oneOf: JSONSchema7Definition[], + oneOf: JSONSchema7[], parentSchema: JSONSchema7, definitions?: SchemaDefinitions ): SchemaOption[] { diff --git a/Composer/packages/adaptive-form/src/components/fields/ObjectArrayField.tsx b/Composer/packages/adaptive-form/src/components/fields/ObjectArrayField.tsx index 169c0a7ef9..51cd4ebedc 100644 --- a/Composer/packages/adaptive-form/src/components/fields/ObjectArrayField.tsx +++ b/Composer/packages/adaptive-form/src/components/fields/ObjectArrayField.tsx @@ -6,7 +6,6 @@ import { jsx } from '@emotion/core'; import React, { useState, useMemo, useRef } from 'react'; import { FieldProps, useShellApi } from '@bfc/extension-client'; import { DefaultButton } from 'office-ui-fabric-react/lib/Button'; -import { JSONSchema7 } from 'json-schema'; import { IconButton } from 'office-ui-fabric-react/lib/Button'; import { TextField, ITextField } from 'office-ui-fabric-react/lib/TextField'; import { TooltipHost } from 'office-ui-fabric-react/lib/Tooltip'; @@ -91,7 +90,7 @@ const ObjectArrayField: React.FC> = (props) => { allOrderProps.length > 2 || orderedProperties.some((property) => Array.isArray(property)) || Object.entries(properties).some(([key, propSchema]) => { - const resolved = resolveRef(propSchema as JSONSchema7, props.definitions); + const resolved = resolveRef(propSchema, props.definitions); return allOrderProps.includes(key) && resolved.$role === 'expression'; }) ); @@ -134,7 +133,7 @@ const ObjectArrayField: React.FC> = (props) => { {...props} transparentBorder id={`${id}.${idx}`} - schema={itemSchema as JSONSchema7} + schema={itemSchema} stackArrayItems={stackArrayItems} value={item.value} {...getArrayItemProps(arrayItems, idx, handleChange)} diff --git a/Composer/packages/adaptive-form/src/components/fields/OneOfField/utils.ts b/Composer/packages/adaptive-form/src/components/fields/OneOfField/utils.ts index 0bfbadf8b7..1e744e55cc 100644 --- a/Composer/packages/adaptive-form/src/components/fields/OneOfField/utils.ts +++ b/Composer/packages/adaptive-form/src/components/fields/OneOfField/utils.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { FieldProps, JSONSchema7, JSONSchema7Definition } from '@bfc/extension-client'; +import { FieldProps, JSONSchema7, SchemaDefinitions } from '@bfc/extension-client'; import merge from 'lodash/merge'; import omit from 'lodash/omit'; import { IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; @@ -23,10 +23,7 @@ function getOptionLabel(schema: JSONSchema7): string { return type || 'unknown'; } -export function getOptions( - schema: JSONSchema7, - definitions?: { [key: string]: JSONSchema7Definition } -): IDropdownOption[] { +export function getOptions(schema: JSONSchema7, definitions?: SchemaDefinitions): IDropdownOption[] { const { type, oneOf } = schema; if (type && Array.isArray(type)) { diff --git a/Composer/packages/adaptive-form/src/utils/resolvePropSchema.ts b/Composer/packages/adaptive-form/src/utils/resolvePropSchema.ts index 12fb4b1027..7bc605f5d6 100644 --- a/Composer/packages/adaptive-form/src/utils/resolvePropSchema.ts +++ b/Composer/packages/adaptive-form/src/utils/resolvePropSchema.ts @@ -1,15 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { JSONSchema7, JSONSchema7Definition } from '@bfc/extension-client'; +import { JSONSchema7, SchemaDefinitions } from '@bfc/extension-client'; import { resolveRef } from './resolveRef'; export function resolvePropSchema( schema: JSONSchema7, path: string, - definitions: { - [k: string]: JSONSchema7Definition; - } = {} + definitions: SchemaDefinitions = {} ): JSONSchema7 | undefined { const propSchema = schema.properties?.[path]; diff --git a/Composer/packages/adaptive-form/src/utils/resolveRef.ts b/Composer/packages/adaptive-form/src/utils/resolveRef.ts index 5fa870f4d1..433ff85adb 100644 --- a/Composer/packages/adaptive-form/src/utils/resolveRef.ts +++ b/Composer/packages/adaptive-form/src/utils/resolveRef.ts @@ -1,12 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { JSONSchema7, JSONSchema7Definition } from '@bfc/extension-client'; +import { JSONSchema7, SchemaDefinitions } from '@bfc/extension-client'; import formatMessage from 'format-message'; -export function resolveRef( - schema: JSONSchema7 = {}, - definitions: { [key: string]: JSONSchema7Definition } = {} -): JSONSchema7 { +export function resolveRef(schema: JSONSchema7 = {}, definitions: SchemaDefinitions = {}): JSONSchema7 { if (typeof schema?.$ref === 'string') { if (!schema?.$ref?.startsWith('#/definitions/')) { return schema; diff --git a/Composer/packages/client/.gitignore b/Composer/packages/client/.gitignore index de820129fc..b612041ef0 100644 --- a/Composer/packages/client/.gitignore +++ b/Composer/packages/client/.gitignore @@ -1,2 +1,3 @@ build/ public/*-bundle.js +public/plugin-host-preload.js diff --git a/Composer/packages/client/config/extensions.config.js b/Composer/packages/client/config/extensions.config.js new file mode 100644 index 0000000000..c1fe1357a8 --- /dev/null +++ b/Composer/packages/client/config/extensions.config.js @@ -0,0 +1,103 @@ +const path = require('path'); + +const PnpWebpackPlugin = require('pnp-webpack-plugin'); +const TerserPlugin = require('terser-webpack-plugin'); + +const paths = require('./paths'); + +module.exports = (webpackEnv) => { + const isEnvDevelopment = webpackEnv === 'development'; + const isEnvProduction = webpackEnv === 'production'; + + return [ + { + entry: { + 'react-bundle': 'react', + }, + mode: isEnvProduction ? 'production' : 'development', + // export react globally under a variable named React + output: { + path: path.resolve(__dirname, '../public'), + library: 'React', + libraryTarget: 'var', + }, + resolve: { + extensions: ['.js'], + }, + optimization: { + minimize: isEnvProduction, + minimizer: [ + new TerserPlugin({ + extractComments: false, + }), + ], + }, + }, + { + entry: { + 'react-dom-bundle': 'react-dom', + }, + mode: isEnvProduction ? 'production' : 'development', + // export react-dom globally under a variable named ReactDOM + output: { + path: path.resolve(__dirname, '../public'), + library: 'ReactDOM', + libraryTarget: 'var', + }, + externals: { + // ReactDOM depends on React, but we need this to resolve to the globally-exposed React variable in react-bundle.js (created by extensions.config.js). + // If we don't do this, ReactDom will bundle its own copy of React and we will have 2 copies which breaks hooks. + react: 'React', + }, + resolve: { + extensions: ['.js'], + }, + optimization: { + minimize: isEnvProduction, + minimizer: [ + new TerserPlugin({ + extractComments: false, + }), + ], + }, + }, + { + mode: isEnvProduction ? 'production' : 'development', + entry: { + 'plugin-host-preload': path.resolve(__dirname, '../extension-container/plugin-host-preload.tsx'), + }, + output: { + path: path.resolve(__dirname, '../public'), + }, + externals: { + // expect react & react-dom to be available in the extension host iframe globally under "React" and "ReactDOM" variables + react: 'React', + 'react-dom': 'ReactDOM', + }, + resolve: { + extensions: ['.js'], + plugins: [PnpWebpackPlugin], + }, + resolveLoader: { + plugins: [ + // Also related to Plug'n'Play, but this time it tells Webpack to load its loaders + // from the current package. + PnpWebpackPlugin.moduleLoader(module), + ], + }, + module: { + rules: [ + { + test: /\.tsx?$/, + loader: require.resolve('ts-loader'), + include: [path.resolve(__dirname, '../extension-container')], + options: PnpWebpackPlugin.tsLoaderOptions({ + transpileOnly: true, + configFile: path.resolve(__dirname, '../tsconfig.build.json'), + }), + }, + ], + }, + }, + ]; +}; diff --git a/Composer/packages/client/config/webpack-react-dom.config.js b/Composer/packages/client/config/webpack-react-dom.config.js deleted file mode 100644 index 4e325e745c..0000000000 --- a/Composer/packages/client/config/webpack-react-dom.config.js +++ /dev/null @@ -1,22 +0,0 @@ -const { resolve } = require('path'); - -module.exports = { - entry: { - 'react-dom-bundle': 'react-dom', - }, - mode: 'production', - // export react-dom globally under a variable named ReactDOM - output: { - path: resolve(__dirname, '../public'), - library: 'ReactDOM', - libraryTarget: 'var', - }, - externals: { - // ReactDOM depends on React, but we need this to resolve to the globally-exposed React variable in react-bundle.js (created by webpack-react.config.js). - // If we don't do this, ReactDom will bundle its own copy of React and we will have 2 copies which breaks hooks. - react: 'React', - }, - resolve: { - extensions: ['.js'], - }, -}; diff --git a/Composer/packages/client/config/webpack-react.config.js b/Composer/packages/client/config/webpack-react.config.js deleted file mode 100644 index 711737994a..0000000000 --- a/Composer/packages/client/config/webpack-react.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const { resolve } = require('path'); - -module.exports = { - entry: { - 'react-bundle': 'react', - }, - mode: 'production', - // export react globally under a variable named React - output: { - path: resolve(__dirname, '../public'), - library: 'React', - libraryTarget: 'var', - }, - resolve: { - extensions: ['.js'], - }, -}; diff --git a/Composer/packages/client/public/plugin-host-preload.js b/Composer/packages/client/extension-container/plugin-host-preload.tsx similarity index 72% rename from Composer/packages/client/public/plugin-host-preload.js rename to Composer/packages/client/extension-container/plugin-host-preload.tsx index 688fa7b79f..13117fd1ac 100644 --- a/Composer/packages/client/public/plugin-host-preload.js +++ b/Composer/packages/client/extension-container/plugin-host-preload.tsx @@ -1,3 +1,14 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import ReactDOM from 'react-dom'; + +if (!document.head.title) { + const title = document.createElement('title'); + title.innerHTML = 'Plugin Host'; + document.head.append(title); +} + // add default doc styles if (!document.getElementById('plugin-host-default-styles')) { const styles = document.createElement('style'); @@ -23,7 +34,8 @@ if (!document.getElementById('plugin-root')) { } // initialize the API object window.Composer = {}; + // init the render function -window.Composer['render'] = function (component) { +window.Composer.render = function (component) { ReactDOM.render(component, document.getElementById('plugin-root')); }; diff --git a/Composer/packages/client/package.json b/Composer/packages/client/package.json index b9417f2435..4c0aab0466 100644 --- a/Composer/packages/client/package.json +++ b/Composer/packages/client/package.json @@ -8,9 +8,9 @@ "node": ">=12" }, "scripts": { - "start": "yarn build:react-bundles && node scripts/start.js", + "start": "yarn build:extension-bundles && node scripts/start.js", "build": "node --max_old_space_size=4096 scripts/build.js", - "build:react-bundles": "webpack --config ./config/webpack-react.config.js && webpack --config ./config/webpack-react-dom.config.js", + "build:extension-bundles": "webpack --config ./config/extensions.config.js", "clean": "rimraf build", "test": "jest", "lint": "eslint --quiet --ext .js,.jsx,.ts,.tsx ./src ./__tests__", diff --git a/Composer/packages/client/public/index.html b/Composer/packages/client/public/index.html index f07ec70b3f..047330b0d4 100644 --- a/Composer/packages/client/public/index.html +++ b/Composer/packages/client/public/index.html @@ -36,7 +36,7 @@ }; window.CSPSettings = { - nonce: window.__nonce__ + nonce: window.__nonce__ }; diff --git a/Composer/packages/client/src/components/PluginHost/PluginHost.tsx b/Composer/packages/client/src/components/PluginHost/PluginHost.tsx index 1b801b878e..07957cd8df 100644 --- a/Composer/packages/client/src/components/PluginHost/PluginHost.tsx +++ b/Composer/packages/client/src/components/PluginHost/PluginHost.tsx @@ -13,8 +13,9 @@ import { iframeStyle } from './styles'; interface PluginHostProps { extraIframeStyles?: SerializedStyles[]; - pluginName?: string; - pluginType?: PluginType; + pluginName: string; + pluginType: PluginType; + bundleId: string; } /** Binds closures around Composer client code to plugin iframe's window object */ @@ -41,7 +42,7 @@ export const PluginHost: React.FC = (props) => { const { extraIframeStyles = [] } = props; useEffect(() => { - const { pluginName, pluginType } = props; + const { pluginName, pluginType, bundleId } = props; // renders the plugin's UI inside of the iframe const renderPluginView = async () => { if (pluginName && pluginType) { @@ -62,13 +63,14 @@ export const PluginHost: React.FC = (props) => { const cb = () => { resolve(); }; + const bundleUri = `/api/extensions/${pluginName}/${bundleId}`; // If plugin bundles end up being too large and block the client thread due to the load, enable the async flag on this call - injectScript(iframeDocument, pluginScriptId, `/api/extensions/${pluginName}/view/${pluginType}`, false, cb); + injectScript(iframeDocument, pluginScriptId, bundleUri, false, cb); }); } }; renderPluginView(); - }, [props.pluginName, props.pluginType, targetRef]); + }, [props.pluginName, props.pluginType, props.bundleId, targetRef]); return ; }; diff --git a/Composer/packages/client/src/pages/language-generation/code-editor.tsx b/Composer/packages/client/src/pages/language-generation/code-editor.tsx index 30e5ec6aba..aa6cfd03ac 100644 --- a/Composer/packages/client/src/pages/language-generation/code-editor.tsx +++ b/Composer/packages/client/src/pages/language-generation/code-editor.tsx @@ -13,7 +13,7 @@ import { RouteComponentProps } from '@reach/router'; import querystring from 'query-string'; import { CodeEditorSettings } from '@bfc/shared'; import { useRecoilValue } from 'recoil'; -import { LgFile } from '@bfc/shared/src/types/indexers'; +import { LgFile } from '@bfc/extension-client'; import { localeState, lgFilesState, settingsState } from '../../recoilModel/atoms/botState'; import { userSettingsState, dispatcherState } from '../../recoilModel'; diff --git a/Composer/packages/client/src/pages/plugin/pluginPageContainer.tsx b/Composer/packages/client/src/pages/plugin/pluginPageContainer.tsx index 662b0ca484..c589300d45 100644 --- a/Composer/packages/client/src/pages/plugin/pluginPageContainer.tsx +++ b/Composer/packages/client/src/pages/plugin/pluginPageContainer.tsx @@ -6,10 +6,14 @@ import { RouteComponentProps } from '@reach/router'; import { PluginHost } from '../../components/PluginHost/PluginHost'; -const PluginPageContainer: React.FC> = (props) => { - const { pluginId } = props; +const PluginPageContainer: React.FC> = (props) => { + const { pluginId, bundleId } = props; - return ; + if (!pluginId || !bundleId) { + return null; + } + + return ; }; export { PluginPageContainer }; diff --git a/Composer/packages/client/src/pages/publish/createPublishTarget.tsx b/Composer/packages/client/src/pages/publish/createPublishTarget.tsx index cc9fe43042..f897f60595 100644 --- a/Composer/packages/client/src/pages/publish/createPublishTarget.tsx +++ b/Composer/packages/client/src/pages/publish/createPublishTarget.tsx @@ -73,8 +73,8 @@ const CreatePublishTarget: React.FC = (props) => { return targetType ? props.types.find((t) => t.name === targetType)?.schema : undefined; }, [props.targets, targetType]); - const hasView = useMemo(() => { - return targetType ? props.types.find((t) => t.name === targetType)?.hasView : undefined; + const targetBundleId = useMemo(() => { + return targetType ? props.types.find((t) => t.name === targetType)?.bundleId : undefined; }, [props.targets, targetType]); const updateName = (e, newName) => { @@ -85,7 +85,7 @@ const CreatePublishTarget: React.FC = (props) => { const saveDisabled = useMemo(() => { const disabled = !targetType || !name || !!errorMessage; - if (hasView) { + if (targetBundleId) { // plugin config must also be valid return disabled || !pluginConfigIsValid; } @@ -107,13 +107,14 @@ const CreatePublishTarget: React.FC = (props) => { }; const publishTargetContent = useMemo(() => { - if (hasView && targetType) { + if (targetBundleId && targetType) { // render custom plugin view return ( ); } @@ -133,7 +134,7 @@ const CreatePublishTarget: React.FC = (props) => {