NOTICKET: Merging OSM/master to OSM/projects
[osm/UI.git] / skyquake / framework / widgets / skyquake_container / skyquakeContainerStore.js
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 //This will reach out to the global routes endpoint
19
20 import Alt from './skyquakeAltInstance.js';
21 import SkyquakeContainerSource from './skyquakeContainerSource.js';
22 import SkyquakeContainerActions from './skyquakeContainerActions';
23 let Utils = require('utils/utils.js');
24 import _indexOf from 'lodash/indexOf';
25 import _isEqual from 'lodash/isEqual';
26 //Temporary, until api server is on same port as webserver
27 import rw from 'utils/rw.js';
28
29 var API_SERVER = rw.getSearchParams(window.location).api_server;
30 var UPLOAD_SERVER = rw.getSearchParams(window.location).upload_server;
31
32 class SkyquakeContainerStore {
33 constructor() {
34 this.currentPlugin = getCurrentPlugin();
35 this.nav = {};
36 this.notifications = [];
37 this.socket = null;
38 this.projects = [];
39 this.user = {};
40 //Notification defaults
41 this.notificationMessage = '';
42 this.displayNotification = false;
43 this.notificationType = 'error';
44 //Screen Loader default
45 this.displayScreenLoader = false;
46 this.bindActions(SkyquakeContainerActions);
47 this.exportAsync(SkyquakeContainerSource);
48
49
50 this.exportPublicMethods({
51 // getNav: this.getNav
52 });
53
54 }
55 getSkyquakeNavSuccess = (data) => {
56 var self = this;
57 this.setState({
58 nav: decorateAndTransformNav(data, self.currentPlugin)
59 })
60 }
61
62 closeSocket = () => {
63 if (this.socket) {
64 window.multiplexer.channel(this.channelId).close();
65 }
66 this.setState({
67 socket: null
68 });
69 }
70 //Remove once logging plugin is implemented
71 getSysLogViewerURLSuccess(data){
72 window.open(data.url);
73 }
74 getSysLogViewerURLError(data){
75 console.log('failed', data)
76 }
77
78 openNotificationsSocketLoading = () => {
79 this.setState({
80 isLoading: true
81 })
82 }
83
84 openNotificationsSocketSuccess = (data) => {
85 var self = this;
86
87 let connection = data.connection;
88 let streamSource = data.streamSource;
89 console.log('Success opening notification socket for stream ', streamSource);
90
91 let ws = window.multiplexer.channel(connection);
92
93 if (!connection) return;
94 self.setState({
95 socket: ws.ws,
96 isLoading: false,
97 channelId: connection
98 });
99
100 ws.onmessage = (socket) => {
101 try {
102 var data = JSON.parse(socket.data);
103 if (!data.notification) {
104 console.warn('No notification in the received payload: ', data);
105 } else {
106 // Temp to test before adding multi-sources
107 data.notification.source = streamSource;
108 if (_indexOf(self.notifications, data.notification) == -1) {
109 // newly appreared event.
110 // Add to the notifications list and setState
111 self.notifications.unshift(data.notification);
112 self.setState({
113 newNotificationEvent: true,
114 newNotificationMsg: data.notification,
115 notifications: self.notifications,
116 isLoading: false
117 });
118 }
119 }
120 } catch(e) {
121 console.log('Error in parsing data on notification socket');
122 }
123 };
124
125 ws.onclose = () => {
126 self.closeSocket();
127 };
128 }
129
130 openNotificationsSocketError = (data) => {
131 console.log('Error opening notification socket', data);
132 }
133
134 getEventStreamsLoading = () => {
135 this.setState({
136 isLoading: true
137 });
138 }
139
140 getEventStreamsSuccess = (streams) => {
141 console.log('Found streams: ', streams);
142 let self = this;
143
144 streams['ietf-restconf-monitoring:streams'] &&
145 streams['ietf-restconf-monitoring:streams']['stream'] &&
146 streams['ietf-restconf-monitoring:streams']['stream'].map((stream) => {
147 stream['access'] && stream['access'].map((streamLocation) => {
148 if (streamLocation['encoding'] == 'ws_json') {
149 setTimeout(() => {
150 self.getInstance().openNotificationsSocket(streamLocation['location'], stream['name']);
151 }, 0);
152 }
153 })
154 })
155
156 this.setState({
157 isLoading: true,
158 streams: streams
159 })
160 }
161
162 getEventStreamsError = (error) => {
163 console.log('Failed to get streams object');
164 this.setState({
165 isLoading: false
166 })
167 }
168
169 openProjectSocketSuccess = (connection) => {
170 var self = this;
171 var ws = window.multiplexer.channel(connection);
172 if (!connection) return;
173 self.setState({
174 socket: ws.ws,
175 channelId: connection
176 });
177 ws.onmessage = function(socket) {
178 try {
179 var data = JSON.parse(socket.data);
180 Utils.checkAuthentication(data.statusCode, function() {
181 self.closeSocket();
182 });
183 if (!_isEqual(data.project, self.projects)) {
184 let user = self.user;
185 user.projects = data.project;
186 self.setState({
187 user: user,
188 projects: data.project
189 });
190 }
191 } catch(e) {
192 console.log('HIT an exception in openProjectSocketSuccess', e);
193 }
194 };
195 }
196 getUserProfileSuccess = (user) => {
197 this.alt.actions.global.hideScreenLoader.defer();
198 this.setState({user})
199 }
200 selectActiveProjectSuccess = (projectId) => {
201 let user = this.user;
202 user.projectId = projectId;
203 this.setState({user});
204 window.location.reload(true);
205 }
206 //Notifications
207 showNotification = (data) => {
208 let state = {
209 displayNotification: true,
210 notificationMessage: data,
211 notificationType: 'error',
212 displayScreenLoader: false
213 }
214 if(typeof(data) == 'string') {
215
216 } else {
217 if(!data) data = {};
218 state.notificationMessage = data.msg || 'Something wrong occurred. Check the network tab and console logs for more information.';
219 if(data.type) {
220 state.notificationType = data.type;
221 }
222 }
223 this.setState(state);
224 }
225 hideNotification = () => {
226 this.setState({
227 displayNotification: false
228 })
229 }
230 //ScreenLoader
231 showScreenLoader = () => {
232 this.setState({
233 displayScreenLoader: true
234 });
235 }
236 hideScreenLoader = () => {
237 this.setState({
238 displayScreenLoader: false
239 })
240 }
241
242 }
243
244 /**
245 * Receives nav data from routes rest endpoint and decorates the data with internal/external linking information
246 * @param {object} nav Nav item from /nav endoingpoint
247 * @param {string} currentPlugin Current plugin name taken from url path.
248 * @return {array} Returns list of constructed nav items.
249 */
250 function decorateAndTransformNav(nav, currentPlugin) {
251 for ( let k in nav) {
252 nav[k].pluginName = k;
253 if (k != currentPlugin) {
254 nav[k].routes.map(function(route, i) {
255 if (API_SERVER) {
256 route.route = '/' + k + '/index.html?api_server=' + API_SERVER + '&upload_server=' + UPLOAD_SERVER + '#' + route.route;
257 } else {
258 route.route = '/' + k + '/#' + route.route;
259 }
260 route.isExternal = true;
261 })
262 }
263 }
264 return nav;
265 }
266
267 function getCurrentPlugin() {
268 var paths = window.location.pathname.split('/');
269 var currentPath = null;
270 if (paths[0] != "") {
271 currentPath = paths[0]
272 } else {
273 currentPath = paths[1];
274 }
275 if (currentPath != null) {
276 return currentPath;
277 } else {
278 console.error('Well, something went horribly wrong with discovering the current plugin name - perhaps you should consider moving this logic to the server?')
279 }
280 }
281
282 export default Alt.createStore(SkyquakeContainerStore, 'SkyquakeContainerStore');