summaryrefslogtreecommitdiffstats
path: root/src/app/model/history/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/model/history/components')
-rw-r--r--src/app/model/history/components/AnimationControls.jsx126
-rw-r--r--src/app/model/history/components/HistoryCard.jsx101
-rw-r--r--src/app/model/history/components/HistoryEntry.jsx55
-rw-r--r--src/app/model/history/components/HistoryGallery.jsx65
-rw-r--r--src/app/model/history/components/NodeDiffCard.jsx106
-rw-r--r--src/app/model/history/components/TopologyDiffCard.jsx151
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;
+