aboutsummaryrefslogtreecommitdiffstats
path: root/ui/imports/ui/reducers
diff options
context:
space:
mode:
Diffstat (limited to 'ui/imports/ui/reducers')
-rw-r--r--ui/imports/ui/reducers/environment-panel.reducer.js194
-rw-r--r--ui/imports/ui/reducers/graph-tooltip-window.reducer.js48
-rw-r--r--ui/imports/ui/reducers/i18n.reducer.js180
-rw-r--r--ui/imports/ui/reducers/index.js33
-rw-r--r--ui/imports/ui/reducers/main-app.reducer.js28
-rw-r--r--ui/imports/ui/reducers/navigation.js99
-rw-r--r--ui/imports/ui/reducers/search-interested-parties.js76
-rw-r--r--ui/imports/ui/reducers/tree-node.reducer.js232
-rw-r--r--ui/imports/ui/reducers/vedge-info-window.reducer.js50
9 files changed, 940 insertions, 0 deletions
diff --git a/ui/imports/ui/reducers/environment-panel.reducer.js b/ui/imports/ui/reducers/environment-panel.reducer.js
new file mode 100644
index 0000000..bac0e72
--- /dev/null
+++ b/ui/imports/ui/reducers/environment-panel.reducer.js
@@ -0,0 +1,194 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+import * as R from 'ramda';
+
+import * as actions from '/imports/ui/actions/environment-panel.actions';
+import { reducer as treeNode } from './tree-node.reducer';
+import {
+ updateTreeNodeInfo,
+ addUpdateChildrenTreeNode,
+ resetTreeNodeChildren,
+ startOpenTreeNode,
+ endOpenTreeNode,
+ startCloseTreeNode,
+ endCloseTreeNode,
+ setChildDetectedTreeNode,
+ setPositionReportIsNeededAsOn,
+ reportNodePositionRetrieved,
+ setScrollToNodeIsNeededAsOn,
+ reportScrollToNodePerformed,
+ resetNeedChildDetection,
+}
+ from '/imports/ui/actions/tree-node.actions';
+
+const defaultState = {
+ _id: null,
+ envName: null,
+ isLoaded: false,
+ treeNode: treeNode(),
+ selectedNode: {
+ _id: null,
+ type: null
+ },
+ showType: 'dashboard'
+};
+
+let newState;
+
+export function reducer(state = defaultState, action) {
+ switch (action.type) {
+ case actions.SET_ENV_NAME:
+ return R.assoc('envName', action.payload.envName, state);
+
+ case actions.UPDATE_ENV_TREE_NODE:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode,
+ updateTreeNodeInfo(action.payload.nodeInfo, 0)),
+ state);
+
+ case actions.ADD_UPDATE_CHILDREN_ENV_TREE_NODE:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode,
+ addUpdateChildrenTreeNode(action.payload.nodePath, action.payload.childrenInfo, 0)),
+ state);
+
+ case actions.RESET_ENV_TREE_NODE_CHILDREN:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, resetTreeNodeChildren(action.payload.nodePath)),
+ state
+ );
+
+ case actions.START_OPEN_ENV_TREE_NODE:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, startOpenTreeNode(action.payload.nodePath)),
+ state
+ );
+
+ case actions.END_OPEN_ENV_TREE_NODE:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, endOpenTreeNode(action.payload.nodePath)),
+ state
+ );
+
+ case actions.START_CLOSE_ENV_TREE_NODE:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, startCloseTreeNode(action.payload.nodePath)),
+ state
+ );
+
+ case actions.END_CLOSE_ENV_TREE_NODE:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, endCloseTreeNode(action.payload.nodePath)),
+ state
+ );
+
+ case actions.SET_ENV_CHILD_DETECTED_TREE_NODE:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, setChildDetectedTreeNode(action.payload.nodePath)),
+ state
+ );
+
+ case actions.SET_ENV_SELECTED_NODE:
+ if (R.pathEq(['selectedNode', '_id'], action.payload.nodeId, state) &&
+ R.pathEq(['selectedNode', 'type'], action.payload.nodeType)
+ ) {
+ return state;
+ }
+
+ return R.merge(state, {
+ selectedNode: {
+ _id: action.payload.nodeId,
+ type: action.payload.nodeType
+ }
+ });
+
+ case actions.SET_ENV_SELECTED_NODE_INFO:
+ newState = R.merge(state, {
+ selectedNode: R.merge(state.selectedNode, {
+ type: action.payload.nodeInfo.type,
+ clique: action.payload.nodeInfo.clique,
+ id_path: action.payload.nodeInfo.id_path
+ })
+ });
+
+ if (! R.isNil(action.payload.nodeInfo.clique)) {
+ newState = R.assoc('showType', 'graph', newState);
+ }
+
+ return newState;
+
+ case actions.SET_ENV_SELECTED_NODE_AS_ENV:
+ return R.merge(state, {
+ selectedNode: {
+ _id: state._id,
+ type: 'environment'
+ }
+ });
+
+ case actions.SET_ENV_ENV_ID:
+ return R.assoc('_id', action.payload._id, state);
+
+ case actions.SET_ENV_AS_LOADED:
+ return R.assoc('isLoaded', true, state);
+
+ case actions.SET_ENV_AS_NOT_LOADED:
+ return R.assoc('isLoaded', false, state);
+
+ case actions.SET_SHOW_DASHBOARD:
+ return R.assoc('showType', 'dashboard', state);
+
+ case actions.SET_SHOW_GRAPH:
+ return R.assoc('showType', 'graph', state);
+
+ case actions.TOGGLE_ENV_SHOW:
+ return R.pipe(
+ R.ifElse(R.equals('dashboard'),
+ R.always('graph'),
+ R.always('dashboard')),
+ R.assoc('showType', R.__, state)
+ )(state.showType);
+
+ case actions.SET_ENV_POSITION_REPORT_IS_NEEDED_AS_ON:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, setPositionReportIsNeededAsOn(action.payload.nodePath)),
+ state
+ );
+
+ case actions.REPORT_ENV_NODE_POSITION_RETRIEVED:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, reportNodePositionRetrieved(
+ action.payload.nodePath, action.payload.rect)),
+ state
+ );
+
+ case actions.SET_ENV_SCROLL_TO_NODE_IS_NEEDED_AS_ON:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, setScrollToNodeIsNeededAsOn(
+ action.payload.nodePath)),
+ state
+ );
+
+ case actions.REPORT_ENV_SCROLL_TO_NODE_PERFORMED:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, reportScrollToNodePerformed(
+ action.payload.nodePath)),
+ state
+ );
+
+ case actions.RESET_ENV_NEED_CHILD_DETECTION:
+ return R.assoc('treeNode',
+ treeNode(state.treeNode, resetNeedChildDetection(
+ action.payload.nodePath)),
+ state
+ );
+
+ default:
+ return state;
+ }
+}
diff --git a/ui/imports/ui/reducers/graph-tooltip-window.reducer.js b/ui/imports/ui/reducers/graph-tooltip-window.reducer.js
new file mode 100644
index 0000000..67f96f1
--- /dev/null
+++ b/ui/imports/ui/reducers/graph-tooltip-window.reducer.js
@@ -0,0 +1,48 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+import * as R from 'ramda';
+
+import * as actions from '/imports/ui/actions/graph-tooltip-window.actions';
+
+const defaultState = {
+ label: '',
+ title: '',
+ left: 0,
+ top: 0,
+ show: false
+};
+
+export function reducer(state = defaultState, action) {
+ let attrsStr;
+ switch (action.type) {
+ case actions.ACTIVATE_GRAPH_TOOLTIP_WINDOW:
+ attrsStr = JSON.stringify(action.payload.attributes, null, 4)
+ .toString()
+ .replace(/\,/g,'<BR>')
+ .replace(/\[/g,'')
+ .replace(/\]/g,'')
+ .replace(/\{/g,'')
+ .replace(/\}/g,'')
+ .replace(/"/g,'');
+
+ return R.merge(state, {
+ label: action.payload.label,
+ title: attrsStr,
+ left: action.payload.left,
+ top: action.payload.top - 28,
+ show: true
+ });
+
+ case actions.CLOSE_GRAPH_TOOLTIP_WINDOW:
+ return R.assoc('show', false, state);
+
+ default:
+ return state;
+ }
+}
diff --git a/ui/imports/ui/reducers/i18n.reducer.js b/ui/imports/ui/reducers/i18n.reducer.js
new file mode 100644
index 0000000..8771aad
--- /dev/null
+++ b/ui/imports/ui/reducers/i18n.reducer.js
@@ -0,0 +1,180 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+//import * as R from 'ramda';
+
+const defaultState = {
+ apis: {
+
+ },
+ collections: {
+ environments: {
+ fields: {
+ eventBasedScan: {
+ header: 'Event based scan',
+ desc: 'Update the inventory in real-time whenever a user makes a change to the OpenStack environment'
+ }
+ }
+ }
+ },
+ components: {
+ environment: {
+ noGraphForLeafMsg: 'No clique for this focal_point',
+ briefInfos: {
+ lastScanning: {
+ header: 'Last scanning'
+ },
+ vConnectorsNum: {
+ header: 'Number of vConnectors'
+ },
+ hostsNum: {
+ header: 'Number of hosts'
+ },
+ vServicesNum: {
+ header: 'Number of vServices'
+ },
+ instancesNum: {
+ header: 'Number of instances'
+ }
+ },
+ listInfoBoxes: {
+ regions: {
+ header: 'Regions'
+ },
+ projects: {
+ header: 'Projects'
+ }
+ }
+ },
+ projectDashboard: {
+ infoBoxes: {
+ networks: {
+ header: 'Number of networks'
+ },
+ ports: {
+ header: 'Number of ports'
+ }
+ }
+ },
+
+ regionDashboard: {
+ infoBoxes: {
+ instances: {
+ header: 'Number of instances'
+ },
+ vServices: {
+ header: 'Number of vServices'
+ },
+ hosts: {
+ header: 'Number of hosts'
+ },
+ vConnectors: {
+ header: 'Number of vConnectors'
+ }
+ },
+ listInfoBoxes: {
+ availabilityZones: {
+ header: 'Availability zones'
+ },
+ aggregates: {
+ header: 'Aggregates'
+ }
+ }
+ },
+
+ zoneDashboard: {
+ infoBoxes: {
+ instances: {
+ header: 'Number of instances'
+ },
+ vServices: {
+ header: 'Number of vServices'
+ },
+ hosts: {
+ header: 'Number of hosts'
+ },
+ vConnectors: {
+ header: 'Number of vConnectors'
+ },
+ vEdges: {
+ header: 'Number of vEdges'
+ }
+ },
+ listInfoBoxes: {
+ hosts: {
+ header: 'Hosts'
+ },
+ }
+ },
+
+ aggregateDashboard: {
+ infoBoxes: {
+ instances: {
+ header: 'Number of instances'
+ },
+ vServices: {
+ header: 'Number of vServices'
+ },
+ hosts: {
+ header: 'Number of hosts'
+ },
+ vConnectors: {
+ header: 'Number of vConnectors'
+ },
+ vEdges: {
+ header: 'Number of vEdges'
+ }
+ },
+ listInfoBoxes: {
+ hosts: {
+ header: 'Hosts'
+ },
+ }
+ },
+
+ hostDashboard: {
+ infoBoxes: {
+ instances: {
+ header: 'Number of instances'
+ },
+ vServices: {
+ header: 'Number of vServices'
+ },
+ vConnectors: {
+ header: 'Number of vConnectors'
+ },
+ networkAgents: {
+ header: 'Number of agents'
+ },
+ pnics: {
+ header: 'Number of pnics'
+ },
+ vEdges: {
+ header: 'Number of vEdges'
+ },
+ ports: {
+ header: 'Number of ports'
+ }
+ },
+ },
+
+ generalFolderNodeDashboard: {
+ mainCubic: {
+ header: 'Number of children'
+ }
+ }
+ }
+};
+
+export function reducer(state = defaultState, action) {
+ switch (action.type) {
+
+ default:
+ return state;
+ }
+}
diff --git a/ui/imports/ui/reducers/index.js b/ui/imports/ui/reducers/index.js
new file mode 100644
index 0000000..6ee909d
--- /dev/null
+++ b/ui/imports/ui/reducers/index.js
@@ -0,0 +1,33 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+import { combineReducers } from 'redux';
+
+import { navigation } from './navigation';
+import { searchInterestedParties } from './search-interested-parties';
+import { reducer as environmentPanel } from './environment-panel.reducer';
+import { reducer as i18n } from './i18n.reducer';
+import { reducer as graphTooltipWindow } from './graph-tooltip-window.reducer';
+import { reducer as vedgeInfoWindow } from './vedge-info-window.reducer';
+import { reducer as mainApp } from './main-app.reducer';
+
+const calipsoApp = combineReducers({
+ api: combineReducers({
+ navigation,
+ searchInterestedParties,
+ i18n
+ }),
+ components: combineReducers({
+ mainApp: mainApp,
+ environmentPanel,
+ graphTooltipWindow,
+ vedgeInfoWindow
+ })
+});
+
+export default calipsoApp;
diff --git a/ui/imports/ui/reducers/main-app.reducer.js b/ui/imports/ui/reducers/main-app.reducer.js
new file mode 100644
index 0000000..abc4574
--- /dev/null
+++ b/ui/imports/ui/reducers/main-app.reducer.js
@@ -0,0 +1,28 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+import * as R from 'ramda';
+
+import * as actions from '/imports/ui/actions/main-app.actions';
+
+const defaultState = {
+ selectedEnvironment: {},
+};
+
+export function reducer(state = defaultState, action) {
+ switch (action.type) {
+ case actions.SET_MAIN_APP_SELECTED_ENVIRONMENT:
+ return R.assoc('selectedEnvironment', {
+ _id: action.payload._id,
+ name: action.payload.name
+ }, state);
+
+ default:
+ return state;
+ }
+}
diff --git a/ui/imports/ui/reducers/navigation.js b/ui/imports/ui/reducers/navigation.js
new file mode 100644
index 0000000..de78ee5
--- /dev/null
+++ b/ui/imports/ui/reducers/navigation.js
@@ -0,0 +1,99 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+import * as R from 'ramda';
+
+import * as actions from '/imports/ui/actions/navigation';
+
+const defaultState = { current: [], lastActionable: [] };
+
+function reducer(state = defaultState, action) {
+ let lastActionable = null;
+
+ switch (action.type) {
+ case actions.SET_CURRENT_NODE:
+ lastActionable = isActionable(action.payload.nodeChain) ? action.payload.nodeChain :
+ state.lastActionable;
+
+ return R.merge(state, {
+ current: action.payload.nodeChain,
+ lastActionable: lastActionable
+ });
+
+ case actions.SET_CURRENT_NODE_FROM_TREE_CONTROL:
+ lastActionable = isActionable(action.payload.nodeChain) ? action.payload.nodeChain :
+ state.lastActionable;
+
+ if (contains(action.payload.nodeChain, state.current)) {
+ let equalLastIndex = findEqualLastIndex(action.payload.nodeChain, state.current);
+ return R.merge(state, {
+ current: R.slice(0, equalLastIndex, action.payload.nodeChain),
+ lastActionable: lastActionable
+ });
+ } else {
+ return R.merge(state, {
+ current: action.payload.nodeChain,
+ lastActionable: lastActionable
+ });
+ }
+
+ default:
+ return state;
+ }
+}
+
+function contains(subArray, array) {
+ let equalLastIndex = findEqualLastIndex(subArray, array);
+
+ if (subArray.length <= array.length &&
+ equalLastIndex >= 0 &&
+ subArray.length === equalLastIndex + 1) {
+
+ return true;
+ }
+
+ return false;
+}
+
+function findEqualLastIndex (arrayA, arrayB) {
+ let indexResult = -1;
+
+ for (let i = 0; (i < arrayA.length) && (i < arrayB.length); i++) {
+ if (equalsNodes(arrayA[i], arrayB[i])) {
+ indexResult = i;
+ } else {
+ break;
+ }
+ }
+
+ return indexResult;
+}
+
+function equalsNodes(nodeA, nodeB) {
+ if (nodeA.fullIdPath !== nodeB.fullIdPath) { return false; }
+ if (nodeA.fullNamePath !== nodeB.fullNamePath) { return false; }
+
+ return true;
+}
+
+function isActionable(nodeChain) {
+ let last = R.last(nodeChain);
+
+ if (R.isNil(last)) { return false; }
+ if (R.isNil(last.item)) { return false; }
+
+ if (! R.isNil(last.item.clique)) { return true; }
+
+ if (last.item.id === 'aggregate-WebEx-RTP-SSD-Aggregate-node-24') {
+ return true;
+ }
+
+ return false;
+}
+
+export const navigation = reducer;
diff --git a/ui/imports/ui/reducers/search-interested-parties.js b/ui/imports/ui/reducers/search-interested-parties.js
new file mode 100644
index 0000000..26220c2
--- /dev/null
+++ b/ui/imports/ui/reducers/search-interested-parties.js
@@ -0,0 +1,76 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+import * as R from 'ramda';
+
+import * as actions from '/imports/ui/actions/search-interested-parties';
+
+const defaultState = {
+ listeners: [],
+ searchTerm: null,
+ searchAutoCompleteTerm: null,
+ searchAutoCompleteFutureId: null
+};
+
+function reducer(state = defaultState, action) {
+ let newListeners;
+
+ switch (action.type) {
+ case actions.ADD_SEARCH_INTERESTED_PARTY:
+ newListeners = R.unionWith(
+ R.eqBy(R.prop('action')),
+ state.listeners,
+ [{ action: action.payload.listener }]);
+ return R.assoc('listeners', newListeners, state);
+
+ case actions.REMOVE_SEARCH_INTERESTED_PARTY:
+ newListeners = R.differenceWith(
+ R.eqBy(R.prop('action')),
+ state.listeners,
+ [{ action:action.payload.listener }]);
+ return R.assoc('listeners', newListeners, state);
+
+ case actions.SET_SEARCH_TERM:
+ asyncCall(() => {
+ notifyListeners(action.payload.searchTerm, state.listeners);
+ });
+ return R.assoc('searchTerm', action.payload.searchTerm, state);
+
+ case actions.SET_SEARCH_AUTO_COMPLETE_TERM:
+ return R.assoc('searchAutoCompleteTerm', action.payload.searchTerm, state);
+
+ case actions.RESET_SEARCH_AUTO_COMPLETE_FUTURE:
+ if (! R.isNil(state.searchAutoCompleteFutureId)) {
+ clearTimeout(state.searchAutoCompleteFutureId);
+ }
+ return R.assoc('searchAutoCompleteFutureId', null, state);
+
+ case actions.SET_SEARCH_AUTO_COMPLETE_FUTURE:
+ if (! R.isNil(state.searchAutoCompleteFutureId)) {
+ clearTimeout(state.searchAutoCompleteFutureId);
+ }
+ return R.assoc('searchAutoCompleteFutureId', action.payload.futureId, state);
+
+ default:
+ return state;
+ }
+}
+
+function asyncCall(fnObject) {
+ setTimeout(() => {
+ fnObject.call(null);
+ }, 0);
+}
+
+function notifyListeners(searchTerm, listeners) {
+ R.forEach((listenerItem) => {
+ listenerItem.action.call(null, searchTerm);
+ }, listeners);
+}
+
+export const searchInterestedParties = reducer;
diff --git a/ui/imports/ui/reducers/tree-node.reducer.js b/ui/imports/ui/reducers/tree-node.reducer.js
new file mode 100644
index 0000000..0a6ec73
--- /dev/null
+++ b/ui/imports/ui/reducers/tree-node.reducer.js
@@ -0,0 +1,232 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+//import { Mongo } from 'meteor/mongo';
+import * as R from 'ramda';
+
+import * as actions from '/imports/ui/actions/tree-node.actions';
+
+const defaultState = {
+ _id: null,
+ nodeInfo: {},
+ openState: 'closed', // opened, start_close, closed, start_open
+ children: [],
+ childDetected: false,
+ needChildDetection: true,
+ linkDetected: false,
+ level: 1,
+ positionNeeded: false,
+ position: null,
+ scrollToNodeIsNeeded: false
+};
+
+export function reducer(state = defaultState, action) {
+ let nodeId;
+ let rest;
+ //let child;
+ //let index;
+
+ if (R.isNil(action)) { return defaultState; }
+
+ switch (action.type) {
+
+ case actions.UPDATE_TREE_NODE_INFO:
+ return R.merge(state, {
+ _id: action.payload.nodeInfo._id._str,
+ nodeInfo: action.payload.nodeInfo,
+ openState: 'closed',
+ children: [],
+ childDetected: false,
+ needChildDetection: true,
+ linkDetected: R.propEq('type', 'host_ref', action.payload.nodeInfo),
+ level: action.payload.level,
+ });
+
+ case actions.ADD_UPDATE_CHILDREN_TREE_NODE:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ let actionChildren = R.map((childInfo) => {
+ let existingChild = R.find(
+ R.pathEq(['nodeInfo', '_id', '_str'], childInfo._id._str), state.children);
+
+ return reducer(existingChild,
+ actions.updateTreeNodeInfo(childInfo, action.payload.level + 1));
+ }, action.payload.childrenInfo);
+
+ let allChildren = R.unionWith(R.eqBy(R.path(['nodeInfo', '_id', '_str'])),
+ actionChildren, state.children);
+
+ /*
+ R.forEach((actionChild) => {
+ let index = R.findIndex(R.pathEq(['nodeInfo', '_id', '_str'], actionChild._id._str),state.children);
+ if (index < 0) {
+ state.children.push(actionChild);
+ } else {
+ state.children[index] = actionChild;
+ }
+ }, actionChildren);
+ let allChildren = state.children;
+ */
+
+ return R.merge(state, {
+ children: allChildren,
+ childDetected: R.length(allChildren) > 0
+ });
+
+ /*
+ state.childDetected = R.length(allChildren) > 0;
+ return state;
+ */
+ }
+
+ return reduceActionOnChild(state,
+ actions.addUpdateChildrenTreeNode(
+ rest, action.payload.childrenInfo, action.payload.level + 1),
+ nodeId);
+
+ case actions.RESET_TREE_NODE_CHILDREN:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.merge(state, {
+ children: [],
+ childDetected: false,
+ needChildDetection: true,
+ });
+ }
+
+ return reduceActionOnChild(state, actions.resetTreeNodeChildren(rest), nodeId);
+
+ case actions.START_OPEN_TREE_NODE:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.assoc('openState', 'start_open', state);
+ }
+
+ return reduceActionOnChild(state, actions.startOpenTreeNode(rest), nodeId);
+
+ case actions.END_OPEN_TREE_NODE:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.assoc('openState', 'opened', state);
+ }
+
+ return reduceActionOnChild(state, actions.endOpenTreeNode(rest), nodeId);
+
+ case actions.START_CLOSE_TREE_NODE:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.assoc('openState', 'start_close', state);
+ }
+
+ return reduceActionOnChild(state, actions.startCloseTreeNode(rest), nodeId);
+
+ case actions.END_CLOSE_TREE_NODE:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.assoc('openState', 'closed', state);
+ }
+
+ return reduceActionOnChild(state, actions.endCloseTreeNode(rest), nodeId);
+
+ case actions.SET_CHILD_DETECTED_TREE_NODE:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.assoc('childDetected', true, state);
+ }
+
+ return reduceActionOnChild(state, actions.setChildDetectedTreeNode(rest), nodeId);
+
+ case actions.SET_POSITION_REPORT_IS_NEEDED_AS_ON:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.assoc('positionNeeded', true, state);
+ }
+
+ return reduceActionOnChild(state, actions.setPositionReportIsNeededAsOn(rest), nodeId);
+
+ case actions.REPORT_NODE_POSITION_RETRIEVED:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.merge(state, {
+ position: {
+ top: action.payload.rect.top,
+ bottom: action.payload.rect.bottom,
+ height: action.payload.rect.height,
+ },
+ positionNeeded: false
+ });
+ }
+
+ return reduceActionOnChild(state,
+ actions.reportNodePositionRetrieved(rest, action.payload.rect), nodeId);
+
+ case actions.SET_SCROLL_TO_NODE_IS_NEEDED_AS_ON:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.assoc('scrollToNodeIsNeeded', true, state);
+ }
+
+ return reduceActionOnChild(state, actions.setScrollToNodeIsNeededAsOn(rest), nodeId);
+
+ case actions.REPORT_SCROLL_TO_NODE_PERFORMED:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.assoc('scrollToNodeIsNeeded', false, state);
+ }
+
+ return reduceActionOnChild(state, actions.reportScrollToNodePerformed(rest), nodeId);
+
+ case actions.RESET_NEED_CHILD_DETECTION:
+ nodeId = R.head(action.payload.nodePath);
+ rest = R.tail(action.payload.nodePath);
+
+ if (R.isNil(nodeId)) {
+ return R.assoc('needChildDetection', false, state);
+ }
+
+ return reduceActionOnChild(state, actions.resetNeedChildDetection(rest), nodeId);
+
+
+ default:
+ return state;
+ }
+}
+
+function reduceActionOnChild(state, action, nodeId) {
+ let index = R.findIndex(R.pathEq(['nodeInfo', '_id', '_str'], nodeId), state.children);
+ if (index < 0) throw 'error in reduce action on child';
+ let child = state.children[index];
+
+ return R.assoc('children',
+ R.update(index,
+ reducer(child, action),
+ state.children),
+ state);
+}
diff --git a/ui/imports/ui/reducers/vedge-info-window.reducer.js b/ui/imports/ui/reducers/vedge-info-window.reducer.js
new file mode 100644
index 0000000..d1be629
--- /dev/null
+++ b/ui/imports/ui/reducers/vedge-info-window.reducer.js
@@ -0,0 +1,50 @@
+/////////////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) and others /
+// /
+// All rights reserved. This program and the accompanying materials /
+// are made available under the terms of the Apache License, Version 2.0 /
+// which accompanies this distribution, and is available at /
+// http://www.apache.org/licenses/LICENSE-2.0 /
+/////////////////////////////////////////////////////////////////////////////////////////
+import * as R from 'ramda';
+
+import * as actions from '/imports/ui/actions/vedge-info-window.actions';
+
+const defaultState = {
+ node: null,
+ left: 0,
+ top: 0,
+ show: false
+};
+
+export function reducer(state = defaultState, action) {
+ let newState;
+
+ switch (action.type) {
+ case actions.ACTIVATE_VEDGE_INFO_WINDOW:
+ newState = R.merge(state, {
+ node: R.pick([
+ '_id',
+ 'id',
+ 'id_path',
+ 'name',
+ 'name_path',
+ 'environment'
+ ], action.payload.node),
+ left: action.payload.left,
+ top: action.payload.top - 28,
+ show: true
+ });
+ return newState;
+
+ case actions.CLOSE_VEDGE_INFO_WINDOW:
+ return R.merge(state, {
+ show: false,
+ top: 0,
+ left: 0
+ });
+
+ default:
+ return state;
+ }
+}