blob: 90bbc887ce4dbbae3a1c9b1a3a45f909df5cec5b [file] [log] [blame]
drveerendra50320952020-03-04 20:30:44 -05001/*-
2 * ============LICENSE_START=======================================================
3 * ONAP CLAMP
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END============================================
19 * ===================================================================
20 *
21 */
22
23
xuegaof1692af2020-04-22 13:54:24 +020024import React, { forwardRef } from 'react';
drveerendra50320952020-03-04 20:30:44 -050025import Button from 'react-bootstrap/Button';
26import Modal from 'react-bootstrap/Modal';
Ted Humphreyb56cb112020-06-12 03:17:35 -040027import Row from 'react-bootstrap/Row';
28import Col from 'react-bootstrap/Col';
drveerendra50320952020-03-04 20:30:44 -050029import styled from 'styled-components';
30import TemplateMenuService from '../../../api/TemplateService';
Ted Humphreyb56cb112020-06-12 03:17:35 -040031import CsvToJson from '../../../utils/CsvToJson';
drveerendra50320952020-03-04 20:30:44 -050032import MaterialTable, {MTableToolbar} from "material-table";
33import IconButton from '@material-ui/core/IconButton';
34import Tooltip from '@material-ui/core/Tooltip';
drveerendra50320952020-03-04 20:30:44 -050035import AddBox from '@material-ui/icons/AddBox';
36import ArrowUpward from '@material-ui/icons/ArrowUpward';
37import Check from '@material-ui/icons/Check';
38import ChevronLeft from '@material-ui/icons/ChevronLeft';
39import VerticalAlignTopIcon from '@material-ui/icons/VerticalAlignTop';
40import VerticalAlignBottomIcon from '@material-ui/icons/VerticalAlignBottom';
41import ChevronRight from '@material-ui/icons/ChevronRight';
42import Clear from '@material-ui/icons/Clear';
43import DeleteOutline from '@material-ui/icons/DeleteOutline';
44import Edit from '@material-ui/icons/Edit';
45import FilterList from '@material-ui/icons/FilterList';
46import FirstPage from '@material-ui/icons/FirstPage';
47import LastPage from '@material-ui/icons/LastPage';
48import Remove from '@material-ui/icons/Remove';
49import Search from '@material-ui/icons/Search';
50import ViewColumn from '@material-ui/icons/ViewColumn';
51
52
53const ModalStyled = styled(Modal)`
Ted Humphreyb56cb112020-06-12 03:17:35 -040054 @media (min-width: 1200px) {
55 .modal-xl {
56 max-width: 96%;
57 }
58 }
drveerendra50320952020-03-04 20:30:44 -050059 background-color: transparent;
60`
Ted Humphreyb56cb112020-06-12 03:17:35 -040061
62const MTableToolbarStyled = styled(MTableToolbar)`
63 display: flex;
64 flex-direction: row;
65 align-items: center;
66`
67const ColPullLeftStyled = styled(Col)`
68 display: flex;
69 flex-direction: row;
70 align-items: center;
71 margin-left: -40px;
72`
73
drveerendra50320952020-03-04 20:30:44 -050074const cellStyle = { border: '1px solid black' };
75const headerStyle = { backgroundColor: '#ddd', border: '2px solid black' };
76const rowHeaderStyle = {backgroundColor:'#ddd', fontSize: '15pt', text: 'bold', border: '1px solid black'};
Ted Humphreyb80ded02020-06-17 21:40:35 -040077
Ted Humphreyb56cb112020-06-12 03:17:35 -040078let dictList = [];
Ted Humphreyb80ded02020-06-17 21:40:35 -040079let subDictFlag = false;
drveerendra50320952020-03-04 20:30:44 -050080
81function SelectSubDictType(props) {
82 const {onChange} = props;
83 const selectedValues = (e) => {
Ted Humphreyb56cb112020-06-12 03:17:35 -040084 let options = e.target.options;
85 let SelectedDictTypes = '';
86 for (let dictType = 0, values = options.length; dictType < values; dictType++) {
drveerendra50320952020-03-04 20:30:44 -050087 if (options[dictType].selected) {
88 SelectedDictTypes = SelectedDictTypes.concat(options[dictType].value);
89 SelectedDictTypes = SelectedDictTypes.concat('|');
90 }
91 }
92 SelectedDictTypes = SelectedDictTypes.slice(0,-1);
93 onChange(SelectedDictTypes);
94 }
Ted Humphreyb80ded02020-06-17 21:40:35 -040095 // When the subDictFlag is true, we need to disable selection of element "type"
drveerendra50320952020-03-04 20:30:44 -050096 return(
97 <div>
Ted Humphreyb80ded02020-06-17 21:40:35 -040098 <select disabled={subDictFlag} multiple={true} onChange={selectedValues}>
drveerendra50320952020-03-04 20:30:44 -050099 <option value="string">string</option>
100 <option value="number">number</option>
101 <option value="datetime">datetime</option>
102 <option value="map">map</option>
103 <option value="json">json</option>
104 </select>
105 </div>
Ted Humphreyb80ded02020-06-17 21:40:35 -0400106 );
drveerendra50320952020-03-04 20:30:44 -0500107}
108
109function SubDict(props) {
110 const {onChange} = props;
111 const subDicts = [];
Ted Humphreyb80ded02020-06-17 21:40:35 -0400112 subDicts.push('none');
Ted Humphreyb56cb112020-06-12 03:17:35 -0400113 if (dictList !== undefined && dictList.length > 0) {
Ted Humphreyb80ded02020-06-17 21:40:35 -0400114 let item;
115 for(item in dictList) {
116 if(dictList[item].secondLevelDictionary === 1) {
117 subDicts.push(dictList[item].name);
118 }
119 }
sebdete7c93262020-04-23 15:17:59 +0200120 }
Ted Humphreyb80ded02020-06-17 21:40:35 -0400121 let optionItems = [];
122 for (let i=0; i<subDicts.length; ++i) {
123 if (i === 0) {
124 optionItems.push(<option selected key={subDicts[i]}>{subDicts[i]}</option>);
125 } else {
126 optionItems.push(<option key={subDicts[i]}>{subDicts[i]}</option>);
127 }
128 }
129
drveerendra50320952020-03-04 20:30:44 -0500130 function selectedValue (e) {
131 onChange(e.target.value);
132 }
Ted Humphreyb80ded02020-06-17 21:40:35 -0400133 // When the subDictFlag is true, we need to disable selection of
134 // the sub-dictionary flag
drveerendra50320952020-03-04 20:30:44 -0500135 return(
Ted Humphreyb80ded02020-06-17 21:40:35 -0400136 <select disabled={subDictFlag} onChange={selectedValue} >
137 {optionItems}
138 </select>
139 );
drveerendra50320952020-03-04 20:30:44 -0500140}
141
142export default class ManageDictionaries extends React.Component {
143 constructor(props, context) {
144 super(props, context);
Ted Humphreyb80ded02020-06-17 21:40:35 -0400145 this.addDictionaryElementRow = this.addDictionaryElementRow.bind(this);
146 this.addDictionaryRow = this.addDictionaryRow.bind(this);
147 this.addReplaceDictionaryRequest = this.addReplaceDictionaryRequest.bind(this);
drveerendra50320952020-03-04 20:30:44 -0500148 this.clickHandler = this.clickHandler.bind(this);
Ted Humphreyb80ded02020-06-17 21:40:35 -0400149 this.deleteDictionaryElementRow = this.deleteDictionaryElementRow.bind(this);
150 this.deleteDictionaryRequest = this.deleteDictionaryRequest.bind(this);
151 this.deleteDictionaryRow = this.deleteDictionaryRow.bind(this);
152 this.fileSelectedHandler = this.fileSelectedHandler.bind(this);
Ted Humphreyb56cb112020-06-12 03:17:35 -0400153 this.getDictionaries = this.getDictionaries.bind(this);
154 this.getDictionaryElements = this.getDictionaryElements.bind(this);
Ted Humphreyb80ded02020-06-17 21:40:35 -0400155 this.handleClose = this.handleClose.bind(this);
156 this.handleDictionaryRowClick = this.handleDictionaryRowClick.bind(this);
157 this.importCsvData = this.importCsvData.bind(this);
Ted Humphreyb56cb112020-06-12 03:17:35 -0400158 this.updateDictionaryElementRow = this.updateDictionaryElementRow.bind(this);
Ted Humphreyb80ded02020-06-17 21:40:35 -0400159 this.updateDictionaryElementsRequest = this.updateDictionaryElementsRequest.bind(this);
160 this.updateDictionaryRow = this.updateDictionaryRow.bind(this);
161 this.readOnly = props.readOnly !== undefined ? props.readOnly : false;
drveerendra50320952020-03-04 20:30:44 -0500162 this.state = {
163 show: true,
Ted Humphreyb56cb112020-06-12 03:17:35 -0400164 currentSelectedDictionary: null,
drveerendra50320952020-03-04 20:30:44 -0500165 exportFilename: '',
166 content: null,
drveerendra50320952020-03-04 20:30:44 -0500167 dictionaryElements: [],
Ted Humphreyb56cb112020-06-12 03:17:35 -0400168 tableIcons: {
169 Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
Ted Humphreyb56cb112020-06-12 03:17:35 -0400170 Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />),
171 DetailPanel: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
172 Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />),
Ted Humphreyb80ded02020-06-17 21:40:35 -0400173 Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
174 Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
Ted Humphreyb56cb112020-06-12 03:17:35 -0400175 Export: forwardRef((props, ref) => <VerticalAlignBottomIcon {...props} ref={ref} />),
176 Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
177 FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
178 LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
179 NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
180 PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />),
181 ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
182 Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
183 SortArrow: forwardRef((props, ref) => <ArrowUpward {...props} ref={ref} />),
184 ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
185 ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />)
186 },
drveerendra50320952020-03-04 20:30:44 -0500187 dictColumns: [
188 {
189 title: "Dictionary Name", field: "name",editable: 'onAdd',
190 cellStyle: cellStyle,
191 headerStyle: headerStyle
192 },
193 {
194 title: "Sub Dictionary ?", field: "secondLevelDictionary", lookup: {0: 'No', 1: 'Yes'},
195 cellStyle: cellStyle,
196 headerStyle: headerStyle
197 },
198 {
199 title: "Dictionary Type", field: "subDictionaryType",lookup: {string: 'string', number: 'number'},
200 cellStyle: cellStyle,
201 headerStyle: headerStyle
202 },
203 {
204 title: "Updated By", field: "updatedBy", editable: 'never',
205 cellStyle: cellStyle,
206 headerStyle: headerStyle
207 },
208 {
209 title: "Last Updated Date", field: "updatedDate", editable: 'never',
210 cellStyle: cellStyle,
211 headerStyle: headerStyle
212 }
213 ],
214 dictElementColumns: [
215 {
216 title: "Element Short Name", field: "shortName",editable: 'onAdd',
217 cellStyle: cellStyle,
218 headerStyle: headerStyle
219 },
Ted Humphreyb56cb112020-06-12 03:17:35 -0400220 {
drveerendra50320952020-03-04 20:30:44 -0500221 title: "Element Name", field: "name",
222 cellStyle: cellStyle,
223 headerStyle: headerStyle
224 },
225 {
226 title: "Element Description", field: "description",
227 cellStyle: cellStyle,
228 headerStyle: headerStyle
Ted Humphreyb56cb112020-06-12 03:17:35 -0400229 },
230 {
drveerendra50320952020-03-04 20:30:44 -0500231 title: "Element Type", field: "type",
232 editComponent: props => (
233 <div>
234 <SelectSubDictType value={props.value} onChange={props.onChange} />
235 </div>
236 ),
237 cellStyle: cellStyle,
238 headerStyle: headerStyle
Ted Humphreyb56cb112020-06-12 03:17:35 -0400239 },
240 {
Ted Humphreyb80ded02020-06-17 21:40:35 -0400241 title: "Sub-Dictionary", field: "subDictionary",
242 editComponent: props => (
drveerendra50320952020-03-04 20:30:44 -0500243 <div>
Ted Humphreyb80ded02020-06-17 21:40:35 -0400244 <SubDict value={props.value} onChange={props.onChange} />
drveerendra50320952020-03-04 20:30:44 -0500245 </div>
246 ),
247 cellStyle: cellStyle,
248 headerStyle: headerStyle
Ted Humphreyb56cb112020-06-12 03:17:35 -0400249 },
250 {
drveerendra50320952020-03-04 20:30:44 -0500251 title: "Updated By", field: "updatedBy", editable: 'never',
252 cellStyle: cellStyle,
253 headerStyle: headerStyle
254 },
255 {
256 title: "Updated Date", field: "updatedDate", editable: 'never',
257 cellStyle: cellStyle,
258 headerStyle: headerStyle
259 }
260 ]
261 }
262 }
263
Ted Humphreyb56cb112020-06-12 03:17:35 -0400264 componentDidMount() {
265 this.getDictionaries();
266 }
drveerendra50320952020-03-04 20:30:44 -0500267
Ted Humphreyb56cb112020-06-12 03:17:35 -0400268 getDictionaries() {
269 TemplateMenuService.getDictionary().then(arrayOfdictionaries => {
270 this.setState({ dictionaries: arrayOfdictionaries, currentSelectedDictionary: null })
Ted Humphreyb80ded02020-06-17 21:40:35 -0400271 // global variable setting used functional components in this file
272 dictList = arrayOfdictionaries;
273 }).catch(() => {
274 console.error('Failed to retrieve dictionaries');
275 this.setState({ dictionaries: [], currentSelectedDictionary: null })
Ted Humphreyb56cb112020-06-12 03:17:35 -0400276 });
277 }
drveerendra50320952020-03-04 20:30:44 -0500278
Ted Humphreyb56cb112020-06-12 03:17:35 -0400279 getDictionaryElements(dictionaryName) {
280 TemplateMenuService.getDictionaryElements(dictionaryName).then(dictionaryElements => {
Ted Humphreyb56cb112020-06-12 03:17:35 -0400281 this.setState({ dictionaryElements: dictionaryElements.dictionaryElements} );
Ted Humphreyb80ded02020-06-17 21:40:35 -0400282 this.setState({ currentSelectDictionary: dictionaryName });
283 }).catch(() => console.error('Failed to retrieve dictionary elements'))
Ted Humphreyb56cb112020-06-12 03:17:35 -0400284 }
drveerendra50320952020-03-04 20:30:44 -0500285
Ted Humphreyb56cb112020-06-12 03:17:35 -0400286 clickHandler(rowData) {
287 this.getDictionaries();
288 }
drveerendra50320952020-03-04 20:30:44 -0500289
Ted Humphreyb56cb112020-06-12 03:17:35 -0400290 handleClose() {
291 this.setState({ show: false });
292 this.props.history.push('/');
293 }
drveerendra50320952020-03-04 20:30:44 -0500294
Ted Humphreyb56cb112020-06-12 03:17:35 -0400295 addReplaceDictionaryRequest(dictionaryEntry) {
296 TemplateMenuService.insDictionary(dictionaryEntry)
Ted Humphreyb80ded02020-06-17 21:40:35 -0400297 .then(resp => {
298 this.getDictionaries();
299 })
300 .catch(() => console.error('Failed to insert new dictionary elements'));
Ted Humphreyb56cb112020-06-12 03:17:35 -0400301 }
drveerendra50320952020-03-04 20:30:44 -0500302
Ted Humphreyb56cb112020-06-12 03:17:35 -0400303 updateDictionaryElementsRequest(dictElements) {
304 let reqData = { "name": this.state.currentSelectedDictionary, 'dictionaryElements': dictElements };
305 TemplateMenuService.insDictionaryElements(reqData)
Ted Humphreyb80ded02020-06-17 21:40:35 -0400306 .then(resp => { this.getDictionaryElements(this.state.currentSelectedDictionary) })
307 .catch(() => console.error('Failed to update dictionary elements'));
Ted Humphreyb56cb112020-06-12 03:17:35 -0400308 }
drveerendra50320952020-03-04 20:30:44 -0500309
Ted Humphreyb56cb112020-06-12 03:17:35 -0400310 deleteDictionaryRequest(dictionaryName) {
311 TemplateMenuService.deleteDictionary(dictionaryName)
Ted Humphreyb80ded02020-06-17 21:40:35 -0400312 .then(resp => {
313 this.getDictionaries();
314 })
315 .catch(() => console.error('Failed to delete dictionary'));
Ted Humphreyb56cb112020-06-12 03:17:35 -0400316 }
317
318 deleteDictionaryElementRequest(dictionaryName, elemenetShortName) {
319 TemplateMenuService.deleteDictionaryElements({ 'name': dictionaryName, 'shortName': elemenetShortName })
320 .then(resp => {
321 this.getDictionaryElements(dictionaryName);
Ted Humphreyb80ded02020-06-17 21:40:35 -0400322 })
323 .catch(() => console.error('Failed to delete dictionary elements'));
Ted Humphreyb56cb112020-06-12 03:17:35 -0400324 }
325
326 fileSelectedHandler = (event) => {
327
328 if (event.target.files[0].type === 'text/csv' || event.target.files[0].type === 'application/vnd.ms-excel') {
329 if (event.target.files && event.target.files[0]) {
330 const reader = new FileReader();
331 reader.onload = (e) => {
Ted Humphreyb80ded02020-06-17 21:40:35 -0400332 let errorMessages = this.importCsvData(reader.result);
333 if (errorMessages !== '') {
Ted Humphreyb56cb112020-06-12 03:17:35 -0400334 alert(errorMessages);
Ted Humphreyb56cb112020-06-12 03:17:35 -0400335 }
Ted Humphreyb56cb112020-06-12 03:17:35 -0400336 }
337 reader.readAsText(event.target.files[0]);
338 }
Ted Humphreyb56cb112020-06-12 03:17:35 -0400339 } else {
340 alert('Please upload .csv extention files only.');
341 }
342 }
drveerendra50320952020-03-04 20:30:44 -0500343
Ted Humphreyb80ded02020-06-17 21:40:35 -0400344 importCsvData(rawCsvData) {
345
346 const jsonKeyNames = [ 'shortName', 'name', 'description', 'type', 'subDictionary' ];
347 const userHeaderNames = [ 'Element Short Name', 'Element Name', 'Element Description', 'Element Type', 'Sub-Dictionary' ];
348 const validTypes = ['string','number','datetime','json','map'];
349
350 let mandatory;
351
352 if (subDictFlag) {
353 mandatory = [ true, true, true, false, false ];
354 } else {
355 mandatory = [ true, true, true, true, false ];
356 }
357
358 let result = CsvToJson(rawCsvData, ',', '||||', userHeaderNames, jsonKeyNames, mandatory);
359
360 let errorMessages = result.errorMessages;
361 let jsonObjArray = result.jsonObjArray;
362
363 let validTypesErrorMesg = '';
364
365 for (let i=0; i < validTypes.length; ++i) {
366 if (i === 0) {
367 validTypesErrorMesg = validTypes[i];
368 } else {
369 validTypesErrorMesg += ',' + validTypes[i];
370 }
371 }
372
373 if (errorMessages !== '') {
374 return errorMessages;
375 }
376
377 // Perform further checks on data that is now in JSON form
378 let subDictionaries = [];
379
380 // NOTE: dictList is a global variable maintained faithfully
381 // by the getDictionaries() method outside this import
382 // functionality.
383 let item;
384 for (item in dictList) {
385 if (dictList[item].secondLevelDictionary === 1) {
386 subDictionaries.push(dictList[item].name);
387 }
388 };
389
390 // Check for valid Sub-Dictionary and Element Type values
391 subDictionaries = subDictionaries.toString();
392 let row = 2;
393 let dictElem;
394 for (dictElem of jsonObjArray) {
395 let itemKey;
396 for (itemKey in dictElem){
397 let value = dictElem[itemKey].trim();
398 let keyIndex = jsonKeyNames.indexOf(itemKey);
399 if (itemKey === 'shortName' && /[^a-zA-Z0-9-_.]/.test(value)) {
400 errorMessages += '\n' + userHeaderNames[keyIndex] +
401 ' at row #' + row +
402 ' can only contain alphanumeric characters and periods, hyphens or underscores';
403 }
404 if (itemKey === 'type' && validTypes.indexOf(value) < 0) {
405 errorMessages += '\nInvalid value of "' + value + '" for "' + userHeaderNames[keyIndex] + '" at row #' + row;
406 errorMessages += '\nValid types are: ' + validTypesErrorMesg;
407 }
408 if (value !== "" && itemKey === 'subDictionary' && subDictionaries.indexOf(value) < 0) {
409 errorMessages += '\nInvalid Sub-Dictionary value of "' + value + '" at row #' + row;
410 }
411 }
412 ++row;
413 }
414 if (errorMessages === '') {
415 // We made it through all the checks. Send it to back end
416 this.updateDictionaryElementsRequest(jsonObjArray);
417 }
418
419 return errorMessages;
420 }
421
Ted Humphreyb56cb112020-06-12 03:17:35 -0400422 addDictionaryRow(newData) {
423 let validData = true;
424 return new Promise((resolve, reject) => {
425 setTimeout(() => {
426 if (/[^a-zA-Z0-9-_.]/.test(newData.name)) {
427 validData = false;
428 alert('Please enter alphanumeric input. Only allowed special characters are:(period, hyphen, underscore)');
Ted Humphreyb80ded02020-06-17 21:40:35 -0400429 reject();
Ted Humphreyb56cb112020-06-12 03:17:35 -0400430 }
431 for (let i = 0; i < this.state.dictionaries.length; i++) {
432 if (this.state.dictionaries[i].name === newData.name) {
433 validData = false;
434 alert(newData.name + ' dictionary name already exists')
Ted Humphreyb80ded02020-06-17 21:40:35 -0400435 reject();
Ted Humphreyb56cb112020-06-12 03:17:35 -0400436 }
437 }
438 if (validData) {
439 this.addReplaceDictionaryRequest(newData);
440 }
441 resolve();
442 }, 1000);
443 });
444 }
445
446
Ted Humphreyb80ded02020-06-17 21:40:35 -0400447 updateDictionaryRow(newData, oldData) {
Ted Humphreyb56cb112020-06-12 03:17:35 -0400448 let validData = true;
Ted Humphreyb80ded02020-06-17 21:40:35 -0400449 return new Promise((resolve, reject) => {
Ted Humphreyb56cb112020-06-12 03:17:35 -0400450 setTimeout(() => {
451 if (/[^a-zA-Z0-9-_.]/.test(newData.name)) {
452 validData = false;
453 alert('Please enter alphanumberic input. Only allowed special characters are:(period, hyphen, underscore)');
Ted Humphreyb80ded02020-06-17 21:40:35 -0400454 reject();
Ted Humphreyb56cb112020-06-12 03:17:35 -0400455 }
456 if (validData) {
457 this.addReplaceDictionaryRequest(newData);
458 }
459 resolve();
460 }, 1000);
461 });
462 }
463
464 deleteDictionaryRow(oldData) {
Ted Humphreyb80ded02020-06-17 21:40:35 -0400465 return new Promise((resolve, reject) => {
Ted Humphreyb56cb112020-06-12 03:17:35 -0400466 setTimeout(() => {
467 this.deleteDictionaryRequest(oldData.name);
468 resolve();
469 }, 1000);
470 });
471 }
472
473 addDictionaryElementRow(newData) {
474 return new Promise((resolve, reject) => {
475 setTimeout(() => {
476 let dictionaryElements = this.state.dictionaryElements;
Ted Humphreyb80ded02020-06-17 21:40:35 -0400477 let errorMessages = '';
Ted Humphreyb56cb112020-06-12 03:17:35 -0400478 for (let i = 0; i < this.state.dictionaryElements.length; i++) {
479 if (this.state.dictionaryElements[i].shortName === newData.shortName) {
480 alert('Short Name "' + newData.shortName + '" already exists');
Ted Humphreyb80ded02020-06-17 21:40:35 -0400481 reject("");
Ted Humphreyb56cb112020-06-12 03:17:35 -0400482 }
483 }
Ted Humphreyb80ded02020-06-17 21:40:35 -0400484 // MaterialTable returns no property at all if the user has not touched a
485 // new column, so we want to add the property with an emptry string
486 // for several cases if that is the case to simplify other checks.
487 if (newData.description === undefined) {
488 newData.description = "";
489 }
490 if (newData.subDictionary === undefined) {
491 newData.subDictionary = null;
492 }
493 if (newData.type === undefined) {
494 newData.type = "";
495 }
496 if (!newData.shortName && /[^a-zA-Z0-9-_.]/.test(newData.shortName)) {
497 errorMessages += '\nShort Name is limited to alphanumeric characters and also period, hyphen, and underscore';
Ted Humphreyb56cb112020-06-12 03:17:35 -0400498 }
499 if (!newData.shortName){
Ted Humphreyb80ded02020-06-17 21:40:35 -0400500 errorMessages += '\nShort Name must be specified';
Ted Humphreyb56cb112020-06-12 03:17:35 -0400501 }
502 if (!newData.name){
Ted Humphreyb80ded02020-06-17 21:40:35 -0400503 errorMessages += '\nElement Name must be specified';
Ted Humphreyb56cb112020-06-12 03:17:35 -0400504 }
Ted Humphreyb80ded02020-06-17 21:40:35 -0400505 if (!newData.type && !subDictFlag){
506 errorMessages += '\nElement Type must be specified';
Ted Humphreyb56cb112020-06-12 03:17:35 -0400507 }
Ted Humphreyb80ded02020-06-17 21:40:35 -0400508 if (errorMessages === '') {
Ted Humphreyb56cb112020-06-12 03:17:35 -0400509 dictionaryElements.push(newData);
Ted Humphreyb80ded02020-06-17 21:40:35 -0400510 this.updateDictionaryElementsRequest([newData]);
Ted Humphreyb56cb112020-06-12 03:17:35 -0400511 resolve();
512 } else {
Ted Humphreyb80ded02020-06-17 21:40:35 -0400513 alert(errorMessages);
514 reject("");
Ted Humphreyb56cb112020-06-12 03:17:35 -0400515 }
516 }, 1000);
517 });
518 }
519
520 updateDictionaryElementRow(newData, oldData) {
Ted Humphreyb80ded02020-06-17 21:40:35 -0400521 return new Promise((resolve, reject) => {
Ted Humphreyb56cb112020-06-12 03:17:35 -0400522 setTimeout(() => {
523 let dictionaryElements = this.state.dictionaryElements;
524 let validData = true;
525 if (!newData.type) {
526 validData = false;
527 alert('Element Type cannot be null');
Ted Humphreyb80ded02020-06-17 21:40:35 -0400528 reject();
Ted Humphreyb56cb112020-06-12 03:17:35 -0400529 }
530 if (validData) {
531 const index = dictionaryElements.indexOf(oldData);
532 dictionaryElements[index] = newData;
Ted Humphreyb80ded02020-06-17 21:40:35 -0400533 this.updateDictionaryElementsRequest([newData]);
Ted Humphreyb56cb112020-06-12 03:17:35 -0400534 }
535 resolve();
536 }, 1000);
537 });
538 }
539
540
541 deleteDictionaryElementRow(oldData) {
542 return new Promise((resolve) => {
543 setTimeout(() => {
544 this.deleteDictionaryElementRequest(this.state.currentSelectedDictionary, oldData.shortName);
545 resolve();
546 }, 1000);
547 });
548 }
549
Ted Humphreyb80ded02020-06-17 21:40:35 -0400550 handleDictionaryRowClick(event, rowData) {
551 subDictFlag = rowData.secondLevelDictionary === 1 ? true : false;
552 this.setState({
553 currentSelectedDictionary : rowData.name,
554 exportFilename: rowData.name
555 })
556 this.getDictionaryElements(rowData.name);
557 }
558
Ted Humphreyb56cb112020-06-12 03:17:35 -0400559 render() {
560 return (
561 <ModalStyled size="xl" show={this.state.show} onHide={this.handleClose} backdrop="static" keyboard={false} >
562 <Modal.Header closeButton>
563 <Modal.Title>Manage Dictionaries</Modal.Title>
564 </Modal.Header>
565 <Modal.Body>
Ted Humphreyb80ded02020-06-17 21:40:35 -0400566 {this.state.currentSelectedDictionary === null ?
567 <MaterialTable
568 title={"Dictionary List"}
569 data={this.state.dictionaries}
570 columns={this.state.dictColumns}
571 icons={this.state.tableIcons}
572 onRowClick={this.handleDictionaryRowClick}
573 options={{
574 headerStyle: rowHeaderStyle,
575 }}
576 editable={!this.readOnly ?
577 {
578 onRowAdd: this.addDictionaryRow,
579 onRowUpdate: this.updateDictionaryRow,
580 onRowDelete: this.deleteDictionaryRow
581 } : undefined }
Ted Humphreyb56cb112020-06-12 03:17:35 -0400582 /> : null
Ted Humphreyb80ded02020-06-17 21:40:35 -0400583 }
584 {this.state.currentSelectedDictionary !== null ?
585 <MaterialTable
586 title={'Dictionary Elements List for ' + (subDictFlag ? 'Sub-Dictionary "' : '"') + this.state.currentSelectedDictionary + '"'}
587 data={this.state.dictionaryElements}
588 columns={this.state.dictElementColumns}
589 icons={this.state.tableIcons}
590 options={{
591 exportAllData: true,
592 exportButton: true,
593 exportFileName: this.state.exportFilename,
594 headerStyle:{backgroundColor:'white', fontSize: '15pt', text: 'bold', border: '1px solid black'}
595 }}
596 components={{
597 Toolbar: props => (
598 <Row>
599 <Col sm="11">
600 <MTableToolbarStyled {...props} />
601 </Col>
602 <ColPullLeftStyled sm="1">
603 <Tooltip title="Import" placement = "bottom">
604 <IconButton aria-label="import" disabled={this.readOnly} onClick={() => this.fileUpload.click()}>
605 <VerticalAlignTopIcon />
606 </IconButton>
607 </Tooltip>
608 <input type="file" ref={(fileUpload) => {this.fileUpload = fileUpload;}}
609 style={{ visibility: 'hidden', width: '1px' }} onChange={this.fileSelectedHandler} />
610 </ColPullLeftStyled>
611 </Row>
612 )
613 }}
614 editable={!this.readOnly ?
615 {
616 onRowAdd: this.addDictionaryElementRow,
617 onRowUpdate: this.updateDictionaryElementRow,
618 onRowDelete: this.deleteDictionaryElementRow
619 } : undefined
620 }
621 /> : null
622 }
623 {this.state.currentSelectedDictionary !== null ? <button onClick={this.clickHandler} style={{marginTop: '25px'}}>Go Back to Dictionaries List</button>:""}
624 </Modal.Body>
625 <Modal.Footer>
626 <Button variant="secondary" type="null" onClick={this.handleClose}>Close</Button>
627 </Modal.Footer>
628 </ModalStyled>
629 );
630 }
Ted Humphreyb56cb112020-06-12 03:17:35 -0400631}