Home Reference Source

src/reducers/hosts.js

import * as types from '../actions/types';

export const getMonitorByHost = (state, host) => state[host] ? state[host].monitor : null;
export const getHostsArray = state => Object.values(state).map(h => ({ ...h, metrics: Object.values(h.metrics) }));

export const getMetricsAll = state => Array.from(Object.values(state).reduce((set, h) => {
    Object.keys(h.metrics).forEach(m => set.add(m));
    return set;
}, new Set()));

export const getMetrics = state => {
    const built = {};
    for (const host of Object.values(state)) {
        for (const metric of Object.values(host.metrics)) {
            if (!built[metric.id]) {
                built[metric.id] = {};
            }
            built[metric.id][host.hostname] = metric;
        }
    }
    return built;
};

const extractHosts = (state, monitor) => Object.entries(state)
    .reduce(
        (c, [ key, obj ]) => {
            const type = obj.monitor === monitor ? 'found' : 'rest';
            return {
                ...c,
                [type]: {
                    ...c[type],
                    [key]: obj
                }
            };
        },
        {
            found: {},
            rest: {}
        }
    );

const setMonitor = (state, monitor) => Object.entries(state)
    .map(([ key, obj ]) => [ key, { ...obj, monitor } ])
    .reduce((c, [ key, obj ]) => ({ ...c, [key]: obj }), {});

const convertMetric = state => {
    const { hosts, ...rest } = state; // eslint-disable-line no-unused-vars
    return rest;
};

const normalize = state => state.reduce((c, obj) => ({
    ...c,
    [obj.hostname]: {
        ...obj,
        metrics: obj.metrics.reduce((d, metric) => ({
            ...d,
            [metric.id]: convertMetric(metric)
        }), {}),
        metricsInvalidated: false
    }
}), {});

const host = (state, action) => {
    switch (action.type) {
        case types.ADD_COMPLEX_METRIC_REQUEST:
        case types.REMOVE_COMPLEX_METRIC_REQUEST:
            return {
                ...state,
                metricsInvalidated: true
            };
        case types.ADD_COMPLEX_METRIC_SUCCESS:
            return {
                ...state,
                metricsInvalidated: false,
                metrics: {
                    ...state.metrics,
                    [action.payload.id]: {
                        ...action.payload,
                        removable: true
                    }
                }
            };
        case types.ADD_COMPLEX_METRIC_FAILURE:
        case types.REMOVE_COMPLEX_METRIC_FAILURE:
            return {
                ...state,
                metricsInvalidated: false
            };
        case types.REMOVE_COMPLEX_METRIC_SUCCESS: {
            const {
                [action.meta.id]: metricToRemove, // eslint-disable-line no-unused-vars
                ...metricsToLeave
            } = state.metrics;
            return {
                ...state,
                metricsInvalidated: false,
                metrics: metricsToLeave
            };
        }
        default:
            return state;
    }
};

export default (state = {}, action) => {
    switch (action.type) {
        case types.GET_HOSTS_SUCCESS:
            return {
                ...extractHosts(state, action.meta.monitor).rest,
                ...setMonitor(normalize(action.payload), action.meta.monitor)
            };
        case types.SET_MONITOR_ADDRESS: {
            const hostsExtracted = extractHosts(state, action.meta.monitor);
            return {
                ...hostsExtracted.rest,
                ...setMonitor(hostsExtracted.found, action.payload.address)
            };
        }
        case types.REMOVE_MONITOR:
            return extractHosts(state, action.meta.monitor).rest;
        case types.REMOVE_TOKEN:
            return {};
        case types.ADD_COMPLEX_METRIC_REQUEST:
        case types.ADD_COMPLEX_METRIC_SUCCESS:
        case types.ADD_COMPLEX_METRIC_FAILURE:
        case types.REMOVE_COMPLEX_METRIC_REQUEST:
        case types.REMOVE_COMPLEX_METRIC_SUCCESS:
        case types.REMOVE_COMPLEX_METRIC_FAILURE: {
            const { [action.meta.host]: target, ...rest } = state;
            return {
                ...rest,
                [action.meta.host]: host(target, action)
            };
        }
        default:
            return state;
    }
};