diff options
Diffstat (limited to 'src/app/model/history/components')
-rw-r--r-- | src/app/model/history/components/AnimationControls.jsx | 126 | ||||
-rw-r--r-- | src/app/model/history/components/HistoryCard.jsx | 101 | ||||
-rw-r--r-- | src/app/model/history/components/HistoryEntry.jsx | 55 | ||||
-rw-r--r-- | src/app/model/history/components/HistoryGallery.jsx | 65 | ||||
-rw-r--r-- | src/app/model/history/components/NodeDiffCard.jsx | 106 | ||||
-rw-r--r-- | src/app/model/history/components/TopologyDiffCard.jsx | 151 |
6 files changed, 604 insertions, 0 deletions
diff --git a/src/app/model/history/components/AnimationControls.jsx b/src/app/model/history/components/AnimationControls.jsx new file mode 100644 index 0000000..3f1eb92 --- /dev/null +++ b/src/app/model/history/components/AnimationControls.jsx @@ -0,0 +1,126 @@ +/* + * ============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 { Link } from 'react-router-dom'; +import Col from 'react-bootstrap/lib/Col'; + +class AnimationControls extends Component { + constructor(props){ + console.log(props); + super(props); + this.props = props; + } + + getIndex = () =>{ + return (this.props.get('sliderTickArray')).indexOf(this.props.get('currentStateHistoryValue')); + } + + navigateAnimation = (index, command) => { + if(!command){ + this.props.set('isPlaying',false); + this.props.set('isStopped', false); + this.props.set('isPaused', true); + this.props.setValueState((this.props.get('sliderTickArray'))[index]); + }else if (command === 'play'){ + this.props.setValueState((this.props.get('sliderTickArray'))[index]); + } + this.props.setNavigate((this.props.get('sliderTickArray'))[index]); + } + + play = () =>{ + if(this.props.get('isPlaying')){ + var index = Math.min((this.props.get('sliderTickArray')).length - 1, this.getIndex() + 1); + this.navigateAnimation(this.getIndex() + 1, 'play'); + if(index === (this.props.get('sliderTickArray')).length - 1){ + this.props.set('isPlaying', false); + this.props.set('isStopped', true); + this.props.set('isPaused', false); + } + }else{ + this.props.clear(this.props.get('intervalId')); + } + } + + animationControl = (controlType) => { + console.log("Control was hit: " + controlType); + switch(controlType){ + case 'play': + if(!this.props.get('isPlaying')){ + if(!this.props.get('intervalId')){ + this.props.set('intervalId', setInterval(this.play, 10000)); + } + this.props.set('isPlaying', true); + this.props.set('isStopped', false); + this.props.set('isPaused', false); + } + break; + case 'pause': + if(this.props.get('isPlaying')){ + this.props.clear(this.props.get('intervalId')); + this.props.set('isPlaying', false); + this.props.set('isPaused', true); + } + break; + case 'stop': + if(this.props.get('isPlaying') || this.props.get('isPaused')){ + this.props.clear(this.props.get('intervalId')); + this.props.set('isPlaying', false); + this.props.set('isStopped', true); + this.props.set('isPaused', false); + } + break; + case 'skipForwardStep': + var index = Math.min((this.props.get('sliderTickArray')).length - 1, this.getIndex() + 1); + this.navigateAnimation(index); + break; + case 'skipBackwardStep': + var index = Math.max(0, this.getIndex() - 1); + this.navigateAnimation(index); + break; + case 'skipForwardLast': + this.navigateAnimation((this.props.get('sliderTickArray')).length - 1); + break; + case 'skipBackwardEpoch': + this.navigateAnimation(0); + break; + default: + this.props.set('isPlaying', false); + this.props.set('isStopped', false); + this.props.set('isPaused', false); + break; + } + } + render(){ + return ( + <Col md={8}> + <i className='icon-controls-skipbackstartover animationControlIcon' onClick={() => this.animationControl('skipBackwardEpoch')} role="img"></i> + <i className='icon-controls-rewind animationControlIcon' onClick={() => this.animationControl('skipBackwardStep')} role="img"></i> + { !this.props.playControlsDisabled && (<span><i className={'icon-controls-pointer ' + (this.props.get('isPlaying') ? 'animationPlayingIcon' : 'animationControlIcon')} onClick={() => this.animationControl('play')} role="img"></i> + <i className={'icon-controls-pause ' + (this.props.get('isPaused') ? 'animationPausedIcon' : 'animationControlIcon')} onClick={() => this.animationControl('pause')} role="img"></i> + <i className={'icon-controls-stop ' + (this.props.get('isStopped') ? 'animationStoppedIcon' : 'animationControlIcon')} onClick={() => this.animationControl('stop')} role="img"></i></span>)} + <i className='icon-controls-fastforward animationControlIcon' onClick={() => this.animationControl('skipForwardStep')} role="img"></i> + <i className='icon-controls-skipforward animationControlIcon' onClick={() => this.animationControl('skipForwardLast')} role="img"></i> + </Col> + ); + } +}; + +export default AnimationControls; diff --git a/src/app/model/history/components/HistoryCard.jsx b/src/app/model/history/components/HistoryCard.jsx new file mode 100644 index 0000000..39d7f57 --- /dev/null +++ b/src/app/model/history/components/HistoryCard.jsx @@ -0,0 +1,101 @@ +/* + * ============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 from 'react'; +import moment from "moment"; +import Col from 'react-bootstrap/lib/Col'; +import Panel from 'react-bootstrap/lib/Panel'; + +const historyCard = (props) => { + if(props && props.node && props.node.properties){ + const properties = (props.node.properties).map((prop, idx) => { + return ( + <Panel> + <Panel.Heading className="custom-accordion"> + <Panel.Title toggle> <strong>{prop.key}</strong> : {'' + prop.value}</Panel.Title> + </Panel.Heading> + <Panel.Collapse> + <Panel.Body className='cardwrap'> + <p><strong>Last Updated By:</strong> {prop.sot}</p> + <p><strong>Last Updated (time):</strong> {moment(prop.timestamp).format('dddd, MMMM Do, YYYY h:mm:ss A')}</p> + <p><strong>Transaction Id:</strong> {(prop['tx-id']) ? prop['tx-id'] : 'N/A'}</p> + </Panel.Body> + </Panel.Collapse> + </Panel> + ); + }); + + //TODO handle no relationships and no attributes + + const relationships = (props.node['related-to']).map((prop, idx) => { + return ( + <p key={idx}><strong>{prop['node-type']}:</strong> {prop.url} {prop['relationship-label']} (added by {prop.sot} on {moment(prop.timestamp).format('dddd, MMMM Do, YYYY h:mm:ss A')})</p> + ); + }); + + return ( + <Col className={""+(props.split ? 'col-lg-4' : 'col-lg-12')}> + <div className='card model-card'> + <div className='card-header'> + <h4 className='card-title'>{props.node.primaryHeader}</h4> + </div> + <div className='card-header'> + {props.node.secondaryHeader} + </div> + <div className='card-content model-card-content'> + {properties} + </div> + <div className='card-footer'> + <Panel> + <Panel.Heading> + <Panel.Toggle> + <button type='button' className='btn btn-outline-primary'> + Relationships + </button> + </Panel.Toggle> + </Panel.Heading> + <Panel.Collapse> + <Panel.Body className='cardwrap'> + {relationships} + </Panel.Body> + </Panel.Collapse> + </Panel> + </div> + </div> + </Col> + ); + }else{ + return( + <Col className={""+(props.split ? 'col-lg-4' : 'col-lg-12')}> + <div className='card model-card'> + <div className='card-header'> + <h4 className='card-title'>No State Found</h4> + </div> + <div className='card-content model-card-content'> + No State was found at the provided timestamp. Please try another timestamp. + </div> + </div> + </Col> + ); + } +}; + +export default historyCard; + diff --git a/src/app/model/history/components/HistoryEntry.jsx b/src/app/model/history/components/HistoryEntry.jsx new file mode 100644 index 0000000..7b1a297 --- /dev/null +++ b/src/app/model/history/components/HistoryEntry.jsx @@ -0,0 +1,55 @@ +/* + * ============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 { Link } from 'react-router-dom'; +import Col from 'react-bootstrap/lib/Col'; + +class HistoryEntry extends Component { + constructor(props){ + console.log(props); + super(props); + this.props = props; + } + + render(){ + this.triggerState = () => { + this.props.triggerState(this.props.entryNodeId, this.props.entryEpoch); + } + return ( + <a className={"list-group-item list-group-item-action flex-column align-items-start "+ (this.props.entryAction === 'Deleted' ? 'group-item-danger' : '')} + onClick={this.triggerState}> + <div className='d-flex w-100 justify-content-between'> + <h3 className="mb-1">{this.props.entryHeader}</h3> + <h3 className="mb-1">{this.props.entryBody}</h3> + <small>{this.props.entryDate}</small> + </div> + <div> + <small>Modified by {this.props.entrySOT}</small> + </div> + <div> + <small>Transaction Id : {this.props.entryTransId}</small> + </div> + </a> + ); + } +}; + +export default HistoryEntry; diff --git a/src/app/model/history/components/HistoryGallery.jsx b/src/app/model/history/components/HistoryGallery.jsx new file mode 100644 index 0000000..0e4c011 --- /dev/null +++ b/src/app/model/history/components/HistoryGallery.jsx @@ -0,0 +1,65 @@ +/* + * ============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 from 'react'; +import Grid from 'react-bootstrap/lib/Grid'; +import Row from 'react-bootstrap/lib/Row'; +import HistoryEntry from './HistoryEntry.jsx'; +/** + * This function will take all of the node objects and turn them into + * a ui grid of HistoryCard components. This function is essentially a container + * for the HistoryCards + * @param props + * @returns {*} + */ +const HistoryGallery = (props) => { + + let entries = null; + if (props.entries && props.entries.length > 0) { + entries = props.entries.map((entry, idx) => { + return ( + <HistoryEntry + key={idx} + triggerState={props.triggerState} + entryKey={entry.key} + entryType={entry.type} + entryValue={entry.value} + entryBody= {entry.body} + entryHeader= {entry.header} + entrySOT={entry.sot} + entryAction= {entry.action} + entryEpoch= {entry.timeRank} + entryNodeId= {props.nodeId} + entryDate={entry.displayTimestamp} + entryTransId = {entry['tx-id']}/> + ); + }); + }else{ + return (<p>No History</p>); + } + + return ( + <div className="list-group"> + {entries} + </div> + ); +}; + +export default HistoryGallery; diff --git a/src/app/model/history/components/NodeDiffCard.jsx b/src/app/model/history/components/NodeDiffCard.jsx new file mode 100644 index 0000000..2bc2a82 --- /dev/null +++ b/src/app/model/history/components/NodeDiffCard.jsx @@ -0,0 +1,106 @@ +/* + * ============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 from 'react'; +import moment from "moment"; +import Col from 'react-bootstrap/lib/Col'; +import Panel from 'react-bootstrap/lib/Panel'; + +const nodeDiffCard = (props) => { + let showNoPropsMessage = true; + let showNoRelationshipsMessage = true; + if(props && props.diff && props.diff.properties){ + const properties = Object.entries(props.diff.properties).map((property, idx) => { + let prop = property[1]; + if(prop && prop.value && prop.value.type !== 'unchanged'){ + showNoPropsMessage = false; + return ( + <div> + <p><strong>Attribute:</strong> {prop.key.data} ({prop.value.type})</p> + </div> + ); + }else if (prop && prop.type){ + showNoPropsMessage = false; + return ( + <div> + <p><strong>Attribute:</strong> {prop.data.key} ({prop.type})</p> + </div> + ); + } + }); + + //TODO handle no relationships and no attributes + + const relationships = Object.entries(props.diff['related-to']).map((property, idx) => { + let prop = property[1]; + if(prop && prop.type && prop.type.type){ + return (''); + }else if(prop && prop.type && !prop.data){ + showNoRelationshipsMessage = false; + return ( + <div> + <p><strong>Relationship</strong>: {prop['relationship-label'].data} {prop['node-type'].data} {prop.url.data} ({prop.type})</p> + </div> + ); + }else if (prop && prop.type && prop.data){ + showNoRelationshipsMessage = false; + return ( + <div> + <p><strong>Relationship</strong>: {prop.data['relationship-label']} {prop.data['node-type']} {prop.data.url} ({prop.type})</p> + </div> + ); + } + }); + + return ( + <Col className='col-lg-4'> + <div className='card model-card'> + <div className='card-header'> + <h4 className='card-title'>Changes from Historic to Current State</h4> + </div> + <div className='card-header'></div> + <div className='card-content model-card-content'> + {properties} + <div className={showNoPropsMessage ? 'show' : 'hidden'}><p><strong>No Attribute differences, current.</strong></p></div> + {relationships} + <div className={showNoRelationshipsMessage ? 'show' : 'hidden'}><p><strong>No Relationship differences, current.</strong></p></div> + </div> + </div> + </Col> + ); + }else{ + return( + <Col className='col-lg-4'> + <div className='card model-card'> + <div className='card-header'> + <h4 className='card-title'>Unable to pull diff</h4> + </div> + <div className='card-header'></div> + <div className='card-content model-card-content'> + Diff unable to be calculated currently, choose a different timeframe. + </div> + </div> + </Col> + ); + } +}; + +export default nodeDiffCard; + diff --git a/src/app/model/history/components/TopologyDiffCard.jsx b/src/app/model/history/components/TopologyDiffCard.jsx new file mode 100644 index 0000000..9d49b17 --- /dev/null +++ b/src/app/model/history/components/TopologyDiffCard.jsx @@ -0,0 +1,151 @@ +/* + * ============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 from 'react'; +import moment from "moment"; +import Col from 'react-bootstrap/lib/Col'; +import Panel from 'react-bootstrap/lib/Panel'; + +const topologyDiffCard = (props) => { + let showNoNodesMessage = true; + if(props && props.node){ + const properties = Object.entries(props.node).map((prop, idx) => { + if (prop){ + showNoNodesMessage = false; + let showNoRelationshipsMessage = true; + let showNoAttributesMessage = true; + let propWorkaround = prop; + if(prop.data){ + propWorkaround = prop.data; + } + let tempProp = propWorkaround[1]; + let attributeProperties = ''; + let relationships = ''; + if(tempProp.properties){ + attributeProperties = Object.entries(tempProp.properties).map((property, idx) => { + let attrProp = property[1]; + if(attrProp && attrProp.value && attrProp.value.type !== 'unchanged'){ + showNoAttributesMessage = false; + return ( + <div> + <p><strong>Attribute:</strong> {attrProp.key.data} ({attrProp.value.type})</p> + </div> + ); + }else if (attrProp && attrProp.type){ + showNoAttributesMessage = false; + return ( + <div> + <p><strong>Attribute:</strong> {attrProp.data.key} ({attrProp.type})</p> + </div> + ); + } + }); + } + if(tempProp['related-to'] || tempProp.data['related-to']){ + let rel = null; + let topLevelType = null; + if(tempProp['related-to']){ + rel = tempProp['related-to']; + }else if (tempProp.data['related-to']) { + rel = tempProp.data['related-to']; + topLevelType = tempProp.type; + } + relationships = Object.entries(rel).map((property, idx) => { + let relationProp = property[1]; + if(relationProp && relationProp.type && relationProp.type.type && relationProp.type.type !== "unchanged"){ + return (''); + }else if(relationProp && relationProp.type && !relationProp.type.type && relationProp.url && relationProp.url.data){ + showNoRelationshipsMessage = false; + return ( + <div> + <p><strong>Relationship</strong>: {relationProp['relationship-label'].data} {relationProp['node-type'].data} {relationProp.url.data} ({relationProp.type})</p> + </div> + ); + }else if (relationProp && relationProp.type && relationProp.data){ + showNoRelationshipsMessage = false; + return ( + <div> + <p><strong>Relationship</strong>: {relationProp.data['relationship-label']} {relationProp.data['node-type']} {relationProp.data.url} ({relationProp.type})</p> + </div> + ); + }else if (topLevelType){ + showNoRelationshipsMessage = false; + return ( + <div> + <p><strong>Relationship</strong>: {relationProp['relationship-label']} {relationProp['node-type']} {relationProp.url} ({topLevelType})</p> + </div> + ); + } + }); + } + return ( + <Panel> + <Panel.Heading className="custom-accordion"> + <Panel.Title toggle><strong>Node:</strong> {prop[0]} <p className={tempProp.type ? 'show' : 'hidden'}>({tempProp.type})</p></Panel.Title> + </Panel.Heading> + <Panel.Collapse> + <Panel.Body className='cardwrap'> + {attributeProperties} + <div className={showNoAttributesMessage ? 'show' : 'hidden'}><p><strong>No Attribute differences, current.</strong></p></div> + {relationships} + <div className={showNoRelationshipsMessage ? 'show' : 'hidden'}><p><strong>No Relationship differences, current.</strong></p></div> + </Panel.Body> + </Panel.Collapse> + </Panel> + ); + }else{ + <div> + <p><strong>Node changes in the topology states</strong></p> + </div> + } + }); + + return ( + <Col className='col-lg-12'> + <div className='card model-card'> + <div className='card-header'> + <h4 className='card-title'>Changes from Historic to Current State</h4> + </div> + <div className='card-header'></div> + <div className='card-content model-card-content'> + {properties} + </div> + </div> + </Col> + ); + }else{ + return( + <Col className='col-lg-12'> + <div className='card model-card'> + <div className='card-header'> + <h4 className='card-title'>Unable to pull diff</h4> + </div> + <div className='card-header'></div> + <div className='card-content model-card-content'> + Diff unable to be calculated currently, choose a different timeframe. + </div> + </div> + </Col> + ); + } +}; + +export default topologyDiffCard; + |