Address Manage Dictionary issues

A variety of bugs are addressed. See JIRA.

Issue-ID: CLAMP-849
Change-Id: I620c1ec774fdcec484f40fc638551960a98973c8
Signed-off-by: Ted Humphrey <Thomas.Humphrey@att.com>
diff --git a/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js b/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js
index 54ac641..58cb9c6 100644
--- a/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js
+++ b/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js
@@ -24,12 +24,14 @@
 import React, { forwardRef } from 'react';
 import Button from 'react-bootstrap/Button';
 import Modal from 'react-bootstrap/Modal';
+import Row from 'react-bootstrap/Row';
+import Col from 'react-bootstrap/Col';
 import styled from 'styled-components';
 import TemplateMenuService from '../../../api/TemplateService';
+import CsvToJson from '../../../utils/CsvToJson';
 import MaterialTable, {MTableToolbar} from "material-table";
 import IconButton from '@material-ui/core/IconButton';
 import Tooltip from '@material-ui/core/Tooltip';
-import Grid from '@material-ui/core/Grid';
 import AddBox from '@material-ui/icons/AddBox';
 import ArrowUpward from '@material-ui/icons/ArrowUpward';
 import Check from '@material-ui/icons/Check';
@@ -49,19 +51,37 @@
 
 
 const ModalStyled = styled(Modal)`
+	@media (min-width: 1200px) {
+		.modal-xl {
+			max-width: 96%;
+		}
+	}
 	background-color: transparent;
 `
+
+const MTableToolbarStyled = styled(MTableToolbar)`
+	display: flex;
+	flex-direction: row;
+	align-items: center;
+`
+const ColPullLeftStyled = styled(Col)`
+	display: flex;
+	flex-direction: row;
+	align-items: center;
+	margin-left: -40px;
+`
+
 const cellStyle = { border: '1px solid black' };
 const headerStyle = { backgroundColor: '#ddd',	border: '2px solid black'	};
 const rowHeaderStyle = {backgroundColor:'#ddd',  fontSize: '15pt', text: 'bold', border: '1px solid black'};
-var dictList = [];
+let dictList = [];
 
 function SelectSubDictType(props) {
 	const {onChange} = props;
 	const selectedValues = (e) => {
-		var options = e.target.options;
-		var SelectedDictTypes = '';
-		for (var dictType = 0, values = options.length; dictType < values; dictType++) {
+		let options = e.target.options;
+		let SelectedDictTypes = '';
+		for (let dictType = 0, values = options.length; dictType < values; dictType++) {
 			if (options[dictType].selected) {
 				SelectedDictTypes = SelectedDictTypes.concat(options[dictType].value);
 				SelectedDictTypes = SelectedDictTypes.concat('|');
@@ -87,15 +107,16 @@
 	const {onChange} = props;
 	const subDicts = [];
 	subDicts.push('Default');
-	if (dictList != "undefined"  && dictList.length > 0) {
-        for(var item in dictList) {
+	if (dictList !== undefined  && dictList.length > 0) {
+	let item;
+        for(item in dictList) {
             if(dictList[item].secondLevelDictionary === 1) {
                 subDicts.push(dictList[item].name);
             }
         };
 	}
 	subDicts.push('');
- 	var optionItems = subDicts.map(
+ 	let optionItems = subDicts.map(
 		(item) => <option key={item}>{item}</option>
 	  );
  	function selectedValue (e) {
@@ -112,46 +133,45 @@
 	constructor(props, context) {
 		super(props, context);
 		this.handleClose = this.handleClose.bind(this);
-		this.getDictionary = this.getDictionary.bind(this);
-		this.getDictionaryElements = this.getDictionaryElements.bind(this);
 		this.clickHandler = this.clickHandler.bind(this);
-		this.addDictionary = this.addDictionary.bind(this);
-		this.deleteDictionary = this.deleteDictionary.bind(this);
+		this.getDictionaries = this.getDictionaries.bind(this);
+		this.getDictionaryElements = this.getDictionaryElements.bind(this);
+		this.addReplaceDictionaryRequest = this.addReplaceDictionaryRequest.bind(this);
+		this.deleteDictionaryRequest = this.deleteDictionaryRequest.bind(this);
+		this.updateDictionaryElementsRequest = this.updateDictionaryElementsRequest.bind(this);
+		this.addDictionaryRow = this.addDictionaryRow.bind(this);
+		this.updateDictionaryRow = this.updateDictionaryRow.bind(this);
+		this.deleteDictionaryRow = this.deleteDictionaryRow.bind(this);
+		this.addDictionaryElementRow = this.addDictionaryElementRow.bind(this);
+		this.deleteDictionaryElementRow = this.deleteDictionaryElementRow.bind(this);
+		this.updateDictionaryElementRow = this.updateDictionaryElementRow.bind(this);
 		this.fileSelectedHandler = this.fileSelectedHandler.bind(this);
 		this.state = {
 			show: true,
 			selectedFile: '',
-			dictNameFlag: false,
+			currentSelectedDictionary: null,
 			exportFilename: '',
 			content: null,
-			newDict: '',
-			newDictItem: '',
-			delDictItem: '',
-			addDict: false,
-			delData: '',
-			delDict: false,
-			validImport: false,
-			dictionaryNames: [],
 			dictionaryElements: [],
-      tableIcons: {
-		Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
-        Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
-        Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
-        Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />),
-        DetailPanel: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
-        Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />),
-        Export: forwardRef((props, ref) => <VerticalAlignBottomIcon {...props} ref={ref} />),
-        Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
-        FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
-        LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
-        NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
-        PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />),
-        ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
-        Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
-        SortArrow: forwardRef((props, ref) => <ArrowUpward {...props} ref={ref} />),
-        ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
-        ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />)
-      },
+			tableIcons: {
+				Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
+				Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
+				Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
+				Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />),
+				DetailPanel: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
+				Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />),
+				Export: forwardRef((props, ref) => <VerticalAlignBottomIcon {...props} ref={ref} />),
+				Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
+				FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
+				LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
+				NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
+				PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />),
+				ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
+				Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
+				SortArrow: forwardRef((props, ref) => <ArrowUpward {...props} ref={ref} />),
+				ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
+				ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />)
+			},
 			dictColumns: [
 				{
 					title: "Dictionary Name", field: "name",editable: 'onAdd',
@@ -185,7 +205,7 @@
 					cellStyle: cellStyle,
 					headerStyle: headerStyle
 				},
-        {
+				{
 					title: "Element Name", field: "name",
 					cellStyle: cellStyle,
 					headerStyle: headerStyle
@@ -194,8 +214,8 @@
 					title: "Element Description", field: "description",
 					cellStyle: cellStyle,
 					headerStyle: headerStyle
-				 },
-				 {
+				},
+				{
 					title: "Element Type", field: "type",
 					editComponent: props => (
 						<div>
@@ -204,8 +224,8 @@
 					),
 					cellStyle: cellStyle,
 					headerStyle: headerStyle
-				 },
-				 {
+				},
+				{
 				    title: "Sub-Dictionary", field: "subDictionary",
 				      editComponent: props => (
 						 <div>
@@ -214,8 +234,8 @@
 				      ),
 				    cellStyle: cellStyle,
 				    headerStyle: headerStyle
-				 },
-				{   
+				},
+				{
 					title: "Updated By", field: "updatedBy", editable: 'never',
 					cellStyle: cellStyle,
 					headerStyle: headerStyle
@@ -229,325 +249,325 @@
 		}
 	}
 
-	componentWillMount() {
-        this.getDictionary();
-    }
+	componentDidMount() {
+		this.getDictionaries();
+	}
 
-    getDictionary() {
-        TemplateMenuService.getDictionary().then(dictionaryNames => {
-            this.setState({ dictionaryNames: dictionaryNames })
-        });
-    }
+	getDictionaries() {
+		TemplateMenuService.getDictionary().then(arrayOfdictionaries => {
+			this.setState({ dictionaries: arrayOfdictionaries, currentSelectedDictionary: null })
+		});
+	}
 
-    getDictionaryElements(dictionaryName) {
-        TemplateMenuService.getDictionaryElements(dictionaryName).then(dictionaryElements => {
-            dictList = this.state.dictionaryNames;
-            this.setState({ dictionaryElements: dictionaryElements.dictionaryElements});
-        });
-    }
+	getDictionaryElements(dictionaryName) {
+		TemplateMenuService.getDictionaryElements(dictionaryName).then(dictionaryElements => {
+			dictList = this.state.dictionaries;
+			this.setState({ dictionaryElements: dictionaryElements.dictionaryElements} );
+		});
+	}
 
-    clickHandler(rowData)   {
-        this.setState({
-            dictNameFlag: false,
-            addDict: false,
-    });
-    }
+	clickHandler(rowData) {
+		this.getDictionaries();
+	}
 
-    handleClose() {
-        this.setState({ show: false });
-        this.props.history.push('/');
-    }
+	handleClose() {
+		this.setState({ show: false });
+		this.props.history.push('/');
+	}
 
-    addDictionary() {
-        var modifiedData = [];
-        if(this.state.newDict !== '') {
-            modifiedData = this.state.newDict;
-        } else {
-            modifiedData = {"name": this.state.dictionaryName, 'dictionaryElements': this.state.newDictItem};
-        }
-        if(this.state.newDictItem === '') {
-            TemplateMenuService.insDictionary(modifiedData).then(resp => {
-            });
-        } else {
-            TemplateMenuService.insDictionaryElements(modifiedData).then(resp => {
-            });
-        }
-    }
+	addReplaceDictionaryRequest(dictionaryEntry) {
+		TemplateMenuService.insDictionary(dictionaryEntry)
+		.then(resp => {})
+		.then(() => {this.getDictionaries()});
+	}
 
-    deleteDictionary() {
-        var modifiedData = [];
-        if(this.state.delData !== '') {
-            modifiedData = this.state.delData.name;
-        } else {
-            modifiedData = {"name": this.state.dictionaryName, "shortName": this.state.delDictItem.shortName};
-        }
-        if(this.state.delDictItem === '') {
-            TemplateMenuService.deleteDictionary(modifiedData).then(resp => {
-            });
-        } else {
-            TemplateMenuService.deleteDictionaryElements(modifiedData).then(resp => {
-            });
-        }
-    }
+	updateDictionaryElementsRequest(dictElements) {
+		let reqData = { "name": this.state.currentSelectedDictionary, 'dictionaryElements': dictElements };
+		TemplateMenuService.insDictionaryElements(reqData)
+		.then(resp => {})
+		.then(() => { this.getDictionaryElements(this.state.currentSelectedDictionary) });
+	}
 
-    fileSelectedHandler = (event) => {
-        const text = this;
-        var dictionaryElements = [];
-        if (event.target.files[0].type === 'text/csv' ) {
-            if (event.target.files && event.target.files[0]) {
-                const reader = new FileReader();
-                reader.onload = function(e) {
-                    var dictElems = reader.result.split('\n');
-                    var jsonObj = [];
-                    var headers = dictElems[0].split(',');
-                    for(var i = 0; i < dictElems.length; i++) {
-                        var data = dictElems[i].split(',');
-                        var obj = {};
-                        for(var j = 0; j < data.length; j++) {
-                            obj[headers[j].trim()] = data[j].trim();
-                        }
-                        jsonObj.push(obj);
-                    }
-                    JSON.stringify(jsonObj);
-                    const dictKeys = ['Element Short Name','Element Name','Element Description','Element Type','Sub-Dictionary'];
-                    const mandatoryKeys = [ 'Element Short Name', 'Element Name', 'Element Type' ];
-                    const validTypes = ['string','number','datetime','json','map'];
-                    if (!dictElems){
-                        text.setState({validData: false});
-                    } else if (headers.length !== dictKeys.length){
-                        text.setState({validImport: false});
-                    } else {
-                        var subDictionaries = [];
-                        for(var item in dictList) {
-                            if(dictList[item].secondLevelDictionary === 1) {
-                                subDictionaries.push(dictList[item].name);
-                            }
-                        };
-                        subDictionaries = subDictionaries.toString();
-                        var row = 0;
-                        for (var dictElem of jsonObj){
-                            ++row;
-                            for (var itemKey in dictElem){
-                                var value = dictElem[itemKey].trim();
-                                if (dictKeys.indexOf(itemKey) < 0){
-                                    var errorMessage = 'unknown field name of, ' + itemKey + ', found in CSV header';
-                                    text.setState({validImport: false});
-                                    alert(errorMessage);
-                                    break;
-                                } else if (value === "" && mandatoryKeys.indexOf(itemKey) >= 0){
-                                    errorMessage = 'value for ' + itemKey + ', at row #, ' + row + ', is empty but required';
-                                    text.setState({validImport: false});
-                                    alert(errorMessage);
-                                    break;
-                                } else if (itemKey === 'Element Type' && validTypes.indexOf(value) < 0 && row > 1) {
-                                    errorMessage = 'invalid dictElemenType of ' + value + ' at row #' + row;
-                                    text.setState({validImport: false});
-                                    alert(errorMessage);
-                                    break;
-                                } else if (value !== "" && itemKey === 'Sub-Dictionary' && subDictionaries.indexOf(value) < 0 && row > 1) {
-                                    errorMessage = 'invalid subDictionary of ' + value + ' at row #' + row;
-                                    text.setState({validImport: false});
-                                    alert(errorMessage);
-                                }
+	deleteDictionaryRequest(dictionaryName) {
+		TemplateMenuService.deleteDictionary(dictionaryName)
+		.then(resp => { this.getDictionaries() });
+	}
+
+	deleteDictionaryElementRequest(dictionaryName, elemenetShortName) {
+		TemplateMenuService.deleteDictionaryElements({ 'name': dictionaryName, 'shortName': elemenetShortName })
+		.then(resp => {
+			this.getDictionaryElements(dictionaryName);
+		});
+	}
+
+	fileSelectedHandler = (event) => {
+
+		if (event.target.files[0].type === 'text/csv' || event.target.files[0].type === 'application/vnd.ms-excel') {
+			if (event.target.files && event.target.files[0]) {
+				const reader = new FileReader();
+				reader.onload = (e) => {
+
+				const jsonKeyNames = [ 'shortName', 'name', 'description', 'type', 'subDictionary' ];
+				const userHeaderNames = [ 'Element Short Name', 'Element Name', 'Element Description', 'Element Type', 'Sub-Dictionary'  ];
+				const mandatory = [ true, true, true, true, false ];
+				const validTypes = ['string','number','datetime','json','map'];
+
+				let result = CsvToJson(reader.result, ',', '||||', userHeaderNames, jsonKeyNames, mandatory);
+
+				let errorMessages = result.errorMessages;
+				let jsonObjArray = result.jsonObjArray;
+
+				let validTypesErrorMesg = '';
+
+				for (let i=0; i < validTypes.length; ++i) {
+					if (i === 0) {
+						validTypesErrorMesg = validTypes[i];
+					} else {
+						validTypesErrorMesg += ',' + validTypes[i];
+					}
+				}
+
+				if (errorMessages !== '') {
+					alert(errorMessages);
+					return;
+				}
+
+				// Perform further checks on data that is now in JSON form
+                    		let subDictionaries = [];
+
+				// NOTE: dictList is a global variable  maintained faithfully
+				//       by the getDictionaries() method outside this import
+				//       functionality.
+				let item;
+                    		for (item in dictList) {
+					if (dictList[item].secondLevelDictionary === 1) {
+						subDictionaries.push(dictList[item].name);
+					}
+				};
+
+				// Check for valid Sub-Dictionary and Element Type values
+				subDictionaries = subDictionaries.toString();
+				let row = 2;
+				let dictElem;
+				for (dictElem of jsonObjArray) {
+					let itemKey;
+					for (itemKey in dictElem){
+						let value = dictElem[itemKey].trim();
+						let keyIndex = jsonKeyNames.indexOf(itemKey);
+						if (itemKey === 'shortName' && /[^a-zA-Z0-9-_.]/.test(value)) {
+							errorMessages += '\n' + userHeaderNames[keyIndex] +
+								' at row #' + row +
+								' can only contain alphanumeric characters and periods, hyphens or underscores';
+						}
+						if (itemKey === 'type' && validTypes.indexOf(value) < 0) {
+							errorMessages += '\nInvalid value of "' + value + '" for "' + userHeaderNames[keyIndex] + '" at row #' + row;
+							errorMessages += '\nValid types are: ' + validTypesErrorMesg;
+						}
+						if (value !== "" && itemKey === 'subDictionary' && subDictionaries.indexOf(value) < 0) {
+							errorMessages += '\nInvalid Sub-Dictionary value of "' + value + '" at row #' + row;
                             }
                         }
+					++row;
                     }
-                    const headerKeys = ['shortName','name','description','type','subDictionary'];
+					if (errorMessages) {
+						alert(errorMessages);
+						return;
+					}
 
-                    for(i = 1; i < dictElems.length; i++) {
-                        data = dictElems[i].split(',');
-                        obj = {};
-                        for(j = 0; j < data.length; j++) {
-                            obj[headerKeys[j].trim()] = data[j].trim();
-                        }
-                        dictionaryElements.push(obj);
-                    }
-                    text.setState({newDictItem: dictionaryElements, addDict: true});
-                }
-                reader.readAsText(event.target.files[0]);
-            }
-            this.setState({selectedFile: event.target.files[0]})
-        } else {
-            text.setState({validImport: false});
-            alert('Please upload .csv extention files only.');
-        }
+					// We made it through all the checks. Send it to back end
+					this.updateDictionaryElementsRequest(jsonObjArray);
+				}
+				reader.readAsText(event.target.files[0]);
+			}
+			this.setState({selectedFile: event.target.files[0]})
+		} else {
+			alert('Please upload .csv extention files only.');
+		}
+	}
 
-    }
-   
-    render() {
-        return (
-            <ModalStyled size="xl" show={this.state.show} onHide={this.handleClose} backdrop="static" keyboard={false} >
-                <Modal.Header closeButton>
-                    <Modal.Title>Manage Dictionaries</Modal.Title>
-                </Modal.Header>
-                <Modal.Body>
-                    {!this.state.dictNameFlag? <MaterialTable
-                        title={"Dictionary List"}
-                        data={this.state.dictionaryNames}
-                        columns={this.state.dictColumns}
-                        icons={this.state.tableIcons}
-                        onRowClick={(event, rowData) => {this.getDictionaryElements(rowData.name);this.setState({dictNameFlag: true, exportFilename: rowData.name, dictionaryName: rowData.name})}}
-                        options={{
-                            headerStyle: rowHeaderStyle,
-                        }}
-                        editable={{
-                            onRowAdd: newData =>
-                            new Promise((resolve, reject) => {
-                                setTimeout(() => {
-                                    {
-                                        const dictionaryNames = this.state.dictionaryNames;
-                                        var validData =  true;
-                                        if(/[^a-zA-Z0-9-_.]/.test(newData.name)) {
-                                            validData = false;
-                                            alert('Please enter alphanumberic input. Only allowed special characters are:(period, hyphen, underscore)');
-                                        }
-                                        for (var i = 0; i < this.state.dictionaryNames.length; i++) {
-                                            if (this.state.dictionaryNames[i].name === newData.name) {
-                                                validData = false;
-                                                alert(newData.name + ' dictionary name already exists')
-                                            }
-                                        }
-                                        if(validData){
-                                            dictionaryNames.push(newData);
-                                            this.setState({ dictionaryNames }, () => resolve());
-                                            this.setState({addDict: true, newDict: newData});
-                                        }
-                                    }
-                                    resolve();
-                                }, 1000);
-                            }),
-                            onRowUpdate: (newData, oldData) =>
-                            new Promise((resolve, reject) => {
-                                setTimeout(() => {
-                                    {
-                                        const dictionaryNames = this.state.dictionaryNames;
-                                        var validData =  true;
-                                        if(/[^a-zA-Z0-9-_.]/.test(newData.name)) {
-                                            validData = false;
-                                            alert('Please enter alphanumberic input. Only allowed special characters are:(period, hyphen, underscore)');
-                                        }
-                                        if(validData){
-                                            const index = dictionaryNames.indexOf(oldData);
-                                            dictionaryNames[index] = newData;
-                                            this.setState({ dictionaryNames }, () => resolve());
-                                            this.setState({addDict: true, newDict: newData});
-                                        }
-                                    }
-                                    resolve();
-                                }, 1000);
-                            }),
-                            onRowDelete: oldData =>
-                new Promise((resolve, reject) => {
-                                setTimeout(() => {
-                                    {
-                                        const data = this.state.dictionaryNames;
-                    const index = data.indexOf(oldData);
-                    data.splice(index, 1);
-                    this.setState({ data }, () => resolve());
-                                        this.setState({delDict: true, delData: oldData})
+	addDictionaryRow(newData) {
+		let validData = true;
+		return new Promise((resolve, reject) => {
+			setTimeout(() => {
+					if (/[^a-zA-Z0-9-_.]/.test(newData.name)) {
+						validData = false;
+						alert('Please enter alphanumeric input. Only allowed special characters are:(period, hyphen, underscore)');
+						reject(() => {});
+					}
+					for (let i = 0; i < this.state.dictionaries.length; i++) {
+						if (this.state.dictionaries[i].name === newData.name) {
+							validData = false;
+							alert(newData.name + ' dictionary name already exists')
+							reject(() => {});
+						}
+					}
+					if (validData) {
+						this.addReplaceDictionaryRequest(newData);
+					}
+					resolve();
+			}, 1000);
+		});
+	}
+
+
+	updateDictionaryRow(oldData, newData) {
+		let validData = true;
+		return new Promise((resolve) => {
+			setTimeout(() => {
+				if (/[^a-zA-Z0-9-_.]/.test(newData.name)) {
+					validData = false;
+					alert('Please enter alphanumberic input. Only allowed special characters are:(period, hyphen, underscore)');
+				}
+				if (validData) {
+					this.addReplaceDictionaryRequest(newData);
+				}
+				resolve();
+			}, 1000);
+		});
+	}
+
+	deleteDictionaryRow(oldData) {
+		return new Promise((resolve) => {
+			setTimeout(() => {
+				this.deleteDictionaryRequest(oldData.name);
+				resolve();
+			}, 1000);
+		});
+	}
+
+	addDictionaryElementRow(newData) {
+		return new Promise((resolve, reject) => {
+			setTimeout(() => {
+				let dictionaryElements = this.state.dictionaryElements;
+				let errorMessage = '';
+				for (let i = 0; i < this.state.dictionaryElements.length; i++) {
+					if (this.state.dictionaryElements[i].shortName === newData.shortName) {
+						alert('Short Name "' + newData.shortName + '" already exists');
+						reject(() => {});
+					}
+				}
+				if (newData.shortName !== '' && /[^a-zA-Z0-9-_.]/.test(newData.shortName)) {
+					errorMessage += '\nShort Name is limited to alphanumeric characters and also period, hyphen, and underscore';
+				}
+				if (!newData.shortName){
+					errorMessage += '\nShort Name must be specified';
+				}
+				if (!newData.name){
+					errorMessage += '\nElement Name must be specified';
+				}
+				if (!newData.type){
+					errorMessage += '\nElement Type must be specified';
+				}
+				if (!newData.description){
+					errorMessage += '\nElement Description must be specified';
+				}
+				if (errorMessage === '') {
+					dictionaryElements.push(newData);
+					this.updateDictionaryElementsRequest(dictionaryElements);
+					resolve();
+				} else {
+					alert(errorMessage);
+					reject(() => {});
+				}
+			}, 1000);
+		});
+	}
+
+	updateDictionaryElementRow(newData, oldData) {
+		return new Promise((resolve) => {
+			setTimeout(() => {
+				let dictionaryElements = this.state.dictionaryElements;
+				let validData =  true;
+				if (!newData.type) {
+					validData = false;
+					alert('Element Type cannot be null');
+				}
+				if (validData) {
+					const index = dictionaryElements.indexOf(oldData);
+					dictionaryElements[index] = newData;
+					this.updateDictionaryElementsRequest(dictionaryElements);
+				}
+				resolve();
+			}, 1000);
+		});
+	}
+
+
+	deleteDictionaryElementRow(oldData) {
+		return new Promise((resolve) => {
+			setTimeout(() => {
+				this.deleteDictionaryElementRequest(this.state.currentSelectedDictionary, oldData.shortName);
+				resolve();
+			}, 1000);
+		});
+	}
+
+	render() {
+		return (
+			<ModalStyled size="xl" show={this.state.show} onHide={this.handleClose} backdrop="static" keyboard={false} >
+				<Modal.Header closeButton>
+					<Modal.Title>Manage Dictionaries</Modal.Title>
+				</Modal.Header>
+				<Modal.Body>
+					{this.state.currentSelectedDictionary === null ? <MaterialTable
+                        	title={"Dictionary List"}
+                        	data={this.state.dictionaries}
+                        	columns={this.state.dictColumns}
+                        	icons={this.state.tableIcons}
+                        	onRowClick={(event, rowData) => {
+								this.setState({
+									currentSelectedDictionary : rowData.name,
+									exportFilename: rowData.name
+								})
+								this.getDictionaryElements(rowData.name);
+							}}
+                        	options={{
+                            	headerStyle: rowHeaderStyle,
+                        	}}
+                        	editable={{
+                            	onRowAdd: this.addDictionaryRow,
+                            	onRowUpdate: this.updateDictionaryRow,
+                            	onRowDelete: this.deleteDictionaryRow
+							}}
+						/> : null
                     }
-                    resolve()
-                }, 1000)
-                })
-                        }}
-                        />:""
-                    }
-                    {this.state.dictNameFlag? <MaterialTable
-                        title={"Dictionary Elements List"}
+                    {this.state.currentSelectedDictionary !== null ? <MaterialTable
+                        title={'Dictionary Elements List for "' + this.state.currentSelectedDictionary + '"'}
                         data={this.state.dictionaryElements}
                         columns={this.state.dictElementColumns}
                         icons={this.state.tableIcons}
                         options={{
+							exportAllData: true,
                             exportButton: true,
                             exportFileName: this.state.exportFilename,
                             headerStyle:{backgroundColor:'white',  fontSize: '15pt', text: 'bold', border: '1px solid black'}
                         }}
                         components={{
                             Toolbar: props => (
-                                <div>
-                                    <MTableToolbar {...props} />
-                                <div>
-                                    <Grid item container xs={12} alignItems="flex-end" direction="column" justify="flex-end">
+								<Row>
+									<Col sm="11">
+                                    	<MTableToolbarStyled {...props} />
+									</Col>
+									<ColPullLeftStyled sm="1">
                                         <Tooltip title="Import" placement = "bottom">
-                                            <IconButton aria-label="import" onClick={() => this.fileUpload.click()}>
-                                                <VerticalAlignTopIcon />
-                                            </IconButton>
+                                        <IconButton aria-label="import" onClick={() => this.fileUpload.click()}>
+                                        	<VerticalAlignTopIcon />
+                                        </IconButton>
                                         </Tooltip>
-                                    </Grid>
-                                </div>
-                                <input type="file" ref={(fileUpload) => {this.fileUpload = fileUpload;}} style={{ visibility: 'hidden'}} onChange={this.fileSelectedHandler} />
-                                </div>
+                                		<input type="file" ref={(fileUpload) => {this.fileUpload = fileUpload;}}
+											style={{ visibility: 'hidden', width: '1px' }} onChange={this.fileSelectedHandler} />
+									</ColPullLeftStyled>
+                                </Row>
                             )
                         }}
                         editable={{
-                            onRowAdd: newData =>
-                            new Promise((resolve, reject) => {
-                                setTimeout(() => {
-                                    {
-                                        const dictionaryElements = this.state.dictionaryElements;
-                                        var validData =  true;
-                                        for (var i = 0; i < this.state.dictionaryElements.length; i++) {
-                                            if (this.state.dictionaryElements[i].shortName === newData.shortName) {
-                                                validData = false;
-                                                alert(newData.shortname + 'short name already exists')
-                                            }
-                                        }
-                                        if(/[^a-zA-Z0-9-_.]/.test(newData.shortName)) {
-                                            validData = false;
-                                            alert('Please enter alphanumberic input. Only allowed special characters are:(period, hyphen, underscore)');
-                                        }
-                                        if(!newData.type){
-                                            validData = false;
-                                            alert('Element Type cannot be null');
-                                        }
-                                        if(validData){
-                                            dictionaryElements.push(newData);
-                                            this.setState({ dictionaryElements }, () => resolve());
-                                            this.setState({addDict: true, newDictItem: [newData]});
-                                        }
-                                    }
-                                    resolve();
-                                }, 1000);
-                            }),
-                            onRowUpdate: (newData, oldData) =>
-                            new Promise((resolve, reject) => {
-                                setTimeout(() => {
-                                    {
-                                        const dictionaryElements = this.state.dictionaryElements;
-                                        var validData =  true;
-                                        if(!newData.type){
-                                            validData = false;
-                                            alert('Element Type cannot be null');
-                                        }
-                                        if(validData){
-                                            const index = dictionaryElements.indexOf(oldData);
-                                            dictionaryElements[index] = newData;
-                                            this.setState({ dictionaryElements }, () => resolve());
-                                            this.setState({addDict: true, newDictItem: [newData]});
-                                        }
-                                    }
-                                    resolve();
-                                }, 1000);
-                            }),
-                            onRowDelete: oldData =>
-                new Promise((resolve, reject) => {
-                                setTimeout(() => {
-                                    {
-                                        let data = this.state.dictionaryElements;
-                    const index = data.indexOf(oldData);
-                    data.splice(index, 1);
-                    this.setState({ data }, () => resolve());
-                                        this.setState({delDict: true, delDictItem: oldData})
-                    }
-                    resolve()
-                }, 1000)
-                })
+                            onRowAdd: this.addDictionaryElementRow,
+                            onRowUpdate: this.updateDictionaryElementRow,
+                            onRowDelete: this.deleteDictionaryElementRow
                         }}
-                        />:""
+                        /> : null
                     }
-                    {this.state.dictNameFlag?<button onClick={this.clickHandler} style={{marginTop: '25px'}}>Go Back to Dictionaries List</button>:""}
-                    {this.state.addDict && this.addDictionary()}
-                    {this.state.delDict && this.deleteDictionary()}
+                    {this.state.currentSelectedDictionary !== null ? <button onClick={this.clickHandler} style={{marginTop: '25px'}}>Go Back to Dictionaries List</button>:""}
                 </Modal.Body>
                 <Modal.Footer>
                     <Button variant="secondary" type="null" onClick={this.handleClose}>Close</Button>
@@ -555,4 +575,4 @@
             </ModalStyled>
         );
     }
-}					
+}