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