7df4e3ec20896f864fa9c607e232c7892c51b2cb
[osm/UI.git] / skyquake / framework / widgets / skyquake_container / eventCenter.jsx
1 /*
2  * 
3  *   Copyright 2016 RIFT.IO Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  *
17  */
18
19  /**
20   * EventCenter module to display a list of events from the system
21   * @module framework/widgets/skyquake_container/EventCenter
22   * @author Kiran Kashalkar <kiran.kashalkar@riftio.com>
23   *
24   */
25
26 import React from 'react';
27 import { Link } from 'react-router';
28 import Utils from 'utils/utils.js';
29 import Crouton from 'react-crouton';
30 import TreeView from 'react-treeview';
31 import _isEqual from 'lodash/isEqual';
32 import _merge from 'lodash/merge';
33 import _indexOf from 'lodash/indexOf';
34 import '../../../node_modules/react-treeview/react-treeview.css';
35 import './eventCenter.scss';
36
37 export default class EventCenter extends React.Component {
38         constructor(props) {
39                 super(props);
40                 this.state = {};
41                 this.state.isOpen = false;
42         }
43
44         componentWillReceiveProps(props) {
45                 let stateObject = {};
46
47                 let notificationList = sessionStorage.getItem('notificationList');
48                 let latestNotification = sessionStorage.getItem('latestNotification');
49
50                 if (props.newNotificationEvent && props.newNotificationMsg) {
51                         if (latestNotification) {
52                                 latestNotification = JSON.parse(latestNotification);
53                                 if (!_isEqual(props.newNotificationMsg, latestNotification)) {
54                                         stateObject.newNotificationEvent = props.newNotificationEvent;
55                                         stateObject.newNotificationMsg = props.newNotificationMsg;
56                                         sessionStorage.setItem('latestNotification', JSON.stringify(stateObject.newNotificationMsg));
57                                 } else {
58                                         stateObject.newNotificationEvent = false;
59                                         stateObject.newNotificationMsg = null;
60                                 }
61                         } else {
62                                 stateObject.newNotificationEvent = true;
63                                 stateObject.newNotificationMsg = props.newNotificationMsg;
64                                 sessionStorage.setItem('latestNotification', JSON.stringify(stateObject.newNotificationMsg));
65                         }
66                 } else {
67                         stateObject.newNotificationEvent = false;
68                         stateObject.newNotificationMsg = null;
69                 }
70
71                 if (notificationList) {
72                         stateObject.notifications = _merge(notificationList, props.notifications);
73                 } else {
74                         stateObject.notifications = props.notifications;
75                 }
76                 sessionStorage.setItem('notifications', JSON.stringify(stateObject.notifications));
77                 this.setState(stateObject);
78         }
79
80         newNotificationReset = () => {
81         this.setState({
82             newNotificationEvent: false
83         });
84     }
85
86         onClickToggleOpenClose(event) {
87                 this.props.onToggle();
88                 this.setState({
89                         isOpen: !this.state.isOpen
90                 });
91         }
92         constructTree(details) {
93                 let markup = [];
94                 for (let key in details) {
95                         if (typeof(details[key]) == "object") {
96                             let html = (
97                                 <TreeView key={key} nodeLabel={key}>
98                                   {this.constructTree(details[key])}
99                                 </TreeView>
100                             );
101                             markup.push(html);
102                         } else {
103                                 markup.push((<div key={key} className="info">{key} = {details[key].toString()}</div>));
104                         }
105                 }
106                 return markup;
107         }
108
109         getNotificationFields(notification) {
110                 let notificationFields = {};
111                 if (notification) {
112
113                         notificationFields.source = notification.source;
114                         notificationFields.eventTime = notification.eventTime;
115
116                         Object.keys(notification).map((notificationKey) => {
117                                 if (_indexOf(['source', 'eventTime'], notificationKey) == -1) {
118                                         notificationFields.eventKey = notificationKey;
119                                         notificationFields.details = notification[notificationFields.eventKey];
120                                 }
121                         });
122
123                 }
124                 return notificationFields;
125         }
126
127         render() {
128                 let html;
129                 let displayNotifications = [];
130                 let displayNotificationsTableHead = null;
131
132                 if (this.state.notifications && this.state.notifications.length > 0) {
133                         displayNotificationsTableHead = (
134                                 <thead>
135                                         <tr key='header' className='header'>
136                                                 <th className='source column'> Source Event Stream </th>
137                                                 <th className='timestamp column'> Timestamp </th>
138                                                 <th className='event column'> Event </th>
139                                                 <th className='details column'> Details </th>
140                                         </tr>
141                                 </thead>
142                         );
143                 }
144
145                 this.state.notifications && this.state.notifications.map((notification, notifIndex) => {
146                         let notificationFields = {};
147
148                         notificationFields = this.getNotificationFields(notification);
149
150                         displayNotifications.push(
151                                 <tr key={notifIndex} className='notificationItem'>
152                                         <td className='source column'> {notificationFields.source} </td>
153                                         <td className='timestamp column'> {notificationFields.eventTime} </td>
154                                         <td className='event column'> {notificationFields.eventKey} </td>
155                                         <td className='details column'>
156                                                 <TreeView key={notifIndex + '-detail'} nodeLabel='Event Details'>
157                                                         {this.constructTree(notificationFields.details)}
158                                                 </TreeView>
159                                         </td>
160                                 </tr>
161                         );
162                 });
163
164                 let openedClassName = this.state.isOpen ? 'open' : 'closed';
165                 html = (
166                         <div className={'eventCenter ' + openedClassName}>
167
168                         <div className='notification'>
169                             <Crouton
170                                 id={Date.now()}
171                                 message={this.getNotificationFields(this.state.newNotificationMsg).eventKey +
172                                         ' notification received. Check Event Center for more details.'}
173                                 type={'info'}
174                                 hidden={!(this.state.newNotificationEvent && this.state.newNotificationMsg)}
175                                 onDismiss={this.newNotificationReset}
176                                 timeout={this.props.dismissTimeout}
177                             />
178                         </div>
179                                 <h1 className='title' data-open-close-icon={this.state.isOpen ? 'open' : 'closed'}
180                                         onClick={this.onClickToggleOpenClose.bind(this)}>
181                                         EVENT CENTER
182                                 </h1>
183                                 <div className='notificationListBody'>
184                                         <table className='notificationList'>
185                                                 {displayNotificationsTableHead}
186                                                 <tbody>
187                                                         {displayNotifications}
188                                                 </tbody>
189                                         </table>
190                                 </div>
191                         </div>
192                 );
193
194                 return html;
195         }
196 }
197
198 EventCenter.defaultProps = {
199         dismissTimeout: 3000
200 }