123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767 |
- /* eslint-disable import/no-webpack-loader-syntax, import/no-unresolved */
- import debug from 'debug';
- import 'moment/locale/zh-cn'
- moment.locale('zh-cn');
- import moment from 'moment';
- import {
- size, each, includes, isEqual
- } from 'lodash';
- import {
- fromJS,
- is as isDeepEqual,
- List as makeList,
- Map as makeMap,
- OrderedMap as makeOrderedMap,
- } from 'immutable';
- import ActionTypes from '../constants/action-types';
- import {
- GRAPH_VIEW_MODE,
- TABLE_VIEW_MODE,
- } from '../constants/naming';
- import {
- graphExceedsComplexityThreshSelector,
- isResourceViewModeSelector,
- } from '../selectors/topology';
- import { isPausedSelector } from '../selectors/time-travel';
- import { activeTopologyZoomCacheKeyPathSelector } from '../selectors/zooming';
- import { applyPinnedSearches } from '../utils/search-utils';
- import {
- findTopologyById,
- setTopologyUrlsById,
- updateTopologyIds,
- filterHiddenTopologies,
- addTopologyFullname,
- getDefaultTopology,
- } from '../utils/topology-utils';
- const log = debug('scope:app-store');
- const error = debug('scope:error');
- // Helpers
- const topologySorter = topology => topology.get('rank');
- // Initial values
- export const initialState = makeMap({
- capabilities: makeMap(),
- contrastMode: false,
- controlPipes: makeOrderedMap(), // pipeId -> controlPipe
- controlStatus: makeMap(),
- currentTopology: null,
- currentTopologyId: null,
- errorUrl: null,
- exportingGraph: false,
- forceRelayout: false,
- gridSortedBy: null,
- gridSortedDesc: null,
- hostname: '...',
- hoveredMetricType: null,
- initialNodesLoaded: false,
- mouseOverEdgeId: null,
- mouseOverNodeId: null,
- nodeDetails: makeOrderedMap(), // nodeId -> details
- nodes: makeOrderedMap(), // nodeId -> node
- // nodes cache, infrequently updated, used for search & resource view
- // topologyId -> nodes
- nodesByTopology: makeMap(),
- nodesLoaded: false,
- // class of metric, e.g. 'cpu', rather than 'host_cpu' or 'process_cpu'.
- // allows us to keep the same metric "type" selected when the topology changes.
- pausedAt: null,
- pinnedMetricType: null,
- pinnedNetwork: null,
- // list of node filters
- pinnedSearches: makeList(),
- plugins: makeList(),
- routeSet: false,
- searchFocused: false,
- searchQuery: '',
- selectedNetwork: null,
- selectedNodeId: null,
- showingHelp: false,
- showingNetworks: false,
- showingTroubleshootingMenu: false,
- storeViewState: true,
- timeTravelTransitioning: false,
- topologies: makeList(),
- topologiesLoaded: false,
- topologyOptions: makeOrderedMap(), // topologyId -> options
- topologyUrlsById: makeOrderedMap(), // topologyId -> topologyUrl
- topologyViewMode: GRAPH_VIEW_MODE,
- version: null,
- versionUpdate: null,
- // Set some initial numerical values to prevent NaN in case of edgy race conditions.
- viewport: makeMap({ height: 0, width: 0 }),
- websocketClosed: false,
- zoomCache: makeMap(),
- });
- function calcSelectType(topology) {
- const result = {
- ...topology,
- options: topology.options && topology.options.map((option) => {
- // Server doesn't return the `selectType` key unless the option is something other than `one`.
- // Default to `one` if undefined, so the component doesn't have to handle this.
- option.selectType = option.selectType || 'one';
- return option;
- })
- };
- if (topology.sub_topologies) {
- result.sub_topologies = topology.sub_topologies.map(calcSelectType);
- }
- return result;
- }
- // adds ID field to topology (based on last part of URL path) and save urls in
- // map for easy lookup
- function processTopologies(state, nextTopologies) {
- // add IDs to topology objects in-place
- const topologiesWithId = updateTopologyIds(nextTopologies);
- // filter out hidden topos
- const visibleTopologies = filterHiddenTopologies(topologiesWithId, state.get('currentTopology'));
- // set `selectType` field for topology and sub_topologies options (recursive).
- const topologiesWithSelectType = visibleTopologies.map(calcSelectType);
- // cache URLs by ID
- state = state.set(
- 'topologyUrlsById',
- setTopologyUrlsById(state.get('topologyUrlsById'), topologiesWithSelectType)
- );
- const topologiesWithFullnames = addTopologyFullname(topologiesWithSelectType);
- const immNextTopologies = fromJS(topologiesWithFullnames).sortBy(topologySorter);
- return state.set('topologies', immNextTopologies);
- }
- function setTopology(state, topologyId) {
- state = state.set('currentTopology', findTopologyById(state.get('topologies'), topologyId));
- return state.set('currentTopologyId', topologyId);
- }
- export function getDefaultTopologyOptions(state) {
- let topologyOptions = makeOrderedMap();
- state.get('topologies').forEach((topology) => {
- let defaultOptions = makeOrderedMap();
- if (topology.has('options') && topology.get('options')) {
- topology.get('options').forEach((option) => {
- const optionId = option.get('id');
- const defaultValue = option.get('defaultValue');
- defaultOptions = defaultOptions.set(optionId, [defaultValue]);
- });
- }
- if (defaultOptions.size) {
- topologyOptions = topologyOptions.set(topology.get('id'), defaultOptions);
- }
- });
- return topologyOptions;
- }
- function closeNodeDetails(state, nodeId) {
- const nodeDetails = state.get('nodeDetails');
- if (nodeDetails.size > 0) {
- const popNodeId = nodeId || nodeDetails.keySeq().last();
- // remove pipe if it belongs to the node being closed
- state = state.update(
- 'controlPipes',
- controlPipes => controlPipes.filter(pipe => pipe.get('nodeId') !== popNodeId)
- );
- state = state.deleteIn(['nodeDetails', popNodeId]);
- }
- if (state.get('nodeDetails').size === 0 || state.get('selectedNodeId') === nodeId) {
- state = state.set('selectedNodeId', null);
- }
- return state;
- }
- function closeAllNodeDetails(state) {
- while (state.get('nodeDetails').size) {
- state = closeNodeDetails(state);
- }
- return state;
- }
- function clearNodes(state) {
- return state
- .update('nodes', nodes => nodes.clear())
- .set('nodesLoaded', false);
- }
- // TODO: These state changes should probably be calculated from selectors.
- function updateStateFromNodes(state) {
- // Apply pinned searches, filters nodes that dont match.
- state = applyPinnedSearches(state);
- // In case node or edge disappears before mouseleave event.
- const nodesIds = state.get('nodes').keySeq();
- if (!nodesIds.contains(state.get('mouseOverNodeId'))) {
- state = state.set('mouseOverNodeId', null);
- }
- if (!nodesIds.some(nodeId => includes(state.get('mouseOverEdgeId'), nodeId))) {
- state = state.set('mouseOverEdgeId', null);
- }
- // Update the nodes cache only if we're not in the resource view mode, as we
- // intentionally want to keep it static before we figure how to keep it up-to-date.
- if (!isResourceViewModeSelector(state)) {
- const nodesForCurrentTopologyKey = ['nodesByTopology', state.get('currentTopologyId')];
- state = state.setIn(nodesForCurrentTopologyKey, state.get('nodes'));
- }
- // Clear the error.
- state = state.set('errorUrl', null);
- return state;
- }
- export function rootReducer(state = initialState, action) {
- if (!action.type) {
- error('Payload missing a type!', action);
- }
- switch (action.type) {
- case ActionTypes.BLUR_SEARCH: {
- return state.set('searchFocused', false);
- }
- case ActionTypes.FOCUS_SEARCH: {
- return state.set('searchFocused', true);
- }
- case ActionTypes.CHANGE_TOPOLOGY_OPTION: {
- // set option on parent topology
- const topology = findTopologyById(state.get('topologies'), action.topologyId);
- if (topology) {
- const topologyId = topology.get('parentId') || topology.get('id');
- const optionKey = ['topologyOptions', topologyId, action.option];
- const currentOption = state.getIn(optionKey);
- if (!isEqual(currentOption, action.value)) {
- state = clearNodes(state);
- }
- state = state.setIn(optionKey, action.value);
- }
- return state;
- }
- case ActionTypes.SET_VIEWPORT_DIMENSIONS: {
- return state.mergeIn(['viewport'], {
- height: action.height,
- width: action.width,
- });
- }
- case ActionTypes.SET_EXPORTING_GRAPH: {
- return state.set('exportingGraph', action.exporting);
- }
- case ActionTypes.SORT_ORDER_CHANGED: {
- return state.merge({
- gridSortedBy: action.sortedBy,
- gridSortedDesc: action.sortedDesc,
- });
- }
- case ActionTypes.SET_VIEW_MODE: {
- return state.set('topologyViewMode', action.viewMode);
- }
- case ActionTypes.CACHE_ZOOM_STATE: {
- return state.setIn(activeTopologyZoomCacheKeyPathSelector(state), action.zoomState);
- }
- case ActionTypes.CLEAR_CONTROL_ERROR: {
- return state.removeIn(['controlStatus', action.nodeId, 'error']);
- }
- case ActionTypes.CLICK_BACKGROUND: {
- if (state.get('showingHelp')) {
- state = state.set('showingHelp', false);
- }
- if (state.get('showingTroubleshootingMenu')) {
- state = state.set('showingTroubleshootingMenu', false);
- }
- return closeAllNodeDetails(state);
- }
- case ActionTypes.CLICK_CLOSE_DETAILS: {
- return closeNodeDetails(state, action.nodeId);
- }
- case ActionTypes.CLOSE_TERMINAL: {
- return state.update('controlPipes', controlPipes => controlPipes.clear());
- }
- case ActionTypes.CLICK_FORCE_RELAYOUT: {
- return state.set('forceRelayout', action.forceRelayout);
- }
- case ActionTypes.CLICK_NODE: {
- const prevSelectedNodeId = state.get('selectedNodeId');
- const prevDetailsStackSize = state.get('nodeDetails').size;
- // click on sibling closes all
- state = closeAllNodeDetails(state);
- state.set('nodeShape', action.origin)
- // select new node if it's not the same (in that case just delesect)
- if (prevDetailsStackSize > 1 || prevSelectedNodeId !== action.nodeId) {
- // dont set origin if a node was already selected, suppresses animation
- const origin = prevSelectedNodeId === null ? action.origin : null;
- state = state.setIn(
- ['nodeDetails', action.nodeId],
- {
- id: action.nodeId,
- label: action.label,
- shape:action.origin,
- origin,
- topologyId: action.topologyId || state.get('currentTopologyId'),
- }
- );
- state = state.set('selectedNodeId', action.nodeId);
- }
- return state;
- }
- case ActionTypes.CLICK_RELATIVE: {
- if (state.hasIn(['nodeDetails', action.nodeId])) {
- // bring to front
- const details = state.getIn(['nodeDetails', action.nodeId]);
- state = state.deleteIn(['nodeDetails', action.nodeId]);
- state = state.setIn(['nodeDetails', action.nodeId], details);
- } else {
- state = state.setIn(
- ['nodeDetails', action.nodeId],
- {
- id: action.nodeId,
- label: action.label,
- origin: action.origin,
- topologyId: action.topologyId
- }
- );
- }
- return state;
- }
- case ActionTypes.CLICK_SHOW_TOPOLOGY_FOR_NODE: {
- state = state.update(
- 'nodeDetails',
- nodeDetails => nodeDetails.filter((v, k) => k === action.nodeId)
- );
- state = state.update('controlPipes', controlPipes => controlPipes.clear());
- state = state.set('selectedNodeId', action.nodeId);
- if (action.topologyId !== state.get('currentTopologyId')) {
- state = setTopology(state, action.topologyId);
- state = clearNodes(state);
- }
- return state;
- }
- case ActionTypes.CLICK_TOPOLOGY: {
- state = closeAllNodeDetails(state);
- const currentTopologyId = state.get('currentTopologyId');
- if (action.topologyId !== currentTopologyId) {
- state = setTopology(state, action.topologyId);
- state = clearNodes(state);
- }
- return state;
- }
- //
- // time control
- //
- case ActionTypes.RESUME_TIME: {
- state = state.set('timeTravelTransitioning', true);
- return state.set('pausedAt', null);
- }
- case ActionTypes.PAUSE_TIME_AT_NOW: {
- state = state.set('timeTravelTransitioning', false);
- // return state.set('pausedAt', moment().utc().format());
- return state.set('pausedAt', moment().utcOffset(8).format())
- }
- case ActionTypes.JUMP_TO_TIME: {
- state = state.set('timeTravelTransitioning', true);
- return state.set('pausedAt', action.timestamp);
- }
- case ActionTypes.FINISH_TIME_TRAVEL_TRANSITION: {
- state = state.set('timeTravelTransitioning', false);
- return clearNodes(state);
- }
- //
- // websockets
- //
- case ActionTypes.OPEN_WEBSOCKET: {
- return state.set('websocketClosed', false);
- }
- case ActionTypes.CLOSE_WEBSOCKET: {
- return state.set('websocketClosed', true);
- }
- //
- // networks
- //
- case ActionTypes.SHOW_NETWORKS: {
- if (!action.visible) {
- state = state.set('selectedNetwork', null);
- state = state.set('pinnedNetwork', null);
- }
- return state.set('showingNetworks', action.visible);
- }
- case ActionTypes.SELECT_NETWORK: {
- return state.set('selectedNetwork', action.networkId);
- }
- case ActionTypes.PIN_NETWORK: {
- return state.merge({
- pinnedNetwork: action.networkId,
- selectedNetwork: action.networkId
- });
- }
- case ActionTypes.UNPIN_NETWORK: {
- return state.merge({
- pinnedNetwork: null,
- });
- }
- //
- // metrics
- //
- case ActionTypes.HOVER_METRIC: {
- return state.set('hoveredMetricType', action.metricType);
- }
- case ActionTypes.UNHOVER_METRIC: {
- return state.set('hoveredMetricType', null);
- }
- case ActionTypes.PIN_METRIC: {
- return state.set('pinnedMetricType', action.metricType);
- }
- case ActionTypes.UNPIN_METRIC: {
- return state.set('pinnedMetricType', null);
- }
- case ActionTypes.SHOW_HELP: {
- return state.set('showingHelp', true);
- }
- case ActionTypes.HIDE_HELP: {
- return state.set('showingHelp', false);
- }
- case ActionTypes.DESELECT_NODE: {
- return closeNodeDetails(state);
- }
- case ActionTypes.DO_CONTROL: {
- return state.setIn(['controlStatus', action.nodeId], makeMap({
- error: null,
- pending: true
- }));
- }
- case ActionTypes.ENTER_EDGE: {
- return state.set('mouseOverEdgeId', action.edgeId);
- }
- case ActionTypes.ENTER_NODE: {
- return state.set('mouseOverNodeId', action.nodeId);
- }
- case ActionTypes.LEAVE_EDGE: {
- return state.set('mouseOverEdgeId', null);
- }
- case ActionTypes.LEAVE_NODE: {
- return state.set('mouseOverNodeId', null);
- }
- case ActionTypes.DO_CONTROL_ERROR: {
- return state.setIn(['controlStatus', action.nodeId], makeMap({
- error: action.error,
- pending: false
- }));
- }
- case ActionTypes.DO_CONTROL_SUCCESS: {
- return state.setIn(['controlStatus', action.nodeId], makeMap({
- error: null,
- pending: false
- }));
- }
- case ActionTypes.UPDATE_SEARCH: {
- state = state.set('pinnedSearches', makeList(action.pinnedSearches));
- state = state.set('searchQuery', action.searchQuery || '');
- return applyPinnedSearches(state);
- }
- case ActionTypes.RECEIVE_CONTROL_NODE_REMOVED: {
- return closeNodeDetails(state, action.nodeId);
- }
- case ActionTypes.RECEIVE_CONTROL_PIPE: {
- return state.setIn(['controlPipes', action.pipeId], makeOrderedMap({
- control: action.control,
- id: action.pipeId,
- nodeId: action.nodeId,
- raw: action.rawTty,
- resizeTtyControl: action.resizeTtyControl
- }));
- }
- case ActionTypes.RECEIVE_CONTROL_PIPE_STATUS: {
- if (state.hasIn(['controlPipes', action.pipeId])) {
- state = state.setIn(['controlPipes', action.pipeId, 'status'], action.status);
- }
- return state;
- }
- case ActionTypes.RECEIVE_ERROR: {
- if (state.get('errorUrl') !== null) {
- state = state.set('errorUrl', action.errorUrl);
- }
- return state;
- }
- case ActionTypes.RECEIVE_NODE_DETAILS: {
- // Ignore the update if paused and the timestamp didn't change.
- const setTimestamp = state.getIn(['nodeDetails', action.details.id, 'timestamp']);
- if (isPausedSelector(state) && action.requestTimestamp === setTimestamp) {
- return state;
- }
- state = state.set('errorUrl', null);
- // disregard if node is not selected anymore
- if (state.hasIn(['nodeDetails', action.details.id])) {
- state = state.updateIn(['nodeDetails', action.details.id], obj => ({
- ...obj,
- details: action.details,
- notFound: false,
- timestamp: action.requestTimestamp,
- }));
- }
- return state;
- }
- case ActionTypes.SET_RECEIVED_NODES_DELTA: {
- // Turn on the table view if the graph is too complex, but skip
- // this block if the user has already loaded topologies once.
- if (!state.get('initialNodesLoaded') && !state.get('nodesLoaded')) {
- if (state.get('topologyViewMode') === GRAPH_VIEW_MODE) {
- state = graphExceedsComplexityThreshSelector(state)
- ? state.set('topologyViewMode', TABLE_VIEW_MODE) : state;
- }
- state = state.set('initialNodesLoaded', true);
- }
- return state.set('nodesLoaded', true);
- }
- case ActionTypes.RECEIVE_NODES_DELTA: {
- // Ignore periodic nodes updates after the first load when paused.
- if (state.get('nodesLoaded') && state.get('pausedAt')) {
- return state;
- }
- log(
- 'RECEIVE_NODES_DELTA',
- 'remove', size(action.delta.remove),
- 'update', size(action.delta.update),
- 'add', size(action.delta.add),
- 'reset', action.delta.reset
- );
- if (action.delta.reset) {
- state = state.set('nodes', makeMap());
- }
- // remove nodes that no longer exist
- each(action.delta.remove, (nodeId) => {
- state = state.deleteIn(['nodes', nodeId]);
- });
- // update existing nodes
- each(action.delta.update, (node) => {
- if (state.hasIn(['nodes', node.id])) {
- // TODO: Implement a manual deep update here, as it might bring a great benefit
- // to our nodes selectors (e.g. layout engine would be completely bypassed if the
- // adjacencies would stay the same but the metrics would get updated).
- state = state.setIn(['nodes', node.id], fromJS(node));
- }
- });
- // add new nodes
- each(action.delta.add, (node) => {
- state = state.setIn(['nodes', node.id], fromJS(node));
- });
- return updateStateFromNodes(state);
- }
- case ActionTypes.RECEIVE_NODES: {
- state = state.set('timeTravelTransitioning', false);
- state = state.set('nodes', fromJS(action.nodes));
- state = state.set('nodesLoaded', true);
- return updateStateFromNodes(state);
- }
- case ActionTypes.RECEIVE_NODES_FOR_TOPOLOGY: {
- return state.setIn(['nodesByTopology', action.topologyId], fromJS(action.nodes));
- }
- case ActionTypes.RECEIVE_NOT_FOUND: {
- if (state.hasIn(['nodeDetails', action.nodeId])) {
- state = state.updateIn(['nodeDetails', action.nodeId], obj => ({
- ...obj,
- notFound: true,
- timestamp: action.requestTimestamp,
- }));
- }
- return state;
- }
- case ActionTypes.RECEIVE_TOPOLOGIES: {
- state = state.set('errorUrl', null);
- state = state.update('topologyUrlsById', topologyUrlsById => topologyUrlsById.clear());
- state = processTopologies(state, action.topologies);
- const currentTopologyId = state.get('currentTopologyId');
- if (!currentTopologyId || !findTopologyById(state.get('topologies'), currentTopologyId)) {
- state = state.set('currentTopologyId', getDefaultTopology(state.get('topologies')));
- log(`Set currentTopologyId to ${state.get('currentTopologyId')}`);
- }
- state = setTopology(state, state.get('currentTopologyId'));
- // Expand topology options with topologies' defaults on first load, but let
- // the current state of topologyOptions (which at this point reflects the
- // URL state) still take the precedence over defaults.
- if (!state.get('topologiesLoaded')) {
- const options = getDefaultTopologyOptions(state).mergeDeep(state.get('topologyOptions'));
- state = state.set('topologyOptions', options);
- state = state.set('topologiesLoaded', true);
- }
- return state;
- }
- case ActionTypes.RECEIVE_API_DETAILS: {
- state = state.set('errorUrl', null);
- return state.merge({
- capabilities: action.capabilities,
- hostname: action.hostname,
- plugins: action.plugins,
- version: action.version,
- versionUpdate: action.newVersion,
- });
- }
- case ActionTypes.ROUTE_TOPOLOGY: {
- state = state.set('routeSet', true);
- state = state.set('pinnedSearches', makeList(action.state.pinnedSearches));
- state = state.set('searchQuery', action.state.searchQuery || '');
- if (state.get('currentTopologyId') !== action.state.topologyId) {
- state = clearNodes(state);
- }
- state = setTopology(state, action.state.topologyId);
- state = state.merge({
- pinnedMetricType: action.state.pinnedMetricType,
- selectedNodeId: action.state.selectedNodeId,
- });
- if (action.state.topologyOptions) {
- const options = getDefaultTopologyOptions(state).mergeDeep(action.state.topologyOptions);
- state = state.set('topologyOptions', options);
- }
- if (action.state.topologyViewMode) {
- state = state.set('topologyViewMode', action.state.topologyViewMode);
- }
- if (action.state.gridSortedBy) {
- state = state.set('gridSortedBy', action.state.gridSortedBy);
- }
- if (action.state.gridSortedDesc !== undefined) {
- state = state.set('gridSortedDesc', action.state.gridSortedDesc);
- }
- if (action.state.contrastMode !== undefined) {
- state = state.set('contrastMode', action.state.contrastMode);
- }
- if (action.state.showingNetworks) {
- state = state.set('showingNetworks', action.state.showingNetworks);
- }
- if (action.state.pinnedNetwork) {
- state = state.set('pinnedNetwork', action.state.pinnedNetwork);
- state = state.set('selectedNetwork', action.state.pinnedNetwork);
- }
- if (action.state.controlPipe) {
- state = state.set('controlPipes', makeOrderedMap({
- [action.state.controlPipe.id]:
- makeOrderedMap(action.state.controlPipe)
- }));
- } else {
- state = state.update('controlPipes', controlPipes => controlPipes.clear());
- }
- if (action.state.nodeDetails) {
- const actionNodeDetails = makeOrderedMap(action.state.nodeDetails.map(h => [h.id, h]));
- // check if detail IDs have changed
- if (!isDeepEqual(state.get('nodeDetails').keySeq(), actionNodeDetails.keySeq())) {
- state = state.set('nodeDetails', actionNodeDetails);
- }
- } else {
- state = state.update('nodeDetails', nodeDetails => nodeDetails.clear());
- }
- return state;
- }
- case ActionTypes.DEBUG_TOOLBAR_INTERFERING: {
- return action.fn(state);
- }
- case ActionTypes.TOGGLE_TROUBLESHOOTING_MENU: {
- return state.set('showingTroubleshootingMenu', !state.get('showingTroubleshootingMenu'));
- }
- case ActionTypes.CHANGE_INSTANCE: {
- state = closeAllNodeDetails(state);
- return state;
- }
- case ActionTypes.TOGGLE_CONTRAST_MODE: {
- return state.set('contrastMode', action.enabled);
- }
- case ActionTypes.SHUTDOWN: {
- return clearNodes(state);
- }
- case ActionTypes.MONITOR_STATE: {
- return state.set('monitor', action.monitor);
- }
- case ActionTypes.SET_STORE_VIEW_STATE: {
- return state.set('storeViewState', action.storeViewState);
- }
- default: {
- return state;
- }
- }
- }
- export default rootReducer;
|