diff --git a/Composer/packages/client/src/CreationFlow/DefineConversation/index.js b/Composer/packages/client/src/CreationFlow/DefineConversation/index.js
index acc19be84a..b152b40c90 100644
--- a/Composer/packages/client/src/CreationFlow/DefineConversation/index.js
+++ b/Composer/packages/client/src/CreationFlow/DefineConversation/index.js
@@ -1,12 +1,11 @@
-import React, { useState, useContext, useEffect, useRef, Fragment } from 'react';
+import React, { useState, useContext, useEffect, useRef } from 'react';
+import { DialogFooter, PrimaryButton, DefaultButton } from 'office-ui-fabric-react';
import formatMessage from 'format-message';
-import { DialogFooter, PrimaryButton, DefaultButton, Stack, StackItem, TextField } from 'office-ui-fabric-react';
+import { DialogModal } from '../../CreationFlow/DialogModal/index';
import { LocationSelectContent } from '../LocationBrowser/LocationSelectContent';
-import { styles as wizardStyles } from '../StepWizard/styles';
import { StoreContext } from './../../store';
-import { name, description } from './styles';
const nameRegex = /^[a-zA-Z0-9-_.]+$/;
@@ -23,16 +22,14 @@ const validateForm = data => {
return errors;
};
-export function DefineConversation(props) {
- const { onSubmit, onGetErrorMessage, onDismiss, enableLocationBrowse } = props;
+export default function DefineConversation(props) {
+ const { onDismiss, onSubmit, onGetErrorMessage } = props;
+ const [formData, setFormData] = useState({ errors: {} });
+ const [disable, setDisable] = useState(false);
const { state } = useContext(StoreContext);
const { storages } = state;
const currentStorageIndex = useRef(0);
- const [formData, setFormData] = useState({ errors: {} });
- const [disable, setDisable] = useState(false);
-
- // set the default path
useEffect(() => {
const index = currentStorageIndex.current;
if (storages[index]) {
@@ -48,24 +45,6 @@ export function DefineConversation(props) {
});
};
- const handleSubmit = e => {
- e.preventDefault();
- const errors = validateForm(formData);
-
- if (Object.keys(errors).length) {
- setFormData({
- ...formData,
- errors,
- });
- return;
- }
-
- onSubmit({
- ...formData,
- });
- };
-
- //disable the next button if the text has errors.
const getErrorMessage = text => {
if (typeof onGetErrorMessage === 'function') {
const result = onGetErrorMessage(text);
@@ -83,45 +62,41 @@ export function DefineConversation(props) {
}
};
- // // update the path in the form and toggle the location picker.
+ const handleSubmit = e => {
+ e.preventDefault();
+ const errors = validateForm(formData);
+
+ if (Object.keys(errors).length) {
+ setFormData({
+ ...formData,
+ errors,
+ });
+ return;
+ }
+
+ onSubmit({
+ ...formData,
+ });
+ };
+
const updateLocation = path => {
updateForm('location')(null, path);
};
return (
-
-
-
+
);
}
diff --git a/Composer/packages/client/src/CreationFlow/DialogModal/index.js b/Composer/packages/client/src/CreationFlow/DialogModal/index.js
new file mode 100644
index 0000000000..5610c0aa23
--- /dev/null
+++ b/Composer/packages/client/src/CreationFlow/DialogModal/index.js
@@ -0,0 +1,40 @@
+import React, { Fragment } from 'react';
+import formatMessage from 'format-message';
+import { Stack, StackItem, TextField } from 'office-ui-fabric-react';
+
+import { styles as wizardStyles } from '../StepWizard/styles';
+
+import { name, description } from './styles';
+
+export function DialogModal(props) {
+ const { horizontal, formData, updateForm, getErrorMessage } = props;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/Composer/packages/client/src/CreationFlow/DefineConversation/styles.js b/Composer/packages/client/src/CreationFlow/DialogModal/styles.js
similarity index 100%
rename from Composer/packages/client/src/CreationFlow/DefineConversation/styles.js
rename to Composer/packages/client/src/CreationFlow/DialogModal/styles.js
diff --git a/Composer/packages/client/src/CreationFlow/index.js b/Composer/packages/client/src/CreationFlow/index.js
index df1d85b80f..5b0280cd34 100644
--- a/Composer/packages/client/src/CreationFlow/index.js
+++ b/Composer/packages/client/src/CreationFlow/index.js
@@ -4,7 +4,7 @@ import { toLower } from 'lodash';
import { CreationFlowStatus, DialogCreationCopy, Steps } from '../constants';
import { CreateOptions } from './CreateOptions/index';
-import { DefineConversation } from './DefineConversation/index';
+import DefineConversation from './DefineConversation/index';
import { OpenProject } from './OpenProject';
import { StoreContext } from './../store';
import { StepWizard } from './StepWizard/StepWizard';
@@ -128,12 +128,7 @@ export function CreationFlow(props) {
[Steps.DEFINE]: {
...DialogCreationCopy.DEFINE_CONVERSATION_OBJECTIVE,
children: (
-
+
),
},
};
diff --git a/Composer/packages/client/src/pages/design/new-dialog-modal.js b/Composer/packages/client/src/pages/design/new-dialog-modal.js
index 0c53a5c416..c37fd556d6 100644
--- a/Composer/packages/client/src/pages/design/new-dialog-modal.js
+++ b/Composer/packages/client/src/pages/design/new-dialog-modal.js
@@ -1,20 +1,91 @@
-import React from 'react';
+import React, { useState } from 'react';
+import { DialogFooter, PrimaryButton, DefaultButton } from 'office-ui-fabric-react';
+import formatMessage from 'format-message';
import { DialogCreationCopy } from '../../constants';
-import { DefineConversation } from '../../CreationFlow/DefineConversation/index';
+import { DialogModal } from '../../CreationFlow/DialogModal/index';
import { DialogWrapper } from '../../components/DialogWrapper/index';
+const nameRegex = /^[a-zA-Z0-9-_.]+$/;
+
+const validateForm = data => {
+ const errors = {};
+ const { name } = data;
+
+ if (!name || !nameRegex.test(name)) {
+ errors.name = formatMessage(
+ 'Spaces and special characters are not allowed. Use letters, numbers, -, or _., numbers, -, and _'
+ );
+ }
+
+ return errors;
+};
+
export default function NewDialogModal(props) {
const { isOpen, onDismiss, onSubmit, onGetErrorMessage } = props;
+ const [formData, setFormData] = useState({ errors: {} });
+ const [disable, setDisable] = useState(false);
+ const updateForm = field => (e, newValue) => {
+ setFormData({
+ ...formData,
+ errors: {},
+ [field]: newValue,
+ });
+ };
+
+ const getErrorMessage = text => {
+ if (typeof onGetErrorMessage === 'function') {
+ const result = onGetErrorMessage(text);
+ if (result === '' && disable) {
+ setDisable(false);
+ }
+
+ if (result !== '' && !disable) {
+ setDisable(true);
+ }
+
+ return result;
+ } else {
+ return '';
+ }
+ };
+
+ const onClickCancel = () => {
+ setFormData({ errors: {} });
+ onDismiss();
+ };
+
+ const handleSubmit = e => {
+ e.preventDefault();
+ const errors = validateForm(formData);
+
+ if (Object.keys(errors).length) {
+ setFormData({
+ ...formData,
+ errors,
+ });
+ return;
+ }
+ onSubmit({
+ ...formData,
+ });
+ };
return (
-
-
+
+
);
}
diff --git a/Composer/packages/server/src/models/asset/assetManager.ts b/Composer/packages/server/src/models/asset/assetManager.ts
index 487f512bf9..be810f3c53 100644
--- a/Composer/packages/server/src/models/asset/assetManager.ts
+++ b/Composer/packages/server/src/models/asset/assetManager.ts
@@ -71,6 +71,7 @@ export class AssetManager {
const folders = await this.templateStorage.readDir(path);
this.projectTemplates = [];
for (const name of folders) {
+ if (!templates[name]) continue;
const absPath = Path.join(path, name);
if ((await this.templateStorage.stat(absPath)).isDir) {
const base = { id: name, name: templates[name].name, description: templates[name].description };