block re-use of existing loop name; support derivation of SvgGenerator

added changes to LoopUI for global style and support of "delete" CL case

Issue-ID: CLAMP-896
Change-Id: I97f603f38c277011835b8e206e5e05226a296606
Signed-off-by: Ted Humphrey <Thomas.Humphrey@att.com>
diff --git a/ui-react/src/components/dialogs/Loop/CreateLoopModal.js b/ui-react/src/components/dialogs/Loop/CreateLoopModal.js
index a8e8dee..5663360 100644
--- a/ui-react/src/components/dialogs/Loop/CreateLoopModal.js
+++ b/ui-react/src/components/dialogs/Loop/CreateLoopModal.js
@@ -37,6 +37,10 @@
 	background-color: transparent;
 `
 
+const ErrMsgStyled = styled.div`
+	color: red;
+`
+
 export default class CreateLoopModal extends React.Component {
 	constructor(props, context) {
 		super(props, context);
@@ -46,17 +50,20 @@
 		this.handleModelName = this.handleModelName.bind(this);
 		this.handleClose = this.handleClose.bind(this);
 		this.handleDropDownListChange = this.handleDropDownListChange.bind(this);
+		this.renderSvg = this.renderSvg.bind(this);
 		this.state = {
 			show: true,
 			chosenTemplateName: '',
+			modelInputErrMsg: '',
 			modelName: '',
 			templateNames: [],
 			fakeLoopCacheWithTemplate: new LoopCache({})
 		};
 	}
 
-	componentWillMount() {
-		this.getAllLoopTemplates();
+	async componentDidMount() {
+		await this.getAllLoopTemplates();
+		await this.getModelNames();
 	}
 
 	handleClose() {
@@ -87,6 +94,17 @@
 		});
 	}
 
+	getModelNames() {
+		TemplateService.getLoopNames().then(loopNames => {
+			if (!loopNames) {
+				loopNames = [];
+			}
+			// Remove LOOP_ prefix
+			let trimmedLoopNames = loopNames.map(str => str.replace('LOOP_', ''));
+			this.setState({ modelNames: trimmedLoopNames });
+		});
+	}
+
 	handleCreate() {
 		if (!this.state.modelName) {
 			alert("A model name is required");
@@ -109,10 +127,25 @@
 		});
 	}
 
-	handleModelName = event => {
-		this.setState({
-			modelName: event.target.value
-		})
+	handleModelName(event) {
+		if (this.state.modelNames.includes(event.target.value)) {
+			this.setState({
+				modelInputErrMsg: 'A model named "' + event.target.value + '" already exists. Please pick another name.',
+				modelName: event.target.value
+			});
+			return;
+		} else {
+			this.setState({
+				modelInputErrMsg: '',
+				modelName: event.target.value
+			});
+		}
+	}
+
+	renderSvg() {
+		return (
+			<SvgGenerator loopCache={this.state.fakeLoopCacheWithTemplate} clickable={false} generatedFrom={SvgGenerator.GENERATED_FROM_TEMPLATE}/>
+		);
 	}
 
 	render() {
@@ -131,15 +164,20 @@
                     <Form.Group as={Row} style={{alignItems: 'center'}} controlId="formSvgPreview">
                     <Form.Label column sm="2">Model Preview:</Form.Label>
                         <Col sm="10">
-                            <SvgGenerator loopCache={this.state.fakeLoopCacheWithTemplate} clickable={false} generatedFrom={SvgGenerator.GENERATED_FROM_TEMPLATE}/>
+                            {this.renderSvg()}
                         </Col>
                     </Form.Group>
 					<Form.Group as={Row} controlId="formPlaintextEmail">
 						<Form.Label column sm="2">Model Name:</Form.Label>
-						<input type="text" style={{width: '50%', marginLeft: '1em' }}
+						<input sm="5" type="text" style={{width: '50%', marginLeft: '1em' }}
 							value={this.state.modelName}
 							onChange={this.handleModelName}
 						/>
+						<span sm="5"/>
+					</Form.Group>
+					<Form.Group as={Row} controlId="formPlaintextEmail">
+						<Form.Label column sm="2"> </Form.Label>
+						<ErrMsgStyled>{this.state.modelInputErrMsg}</ErrMsgStyled>
 					</Form.Group>
 				</Modal.Body>
 				<Modal.Footer>
diff --git a/ui-react/src/components/dialogs/Loop/CreateLoopModal.test.js b/ui-react/src/components/dialogs/Loop/CreateLoopModal.test.js
index 5b6ea9e..1caa22d 100644
--- a/ui-react/src/components/dialogs/Loop/CreateLoopModal.test.js
+++ b/ui-react/src/components/dialogs/Loop/CreateLoopModal.test.js
@@ -29,16 +29,18 @@
 describe('Verify CreateLoopModal', () => {
 
   it('Test the render method', async () => {
-	const flushPromises = () => new Promise(setImmediate);
+    const flushPromises = () => new Promise(setImmediate);
     TemplateService.getAllLoopTemplates = jest.fn().mockImplementation(() => {
-    	return Promise.resolve([{"name":"template1"},{"name":"template2"}]);
-	});
-	
-	const component = shallow(<CreateLoopModal/>);
+      return Promise.resolve([{"name":"template1"},{"name":"template2"}]);
+    });
+    TemplateService.getLoopNames = jest.fn().mockImplementation(() => {
+      return Promise.resolve([]);
+    });
+
+    const component = shallow(<CreateLoopModal/>);
     expect(component).toMatchSnapshot();
-	await flushPromises();
-	component.update();
-		
+    await flushPromises();
+    component.update();
     expect(component.state('templateNames')).toStrictEqual([{"label": "template1", "value": "template1", "templateObject": {"name": "template1"}}, {"label": "template2", "value": "template2","templateObject": {"name": "template2"}}]);
   });
 
@@ -61,17 +63,22 @@
     expect(component.state('fakeLoopCacheWithTemplate').getLoopName()).toEqual("fakeLoop");
   });
 
-
-
-  it('handleModelName event', () => {
+  it('handleModelName event', async () => {
+    const flushPromises = () => new Promise(setImmediate);
+    TemplateService.getAllLoopTemplates = jest.fn().mockImplementation(() => {
+      return Promise.resolve([{"name":"template1"},{"name":"template2"}]);
+    });
+    TemplateService.getLoopNames = jest.fn().mockImplementation(() => {
+      return Promise.resolve([]);
+    });
     const event = {target: {value : "model1"} };
     const component = shallow(<CreateLoopModal/>);
+    await flushPromises();
     component.find('input').simulate('change', event);
     component.update();
     expect(component.state('modelName')).toEqual("model1");
   });
 
-
   it('Test handleClose', () => {
     const historyMock = { push: jest.fn() }; 
     const handleClose = jest.spyOn(CreateLoopModal.prototype,'handleClose');
diff --git a/ui-react/src/components/dialogs/Loop/OpenLoopModal.js b/ui-react/src/components/dialogs/Loop/OpenLoopModal.js
index 7ca90b4..b45df65 100644
--- a/ui-react/src/components/dialogs/Loop/OpenLoopModal.js
+++ b/ui-react/src/components/dialogs/Loop/OpenLoopModal.js
@@ -48,7 +48,8 @@
 		this.handleOpen = this.handleOpen.bind(this);
 		this.handleClose = this.handleClose.bind(this);
 		this.handleDropDownListChange = this.handleDropDownListChange.bind(this);
-		this.showReadOnly = props.showReadOnly ? props.showReadOnly : true;
+		this.renderSvg = this.renderSvg.bind(this);
+		this.showReadOnly = props.showReadOnly !== undefined ? props.showReadOnly : true;
 		this.state = {
 			show: true,
 			chosenLoopName: '',
@@ -90,6 +91,12 @@
 		this.props.loadLoopFunction(this.state.chosenLoopName);
 	}
 
+	renderSvg() {
+		return(
+				<SvgGenerator loopCache={this.state.loopCacheOpened} clickable={false} generatedFrom={SvgGenerator.GENERATED_FROM_INSTANCE}/>
+		);
+	}
+
 	render() {
 		return (
 			<ModalStyled size="xl" show={this.state.show} onHide={this.handleClose} backdrop="static" keyboard={false} >
@@ -107,7 +114,7 @@
 					<Form.Group as={Row} style={{alignItems: 'center'}} controlId="formSvgPreview">
 						<Form.Label column sm="2">Model Preview:</Form.Label>
 						<Col sm="10">
-						    <SvgGenerator loopCache={this.state.loopCacheOpened} clickable={false} generatedFrom={SvgGenerator.GENERATED_FROM_INSTANCE}/>
+						    {this.renderSvg()}
 						</Col>
 					</Form.Group>
 					{this.showReadOnly === true ?
diff --git a/ui-react/src/components/dialogs/Loop/__snapshots__/CreateLoopModal.test.js.snap b/ui-react/src/components/dialogs/Loop/__snapshots__/CreateLoopModal.test.js.snap
index e69b809..b057816 100644
--- a/ui-react/src/components/dialogs/Loop/__snapshots__/CreateLoopModal.test.js.snap
+++ b/ui-react/src/components/dialogs/Loop/__snapshots__/CreateLoopModal.test.js.snap
@@ -107,6 +107,7 @@
       </FormLabel>
       <input
         onChange={[Function]}
+        sm="5"
         style={
           Object {
             "marginLeft": "1em",
@@ -116,6 +117,30 @@
         type="text"
         value=""
       />
+      <span
+        sm="5"
+      />
+    </FormGroup>
+    <FormGroup
+      as={
+        Object {
+          "$$typeof": Symbol(react.forward_ref),
+          "defaultProps": Object {
+            "noGutters": false,
+          },
+          "render": [Function],
+        }
+      }
+      controlId="formPlaintextEmail"
+    >
+      <FormLabel
+        column={true}
+        sm="2"
+        srOnly={false}
+      >
+         
+      </FormLabel>
+      <styled.div />
     </FormGroup>
   </ModalBody>
   <ModalFooter>