aboutsummaryrefslogtreecommitdiffstats
path: root/runtime/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js')
-rw-r--r--runtime/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js1124
1 files changed, 565 insertions, 559 deletions
diff --git a/runtime/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js b/runtime/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js
index 90bbc887c..d7ba8d1c6 100644
--- a/runtime/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js
+++ b/runtime/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js
@@ -29,7 +29,7 @@ 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 MaterialTable, { MTableToolbar } from "material-table";
import IconButton from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip';
import AddBox from '@material-ui/icons/AddBox';
@@ -51,581 +51,587 @@ import ViewColumn from '@material-ui/icons/ViewColumn';
const ModalStyled = styled(Modal)`
- @media (min-width: 1200px) {
- .modal-xl {
- max-width: 96%;
- }
- }
- background-color: transparent;
+ @media (min-width: 1200px) {
+ .modal-xl {
+ max-width: 96%;
+ }
+ }
+ background-color: transparent;
`
const MTableToolbarStyled = styled(MTableToolbar)`
- display: flex;
- flex-direction: row;
- align-items: center;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
`
const ColPullLeftStyled = styled(Col)`
- display: flex;
- flex-direction: row;
- align-items: center;
- margin-left: -40px;
+ 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'};
+const headerStyle = { backgroundColor: '#ddd', border: '2px solid black' };
+const rowHeaderStyle = { backgroundColor: '#ddd', fontSize: '15pt', text: 'bold', border: '1px solid black' };
let dictList = [];
let subDictFlag = false;
function SelectSubDictType(props) {
- const {onChange} = props;
- const selectedValues = (e) => {
- 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('|');
- }
- }
- SelectedDictTypes = SelectedDictTypes.slice(0,-1);
- onChange(SelectedDictTypes);
- }
- // When the subDictFlag is true, we need to disable selection of element "type"
- return(
- <div>
- <select disabled={subDictFlag} multiple={true} onChange={selectedValues}>
- <option value="string">string</option>
- <option value="number">number</option>
- <option value="datetime">datetime</option>
- <option value="map">map</option>
- <option value="json">json</option>
- </select>
- </div>
- );
+ const { onChange } = props;
+ const selectedValues = (e) => {
+ 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('|');
+ }
+ }
+ SelectedDictTypes = SelectedDictTypes.slice(0, -1);
+ onChange(SelectedDictTypes);
+ }
+ // When the subDictFlag is true, we need to disable selection of element "type"
+ return (
+ <div>
+ <select disabled={ subDictFlag } multiple={ true } onChange={ selectedValues }>
+ <option value="string">string</option>
+ <option value="number">number</option>
+ <option value="datetime">datetime</option>
+ <option value="map">map</option>
+ <option value="json">json</option>
+ </select>
+ </div>
+ );
}
function SubDict(props) {
- const {onChange} = props;
- const subDicts = [];
- subDicts.push('none');
- if (dictList !== undefined && dictList.length > 0) {
- let item;
- for(item in dictList) {
- if(dictList[item].secondLevelDictionary === 1) {
- subDicts.push(dictList[item].name);
- }
- }
- }
- let optionItems = [];
- for (let i=0; i<subDicts.length; ++i) {
- if (i === 0) {
- optionItems.push(<option selected key={subDicts[i]}>{subDicts[i]}</option>);
- } else {
- optionItems.push(<option key={subDicts[i]}>{subDicts[i]}</option>);
- }
- }
-
- function selectedValue (e) {
- onChange(e.target.value);
- }
- // When the subDictFlag is true, we need to disable selection of
- // the sub-dictionary flag
- return(
- <select disabled={subDictFlag} onChange={selectedValue} >
- {optionItems}
- </select>
- );
+ const { onChange } = props;
+ const subDicts = [];
+ subDicts.push('none');
+ if (dictList !== undefined && dictList.length > 0) {
+ let item;
+ for (item in dictList) {
+ if (dictList[item].secondLevelDictionary === 1) {
+ subDicts.push(dictList[item].name);
+ }
+ }
+ }
+ let optionItems = [];
+ for (let i = 0; i < subDicts.length; ++i) {
+ if (i === 0) {
+ optionItems.push(<option selected key={ subDicts[i] }>{ subDicts[i] }</option>);
+ } else {
+ optionItems.push(<option key={ subDicts[i] }>{ subDicts[i] }</option>);
+ }
+ }
+
+ function selectedValue(e) {
+ onChange(e.target.value);
+ }
+
+ // When the subDictFlag is true, we need to disable selection of
+ // the sub-dictionary flag
+ return (
+ <select disabled={ subDictFlag } onChange={ selectedValue }>
+ { optionItems }
+ </select>
+ );
}
export default class ManageDictionaries extends React.Component {
- constructor(props, context) {
- super(props, context);
- this.addDictionaryElementRow = this.addDictionaryElementRow.bind(this);
- this.addDictionaryRow = this.addDictionaryRow.bind(this);
- this.addReplaceDictionaryRequest = this.addReplaceDictionaryRequest.bind(this);
- this.clickHandler = this.clickHandler.bind(this);
- this.deleteDictionaryElementRow = this.deleteDictionaryElementRow.bind(this);
- this.deleteDictionaryRequest = this.deleteDictionaryRequest.bind(this);
- this.deleteDictionaryRow = this.deleteDictionaryRow.bind(this);
- this.fileSelectedHandler = this.fileSelectedHandler.bind(this);
- this.getDictionaries = this.getDictionaries.bind(this);
- this.getDictionaryElements = this.getDictionaryElements.bind(this);
- this.handleClose = this.handleClose.bind(this);
- this.handleDictionaryRowClick = this.handleDictionaryRowClick.bind(this);
- this.importCsvData = this.importCsvData.bind(this);
- this.updateDictionaryElementRow = this.updateDictionaryElementRow.bind(this);
- this.updateDictionaryElementsRequest = this.updateDictionaryElementsRequest.bind(this);
- this.updateDictionaryRow = this.updateDictionaryRow.bind(this);
- this.readOnly = props.readOnly !== undefined ? props.readOnly : false;
- this.state = {
- show: true,
- currentSelectedDictionary: null,
- exportFilename: '',
- content: null,
- dictionaryElements: [],
- tableIcons: {
- Add: forwardRef((props, ref) => <AddBox {...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} />),
- Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
- Clear: forwardRef((props, ref) => <Clear {...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',
- cellStyle: cellStyle,
- headerStyle: headerStyle
- },
- {
- title: "Sub Dictionary ?", field: "secondLevelDictionary", lookup: {0: 'No', 1: 'Yes'},
- cellStyle: cellStyle,
- headerStyle: headerStyle
- },
- {
- title: "Dictionary Type", field: "subDictionaryType",lookup: {string: 'string', number: 'number'},
- cellStyle: cellStyle,
- headerStyle: headerStyle
- },
- {
- title: "Updated By", field: "updatedBy", editable: 'never',
- cellStyle: cellStyle,
- headerStyle: headerStyle
- },
- {
- title: "Last Updated Date", field: "updatedDate", editable: 'never',
- cellStyle: cellStyle,
- headerStyle: headerStyle
- }
- ],
- dictElementColumns: [
- {
- title: "Element Short Name", field: "shortName",editable: 'onAdd',
- cellStyle: cellStyle,
- headerStyle: headerStyle
- },
- {
- title: "Element Name", field: "name",
- cellStyle: cellStyle,
- headerStyle: headerStyle
- },
- {
- title: "Element Description", field: "description",
- cellStyle: cellStyle,
- headerStyle: headerStyle
- },
- {
- title: "Element Type", field: "type",
- editComponent: props => (
- <div>
- <SelectSubDictType value={props.value} onChange={props.onChange} />
- </div>
- ),
- cellStyle: cellStyle,
- headerStyle: headerStyle
- },
- {
- title: "Sub-Dictionary", field: "subDictionary",
- editComponent: props => (
- <div>
- <SubDict value={props.value} onChange={props.onChange} />
- </div>
- ),
- cellStyle: cellStyle,
- headerStyle: headerStyle
- },
- {
- title: "Updated By", field: "updatedBy", editable: 'never',
- cellStyle: cellStyle,
- headerStyle: headerStyle
- },
- {
- title: "Updated Date", field: "updatedDate", editable: 'never',
- cellStyle: cellStyle,
- headerStyle: headerStyle
- }
- ]
- }
- }
-
- componentDidMount() {
- this.getDictionaries();
- }
-
- getDictionaries() {
- TemplateMenuService.getDictionary().then(arrayOfdictionaries => {
- this.setState({ dictionaries: arrayOfdictionaries, currentSelectedDictionary: null })
- // global variable setting used functional components in this file
- dictList = arrayOfdictionaries;
- }).catch(() => {
- console.error('Failed to retrieve dictionaries');
- this.setState({ dictionaries: [], currentSelectedDictionary: null })
- });
- }
-
- getDictionaryElements(dictionaryName) {
- TemplateMenuService.getDictionaryElements(dictionaryName).then(dictionaryElements => {
- this.setState({ dictionaryElements: dictionaryElements.dictionaryElements} );
- this.setState({ currentSelectDictionary: dictionaryName });
- }).catch(() => console.error('Failed to retrieve dictionary elements'))
- }
-
- clickHandler(rowData) {
- this.getDictionaries();
- }
-
- handleClose() {
- this.setState({ show: false });
- this.props.history.push('/');
- }
-
- addReplaceDictionaryRequest(dictionaryEntry) {
- TemplateMenuService.insDictionary(dictionaryEntry)
- .then(resp => {
- this.getDictionaries();
- })
- .catch(() => console.error('Failed to insert new dictionary elements'));
- }
-
- updateDictionaryElementsRequest(dictElements) {
- let reqData = { "name": this.state.currentSelectedDictionary, 'dictionaryElements': dictElements };
- TemplateMenuService.insDictionaryElements(reqData)
- .then(resp => { this.getDictionaryElements(this.state.currentSelectedDictionary) })
- .catch(() => console.error('Failed to update dictionary elements'));
- }
-
- deleteDictionaryRequest(dictionaryName) {
- TemplateMenuService.deleteDictionary(dictionaryName)
- .then(resp => {
- this.getDictionaries();
- })
- .catch(() => console.error('Failed to delete dictionary'));
- }
-
- deleteDictionaryElementRequest(dictionaryName, elemenetShortName) {
- TemplateMenuService.deleteDictionaryElements({ 'name': dictionaryName, 'shortName': elemenetShortName })
- .then(resp => {
- this.getDictionaryElements(dictionaryName);
- })
- .catch(() => console.error('Failed to delete dictionary elements'));
- }
-
- 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) => {
- let errorMessages = this.importCsvData(reader.result);
- if (errorMessages !== '') {
- alert(errorMessages);
- }
- }
- reader.readAsText(event.target.files[0]);
- }
- } else {
- alert('Please upload .csv extention files only.');
- }
- }
-
- importCsvData(rawCsvData) {
-
- const jsonKeyNames = [ 'shortName', 'name', 'description', 'type', 'subDictionary' ];
- const userHeaderNames = [ 'Element Short Name', 'Element Name', 'Element Description', 'Element Type', 'Sub-Dictionary' ];
- const validTypes = ['string','number','datetime','json','map'];
-
- let mandatory;
-
- if (subDictFlag) {
- mandatory = [ true, true, true, false, false ];
- } else {
- mandatory = [ true, true, true, true, false ];
- }
-
- let result = CsvToJson(rawCsvData, ',', '||||', 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 !== '') {
- return errorMessages;
- }
-
- // 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;
- }
- if (errorMessages === '') {
- // We made it through all the checks. Send it to back end
- this.updateDictionaryElementsRequest(jsonObjArray);
- }
-
- return errorMessages;
- }
-
- 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(newData, oldData) {
- let validData = true;
- return new Promise((resolve, reject) => {
- setTimeout(() => {
- if (/[^a-zA-Z0-9-_.]/.test(newData.name)) {
- validData = false;
- alert('Please enter alphanumberic input. Only allowed special characters are:(period, hyphen, underscore)');
- reject();
- }
- if (validData) {
- this.addReplaceDictionaryRequest(newData);
- }
- resolve();
- }, 1000);
- });
- }
-
- deleteDictionaryRow(oldData) {
- return new Promise((resolve, reject) => {
- setTimeout(() => {
- this.deleteDictionaryRequest(oldData.name);
- resolve();
- }, 1000);
- });
- }
-
- addDictionaryElementRow(newData) {
- return new Promise((resolve, reject) => {
- setTimeout(() => {
- let dictionaryElements = this.state.dictionaryElements;
- let errorMessages = '';
- 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("");
- }
- }
- // MaterialTable returns no property at all if the user has not touched a
- // new column, so we want to add the property with an emptry string
- // for several cases if that is the case to simplify other checks.
- if (newData.description === undefined) {
- newData.description = "";
- }
- if (newData.subDictionary === undefined) {
- newData.subDictionary = null;
- }
- if (newData.type === undefined) {
- newData.type = "";
- }
- if (!newData.shortName && /[^a-zA-Z0-9-_.]/.test(newData.shortName)) {
- errorMessages += '\nShort Name is limited to alphanumeric characters and also period, hyphen, and underscore';
- }
- if (!newData.shortName){
- errorMessages += '\nShort Name must be specified';
- }
- if (!newData.name){
- errorMessages += '\nElement Name must be specified';
- }
- if (!newData.type && !subDictFlag){
- errorMessages += '\nElement Type must be specified';
- }
- if (errorMessages === '') {
- dictionaryElements.push(newData);
- this.updateDictionaryElementsRequest([newData]);
- resolve();
- } else {
- alert(errorMessages);
- reject("");
- }
- }, 1000);
- });
- }
-
- updateDictionaryElementRow(newData, oldData) {
- return new Promise((resolve, reject) => {
- setTimeout(() => {
- let dictionaryElements = this.state.dictionaryElements;
- let validData = true;
- if (!newData.type) {
- validData = false;
- alert('Element Type cannot be null');
- reject();
- }
- if (validData) {
- const index = dictionaryElements.indexOf(oldData);
- dictionaryElements[index] = newData;
- this.updateDictionaryElementsRequest([newData]);
- }
- resolve();
- }, 1000);
- });
- }
-
-
- deleteDictionaryElementRow(oldData) {
- return new Promise((resolve) => {
- setTimeout(() => {
- this.deleteDictionaryElementRequest(this.state.currentSelectedDictionary, oldData.shortName);
- resolve();
- }, 1000);
- });
- }
-
- handleDictionaryRowClick(event, rowData) {
- subDictFlag = rowData.secondLevelDictionary === 1 ? true : false;
- this.setState({
- currentSelectedDictionary : rowData.name,
- exportFilename: rowData.name
- })
- this.getDictionaryElements(rowData.name);
- }
-
- 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={this.handleDictionaryRowClick}
- options={{
- headerStyle: rowHeaderStyle,
- }}
- editable={!this.readOnly ?
- {
- onRowAdd: this.addDictionaryRow,
- onRowUpdate: this.updateDictionaryRow,
- onRowDelete: this.deleteDictionaryRow
- } : undefined }
- /> : null
- }
- {this.state.currentSelectedDictionary !== null ?
- <MaterialTable
- title={'Dictionary Elements List for ' + (subDictFlag ? 'Sub-Dictionary "' : '"') + 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 => (
- <Row>
- <Col sm="11">
- <MTableToolbarStyled {...props} />
- </Col>
- <ColPullLeftStyled sm="1">
- <Tooltip title="Import" placement = "bottom">
- <IconButton aria-label="import" disabled={this.readOnly} onClick={() => this.fileUpload.click()}>
- <VerticalAlignTopIcon />
- </IconButton>
- </Tooltip>
- <input type="file" ref={(fileUpload) => {this.fileUpload = fileUpload;}}
- style={{ visibility: 'hidden', width: '1px' }} onChange={this.fileSelectedHandler} />
- </ColPullLeftStyled>
- </Row>
- )
- }}
- editable={!this.readOnly ?
- {
- onRowAdd: this.addDictionaryElementRow,
- onRowUpdate: this.updateDictionaryElementRow,
- onRowDelete: this.deleteDictionaryElementRow
- } : undefined
- }
- /> : null
- }
- {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>
- </Modal.Footer>
- </ModalStyled>
- );
- }
+ constructor(props, context) {
+ super(props, context);
+ this.addDictionaryElementRow = this.addDictionaryElementRow.bind(this);
+ this.addDictionaryRow = this.addDictionaryRow.bind(this);
+ this.addReplaceDictionaryRequest = this.addReplaceDictionaryRequest.bind(this);
+ this.clickHandler = this.clickHandler.bind(this);
+ this.deleteDictionaryElementRow = this.deleteDictionaryElementRow.bind(this);
+ this.deleteDictionaryRequest = this.deleteDictionaryRequest.bind(this);
+ this.deleteDictionaryRow = this.deleteDictionaryRow.bind(this);
+ this.fileSelectedHandler = this.fileSelectedHandler.bind(this);
+ this.getDictionaries = this.getDictionaries.bind(this);
+ this.getDictionaryElements = this.getDictionaryElements.bind(this);
+ this.handleClose = this.handleClose.bind(this);
+ this.handleDictionaryRowClick = this.handleDictionaryRowClick.bind(this);
+ this.importCsvData = this.importCsvData.bind(this);
+ this.updateDictionaryElementRow = this.updateDictionaryElementRow.bind(this);
+ this.updateDictionaryElementsRequest = this.updateDictionaryElementsRequest.bind(this);
+ this.updateDictionaryRow = this.updateDictionaryRow.bind(this);
+ this.readOnly = props.readOnly !== undefined ? props.readOnly : false;
+ this.state = {
+ show: true,
+ currentSelectedDictionary: null,
+ exportFilename: '',
+ content: null,
+ dictionaryElements: [],
+ tableIcons: {
+ Add: forwardRef((props, ref) => <AddBox { ...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 }/>),
+ Check: forwardRef((props, ref) => <Check { ...props } ref={ ref }/>),
+ Clear: forwardRef((props, ref) => <Clear { ...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',
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ },
+ {
+ title: "Sub Dictionary ?", field: "secondLevelDictionary", lookup: { 0: 'No', 1: 'Yes' },
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ },
+ {
+ title: "Dictionary Type", field: "subDictionaryType", lookup: { string: 'string', number: 'number' },
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ },
+ {
+ title: "Updated By", field: "updatedBy", editable: 'never',
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ },
+ {
+ title: "Last Updated Date", field: "updatedDate", editable: 'never',
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ }
+ ],
+ dictElementColumns: [
+ {
+ title: "Element Short Name", field: "shortName", editable: 'onAdd',
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ },
+ {
+ title: "Element Name", field: "name",
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ },
+ {
+ title: "Element Description", field: "description",
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ },
+ {
+ title: "Element Type", field: "type",
+ editComponent: props => (
+ <div>
+ <SelectSubDictType value={ props.value } onChange={ props.onChange }/>
+ </div>
+ ),
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ },
+ {
+ title: "Sub-Dictionary", field: "subDictionary",
+ editComponent: props => (
+ <div>
+ <SubDict value={ props.value } onChange={ props.onChange }/>
+ </div>
+ ),
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ },
+ {
+ title: "Updated By", field: "updatedBy", editable: 'never',
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ },
+ {
+ title: "Updated Date", field: "updatedDate", editable: 'never',
+ cellStyle: cellStyle,
+ headerStyle: headerStyle
+ }
+ ]
+ }
+ }
+
+ componentDidMount() {
+ this.getDictionaries();
+ }
+
+ getDictionaries() {
+ TemplateMenuService.getDictionary().then(arrayOfdictionaries => {
+ this.setState({ dictionaries: arrayOfdictionaries, currentSelectedDictionary: null })
+ // global variable setting used functional components in this file
+ dictList = arrayOfdictionaries;
+ }).catch(() => {
+ console.error('Failed to retrieve dictionaries');
+ this.setState({ dictionaries: [], currentSelectedDictionary: null })
+ });
+ }
+
+ getDictionaryElements(dictionaryName) {
+ TemplateMenuService.getDictionaryElements(dictionaryName).then(dictionaryElements => {
+ this.setState({ dictionaryElements: dictionaryElements.dictionaryElements });
+ this.setState({ currentSelectDictionary: dictionaryName });
+ }).catch(() => console.error('Failed to retrieve dictionary elements'))
+ }
+
+ clickHandler(rowData) {
+ this.getDictionaries();
+ }
+
+ handleClose() {
+ this.setState({ show: false });
+ this.props.history.push('/');
+ }
+
+ addReplaceDictionaryRequest(dictionaryEntry) {
+ TemplateMenuService.insDictionary(dictionaryEntry)
+ .then(resp => {
+ this.getDictionaries();
+ })
+ .catch(() => console.error('Failed to insert new dictionary elements'));
+ }
+
+ updateDictionaryElementsRequest(dictElements) {
+ let reqData = { "name": this.state.currentSelectedDictionary, 'dictionaryElements': dictElements };
+ TemplateMenuService.insDictionaryElements(reqData)
+ .then(resp => {
+ this.getDictionaryElements(this.state.currentSelectedDictionary)
+ })
+ .catch(() => console.error('Failed to update dictionary elements'));
+ }
+
+ deleteDictionaryRequest(dictionaryName) {
+ TemplateMenuService.deleteDictionary(dictionaryName)
+ .then(resp => {
+ this.getDictionaries();
+ })
+ .catch(() => console.error('Failed to delete dictionary'));
+ }
+
+ deleteDictionaryElementRequest(dictionaryName, elemenetShortName) {
+ TemplateMenuService.deleteDictionaryElements({ 'name': dictionaryName, 'shortName': elemenetShortName })
+ .then(resp => {
+ this.getDictionaryElements(dictionaryName);
+ })
+ .catch(() => console.error('Failed to delete dictionary elements'));
+ }
+
+ 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) => {
+ let errorMessages = this.importCsvData(reader.result);
+ if (errorMessages !== '') {
+ alert(errorMessages);
+ }
+ }
+ reader.readAsText(event.target.files[0]);
+ }
+ } else {
+ alert('Please upload .csv extention files only.');
+ }
+ }
+
+ importCsvData(rawCsvData) {
+
+ const jsonKeyNames = ['shortName', 'name', 'description', 'type', 'subDictionary'];
+ const userHeaderNames = ['Element Short Name', 'Element Name', 'Element Description', 'Element Type', 'Sub-Dictionary'];
+ const validTypes = ['string', 'number', 'datetime', 'json', 'map'];
+
+ let mandatory;
+
+ if (subDictFlag) {
+ mandatory = [true, true, true, false, false];
+ } else {
+ mandatory = [true, true, true, true, false];
+ }
+
+ let result = CsvToJson(rawCsvData, ',', '||||', 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 !== '') {
+ return errorMessages;
+ }
+
+ // 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;
+ }
+ if (errorMessages === '') {
+ // We made it through all the checks. Send it to back end
+ this.updateDictionaryElementsRequest(jsonObjArray);
+ }
+
+ return errorMessages;
+ }
+
+ 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(newData, oldData) {
+ let validData = true;
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ if (/[^a-zA-Z0-9-_.]/.test(newData.name)) {
+ validData = false;
+ alert('Please enter alphanumberic input. Only allowed special characters are:(period, hyphen, underscore)');
+ reject();
+ }
+ if (validData) {
+ this.addReplaceDictionaryRequest(newData);
+ }
+ resolve();
+ }, 1000);
+ });
+ }
+
+ deleteDictionaryRow(oldData) {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ this.deleteDictionaryRequest(oldData.name);
+ resolve();
+ }, 1000);
+ });
+ }
+
+ addDictionaryElementRow(newData) {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ let dictionaryElements = this.state.dictionaryElements;
+ let errorMessages = '';
+ 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("");
+ }
+ }
+ // MaterialTable returns no property at all if the user has not touched a
+ // new column, so we want to add the property with an emptry string
+ // for several cases if that is the case to simplify other checks.
+ if (newData.description === undefined) {
+ newData.description = "";
+ }
+ if (newData.subDictionary === undefined) {
+ newData.subDictionary = null;
+ }
+ if (newData.type === undefined) {
+ newData.type = "";
+ }
+ if (!newData.shortName && /[^a-zA-Z0-9-_.]/.test(newData.shortName)) {
+ errorMessages += '\nShort Name is limited to alphanumeric characters and also period, hyphen, and underscore';
+ }
+ if (!newData.shortName) {
+ errorMessages += '\nShort Name must be specified';
+ }
+ if (!newData.name) {
+ errorMessages += '\nElement Name must be specified';
+ }
+ if (!newData.type && !subDictFlag) {
+ errorMessages += '\nElement Type must be specified';
+ }
+ if (errorMessages === '') {
+ dictionaryElements.push(newData);
+ this.updateDictionaryElementsRequest([newData]);
+ resolve();
+ } else {
+ alert(errorMessages);
+ reject("");
+ }
+ }, 1000);
+ });
+ }
+
+ updateDictionaryElementRow(newData, oldData) {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ let dictionaryElements = this.state.dictionaryElements;
+ let validData = true;
+ if (!newData.type) {
+ validData = false;
+ alert('Element Type cannot be null');
+ reject();
+ }
+ if (validData) {
+ const index = dictionaryElements.indexOf(oldData);
+ dictionaryElements[index] = newData;
+ this.updateDictionaryElementsRequest([newData]);
+ }
+ resolve();
+ }, 1000);
+ });
+ }
+
+
+ deleteDictionaryElementRow(oldData) {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ this.deleteDictionaryElementRequest(this.state.currentSelectedDictionary, oldData.shortName);
+ resolve();
+ }, 1000);
+ });
+ }
+
+ handleDictionaryRowClick(event, rowData) {
+ subDictFlag = rowData.secondLevelDictionary === 1 ? true : false;
+ this.setState({
+ currentSelectedDictionary: rowData.name,
+ exportFilename: rowData.name
+ })
+ this.getDictionaryElements(rowData.name);
+ }
+
+ 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={ this.handleDictionaryRowClick }
+ options={ {
+ headerStyle: rowHeaderStyle,
+ } }
+ editable={ !this.readOnly ?
+ {
+ onRowAdd: this.addDictionaryRow,
+ onRowUpdate: this.updateDictionaryRow,
+ onRowDelete: this.deleteDictionaryRow
+ } : undefined }
+ /> : null
+ }
+ { this.state.currentSelectedDictionary !== null ?
+ <MaterialTable
+ title={ 'Dictionary Elements List for ' + (subDictFlag ? 'Sub-Dictionary "' : '"') + 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 => (
+ <Row>
+ <Col sm="11">
+ <MTableToolbarStyled { ...props } />
+ </Col>
+ <ColPullLeftStyled sm="1">
+ <Tooltip title="Import" placement="bottom">
+ <IconButton aria-label="import" disabled={ this.readOnly } onClick={ () => this.fileUpload.click() }>
+ <VerticalAlignTopIcon/>
+ </IconButton>
+ </Tooltip>
+ <input type="file" ref={ (fileUpload) => {
+ this.fileUpload = fileUpload;
+ } }
+ style={ { visibility: 'hidden', width: '1px' } } onChange={ this.fileSelectedHandler }/>
+ </ColPullLeftStyled>
+ </Row>
+ )
+ } }
+ editable={ !this.readOnly ?
+ {
+ onRowAdd: this.addDictionaryElementRow,
+ onRowUpdate: this.updateDictionaryElementRow,
+ onRowDelete: this.deleteDictionaryElementRow
+ } : undefined
+ }
+ /> : null
+ }
+ { 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>
+ </Modal.Footer>
+ </ModalStyled>
+ );
+ }
}