X-Git-Url: https://gerrit.onap.org/r/gitweb?p=aai%2Fsparky-fe.git;a=blobdiff_plain;f=src%2Fapp%2Fbyoq%2FCustomDslBuilder.jsx;fp=src%2Fapp%2Fbyoq%2FCustomDslBuilder.jsx;h=1e034fade0043776fcf914910fa94e4a1c06f995;hp=0000000000000000000000000000000000000000;hb=5ee7367a101143715c2869d72ea4a6fbf55f5af6;hpb=ddc05d4ea0254b427fea6ec80e2b03950eeca4ce diff --git a/src/app/byoq/CustomDslBuilder.jsx b/src/app/byoq/CustomDslBuilder.jsx new file mode 100644 index 0000000..1e034fa --- /dev/null +++ b/src/app/byoq/CustomDslBuilder.jsx @@ -0,0 +1,1725 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import React, {Component} from 'react'; +import commonApi from 'utils/CommonAPIService.js'; +import {GeneralCommonFunctions} from 'utils/GeneralCommonFunctions.js'; +import Modal from 'react-bootstrap/lib/Modal'; +import Grid from 'react-bootstrap/lib/Grid'; +import FormGroup from 'react-bootstrap/lib/FormGroup'; +import FormControl from 'react-bootstrap/lib/FormControl'; +import ControlLabel from 'react-bootstrap/lib/ControlLabel'; +import Button from 'react-bootstrap/lib/Button'; +import {GlobalExtConstants} from 'utils/GlobalExtConstants.js'; +import Spinner from 'utils/SpinnerContainer.jsx'; +import Row from 'react-bootstrap/lib/Row'; +import Col from 'react-bootstrap/lib/Col'; +import Panel from 'react-bootstrap/lib/Panel'; +import Tooltip from 'react-bootstrap/lib/Tooltip'; +import FilterTypes from 'generic-components/filter/components/FilterTypes.jsx'; +import PathFilterDslBuilder from './PathFilterDslBuilder.jsx'; +import CustomDSLSaveLoad from 'app/byoq/CustomDSLSaveLoad.jsx'; +import BootstrapSwitchButton from 'bootstrap-switch-button-react'; +import * as d3 from "d3"; +import 'd3-selection-multi'; + + +let EDGERULES = GlobalExtConstants.EDGERULES; +let OXM = GlobalExtConstants.OXM; +let INVLIST = GlobalExtConstants.INVLIST; +let ENVIRONMENT = GlobalExtConstants.ENVIRONMENT; +let APERTURE_SERVICE = JSON.parse(sessionStorage.getItem(ENVIRONMENT + 'APERTURE_SERVICE')); + + +let nodeTypes = []; +let properties = null; +let traverseRulesDsl = []; + +const settings = { + 'NODESERVER': INVLIST.NODESERVER, + 'PROXY': INVLIST.PROXY, + 'PREFIX': INVLIST.PREFIX, + 'VERSION': INVLIST.VERSION, + 'APERTURE': INVLIST.APERTURE, + 'USESTUBS': INVLIST.useStubs +}; +class CustomDslBuilder extends Component { + constructor(props) { + console.log('props>>>>',props); + super(props); + this.saveLoadComponent = React.createRef(); + APERTURE_SERVICE=JSON.parse(sessionStorage.getItem(ENVIRONMENT + 'APERTURE_SERVICE')); + this.state = {edgeRules : null, + connectableNodes:[], + showNodeModal: false, + enableModalFeedback: false, + showEditNodeModal: false, + treemap: null, + root: null, + svg: null, + duration: null, + g: null, + selectedNode: null, + traverseToNodes:[], + traverseToNodeAttributes: [], + nodeDetails: [], + dslQuery: '', + editModel:'', + showEditModal: false, + zoomFit: null, + autoZoomEnabled: true, + aggregateObjects: false, + init: true, + filterTypeDisplay: 'Filter Type', + selectedfilterType:[], + oxmMapping: null, + initialRootEdit: true, + showPathFilterDslBuilder: false, + pathFilterNodeType: '', + pathFilterNodeName:'', + pathFIlterAttrDetails: [], + dslPathBuilder:'', + dslPathTree:'', + loadedQueries: [], + queryDescription: '', + queryName: '', + category:'', + queryId:'', + treeLoadErrMsg: '', + isEditEnable:false, + pathFilterIndex:0, + isDataSteward: sessionStorage.getItem(ENVIRONMENT + 'roles') && sessionStorage.getItem(ENVIRONMENT + 'roles').indexOf('data_steward_ui_view') > -1, + isPublicChecked: sessionStorage.getItem(ENVIRONMENT + 'roles') && sessionStorage.getItem(ENVIRONMENT + 'roles').indexOf('data_steward_ui_view') > -1, + enableRealTime: JSON.parse(sessionStorage.getItem(ENVIRONMENT + 'ENABLE_ANALYSIS')) + } + this.baseState=this.state; + } + componentDidMount () { + console.log('componentDidMount',JSON.stringify(this.props)); + //this.buildSQLStatementsFromSchema(); + this.processEdgeRules(EDGERULES); + if(this.props.match.params.type && this.props.match.params.propId) { + this.build(this.props.match.params.type, this.props.match.params.propId); + } + } + initialize = () =>{ + this.setState({enableModalFeedback: true}, function () { + //console.log("EnableModalFeedback: " + this.state.enableModalFeedback); + setTimeout(() => {this.postSpinner()},1); + }); + } + + postSpinner = () => { + + var nodeDetails = []; + var node = null; + console.log('initializing'); + var id = GeneralCommonFunctions.generateID(); + var nodeTypes = GeneralCommonFunctions.getNodeTypes(); + for (var i = 0; i < nodeTypes.length; i++) { + node = nodeTypes[i] + id; + var attributes = GeneralCommonFunctions.getFilteringOptions(nodeTypes[i]); + if(!nodeDetails[node] && Object.keys(attributes).length > 0){ + nodeDetails[node] = {}; + nodeDetails[node].nodeType = nodeTypes[i]; + nodeDetails[node].isSelected = false; + nodeDetails[node].attrDetails = attributes; + nodeDetails[node].parentContainer = GeneralCommonFunctions.populateContainer(nodeTypes[i]); + } + } + let nodesSorted = nodeDetails.sort(function (filter1, filter2) { + if (filter1.nodeType < filter2.nodeType) { + return -1; + } else if (filter1.nodeType > filter2.nodeType) { + return 1; + } else { + return 0; + } + }); + //console.log('Node Types List' + JSON.stringify(nodesSorted)); + nodeDetails = nodesSorted; + this.setState({nodeDetails: nodeDetails, showNodeModal: true, enableModalFeedback: false}); + } + processEdgeRules = (data) => { + this.setState({ + edgeRules: data.rules + },()=>{this.baseState=this.state}); + } + closeNodeModal = () =>{ + this.setState({ + showNodeModal: false, + enableModalFeedback: false, + traverseToNodes: [], + selectedNode: null + }); + } + closeEditNodeModal = () =>{ + this.setState({ + showEditNodeModal: false, + selectedNode: null, + showPathFilterDslBuilder: false + }); + } + closePathNodeModal = () =>{ + console.log('closePathNodeModal>>>>>>>'); + this.setState({ + showPathFilterDslBuilder: false, + pathFilterNodeType: '', + pathFilterNodeName:'', + pathFIlterAttrDetails: [] + }); + } + submitPathNodeModal = (dslQuery,nodetype,dslQueryTree,isEditEnable,pathFilterIndex) =>{ + console.log('CustomDSLBuilder submitPathNodeModel>>>>>dslQuery ###',dslQuery); + console.log(isEditEnable+'<>>>',this.state.nodeDetails) + var nodeDetails = this.state.nodeDetails; + if(!nodeDetails[nodetype].dslPath){ + nodeDetails[nodetype].dslPath=[]; + nodeDetails[nodetype].dslPathTree=[]; + } + if(isEditEnable){ + nodeDetails[nodetype].dslPath[pathFilterIndex]=dslQuery; + nodeDetails[nodetype].dslPathTree[pathFilterIndex]=dslQueryTree; + console.log('nodeDetails on edit>>>>>>>>>',nodeDetails); + }else{ + nodeDetails[nodetype].dslPath.push(dslQuery); + nodeDetails[nodetype].dslPathTree.push(dslQueryTree); + } + this.setState({ nodeDetails: nodeDetails },()=>{this.closePathNodeModal()}); + } + editPathNodeModal = (key,path,tree,indx) =>{ + console.log('editPathNodeModal>>>>>>>>>###',indx); + let attrDetails=this.state.nodeDetails[key].attrDetails; + let nodeType=this.state.nodeDetails[key].nodeType; + this.setState({showPathFilterDslBuilder: true,pathFilterNodeType: key,pathFilterNodeName:nodeType,pathFIlterAttrDetails: '',dslPathBuilder: path,dslPathTree:tree,isEditEnable:true,pathFilterIndex:indx}); + } + deletePathNodeModal = (key,path,tree,index) =>{ + console.log(index+'<>>>>',key); + var nodeDetails = this.state.nodeDetails; + nodeDetails[key].dslPath.splice(index,1); + nodeDetails[key].dslPathTree.splice(index,1); + this.setState({ nodeDetails: nodeDetails }); + } + onNodeCheckbox(e) { + var nodeDetails = this.state.nodeDetails; + if (e.target.checked) { + nodeDetails[e.target.value].isSelected = true; + this.selectAll(e.target.value); + }else { + nodeDetails[e.target.value].isSelected = false; + this.deselectAll(e.target.value); + } + // update the state with the new array of traverse to nodes + this.setState({ nodeDetails: nodeDetails }); + } + onNodeRadio(e) { + var nodeDetails = this.state.nodeDetails; + if (e.target.checked) { + nodeDetails[e.target.value].isSelected = true; + this.selectAll(e.target.value); + } + for (var key in nodeDetails) { + if(key != e.target.value && nodeDetails[key].isSelected ){ + nodeDetails[key].isSelected = false; + this.deselectAll(key); + } + } + // update the state with the new array of traverse to nodes + this.setState({ nodeDetails: nodeDetails }); + } + onAutoZoomCheckbox(e) { + var cbValue = false; + if (e.target.checked) { + cbValue = true; + }else { + cbValue = false; + } + this.setState({ autoZoomEnabled: cbValue }); + } + onAggregateCheckbox(e) { + var cbValue = false; + if (e.target.checked) { + cbValue = true; + }else { + cbValue = false; + } + this.setState({ aggregateObjects: cbValue }); + } + onAttributeCheckbox(e){ + let splitVal = e.target.value.split("|"); + let nodeKey = splitVal[0]; + let attrValue = splitVal[1]; + let nodeDetails = this.state.nodeDetails; + let node = nodeDetails[nodeKey]; + let attribute = null; + if(!node.attrDetails){ + node.attrDetails = []; + } + if(!node.attrDetails[attrValue]){ + node.attrDetails[attrValue] = {}; + node.attrDetails[attrValue].isSelected = true; + node.attrDetails[attrValue].filterValue = []; + node.attrDetails[attrValue].filterType = []; + node.attrDetails[attrValue].dslPath = []; + node.attrDetails[attrValue].dslPathTree = []; + } + + // check if the check box is checked or unchecked + if (e.target.checked) { + // add the value of the checkbox to nodes array + node.attrDetails[attrValue].isSelected = true; + node.attrDetails[attrValue].filterType[0]='EQ'; + } else { + // or remove the value from the unchecked checkbox from the array + node.attrDetails[attrValue].isSelected = false; + //node.attrDetails[attrValue].filterType = ['']; + //node.attrDetails[attrValue].filterValue = ['']; + } + nodeDetails[nodeKey] = node; + // update the state with the new array of traverse to nodes + this.setState({ nodeDetails: nodeDetails }); + } + onFilterValueChange(e, nodeKey, attrKey, indx){ + let nodeDetails = this.state.nodeDetails; + let node = nodeDetails[nodeKey]; + if(!node.attrDetails){ + node.attrDetails = []; + } + if(!node.attrDetails[attrKey]){ + node.attrDetails[attrKey] = {}; + node.attrDetails[attrKey].isSelected = true; + node.attrDetails[attrKey].filterValue = []; + node.attrDetails[attrKey].filterType = []; + node.attrDetails[attrValue].dslPath = []; + node.attrDetails[attrValue].dslPathTree = []; + } + // add the value of the checkbox to nodes array + //node.attrDetails[attrKey].filterValue.push(e.target.value); + let filterValArr=node.attrDetails[attrKey].filterValue; + filterValArr[indx]=e.target.value; + node.attrDetails[attrKey].filterValue=filterValArr; + nodeDetails[nodeKey] = node; + // update the state with the new array of traverse to nodes + this.setState({ nodeDetails: nodeDetails }); + } + submitNodeModal = () =>{ + if(this.state.selectedNode){ + var d = this.state.selectedNode; + for(var node in this.state.nodeDetails){ + if(this.state.nodeDetails[node].isSelected){ + var newNodeObj = { + type: 'node', + name: this.state.nodeDetails[node].nodeType, + details: {} + }; + //Creates new Node + Object.assign(newNodeObj.details, this.state.nodeDetails[node]); + var newNode = d3.hierarchy(newNodeObj); + newNode.depth = d.depth + 1; + newNode.height = d.height - 1; + newNode.parent = d; + newNode.id = node; + if(!d.children){ + d.children = []; + } + if(newNodeObj.details){ + var selectedAttributeCount = 0; + for (var key in newNodeObj.details.attrDetails){ + if (newNodeObj.details.attrDetails[key].isSelected){ + selectedAttributeCount++; + } + if(selectedAttributeCount === Object.keys(newNodeObj.details.attrDetails).length){ + newNodeObj.details.includeInOutput = true; + } + } + } + d.children.push(newNode); + this.setState({ nodeDetails: [] }); + } + } + this.update(this, d); + this.setState({ + showNodeModal: false, + enableModalFeedback: false, + traverseToNodes: [], + selectedNode: null + }); + }else{ + var nodeType = ""; + var attrDetails = null; + var dslPath =[]; + var dslPathTree=[]; + for (var key in this.state.nodeDetails) { + if(this.state.nodeDetails[key].isSelected){ + nodeType = this.state.nodeDetails[key].nodeType; + attrDetails = this.state.nodeDetails[key].attrDetails; + dslPath =this.state.nodeDetails[key].dslPath; + dslPathTree=this.state.nodeDetails[key].dslPathTree; + } + } + this.build(nodeType, null, attrDetails,null,dslPath,dslPathTree); + this.setState({ nodeDetails: [], showNodeModal: false, enableModalFeedback:false, traverseToNodes: [], selectedNode: null }); + } + } + submitEditNodeModal = () =>{ + this.update(this, this.state.selectedNode); + this.setState({showEditNodeModal: false,showPathFilterDslBuilder:false}); + } + populateEdgeRules = (nodeType) => { + let nodeDetails=GeneralCommonFunctions.populateEdgeRules(nodeType,this.state.edgeRules); + this.setState({ + nodeDetails: nodeDetails + }); + } + + buildOXMAttributesAndReturn = (nodeType) =>{ + var oxmArray = []; + var result = JSON.parse(OXM); + var arrayOfTypes = result['xml-bindings']['java-types'][0]['java-type']; + for (var i = 0; i < arrayOfTypes.length; i++) { + var propertiesDsl = []; + for (var j = 0; j < arrayOfTypes[i]['java-attributes'][0]['xml-element'].length; j++) { + let property = arrayOfTypes[i]['java-attributes'][0]['xml-element'][j]['$']['name']; + let type = arrayOfTypes[i]['java-attributes'][0]['xml-element'][j]['$']['type']; + if (type === 'java.lang.String' || type === 'java.lang.Boolean') { + propertiesDsl[property] = {}; + propertiesDsl[property].isSelected = false; + propertiesDsl[property].attributeName = property; + propertiesDsl[property].filterValue = ['']; + propertiesDsl[property].filterType = ['']; + propertiesDsl[property].dslPath = []; + propertiesDsl[property].dslPathTree = []; + } + } + let sortedPropertiesDsl = propertiesDsl.sort(function (filter1, filter2) { + if (filter1.attributeName < filter2.attributeName) { + return -1; + } else if (filter1.attributeName > filter2.attributeName) { + return 1; + } else { + return 0; + } + }); + oxmArray[GeneralCommonFunctions.camelToDash(arrayOfTypes[i]['xml-root-element'][0]['$']['name'])] = sortedPropertiesDsl; + } + this.setState({oxmMapping: oxmArray}); + return oxmArray[nodeType]; + } + + runDSL = () => { + console.log("running DSL"); + let paramToPassThrough = ''; + if(this.state.aggregateObjects){ + paramToPassThrough = '/customDsl/built-aggregate/' + btoa('
' + this.state.dslQuery + '
'); + }else{ + paramToPassThrough = '/customDsl/built/' + btoa('
' + this.state.dslQuery + '
'); + } + this.props.history.push(paramToPassThrough); + } + submitEditAndRunDSL = () =>{ + this.setState({ dslQuery: this.state.editModel }, () => this.runDSL()); + } + showEditDSLModal = () => { + console.log("enabling DSL edit modal"); + this.setState({ editModel: this.state.dslQuery, showEditModal: true }); + } + closeEditDSLModal = () => { + console.log("closing DSL edit modal"); + this.setState({ showEditModal: false }); + } + bindEdits = (e) => { + this.setState({ editModel: e.target.value }); + } + populateDSL = (tree, isInit) =>{ + var DSL = ''; + var treeArray = ''; + var treeArrayLength = 0; + if(isInit){ + treeArray = tree; + treeArrayLength = 1; + }else{ + treeArray = tree.children; + treeArrayLength = tree.children.length; + } + for(var k = 0; treeArray && k < treeArrayLength; k++){ + if(k === 0 && treeArrayLength > 1){ + DSL += '['; + } + var node = ''; + if(isInit){ + node = tree; + }else{ + node = treeArray[k]; + } + if(node.data){ + console.log('Node data while rendering DSl path>>',JSON.stringify(node.data)); + DSL += node.data.name; + let propState=false; + if(node.data.details){ + var tempAttributeString = ''; + var selectedAttributeCount = 0; + for (var key in node.data.details.attrDetails){ + if (node.data.details.attrDetails[key].isSelected){ + selectedAttributeCount++; + let aliasWithProp=node.data.details.attrDetails[key].attributeName; + if(node.data.details.attrDetails[key].alias){ + aliasWithProp= aliasWithProp+'\' as \''+node.data.details.attrDetails[key].alias; + } + if(selectedAttributeCount === 1){ + tempAttributeString += '{\'' + aliasWithProp +'\''; + propState=true; + }else{ + tempAttributeString += ',\'' + aliasWithProp + '\''; + } + } + } + if(selectedAttributeCount === Object.keys(node.data.details.attrDetails).length){ + DSL+= '*'; + } + if((selectedAttributeCount < Object.keys(node.data.details.attrDetails).length) && propState){ + DSL += tempAttributeString + '}'; + } + for (var key in node.data.details.attrDetails){ + if(node.data.details.attrDetails[key].filterValue && node.data.details.attrDetails[key].filterValue[0] !==''){ + DSL += '(\'' + node.data.details.attrDetails[key].attributeName + '\','; + let dslValues=''; + for(var indx=0; indx0) ? dslValues+',':dslValues; + if(this.state.enableRealTime && node.data.details.attrDetails[key].filterType && node.data.details.attrDetails[key].filterType[indx]){ + dslValues += node.data.details.attrDetails[key].filterType[indx]+'(\''+ node.data.details.attrDetails[key].filterValue[indx] + '\')'; + }else{ + dslValues +='\''+node.data.details.attrDetails[key].filterValue[indx] + '\''; + } + if(node.data.details.attrDetails[key].filterValue.length-1 === indx){ + dslValues +=')'; + } + } + DSL += dslValues; + } + } + if(node.data.details.dslPath && node.data.details.dslPath.length>0){ + for(var n in node.data.details.dslPath){ + DSL += node.data.details.dslPath[n]; + } + } + } + } + if(node.children){ + DSL+= '>' + this.populateDSL(node); + } + if(k !== treeArrayLength - 1){ + DSL += ','; + } + if(k === treeArrayLength - 1 && treeArrayLength > 1){ + DSL += ']'; + } + } + return DSL; + } + update = (base, source, isInit) => { + + // Assigns the x and y position for the nodes + var treeData = base.state.treemap(base.state.root); + + var DSL = base.populateDSL(treeData, true); + console.log(JSON.stringify("DSL :" + DSL)); + + this.setState({ dslQuery: DSL }); + + // Compute the new tree layout. + var nodes = treeData.descendants(), + links = treeData.descendants().slice(1); + + var list1 = d3.selectAll(".fa") + .filter(".fa-plus") + .style("display", "block"); + + // Normalize for fixed-depth. + nodes.forEach(function(d){ d.y = d.depth * 100}); + // ****************** Nodes section *************************** + + // Update the nodes... + var node = base.state.g.selectAll('g.node') + .data(nodes, function(d) {return d.id }); + + // Enter any new modes at the parent's previous position. + var nodeEnter = node.enter().append('g') + .attr('class', 'node') + .attr("transform", function(d) { + return "translate(" + source.y0 + "," + source.x0 + ")"; + }) + // .on('click', click) + .on('dblclick', doubleClick); + + // Add Circle for the nodes + nodeEnter.append('circle') + .attr('class', 'node') + .attr('r', 1e-6) + .style("fill", "lightsteelblue"); + nodeEnter.append("svg:foreignObject") + .attr("width", 20) + .attr("height", 25) + .attr("y", -14) + .attr("x", -10) + .append("xhtml:span") + .attr("class", function (d) { + let icon = ''; + if(!INVLIST.IS_ONAP){ + icon = 'icon-datanetwork-serverL'; + }else{ + icon = 'browse-fa fa fa-server'; + } + if(d.data.details && d.data.details.parentContainer){ + var iconKey = ((d.data.details.parentContainer).replace(/-/g, '')).toUpperCase(); + if(INVLIST.INVENTORYLIST[iconKey] && INVLIST.INVENTORYLIST[iconKey].icon){ + return INVLIST.INVENTORYLIST[iconKey].icon; + }else{ + return icon; + } + }else{ + return icon; + } + }) + .style("font-size", function (d) { + if (!INVLIST.IS_ONAP){ + return "20px"; + } else { + return "16px"; + } + }) + .attr("id", function (d) {return "nodeIcon" + d.id}) + .style("color", '#387dff') + .style("display", "block") + .style("padding-top",function(d){ + if (!INVLIST.IS_ONAP){ + return "0px"; + } else { + return "8px"; + } + }); + + nodeEnter.append("svg:foreignObject") + .attr("width", 6) + .attr("height", 6) + .attr("y", 10) + .attr("x", -10) + .on('click', function (d) { + if(d.data.details.isRootNode){ + d = null; + base.resetBuilder(); + }else{ + for(var i = 0; d.parent.children && i < d.parent.children.length; i++){ + if (d.parent.children.length > 1 && d.data.name === d.parent.children[i].data.name){ + d.parent.children.splice(i, 1); + }else if (d.parent.children.length === 1 && d.data.name === d.parent.children[i].data.name){ + d.parent.children = null; + } + } + base.update(base, d); + } + }) + .append("xhtml:span") + .attr("class", "fa fa-minus") + .style("padding-top", "1px") + .style("font-size", function (d){ return "5px";}) + .attr("id", function (d) {return "nodeDelete" + d.data.id}) + .style("color", '#387dff') + .style("display", function (d) {return "block";}); + nodeEnter.append("svg:foreignObject") + .attr("width", 6) + .attr("height", 6) + .attr("y", 10) + .attr("x", 5) + .on('click', function (d) { base.setState({enableModalFeedback: true}, function () {setTimeout(() => {add(d)},1);})}) + .append("xhtml:span") + .attr("class", "fa fa-plus") + .style("padding-top", "1px") + .style("font-size", function (d){ return "5px";}) + .attr("id", function (d) {return "nodeAdd" + d.data.id}) + .style("color", '#387dff'); + nodeEnter.append("svg:foreignObject") + .attr("width", 6) + .attr("height", 6) + .attr("y", -17) + .attr("x", -10) + .on('click', function (d) { edit(d)}) + .append("xhtml:span") + .attr("class", "fa fa-pencil-square") + .style("padding-top", "1px") + .style("font-size", function (d){ return "5px";}) + .attr("id", function (d) {return "nodeEdit" + d.data.id}) + .style("color", '#387dff'); + // Add labels for the nodes + nodeEnter.append("svg:foreignObject") + .attr("width", 60) + .attr("height", 40) + .attr("y", -10) + .attr("x", -75) + .append("xhtml:span") + .append('text') + .attr("dy", ".35em") + .attr("x", function(d) { + return d.children ? -13 : 13; + }) + .text(function(d) { return d.data.name; }) + .style("float","right") + .style("color", '#000000'); + + // UPDATE + var nodeUpdate = nodeEnter.merge(node); + var postNodeDrawnCallBack = function (d){ + if(!isInit && base.state.autoZoomEnabled || d.data.details.isRootNode){ + base.state.zoomFit(); + } + } + // Transition to the proper position for the node + nodeUpdate.transition() + .duration(base.state.duration) + .attr("transform", function(d) { + return "translate(" + d.y + "," + d.x + ")" + }).on("end", postNodeDrawnCallBack); + + // Update the node attributes and style + nodeUpdate.select('circle.node') + .attr('r', 11) + .style("fill", "lightsteelblue") + .attr('cursor', 'pointer'); + + + // Remove any exiting nodes + var nodeExit = node.exit().transition() + .duration(base.state.duration) + .attr("transform", function(d) { + return "translate(" + source.y + "," + source.x + ")"; + }) + .remove(); + + // On exit reduce the node circles size to 0 + nodeExit.select('circle') + .attr('r', 1e-6); + + // On exit reduce the opacity of text labels + nodeExit.select('text') + .style('fill-opacity', 1e-6); + + // ****************** links section *************************** + + // Update the links... + var link = base.state.g.selectAll('path.link') + .data(links, function(d) { return d.id; }); + + // Enter any new links at the parent's previous position. + var linkEnter = link.enter().insert('path', "g") + .attr("class", "link") + .attr('d', function(d){ + var o = {x: source.x0, y: source.y0} + return diagonal(o, o) + }); + + // UPDATE + var linkUpdate = linkEnter.merge(link); + + // Transition back to the parent element position + linkUpdate.transition() + .duration(base.state.duration) + .attr('d', function(d){ return diagonal(d, d.parent) }); + + // Remove any exiting links + var linkExit = link.exit().transition() + .duration(base.state.duration) + .attr('d', function(d) { + var o = {x: source.x, y: source.y} + return diagonal(o, o) + }) + .remove(); + + // Store the old positions for transition. + nodes.forEach(function(d){ + d.x0 = d.x; + d.y0 = d.y; + }); + + // Creates a curved (diagonal) path from parent to the child nodes + function diagonal(s, d) { + var path = 'M ' + s.y + ' ' + s.x + ' C ' + ((s.y + d.y) / 2) + ' ' + s.x + ' ' + (s.y + d.y) / 2 + ' ' + d.x + ' ' + d.y + ' ' + d.x; + return path + } + base.state.svg.on("dblclick.zoom", null); + // Toggle children on click. + function add(d){ + base.populateEdgeRules(d.data.name,base.state.edgeRules); + if(!d.children){ + d.children = []; + d.data.children = []; + } + base.setState({ + selectedNode: d, + showNodeModal: true, + enableModalFeedback: false + }); + + } + function edit(d){ + console.log("object editing: " + d); + var nodeDetails = base.state.nodeDetails; + //set up node details to have the node to edit + if(d.data.details.isRootNode && base.props.match.params.type){ + var attributes = GeneralCommonFunctions.getFilteringOptions(d.data.details.nodeType); + if(Object.keys(attributes).length > 0){ + nodeDetails[0] = {}; + nodeDetails[0].isRootNode = true; + nodeDetails[0].nodeType = base.props.match.params.type; + nodeDetails[0].isSelected = true; + nodeDetails[0].attrDetails = attributes; + if(base.state.initialRootEdit){ + for (var key in nodeDetails[0].attrDetails) { + nodeDetails[0].attrDetails[key].isSelected = true; + } + } + nodeDetails[0].parentContainer = GeneralCommonFunctions.populateContainer(base.props.match.params.type); + for (var key in d.data.details.attrDetails) { + nodeDetails[0].attrDetails[key] = d.data.details.attrDetails[key]; + if(base.state.initialRootEdit){ + nodeDetails[0].attrDetails[key].filterType = []; + nodeDetails[0].attrDetails[key].filterType.push('EQ'); + } + } + } + d.data.details = nodeDetails[0]; + base.setState({ + initialRootEdit: false + }); + }else{ + nodeDetails[0] = d.data.details; + } + base.setState({ + selectedNode: d, + showEditNodeModal: true, + showPathFilterDslBuilder: false + }); + } + function doubleClick(d) { + edit(d); + } + } + selectAll = (nodeKey) =>{ + var nodeDetails = this.state.nodeDetails; + for (var key in nodeDetails[nodeKey].attrDetails) { + nodeDetails[nodeKey].attrDetails[key].isSelected = true; + } + this.setState({nodeDetails: nodeDetails}); + } + deselectAll = (nodeKey) =>{ + var nodeDetails = this.state.nodeDetails; + for (var key in nodeDetails[nodeKey].attrDetails) { + nodeDetails[nodeKey].attrDetails[key].isSelected = false; + } + this.setState({nodeDetails: nodeDetails}); + } + build = (type, propID, attrDetails, preBuiltTree,dslPath,dslPathTree) =>{ + var selected = null; + var treeData; + if(!preBuiltTree && type && (propID || attrDetails)){ + let nodeType = type; + treeData = { + "name": nodeType, + "id": nodeType, + "children": [], + "details":{}, + "dslPath":[], + "dslPathTree":[] + } + treeData.details.includeInOutput = true; + treeData.details.isSelected = true; + treeData.details.isRootNode = true; + treeData.details.nodeType = nodeType; + if(attrDetails){ + treeData.details.attrDetails = attrDetails; + } else{ + treeData.details.attrDetails = {}; + } + if(dslPath && dslPath.length>0 && dslPathTree && dslPathTree.length>0){ + treeData.details.dslPath=dslPath; + treeData.details.dslPathTree=dslPathTree; + } + if(propID){ + let propIds = (propID) ? propID.split(';') : ''; + let propertyValue = ''; + for(var i in propIds){ + let propValue = propIds[i].split(':'); + console.log(propValue[0] + '....' + propValue[1]); + treeData.details.attrDetails[propValue[0]] = {}; + treeData.details.attrDetails[propValue[0]].filterValue=[]; + treeData.details.attrDetails[propValue[0]].filterValue.push(atob(propValue[1]).replace('
','').replace('
','')); + treeData.details.attrDetails[propValue[0]].attributeName = propValue[0]; + treeData.details.attrDetails[propValue[0]].isSelected = true; + } + } + }else if (preBuiltTree){ + treeData = preBuiltTree; + if(treeData.details && treeData.details.dslPathTree && treeData.details.dslPathTree.length>0){ + for(var x=0;x0){ + for(var x=0;x{this.update(this, root, true);}) + + // Collapse the node and all it's children + function collapse(d) { + if(d.children) { + d.children.forEach(collapse) + d.children = null + } + } + } + + updateDslPathValueOnExtract=(treeDataChildren)=>{ + if(treeDataChildren.details && treeDataChildren.details.dslPathTree && treeDataChildren.details.dslPathTree.length>0){ + for(var x=0;x0){ + for(var x=0;x{ + console.log(listname+'onTargetMenuOfFilterTypes',id); + let keysOfArray=id.split('#'); + let nodekey=keysOfArray[0]; + let attrKey=keysOfArray[1]; + let indx=parseInt(keysOfArray[2]); + let nodeDetails = this.state.nodeDetails; + let node = nodeDetails[nodekey]; + if(!node.attrDetails){ + node.attrDetails = []; + } + if(!node.attrDetails[attrKey]){ + node.attrDetails[attrKey] = {}; + node.attrDetails[attrKey].isSelected = true; + node.attrDetails[attrKey].filterValue = []; + node.attrDetails[attrKey].filterType = []; + }else{ + let filterTypes=node.attrDetails[attrKey].filterType; + filterTypes[indx]=listname; + node.attrDetails[attrKey].filterType=filterTypes; + } + nodeDetails[nodekey] = node; + // update the state with the new array of traverse to nodes + this.setState({ nodeDetails: nodeDetails }); + }; + filterTags = (key,property,state) =>{ + let filterTags =''; + let filters=''; + state=true;//always enable, in future if wants to disable remove this line + if(APERTURE_SERVICE && this.state.enableRealTime){ + let nodeDetails = this.state.nodeDetails; + let node = nodeDetails[key]; + filterTags= Object.keys(Object.keys(node.attrDetails[property].filterType)).map((indx) =>{ + let selectedFilter=(node.attrDetails[property].filterType[indx]!=='')?node.attrDetails[property].filterType[indx]:this.state.filterTypeDisplay; + return
+ +
+ }); + filters= {filterTags}; + } + return filters; + }; + addOrTemplate=(nodeKey,attrKey,indx)=>{ + let nodeDetails = this.state.nodeDetails; + let node = nodeDetails[nodeKey]; + node.attrDetails[attrKey].filterValue.push(''); + node.attrDetails[attrKey].filterType.push('EQ'); + nodeDetails[nodeKey] = node; + // update the state with the new array of traverse to nodes + this.setState({ nodeDetails: nodeDetails }); + }; + deleteOrTemplate=(nodeKey,attrKey,index)=>{ + let nodeDetails = this.state.nodeDetails; + let node = nodeDetails[nodeKey]; + let filterValuesArray=node.attrDetails[attrKey].filterValue; + let filterTypeArray=node.attrDetails[attrKey].filterType; + filterValuesArray.splice(index,1); + filterTypeArray.splice(index,1); + node.attrDetails[attrKey].filterValue=filterValuesArray; + node.attrDetails[attrKey].filterType=filterTypeArray; + nodeDetails[nodeKey] = node; + this.setState({ nodeDetails: nodeDetails }); + } + toggleRealTimeAnalysisCallback=(checked)=>{ + console.log('toggleRealTimeAnalysisCallback>>>>',checked); + sessionStorage.setItem(ENVIRONMENT + 'ENABLE_ANALYSIS', !checked); + this.baseState.enableRealTime=!checked; + this.baseState.init= true; + this.setState({...this.baseState},()=>{document.getElementById("DSLBuilder").innerHTML='';}); + } + renderPathFilterBuilder=(key,dslPath,dslPathTree)=>{ + console.log('renderPathFilterBuilder>>>>',key); + let attrDetails=this.state.nodeDetails[key].attrDetails; + let nodeType=this.state.nodeDetails[key].nodeType; + this.setState({showPathFilterDslBuilder: true,pathFilterNodeType: key,pathFilterNodeName:nodeType,pathFIlterAttrDetails: attrDetails,dslPathBuilder: dslPath,dslPathTree:dslPathTree,isEditEnable:false}); + } + /* Load Functions */ + getAndPopulateTreeFromDSL = (dslQuery) =>{ + var treeObject = []; + var payload = {dsl: dslQuery}; + settings['ISAPERTURE'] = true; + commonApi(settings, 'dsl/convert-query-to-tree', 'PUT', payload, 'ConvertQueryToTree') + .then(res => { + console.log('res:' + res.data, 'load'); + if(res.status === 200 || res.status === 404){ + if(res.data.status && (res.data.status !== 200 && res.data.status !== 201 && res.data.status !== 404)){ + this.triggerError(res.data, 'treeLoad'); + }else{ + treeObject = res.data; + this.setState({ + enableTreeLoadBusyFeedback:false, + treeLoadErrMsg: null + }); + console.log("TREE OBJECT: " + JSON.stringify(treeObject)); + //clear the svg + if(this.state.svg){ + this.state.svg.selectAll("*").remove(); + } + //set the init state + this.setState({init: true, dslQuery: '', initialRootEdit: false, nodeDetails: [], selectedNode: null }); + var initNode = this.extractNodeDetails(treeObject.children[0], true); + if(!this.state.treeLoadErrMsg || this.state.treeLoadErrMsg === ''){ + console.log(JSON.stringify(initNode)); + this.build(null, null, null, initNode); + setTimeout(() => { this.state.zoomFit() }, 600); + //scroll to the hidden static modal since svg offsetTop doesnt work for DSLBuilder id + GeneralCommonFunctions.scrollTo('customDslBuilderModel'); + }else{ + this.triggerError(null, 'invalidQuery'); + } + } + }else{ + this.triggerError(res.data, 'treeLoad'); + } + }, error=>{ + if(error.response.status === 404){ + this.setState({enableTreeLoadBusyFeedback:false}); + }else{ + this.triggerError(error.response.data, 'treeLoad'); + } + }).catch(error => { + this.triggerError(error, 'treeLoad'); + }) + + }; + resetBuilder = () => { + if(this.state.svg){ + this.state.svg.selectAll("*").remove(); + } + this.setState({ + init: true, + dslQuery: '', + queryName:'', + queryDescription:'', + initialRootEdit: false, + nodeDetails: [], + selectedNode: null, + treeLoadErrMsg: '', + enableTreeLoadBusyFeedback: false, + aggregateObjects: false + }); + } + triggerError = (error, type) => { + console.error('[CustomDslBuilder.jsx] error : ', JSON.stringify(error)); + let errMsg = ''; + if(error && error.status && error.message){ + errMsg += "Error Occurred: " + error.status + ' - ' +error.message; + }else{ + errMsg += "Error Occurred: " + JSON.stringify(error); + } + console.log(errMsg); + if(type === 'treeLoad' || type === 'invalidQuery'){ + this.resetBuilder(); + var errorMessage = errMsg; + if(type === 'invalidQuery'){ + errorMessage = 'The loaded query uses DSL syntax not supported by the DSL Builder,' + + ' please only load queries compatible with the builder. For more' + + ' information on this error, please contact an administrator.'; + } + this.setState({treeLoadErrMsg: errorMessage}); + GeneralCommonFunctions.scrollTo('treeLoadErrorMessage'); + }else{ + console.log('[CustomDslBuilder.jsx] :: triggerError invoked with invalid type : ' + type); + } + } + validLoadableDSL = (dslQuery) => { + var valid = false; + dslQuery = dslQuery.replace(/\s/g, ''); + valid = dslQuery.indexOf(']>') === -1 && !(new RegExp("LIMIT[0-9]+$").test(dslQuery)); + return valid; + } + loadCallback = (name, description, category, dslQuery, isAggregate, type, queryId, id, templateDetails, makeCall) =>{ + var decodedDslQuery = atob(dslQuery).replace('
','').replace('
',''); + if(this.validLoadableDSL(decodedDslQuery)){ + if(name !== '' && description !== ''){ + this.setState({ + queryName:name, + queryDescription:description, + category:category, + isPublicChecked: type === 'public', + queryId: queryId, + treeLoadErrMsg: null, + aggregateObjects: isAggregate === "true" + }); + console.log("DSL Query Loaded: "+ decodedDslQuery); + console.log("DSL Query Name: "+ name); + console.log("DSL Query Description: "+ description); + console.log("DSL Query ID: "+ queryId); + console.log("DSL Query Category: "+ category); + console.log("DSL Query isAggregate: "+ isAggregate); + console.log("DSL Query type: "+ type); + var treeObject = this.getAndPopulateTreeFromDSL(decodedDslQuery); + } + }else{ + this.triggerError(null, "invalidQuery"); + } + } + extractNodeDetails = (node, isRoot) =>{ + let nodeType = node['node-type']; + let nodeData = { + "name": nodeType, + "id": nodeType, + "children": [], + "details":{} + } + nodeData.details.includeInOutput = node.store; + nodeData.details.isSelected = true; + nodeData.details.isRootNode = isRoot; + nodeData.details.nodeType = nodeType; + var attributes = GeneralCommonFunctions.getFilteringOptions(nodeType); + nodeData.details.attrDetails = attributes; + nodeData.details.parentContainer = GeneralCommonFunctions.populateContainer(nodeType); + if(node.store && !node['requested-props']){ + for(var key in nodeData.details.attrDetails){ + nodeData.details.attrDetails[key].isSelected = true; + } + }else if (node.store && node['requested-props']){ + for(var key in node['requested-props']){ + nodeData.details.attrDetails[key].isSelected = true; + nodeData.details.attrDetails[key].alias=node['requested-props'][key]; + } + } + var isValid = true; + for (var x in node['node-filter']){ + if(isValid){ + for (var y in node['node-filter'][x]) { + if(isValid){ + var attrKey = node['node-filter'][x][y]['key']; + var filter = node['node-filter'][x][y]['filter']; + //If aperture is not turned on and query loaded uses anything besides EQ throw error + if(!APERTURE_SERVICE && filter !== 'EQ'){ + this.triggerError(null, "invalidQuery"); + isValid = false; + } + if(!nodeData.details.attrDetails[attrKey]){ + nodeData.details.attrDetails[attrKey] = {}; + } + if(nodeData.details.attrDetails[attrKey].filterType.length > 0 && nodeData.details.attrDetails[attrKey].filterType[0] === ''){ + nodeData.details.attrDetails[attrKey].filterType = []; + } + if(nodeData.details.attrDetails[attrKey].filterValue.length > 0 && nodeData.details.attrDetails[attrKey].filterValue[0] === ''){ + nodeData.details.attrDetails[attrKey].filterValue = []; + } + //if a filter had no values associated to it throw a not supported error + if(node['node-filter'][x][y]['value'][0]){ + for (var i in node['node-filter'][x][y]['value']){ + nodeData.details.attrDetails[attrKey].filterType.push(filter); + nodeData.details.attrDetails[attrKey].filterValue.push(node['node-filter'][x][y]['value'][i]); + } + if(!nodeData.details.attrDetails[attrKey].attributeName){ + nodeData.details.attrDetails[attrKey].attributeName = attrKey; + } + }else{ + this.triggerError(null, "invalidQuery"); + isValid = false; + } + } + } + } + } + var initWhereNode = null; + if(node['where-filter'].length > 0){ + for(var index in node['where-filter']){ + initWhereNode = this.extractNodeDetails(node['where-filter'][index].children[0], true); + } + } + if(initWhereNode){ + nodeData.details.dslPath=[]; + nodeData.details.dslPathTree=[]; + nodeData.details.dslPathTree.push(initWhereNode); + } + if(node.children.length > 0){ + for(var i = 0; i < node.children.length; i++){ + nodeData.children[i] = this.extractNodeDetails(node.children[i], false); + } + } + return nodeData; + } + + setQueriesState = (savedQueries) =>{ + this.setState({ + loadedQueries: savedQueries + }); + }; + /* End Load Functions */ + render(){ + var toggelRealtimeAnalysis = ''; + if(APERTURE_SERVICE){ + toggelRealtimeAnalysis =
{ + this.toggleRealTimeAnalysisCallback(checked); + }} + />
+ } + return( +
+ {toggelRealtimeAnalysis} +
+
+
+
+

Visual Query Builder for Build Your Own Query

+

+ Visually build your own query, you can click the + icon to add objects to your query, + - icon to remove objects from your query, or the pencil icon/double click to edit attributes. + Single click and drag in the view to pan, use scrollwheel or pinch to zoom.
+

+
+
+
+ + +
+ +
+
+ + +
+ + +
+
+ +
+ + + Modify Query + + +
+ {Object.keys(this.state.nodeDetails).sort().map((key, node) => ( +
+ + + +
+ + +
Options
+
+
+
+ + +
Options
+
+
+
+
+ + +
+
+ +
+
+ {this.state.nodeDetails[key].dslPath && this.state.nodeDetails[key].dslPath.length>0 && + + + + DSL PATH Filter + + + Action + + + } + + {this.state.nodeDetails[key].dslPath && Object.keys(this.state.nodeDetails[key].dslPath).map((indx) => { + return( + + +
+ {this.state.nodeDetails[key].dslPath[indx]} +
+ + + + + +
+ ) + })} +
+
+ + +
+ + + + Include in Output + + {APERTURE_SERVICE && this.state.enableRealTime && + Filter Types + } + + Filter By (Optional) + + + {Object.keys(this.state.nodeDetails[key].attrDetails).sort().map((attrKey, attr) => { + return( + + +
+ +
+ + {this.filterTags(key,attrKey,this.state.nodeDetails[key].attrDetails[attrKey].isSelected)} + + {Object.keys(this.state.nodeDetails[key].attrDetails[attrKey].filterValue).map((indx) =>{ + return( +
+ {this.state.nodeDetails[key].attrDetails[attrKey].filterValue[indx] ==='' && {this.onFilterValueChange(e, key, attrKey,indx);}} + /> + } + {this.state.nodeDetails[key].attrDetails[attrKey].filterValue[indx] !=='' && {this.onFilterValueChange(e, key, attrKey,indx);}} + placeholder={"Enter " + attrKey } + className='inputFilter' + value={this.state.nodeDetails[key].attrDetails[attrKey].filterValue[indx]} + /> + } + {indx == 0 && } + {indx > 0 && } + +
+ ) + })} + + +
+ ); + } + )} +
+
+
+
+
+ ))} +
+
+ + + Build DSL Path + + + + + +
+
+ + + + +
+
+
+ + + Modify Node + + +
+
+ + + +
+ +
+
+
+ + + +
+ +
+
+ {this.state.selectedNode + && this.state.selectedNode.data + && this.state.selectedNode.data.details + && this.state.nodeDetails[0] + && this.state.nodeDetails[0].dslPath && this.state.nodeDetails[0].dslPath.length>0 && + + + DSL PATH Filter + + + Action + + } +
+ {this.state.selectedNode + && this.state.selectedNode.data + && this.state.selectedNode.data.details + && this.state.nodeDetails[0] + && this.state.nodeDetails[0].dslPath && Object.keys(this.state.nodeDetails[0].dslPath).map((indx) => { + return( + + +
+ {this.state.nodeDetails[0].dslPath[indx]} +
+ + + + + +
+ ) + })} +
+ + +
+ + + + Include in Output + + {this.state.enableRealTime && + Filter Types + } + + Filter By (Optional) + + + {this.state.selectedNode + && this.state.selectedNode.data + && this.state.selectedNode.data.details + && this.state.nodeDetails[0] + && Object.keys(this.state.nodeDetails[0].attrDetails).sort().map((attrKey, attr) => { + return( + + +
+ +
+ + {this.filterTags(0,attrKey, this.state.nodeDetails[0].attrDetails[attrKey].isSelected)} + + {Object.keys(this.state.nodeDetails[0].attrDetails[attrKey].filterValue).map((indx) =>{ + return( +
+ + {this.state.nodeDetails[0].attrDetails[attrKey].filterValue[indx] ==='' && {this.onFilterValueChange(e, 0, attrKey, indx);}} + /> + } + {this.state.nodeDetails[0].attrDetails[attrKey].filterValue[indx] !=='' && {this.onFilterValueChange(e, 0, attrKey,indx);}} + placeholder={"Enter " + attrKey } + className='inputFilter' + value={this.state.nodeDetails[0].attrDetails[attrKey].filterValue[indx]} + /> + } + {indx == 0 && } + {indx > 0 && } + +
+ ) + })} + + +
+ ); + } + )} +
+
+
+
+
+
+ + + Build DSL Path + + + + + +
+
+ + + + +
+
+
+ + + Edit DSL Query + + +
+ + DSL Query + + +
+
+ + + + +
+
+
+
+
+

{this.state.queryName}

+
+
+
+
+

{this.state.queryDescription}

+
+
+
+
+

DSL Query: {this.state.dslQuery}

+
+
+
+ {this.state.enableModalFeedback && } + +
+
+ ); + } +} + +export default CustomDslBuilder;