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
52 commits
Select commit Hold shift + click to select a range
2ba9e39
decompose shell and api into smaller types
a-b-r-o-w-n Oct 8, 2020
89eb970
nest plugin pages under bot scope
a-b-r-o-w-n Oct 9, 2020
827a071
simplify webpack config
a-b-r-o-w-n Oct 9, 2020
25cce5d
make extension client external
a-b-r-o-w-n Oct 9, 2020
215405f
add mechanism to sync client shell to iframe plugin host
a-b-r-o-w-n Oct 12, 2020
edb859e
only fetch extensions when app mounts
a-b-r-o-w-n Oct 12, 2020
43feb20
add plugin pages selector
a-b-r-o-w-n Oct 12, 2020
1f162a8
output source maps with extension bundles
a-b-r-o-w-n Oct 12, 2020
2b497b8
rename file
a-b-r-o-w-n Oct 12, 2020
3550723
clean up manifest after loading extensions
a-b-r-o-w-n Oct 12, 2020
2b0ab78
add project api hook
a-b-r-o-w-n Oct 12, 2020
ed28e6d
update sample plugin to use project api
a-b-r-o-w-n Oct 12, 2020
0fd405d
Merge branch 'main' into abrown/extensions/page-api
a-b-r-o-w-n Oct 12, 2020
3840930
Merge branch 'main' into abrown/extensions/page-api
a-b-r-o-w-n Oct 13, 2020
7df7985
disable sample-ui-plugin
a-b-r-o-w-n Oct 13, 2020
96f8138
do not sync store to window
a-b-r-o-w-n Oct 13, 2020
6adfabb
Merge branch 'main' into abrown/extensions/page-api
a-b-r-o-w-n Oct 14, 2020
9d11484
prepare test-utils and types for publishing
a-b-r-o-w-n Oct 14, 2020
3239a94
update package references to published pacakges
a-b-r-o-w-n Oct 14, 2020
90fbbb4
add types package
a-b-r-o-w-n Oct 14, 2020
caceb06
remove shared dependency from extension-client
a-b-r-o-w-n Oct 13, 2020
cb10bd4
remove data from shell
a-b-r-o-w-n Oct 13, 2020
b2e7bf1
more types updates
a-b-r-o-w-n Oct 14, 2020
5d19a6d
add useFormHook to expose current form data
a-b-r-o-w-n Oct 14, 2020
09235d7
Merge branch 'main' into abrown/extensions/page-api
a-b-r-o-w-n Oct 14, 2020
5b928c6
Merge branch 'abrown/extensions/page-api' into abrown/extensions/hook…
a-b-r-o-w-n Oct 14, 2020
7ca96a6
re-order useEffects
a-b-r-o-w-n Oct 14, 2020
6320acc
Merge branch 'abrown/extensions/page-api' into abrown/extensions/hook…
a-b-r-o-w-n Oct 14, 2020
e35cc61
Merge branch 'main' into abrown/extensions/page-api
a-b-r-o-w-n Oct 14, 2020
eccd4f1
Merge branch 'abrown/extensions/page-api' into abrown/extensions/hook…
a-b-r-o-w-n Oct 14, 2020
067e798
Merge branch 'main' into abrown/extensions/page-api
a-b-r-o-w-n Oct 14, 2020
36aec9b
Merge branch 'abrown/extensions/page-api' into abrown/extensions/hook…
a-b-r-o-w-n Oct 14, 2020
10d62cb
add missing import
a-b-r-o-w-n Oct 14, 2020
a787063
move types to dependencies
a-b-r-o-w-n Oct 14, 2020
c1cd2a0
fix type errors
a-b-r-o-w-n Oct 14, 2020
c7365d1
add missing dependency
a-b-r-o-w-n Oct 14, 2020
96db656
Merge branch 'main' into abrown/extensions/hooks-refactor
a-b-r-o-w-n Oct 14, 2020
9f01bfe
fix tests
a-b-r-o-w-n Oct 14, 2020
a9109af
remove old comments
a-b-r-o-w-n Oct 14, 2020
e111ad3
update lockfile
a-b-r-o-w-n Oct 14, 2020
2c64035
Merge branch 'main' into abrown/extensions/hooks-refactor
a-b-r-o-w-n Oct 15, 2020
db18ee1
use stub currentDialog when none found
a-b-r-o-w-n Oct 15, 2020
d209284
fix build:dev
a-b-r-o-w-n Oct 15, 2020
7b7e820
Merge branch 'main' into abrown/extensions/hooks-refactor
a-b-r-o-w-n Oct 15, 2020
6b8dbaf
fix merge conflict
a-b-r-o-w-n Oct 15, 2020
b5548f7
form dialog templates electron asar unpacked
sorgh Oct 15, 2020
529d138
Merge branch 'abrown/extensions/hooks-refactor' of https://github.com…
sorgh Oct 15, 2020
2e6d2bd
Merge branch 'main' of https://github.com/microsoft/BotFramework-Comp…
sorgh Oct 15, 2020
aa0c442
Move templates to unpacked
sorgh Oct 16, 2020
44a02dd
Update hint texts and minor fixes
sorgh Oct 16, 2020
30014bd
Merge branch 'main' of https://github.com/microsoft/BotFramework-Comp…
sorgh Oct 16, 2020
1c75a2b
Merge branch 'main' of https://github.com/microsoft/BotFramework-Comp…
sorgh Oct 17, 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
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const CreateFormDialogSchemaModal: React.FC<Props> = (props) => {
<Stack>
<TextField
required
autoComplete="off"
errorMessage={formErrors.name}
label={formatMessage('Name')}
styles={name}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
botProjectSpaceLoadedState,
botStatusState,
currentProjectIdState,
filePersistenceState,
projectMetaDataState,
} from '../atoms';
import { dispatcherState } from '../DispatcherWrapper';
Expand Down Expand Up @@ -343,6 +344,7 @@ export const projectDispatcher = () => {
});

const reloadProject = async (callbackHelpers: CallbackInterface, response: any) => {
callbackHelpers.reset(filePersistenceState(response.data.id));
const { projectData, botFiles } = loadProjectData(response);

await initBotState(callbackHelpers, projectData, botFiles);
Expand Down
3 changes: 2 additions & 1 deletion Composer/packages/electron-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
"clean": "rimraf build && rimraf dist && rimraf l10ntemp",
"copy-extensions": "node scripts/copy-extensions.js",
"copy-runtime": "node scripts/copy-runtime.js",
"copy-form-dialog-templates": "node scripts/copy-form-dialog-templates.js",
"dist": "node scripts/electronBuilderDist.js",
"dist:full": "yarn clean && yarn build && yarn run pack && yarn copy-runtime && yarn copy-extensions && yarn dist",
"dist:full": "yarn clean && yarn build && yarn run pack && yarn copy-runtime && yarn copy-extensions && yarn copy-form-dialog-templates && yarn dist",
"lint": "eslint --quiet ./src",
"lint:fix": "yarn lint --fix",
"pack": "node scripts/electronBuilderPack.js",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

const fs = require('fs-extra');
const { resolve } = require('path');
const electronBuildConfig = require('../electron-builder-config.json');

const tag = 'copy-form-dialogs-templates.js';

const source = resolve(__dirname, '../../../node_modules/@microsoft/bf-generate-library/templates');
const unpackedDir = 'app.asar.unpacked/form-dialog-templates';
console.log(`[${tag}] Copying templates from: ${source}`);

let destination;
switch (process.platform) {
case 'darwin':
const productName = electronBuildConfig.productName;
destination = resolve(__dirname, `../dist/mac/${productName}.app/Contents/Resources`, unpackedDir);
console.log(`[${tag}] Mac detected. Copying templates to: ${destination}`);
break;

case 'linux':
destination = resolve(__dirname, '../dist/linux-unpacked/resources', unpackedDir);
console.log(`[${tag}] Linux detected. Copying templates to: ${destination}`);
break;

case 'win32':
destination = resolve(__dirname, '../dist/win-unpacked/resources', unpackedDir);
console.log(`[${tag}] Windows detected. Copying templates to ${destination}`);
break;

default:
console.error(`[${tag}] Detected platform is not Mac / Linux / Windows`);
process.exit(1);
}

// copy templates from bf-generate-library/templates to asar unpacked dir under packaged electron app
fs.copy(source, destination, { filter: (src) => !src.endsWith('.md') }, (err) => {
if (err) {
console.error(`[${tag}] Error while copying plugins: `, err);
return;
}
console.log(`[${tag}] Copied plugins successfully.`);
});
1 change: 1 addition & 0 deletions Composer/packages/electron-server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ async function loadServer() {
const unpackedDir = getUnpackedAsarPath();
process.env.COMPOSER_RUNTIME_FOLDER = join(unpackedDir, 'runtime');
process.env.COMPOSER_BUILTIN_EXTENSIONS_DIR = join(unpackedDir, 'build', 'extensions');
process.env.COMPOSER_FORM_DIALOG_TEMPLATES_DIR = join(unpackedDir, 'form-dialog-templates');
}

// only create a new data directory if packaged electron app
Expand Down
2 changes: 1 addition & 1 deletion Composer/packages/form-dialogs/src/atoms/appState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const formDialogSchemaJsonSelector = selector({
const schemaPropertyStores = propertyIds.map((pId) => get(formDialogPropertyAtom(pId)));

let jsonObject: object = {
schema: schemaDraftUrl,
$schema: schemaDraftUrl,
type: 'object',
$requires: ['standard.schema'],
};
Expand Down
2 changes: 1 addition & 1 deletion Composer/packages/form-dialogs/src/atoms/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const createSchemaStoreFromJson = (schemaName: string, jsonString: string
const propertyType = propertyData?.type || 'ref';
const array = propertyType === 'array';
const payload = retrievePayload(propertyType, propertyData, array);
const kind = <FormDialogPropertyKind>(propertyType === 'array' ? payload.kind : propertyType);
const kind = <FormDialogPropertyKind>(propertyType === 'array' ? payload.kind || 'ref' : propertyType);
const required = requiredArray.indexOf(name) !== -1;
const examples = examplesRecord[name] || [];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,12 @@ export const FormDialogPropertyCard = React.memo((props: FormDialogPropertyCardP
styles={{ root: { flex: 1 } }}
value={name}
onChange={changeName}
onRenderLabel={onRenderLabel(formatMessage('Property name help text'), propertyNameTooltipId)}
onRenderLabel={onRenderLabel(
formatMessage(
`A property is a piece of information that your bot will collect. The property name is the name used in Composer; it is not necessarily the same text that will appear in your bot's messages.`
),
propertyNameTooltipId
)}
/>
<Stack
horizontal
Expand Down Expand Up @@ -232,7 +237,10 @@ export const FormDialogPropertyCard = React.memo((props: FormDialogPropertyCardP
checked={array}
label={formatMessage('Accepts multiple values')}
onChange={changeArray}
onRenderLabel={onRenderLabel(formatMessage('Property array help text'), propertyArrayTooltipId)}
onRenderLabel={onRenderLabel(
formatMessage('This option allows your users to give multiple values for this property.'),
propertyArrayTooltipId
)}
/>
</Stack>
</Stack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ export const NumberPropertyContent = React.memo((props: Props) => {
minimum: payload.kind === 'integer' ? parseInt(value, 10) : parseFloat(value),
})
}
onRenderLabel={onRenderLabel(formatMessage('Minimum help text'), minTooltipId)}
onRenderLabel={onRenderLabel(
formatMessage(
'Optional. Setting a minimum value enables your bot to reject a value that is too small and re-prompt the user for a new value.'
),
minTooltipId
)}
/>
<TextField
aria-describedby={maxTooltipId}
Expand All @@ -60,7 +65,12 @@ export const NumberPropertyContent = React.memo((props: Props) => {
maximum: payload.kind === 'integer' ? parseInt(value, 10) : parseFloat(value),
})
}
onRenderLabel={onRenderLabel(formatMessage('Maximum help text'), maxTooltipId)}
onRenderLabel={onRenderLabel(
formatMessage(
'Optional. Setting a maximum value enables your bot to reject a value that is too large and re-prompt the user for a new value.'
),
maxTooltipId
)}
/>
</Stack>
</Stack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,12 @@ export const PropertyTypeSelector = React.memo((props: Props) => {
selectedKey={selectedKey}
styles={{ root: { minWidth: 200 } }}
onChange={change}
onRenderLabel={onRenderLabel(formatMessage('Property type help text'), propertyTypeTooltipId)}
onRenderLabel={onRenderLabel(
formatMessage(
`The property type defines the expected input. The type can be a list (or enum) of defined values or a data format, such as a date, email, number, or string.`
),
propertyTypeTooltipId
)}
/>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ export const StringPropertyContent = React.memo((props: Props) => {
label={formatMessage('Accepted values')}
values={payload.enums || []}
onChange={changeEnum}
onRenderLabel={onRenderLabel(formatMessage('Enum help text'), tooltipId)}
onRenderLabel={onRenderLabel(
formatMessage(
'For properties of type list (or enum), your bot accepts only the values you define. After your dialog is generated, you can provide synonyms for each value.'
),
tooltipId
)}
/>
)
);
Expand Down
2 changes: 1 addition & 1 deletion Composer/packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@bfc/lu-languageserver": "*",
"@bfc/shared": "*",
"@microsoft/bf-dispatcher": "^4.11.0-beta.20201015.008a3a4",
"@microsoft/bf-generate-library": "^4.10.0-daily.20201008.172736",
"@microsoft/bf-generate-library": "^4.10.0-daily.20201015.174962",
"@microsoft/bf-lu": "^4.11.0-dev.20201013.7ccb128",
"archiver": "^5.0.2",
"axios": "^0.19.2",
Expand Down
35 changes: 31 additions & 4 deletions Composer/packages/server/src/controllers/formDialog.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { Request, Response } from 'express';
import * as path from 'path';

import { ExtensionContext } from '@bfc/extension';
import { schemas, expandPropertyDefinition } from '@microsoft/bf-generate-library';
import { expandPropertyDefinition, schemas } from '@microsoft/bf-generate-library';
import { Request, Response } from 'express';
import * as fs from 'fs-extra';

import { BotProjectService } from '../services/project';

// If we are in electron, the env variable has the asar.unpacked path to the templates
// Otherwise, library uses built in templates path
const getTemplatesRootDir = () =>
process.env.COMPOSER_FORM_DIALOG_TEMPLATES_DIR ? process.env.COMPOSER_FORM_DIALOG_TEMPLATES_DIR : undefined;

const getTemplateDirs = async () => {
const templatesRootDir = getTemplatesRootDir();
const dirs: string[] = [];
if (templatesRootDir && templatesRootDir.length) {
for (const dirName of await fs.readdir(templatesRootDir)) {
const dir = path.join(templatesRootDir, dirName);
if ((await fs.lstat(dir)).isDirectory()) {
// Add templates subdirectories as templates
dirs.push(dir);
}
}
}

return dirs;
};

const expandJsonSchemaProperty = async (req: Request, res: Response) => {
const { propertyName, schema } = req.body;
const result = await expandPropertyDefinition(propertyName, schema);
Expand All @@ -21,7 +45,8 @@ const expandJsonSchemaProperty = async (req: Request, res: Response) => {
};

const getTemplateSchemas = async (req: Request, res: Response) => {
const result = await schemas();
const templatesDirs = await getTemplateDirs();
const result = await schemas(templatesDirs);

if (result !== undefined) {
res.status(200).json(result);
Expand All @@ -40,7 +65,9 @@ const generate = async (req: Request, res: Response) => {
if (currentProject !== undefined) {
const { name } = req.body;

await currentProject.generateDialog(name);
const templatesDirs = await getTemplateDirs();

await currentProject.generateDialog(name, templatesDirs);
const updatedProject = await BotProjectService.getProjectById(projectId, user);
res.status(200).json({ id: projectId, ...updatedProject.getProject() });
} else {
Expand Down
Loading