<commit_before>import _ from 'lodash';
import { LAYER_TYPES } from 'constants';
import {
  SET_LAYERS,
  SET_LAYER_HEADER,
  TOGGLE_LAYER_VISIBILITY,
  TOGGLE_LAYER_WORKSPACE_PRESENCE,
  SET_LAYER_OPACITY,
  SET_LAYER_HUE,
  SET_MAX_ZOOM,
  SET_OVERALL_TIMELINE_DATES,
  ADD_CUSTOM_LAYER,
  TOGGLE_LAYER_PANEL_EDIT_MODE,
  SET_WORKSPACE_LAYER_LABEL,
  SHOW_CONFIRM_LAYER_REMOVAL_MESSAGE
} from 'actions';
import { refreshFlagFiltersLayers } from 'actions/filters';
import { initHeatmapLayers, addHeatmapLayerFromLibrary, removeHeatmapLayerFromLibrary, loadAllTilesForLayer } from 'actions/heatmap';

function loadLayerHeader(tilesetUrl, token) {
  const headers = {
    'Content-Type': 'application/json',
    Accept: 'application/json'
  };

  if (token) {
    headers.Authorization = `Bearer ${token}`;
  }

  return new Promise((resolve) => {
    fetch(`${tilesetUrl}/header`, {
      method: 'GET',
      headers
    })
    .then((res) => {
      if (res.status >= 400) {
        console.warn(`loading of layer failed ${tilesetUrl}`);
        Promise.reject();
        return null;
      }
      return res.json();
    })
    .then((data) => {
      resolve(data);
    }).catch((err) => {
      console.warn(err);
    });
  });
}

function setGlobalFiltersFromHeader(data) {
  return (dispatch) => {
    if (data.maxZoom !== undefined) {
      dispatch({
        type: SET_MAX_ZOOM,
        payload: data.maxZoom
      });
    }

    if (!!data.colsByName && !!data.colsByName.datetime && !!data.colsByName.datetime.max && !!data.colsByName.datetime.min) {
      dispatch({
        type: SET_OVERALL_TIMELINE_DATES,
        payload: [new Date(data.colsByName.datetime.min), new Date(data.colsByName.datetime.max)]
      });
    }
  };
}

function setLayerHeader(layerId, header) {
  return (dispatch) => {
    dispatch({
      type: SET_LAYER_HEADER,
      payload: {
        layerId,
        header
      }
    });
  };
}

export function initLayers(workspaceLayers, libraryLayers) {
  return (dispatch, getState) => {
    const state = getState();
    if (state.user.userPermissions !== null && state.user.userPermissions.indexOf('seeVesselsLayers') === -1) {
      workspaceLayers = workspaceLayers.filter(l => l.type !== LAYER_TYPES.Heatmap);
      libraryLayers = libraryLayers.filter(l => l.type !== LAYER_TYPES.Heatmap);
    }

    workspaceLayers.forEach((layer) => {
      layer.label = layer.label || layer.title;
      layer.added = true;
      layer.library = false;
    });

    libraryLayers.forEach((libraryLayer) => {
      const matchedWorkspaceLayer = _.find(workspaceLayers, workspaceLayer => libraryLayer.id === workspaceLayer.id);
      if (matchedWorkspaceLayer) {
        Object.assign(matchedWorkspaceLayer, {
          library: true,
          added: true,
          description: libraryLayer.description || matchedWorkspaceLayer.description,
          reportId: libraryLayer.reportId
        });
        if (matchedWorkspaceLayer.type === LAYER_TYPES.Heatmap) {
          matchedWorkspaceLayer.url = libraryLayer.url || matchedWorkspaceLayer.url;
        }
      } else {
        workspaceLayers.push(Object.assign(libraryLayer, { added: false }));
      }
    });

    // parses opacity attribute
    workspaceLayers.forEach((layer) => {
      const l = layer;
      if (!!layer.opacity) {
        l.opacity = parseFloat(layer.opacity);
      } else {
        l.opacity = 1;
      }
    });

    const headersPromises = [];
    workspaceLayers
      .filter(l => l.type === LAYER_TYPES.Heatmap && l.added === true)
      .forEach((heatmapLayer) => {
        const headerPromise = loadLayerHeader(heatmapLayer.url, getState().user.token);
        headerPromise.then((header) => {
          if (header !== null) {
            heatmapLayer.header = header;
            dispatch(setGlobalFiltersFromHeader(header));
          }
        });
        headersPromises.push(headerPromise);
      });

    const headersPromise = Promise.all(headersPromises.map(p => p.catch(e => e)));
    headersPromise
    .then(() => {
      dispatch({
        type: SET_LAYERS,
        payload: workspaceLayers.filter(layer => layer.type !== LAYER_TYPES.Heatmap || layer.header !== undefined)
      });
      dispatch(initHeatmapLayers());
      dispatch(refreshFlagFiltersLayers());
    }).catch((err) => {
      console.warn(err);
    });

    return headersPromise;
  };
}

export function toggleLayerVisibility(layerId, forceStatus = null) {
  return (dispatch, getState) => {
    const layer = getState().layers.workspaceLayers.find(l => l.id === layerId);
    const visibility = (forceStatus !== null) ? forceStatus : !layer.visible;
    dispatch({
      type: TOGGLE_LAYER_VISIBILITY,
      payload: {
        layerId,
        visibility
      }
    });

    if (visibility === true) {
      // TODO clean tile first, if zoom has changed
      dispatch(loadAllTilesForLayer(layerId));
    }
  };
}

export function toggleLayerWorkspacePresence(layerId, forceStatus = null) {
  return (dispatch, getState) => {
    const newLayer = getState().layers.workspaceLayers.find(layer => layer.id === layerId);
    const added = (forceStatus !== null) ? forceStatus : !newLayer.added;
    dispatch({
      type: TOGGLE_LAYER_WORKSPACE_PRESENCE,
      payload: {
        layerId,
        added
      }
    });
    if (newLayer.type === LAYER_TYPES.Heatmap) {
      if (added === true) {
        const url = newLayer.url;

        if (newLayer.header === undefined) {
          loadLayerHeader(url, getState().user.token).then((header) => {
            if (header) {
              dispatch(setLayerHeader(layerId, header));
              dispatch(addHeatmapLayerFromLibrary(layerId, url));
              dispatch(setGlobalFiltersFromHeader(header));
              dispatch(refreshFlagFiltersLayers());
            }
          });
        } else {
          dispatch(addHeatmapLayerFromLibrary(layerId, url));
          dispatch(refreshFlagFiltersLayers());
        }
      } else {
        dispatch(removeHeatmapLayerFromLibrary(layerId));
        dispatch(refreshFlagFiltersLayers());
      }
    }
  };
}

export function setLayerOpacity(opacity, layerId) {
  return {
    type: SET_LAYER_OPACITY,
    payload: {
      layerId,
      opacity
    }
  };
}

export function setLayerHue(hue, layerId) {
  return (dispatch) => {
    dispatch({
      type: SET_LAYER_HUE,
      payload: {
        layerId,
        hue
      }
    });
    // TODO we might want to override all filters hue settings here (see with Dani)
    dispatch(refreshFlagFiltersLayers());
  };
}

export function addCustomLayer(id, url, name, description) {
  return {
    type: ADD_CUSTOM_LAYER,
    payload: {
      id,
      url,
      name,
      description
    }
  };
}

export function toggleLayerPanelEditMode(forceMode = null) {
  return {
    type: TOGGLE_LAYER_PANEL_EDIT_MODE,
    payload: {
      forceMode
    }
  };
}

export function setLayerLabel(layerId, label) {
  return {
    type: SET_WORKSPACE_LAYER_LABEL,
    payload: {
      layerId, label
    }
  };
}

export function confirmLayerRemoval(layerId) {
  return {
    type: SHOW_CONFIRM_LAYER_REMOVAL_MESSAGE,
    payload: layerId
  };
}
<commit_msg>Remove unrelated code<commit_after>import _ from 'lodash';
import { LAYER_TYPES } from 'constants';
import {
  SET_LAYERS,
  SET_LAYER_HEADER,
  TOGGLE_LAYER_VISIBILITY,
  TOGGLE_LAYER_WORKSPACE_PRESENCE,
  SET_LAYER_OPACITY,
  SET_LAYER_HUE,
  SET_MAX_ZOOM,
  SET_OVERALL_TIMELINE_DATES,
  ADD_CUSTOM_LAYER,
  TOGGLE_LAYER_PANEL_EDIT_MODE,
  SET_WORKSPACE_LAYER_LABEL,
  SHOW_CONFIRM_LAYER_REMOVAL_MESSAGE
} from 'actions';
import { refreshFlagFiltersLayers } from 'actions/filters';
import { initHeatmapLayers, addHeatmapLayerFromLibrary, removeHeatmapLayerFromLibrary, loadAllTilesForLayer } from 'actions/heatmap';

function loadLayerHeader(tilesetUrl, token) {
  const headers = {
    'Content-Type': 'application/json',
    Accept: 'application/json'
  };

  if (token) {
    headers.Authorization = `Bearer ${token}`;
  }

  return new Promise((resolve) => {
    fetch(`${tilesetUrl}/header`, {
      method: 'GET',
      headers
    })
    .then((res) => {
      if (res.status >= 400) {
        console.warn(`loading of layer failed ${tilesetUrl}`);
        Promise.reject();
        return null;
      }
      return res.json();
    })
    .then((data) => {
      resolve(data);
    }).catch((err) => {
      console.warn(err);
    });
  });
}

function setGlobalFiltersFromHeader(data) {
  return (dispatch) => {
    if (data.maxZoom !== undefined) {
      dispatch({
        type: SET_MAX_ZOOM,
        payload: data.maxZoom
      });
    }

    if (!!data.colsByName && !!data.colsByName.datetime && !!data.colsByName.datetime.max && !!data.colsByName.datetime.min) {
      dispatch({
        type: SET_OVERALL_TIMELINE_DATES,
        payload: [new Date(data.colsByName.datetime.min), new Date(data.colsByName.datetime.max)]
      });
    }
  };
}

function setLayerHeader(layerId, header) {
  return (dispatch) => {
    dispatch({
      type: SET_LAYER_HEADER,
      payload: {
        layerId,
        header
      }
    });
  };
}

export function initLayers(workspaceLayers, libraryLayers) {
  return (dispatch, getState) => {
    const state = getState();
    if (state.user.userPermissions !== null && state.user.userPermissions.indexOf('seeVesselsLayers') === -1) {
      workspaceLayers = workspaceLayers.filter(l => l.type !== LAYER_TYPES.Heatmap);
      libraryLayers = libraryLayers.filter(l => l.type !== LAYER_TYPES.Heatmap);
    }

    workspaceLayers.forEach((layer) => {
      layer.label = layer.label || layer.title;
      layer.added = true;
      layer.library = false;
    });

    libraryLayers.forEach((libraryLayer) => {
      const matchedWorkspaceLayer = _.find(workspaceLayers, workspaceLayer => libraryLayer.id === workspaceLayer.id);
      if (matchedWorkspaceLayer) {
        Object.assign(matchedWorkspaceLayer, {
          library: true,
          added: true,
          description: libraryLayer.description || matchedWorkspaceLayer.description,
          reportId: libraryLayer.reportId
        });
      } else {
        workspaceLayers.push(Object.assign(libraryLayer, { added: false }));
      }
    });

    // parses opacity attribute
    workspaceLayers.forEach((layer) => {
      const l = layer;
      if (!!layer.opacity) {
        l.opacity = parseFloat(layer.opacity);
      } else {
        l.opacity = 1;
      }
    });

    const headersPromises = [];
    workspaceLayers
      .filter(l => l.type === LAYER_TYPES.Heatmap && l.added === true)
      .forEach((heatmapLayer) => {
        const headerPromise = loadLayerHeader(heatmapLayer.url, getState().user.token);
        headerPromise.then((header) => {
          if (header !== null) {
            heatmapLayer.header = header;
            dispatch(setGlobalFiltersFromHeader(header));
          }
        });
        headersPromises.push(headerPromise);
      });

    const headersPromise = Promise.all(headersPromises.map(p => p.catch(e => e)));
    headersPromise
    .then(() => {
      dispatch({
        type: SET_LAYERS,
        payload: workspaceLayers.filter(layer => layer.type !== LAYER_TYPES.Heatmap || layer.header !== undefined)
      });
      dispatch(initHeatmapLayers());
      dispatch(refreshFlagFiltersLayers());
    }).catch((err) => {
      console.warn(err);
    });

    return headersPromise;
  };
}

export function toggleLayerVisibility(layerId, forceStatus = null) {
  return (dispatch, getState) => {
    const layer = getState().layers.workspaceLayers.find(l => l.id === layerId);
    const visibility = (forceStatus !== null) ? forceStatus : !layer.visible;
    dispatch({
      type: TOGGLE_LAYER_VISIBILITY,
      payload: {
        layerId,
        visibility
      }
    });

    if (visibility === true) {
      // TODO clean tile first, if zoom has changed
      dispatch(loadAllTilesForLayer(layerId));
    }
  };
}

export function toggleLayerWorkspacePresence(layerId, forceStatus = null) {
  return (dispatch, getState) => {
    const newLayer = getState().layers.workspaceLayers.find(layer => layer.id === layerId);
    const added = (forceStatus !== null) ? forceStatus : !newLayer.added;
    dispatch({
      type: TOGGLE_LAYER_WORKSPACE_PRESENCE,
      payload: {
        layerId,
        added
      }
    });
    if (newLayer.type === LAYER_TYPES.Heatmap) {
      if (added === true) {
        const url = newLayer.url;

        if (newLayer.header === undefined) {
          loadLayerHeader(url, getState().user.token).then((header) => {
            if (header) {
              dispatch(setLayerHeader(layerId, header));
              dispatch(addHeatmapLayerFromLibrary(layerId, url));
              dispatch(setGlobalFiltersFromHeader(header));
              dispatch(refreshFlagFiltersLayers());
            }
          });
        } else {
          dispatch(addHeatmapLayerFromLibrary(layerId, url));
          dispatch(refreshFlagFiltersLayers());
        }
      } else {
        dispatch(removeHeatmapLayerFromLibrary(layerId));
        dispatch(refreshFlagFiltersLayers());
      }
    }
  };
}

export function setLayerOpacity(opacity, layerId) {
  return {
    type: SET_LAYER_OPACITY,
    payload: {
      layerId,
      opacity
    }
  };
}

export function setLayerHue(hue, layerId) {
  return (dispatch) => {
    dispatch({
      type: SET_LAYER_HUE,
      payload: {
        layerId,
        hue
      }
    });
    // TODO we might want to override all filters hue settings here (see with Dani)
    dispatch(refreshFlagFiltersLayers());
  };
}

export function addCustomLayer(id, url, name, description) {
  return {
    type: ADD_CUSTOM_LAYER,
    payload: {
      id,
      url,
      name,
      description
    }
  };
}

export function toggleLayerPanelEditMode(forceMode = null) {
  return {
    type: TOGGLE_LAYER_PANEL_EDIT_MODE,
    payload: {
      forceMode
    }
  };
}

export function setLayerLabel(layerId, label) {
  return {
    type: SET_WORKSPACE_LAYER_LABEL,
    payload: {
      layerId, label
    }
  };
}

export function confirmLayerRemoval(layerId) {
  return {
    type: SHOW_CONFIRM_LAYER_REMOVAL_MESSAGE,
    payload: layerId
  };
}
<|endoftext|>


<commit_before>/* See license.txt for terms of usage */
/*jshint esnext:true, es5:true, curly:false */
/*global FBTrace:true, XPCNativeWrapper:true, Window:true, define:true */

define([
    "firebug/firebug",
    "firebug/lib/trace",
    "firebug/lib/object",
    "firebug/lib/events",
    "firebug/lib/dom",
    "firebug/lib/css",
    "firebug/lib/search",
    "firebug/chrome/reps",
    "firebug/dom/domBasePanel",
    "firebug/dom/domModule",
],
function(Firebug, FBTrace, Obj, Events, Dom, Css, Search, FirebugReps, DOMBasePanel, DOMModule) {

// ********************************************************************************************* //
// Constants

var Trace = FBTrace.to("DBG_DOM");
var TraceError = FBTrace.to("DBG_ERRORS");

// ********************************************************************************************* //
// DOM Panel

/**
 * @panel This object represents a DOM panel in the main Firebug UI.
 */
function DOMPanel()
{
}

DOMPanel.DirTable = DOMBasePanel.prototype.dirTablePlate;
DOMPanel.prototype = Obj.extend(DOMBasePanel.prototype,
/** @lends DOMPanel */
{
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // extends Panel

    name: "dom",
    searchable: true,
    statusSeparator: ">",
    enableA11y: true,
    deriveA11yFrom: "console",
    searchType : "dom",
    order: 50,
    inspectable: true,

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Initialization

    initialize: function()
    {
        this.onClick = Obj.bind(this.onClick, this);

        DOMModule.addListener(this);

        DOMBasePanel.prototype.initialize.apply(this, arguments);
    },

    destroy: function(state)
    {
        DOMModule.removeListener(this);

        Panel.destroy.apply(this, arguments);
    },

    initializeNode: function(oldPanelNode)
    {
        Events.addEventListener(this.panelNode, "click", this.onClick, false);

        DOMBasePanel.prototype.initializeNode.apply(this, arguments);
    },

    destroyNode: function()
    {
        Events.removeEventListener(this.panelNode, "click", this.onClick, false);

        DOMBasePanel.prototype.destroyNode.apply(this, arguments);
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Search

    search: function(text, reverse)
    {
        if (!text)
        {
            delete this.currentSearch;
            this.highlightNode(null);
            this.document.defaultView.getSelection().removeAllRanges();
            return false;
        }

        var row;
        if (this.currentSearch && text === this.currentSearch.text)
        {
            // xxxsz: 'Firebug.Search' is used here instead of 'Search' because we need to refer to
            // 'firebug/chrome/searchBox' and not to 'firebug/lib/search'
            // TODO: Rework 'searchBox.js', so it doesn't inject itself into the global 'Firebug'
            // scope anymore
            row = this.currentSearch.findNext(true, undefined, reverse,
                Firebug.Search.isCaseSensitive(text));
        }
        else
        {
            var findRow = function(node)
            {
                return Dom.getAncestorByClass(node, "memberRow");
            };

            this.currentSearch = new Search.TextSearch(this.panelNode, findRow);

            // xxxsz: 'Firebug.Search' is used here instead of 'Search' because we need to refer to
            // 'firebug/chrome/searchBox' and not to 'firebug/lib/search'
            row = this.currentSearch.find(text, reverse, Firebug.Search.isCaseSensitive(text));
        }

        if (row)
        {
            var sel = this.document.defaultView.getSelection();
            sel.removeAllRanges();
            sel.addRange(this.currentSearch.range);

            Dom.scrollIntoCenterView(row, this.panelNode);

            this.highlightNode(row);
            Events.dispatch(this.fbListeners, "onDomSearchMatchFound", [this, text, row]);
            return true;
        }
        else
        {
            this.document.defaultView.getSelection().removeAllRanges();
            Events.dispatch(this.fbListeners, "onDomSearchMatchFound", [this, text, null]);
            return false;
        }
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

    selectRow: function(row, target)
    {
        if (!target)
            target = row.lastChild.firstChild;

        var object = target && target.repObject, type = typeof object;
        if (!object || !this.supportsObject(object, type))
            return;

        this.pathToAppend = DOMBasePanel.getPath(row);

        // If the object is inside an array, look up its index
        var valueBox = row.lastChild.firstChild;
        if (Css.hasClass(valueBox, "objectBox-array"))
        {
            var arrayIndex = FirebugReps.Arr.getItemIndex(target);
            this.pathToAppend.push(arrayIndex);
        }

        // Make sure we get a fresh status path for the object, since otherwise
        // it might find the object in the existing path and not refresh it
        Firebug.chrome.clearStatusPath();

        this.select(object, true);
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

    onClick: function(event)
    {
        var repNode = Firebug.getRepNode(event.target);
        if (repNode)
        {
            var row = Dom.getAncestorByClass(event.target, "memberRow");
            if (row)
            {
                this.selectRow(row, repNode);
                Events.cancelEvent(event);
            }
        }
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Breakpoints, DOMModule Listener

    onDomBreakpointAdded: function(context, object, name)
    {
        Trace.sysout("domBasePanel.onDomBreakpointAdded; propName: " + name +
            " (panel: " + this.name + ")", object);

        this.updateBreakpoints(object);
    },

    onDomBreakpointRemoved: function(context, object, name)
    {
        Trace.sysout("domBasePanel.onDomBreakpointRemoved; propName: " + name +
            " (panel: " + this.name + ")", object);

        this.updateBreakpoints(object);
    },

    updateBreakpoints: function(object)
    {
        // xxxHonza: the update should be smarter if possible. Can we just lookup
        // for the specific object and update the row directly?
        // Can we utilize DomTree widget?

        var breakpoints = this.context.dom.breakpoints;
        var rows = Dom.getElementsByClass(this.panelNode, "memberRow");
        for (var i = 0; i < rows.length; i++)
        {
            var row = rows[i];
            var member = row.domObject;

            var bp = breakpoints.findBreakpoint(member.object, member.name);
            if (bp)
            {
                row.setAttribute("breakpoint", "true");

                if (!bp.checked)
                    row.setAttribute("disabledBreakpoint", "true");
            }
            else
            {
                row.removeAttribute("breakpoint");
                row.removeAttribute("disabledBreakpoint");
            }
        }

        return null;
    },
});

// ********************************************************************************************* //
// Registration

Firebug.registerPanel(DOMPanel);

// xxxHonza: backward compatibility
Firebug.DOMPanel = DOMPanel;

return DOMPanel;

// ********************************************************************************************* //
});
<commit_msg>Use the right super object<commit_after>/* See license.txt for terms of usage */
/*jshint esnext:true, es5:true, curly:false */
/*global FBTrace:true, XPCNativeWrapper:true, Window:true, define:true */

define([
    "firebug/firebug",
    "firebug/lib/trace",
    "firebug/lib/object",
    "firebug/lib/events",
    "firebug/lib/dom",
    "firebug/lib/css",
    "firebug/lib/search",
    "firebug/chrome/reps",
    "firebug/dom/domBasePanel",
    "firebug/dom/domModule",
],
function(Firebug, FBTrace, Obj, Events, Dom, Css, Search, FirebugReps, DOMBasePanel, DOMModule) {

// ********************************************************************************************* //
// Constants

var Trace = FBTrace.to("DBG_DOM");
var TraceError = FBTrace.to("DBG_ERRORS");

// ********************************************************************************************* //
// DOM Panel

/**
 * @panel This object represents a DOM panel in the main Firebug UI.
 */
function DOMPanel()
{
}

DOMPanel.DirTable = DOMBasePanel.prototype.dirTablePlate;
DOMPanel.prototype = Obj.extend(DOMBasePanel.prototype,
/** @lends DOMPanel */
{
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // extends Panel

    name: "dom",
    searchable: true,
    statusSeparator: ">",
    enableA11y: true,
    deriveA11yFrom: "console",
    searchType : "dom",
    order: 50,
    inspectable: true,

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Initialization

    initialize: function()
    {
        this.onClick = Obj.bind(this.onClick, this);

        DOMModule.addListener(this);

        DOMBasePanel.prototype.initialize.apply(this, arguments);
    },

    destroy: function(state)
    {
        DOMModule.removeListener(this);

        DOMBasePanel.destroy.apply(this, arguments);
    },

    initializeNode: function(oldPanelNode)
    {
        Events.addEventListener(this.panelNode, "click", this.onClick, false);

        DOMBasePanel.prototype.initializeNode.apply(this, arguments);
    },

    destroyNode: function()
    {
        Events.removeEventListener(this.panelNode, "click", this.onClick, false);

        DOMBasePanel.prototype.destroyNode.apply(this, arguments);
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Search

    search: function(text, reverse)
    {
        if (!text)
        {
            delete this.currentSearch;
            this.highlightNode(null);
            this.document.defaultView.getSelection().removeAllRanges();
            return false;
        }

        var row;
        if (this.currentSearch && text === this.currentSearch.text)
        {
            // xxxsz: 'Firebug.Search' is used here instead of 'Search' because we need to refer to
            // 'firebug/chrome/searchBox' and not to 'firebug/lib/search'
            // TODO: Rework 'searchBox.js', so it doesn't inject itself into the global 'Firebug'
            // scope anymore
            row = this.currentSearch.findNext(true, undefined, reverse,
                Firebug.Search.isCaseSensitive(text));
        }
        else
        {
            var findRow = function(node)
            {
                return Dom.getAncestorByClass(node, "memberRow");
            };

            this.currentSearch = new Search.TextSearch(this.panelNode, findRow);

            // xxxsz: 'Firebug.Search' is used here instead of 'Search' because we need to refer to
            // 'firebug/chrome/searchBox' and not to 'firebug/lib/search'
            row = this.currentSearch.find(text, reverse, Firebug.Search.isCaseSensitive(text));
        }

        if (row)
        {
            var sel = this.document.defaultView.getSelection();
            sel.removeAllRanges();
            sel.addRange(this.currentSearch.range);

            Dom.scrollIntoCenterView(row, this.panelNode);

            this.highlightNode(row);
            Events.dispatch(this.fbListeners, "onDomSearchMatchFound", [this, text, row]);
            return true;
        }
        else
        {
            this.document.defaultView.getSelection().removeAllRanges();
            Events.dispatch(this.fbListeners, "onDomSearchMatchFound", [this, text, null]);
            return false;
        }
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

    selectRow: function(row, target)
    {
        if (!target)
            target = row.lastChild.firstChild;

        var object = target && target.repObject, type = typeof object;
        if (!object || !this.supportsObject(object, type))
            return;

        this.pathToAppend = DOMBasePanel.getPath(row);

        // If the object is inside an array, look up its index
        var valueBox = row.lastChild.firstChild;
        if (Css.hasClass(valueBox, "objectBox-array"))
        {
            var arrayIndex = FirebugReps.Arr.getItemIndex(target);
            this.pathToAppend.push(arrayIndex);
        }

        // Make sure we get a fresh status path for the object, since otherwise
        // it might find the object in the existing path and not refresh it
        Firebug.chrome.clearStatusPath();

        this.select(object, true);
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

    onClick: function(event)
    {
        var repNode = Firebug.getRepNode(event.target);
        if (repNode)
        {
            var row = Dom.getAncestorByClass(event.target, "memberRow");
            if (row)
            {
                this.selectRow(row, repNode);
                Events.cancelEvent(event);
            }
        }
    },

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Breakpoints, DOMModule Listener

    onDomBreakpointAdded: function(context, object, name)
    {
        Trace.sysout("domBasePanel.onDomBreakpointAdded; propName: " + name +
            " (panel: " + this.name + ")", object);

        this.updateBreakpoints(object);
    },

    onDomBreakpointRemoved: function(context, object, name)
    {
        Trace.sysout("domBasePanel.onDomBreakpointRemoved; propName: " + name +
            " (panel: " + this.name + ")", object);

        this.updateBreakpoints(object);
    },

    updateBreakpoints: function(object)
    {
        // xxxHonza: the update should be smarter if possible. Can we just lookup
        // for the specific object and update the row directly?
        // Can we utilize DomTree widget?

        var breakpoints = this.context.dom.breakpoints;
        var rows = Dom.getElementsByClass(this.panelNode, "memberRow");
        for (var i = 0; i < rows.length; i++)
        {
            var row = rows[i];
            var member = row.domObject;

            var bp = breakpoints.findBreakpoint(member.object, member.name);
            if (bp)
            {
                row.setAttribute("breakpoint", "true");

                if (!bp.checked)
                    row.setAttribute("disabledBreakpoint", "true");
            }
            else
            {
                row.removeAttribute("breakpoint");
                row.removeAttribute("disabledBreakpoint");
            }
        }

        return null;
    },
});

// ********************************************************************************************* //
// Registration

Firebug.registerPanel(DOMPanel);

// xxxHonza: backward compatibility
Firebug.DOMPanel = DOMPanel;

return DOMPanel;

// ********************************************************************************************* //
});
<|endoftext|>


<commit_before>  Meteor.autorun(function() {
      Meteor.call('activeGeohashes',function (err,data) {
        // console.log(data);
        activeGeohashes = data;
      });
    Meteor.subscribe('messages', 'global' );
  });

Template.home.rendered = function() {
  markersArray = [];

    var mapCenter = new google.maps.LatLng(45.0,7.5);
    var myOptions = {
      zoom: 2,
      center: mapCenter,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    // FIXME: error in 1st render & duplication with localize
      map = new google.maps.Map(document.getElementById("maphome"), myOptions);

      // add geolocalized messages
      if (typeof activeGeohashes !== "undefined"){
        _(activeGeohashes).each(function (gh) {
          var geo = geohash.decode(gh);
          var el = {
            lat: geo[0], lon:geo[1], ghash:gh
          };

          // FIX: bad coords
          //console.log('a-'+el.lon+" "+el.lat);
          var marker = new google.maps.Marker({
            position: new google.maps.LatLng(el.lat, el.lon),
            draggable: false,
            map: map
          });

          // infowindow
          var infowindow = new google.maps.InfoWindow({
              content: '
 Chat Area
'+el.ghash+'

'
          });
          google.maps.event.addListener(marker, 'click', function() {
            infowindow.open(map,marker);
          });

          markersArray.push(marker);

          // var markerCluster = new MarkerClusterer(map, markers);
        });

        map.setCenter(mapCenter);

        var markerCluster = new MarkerClusterer(map, markersArray);

      }
}<commit_msg>linkable public chat<commit_after>  Meteor.autorun(function() {
      Meteor.call('activeGeohashes',function (err,data) {
        // console.log(data);
        activeGeohashes = data;
      });
    Meteor.subscribe('messages', 'global' );
  });

Template.home.rendered = function() {
  markersArray = [];

    var mapCenter = new google.maps.LatLng(45.0,7.5);
    var myOptions = {
      zoom: 2,
      center: mapCenter,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    // FIXME: error in 1st render & duplication with localize
      map = new google.maps.Map(document.getElementById("maphome"), myOptions);

      // add geolocalized messages
      if (typeof activeGeohashes !== "undefined"){
        _(activeGeohashes).each(function (gh) {
          var geo = geohash.decode(gh);
          var el = {
            lat: geo[0], lon:geo[1], ghash:gh
          };

          // FIX: bad coords
          //console.log('a-'+el.lon+" "+el.lat);
          var marker = new google.maps.Marker({
            position: new google.maps.LatLng(el.lat, el.lon),
            draggable: false,
            map: map
          });

          // infowindow
          var infowindow = new google.maps.InfoWindow({
              content: '
 Chat Area
Go to this chat!

'
          });
          google.maps.event.addListener(marker, 'click', function() {
            infowindow.open(map,marker);
          });

          markersArray.push(marker);

          // var markerCluster = new MarkerClusterer(map, markers);
        });

        map.setCenter(mapCenter);

        var markerCluster = new MarkerClusterer(map, markersArray);

      }
}<|endoftext|>


<commit_before>Template.layout.helpers({
	testWarningClass: function() {
		if (Meteor.settings && Meteor.settings.public && Meteor.settings.public.testWarning) {
			return "testWarning";
		}
		return false;
	},
	translate: function() {
		var route = Router.current().route;
		return route && route.getName === "mfTrans";
	},

	mayTranslate: function() {
		return !!Meteor.user();
	}
});

Template.layout.rendered = function() {
	$(window).resize(function(event){ getViewportWidth(); });
};
<commit_msg>fix display of translate info fixes #468<commit_after>Template.layout.helpers({
	testWarningClass: function() {
		if (Meteor.settings && Meteor.settings.public && Meteor.settings.public.testWarning) {
			return "testWarning";
		}
		return false;
	},
	translate: function() {
		var route = Router.current().route;
		return route && route.getName() === "mfTrans";
	},

	mayTranslate: function() {
		return !!Meteor.user();
	}
});

Template.layout.rendered = function() {
	$(window).resize(function(event){ getViewportWidth(); });
};
<|endoftext|>


<commit_before>import get from 'lodash/get';
import cloneDeep from 'lodash/cloneDeep';

import { dateFormatMap } from './date';

const extractColumns = (mappings, key) =>
	Object.keys((mappings || {})[key] || []);

const META_FIELDS = ['_index', '_type'];

const es6mappings = {
	'Text: Aggs': {
		type: 'text',
		fields: {
			keyword: {
				type: 'keyword',
				index: 'true',
				ignore_above: 256,
			},
			autosuggest: {
				type: 'text',
				index: 'true',
				analyzer: 'autosuggest_analyzer',
				search_analyzer: 'simple',
			},
		},
		analyzer: 'standard',
		search_analyzer: 'standard',
	},
	'Text: Search': {
		type: 'text',
		fields: {
			keyword: {
				type: 'keyword',
				index: 'true',
				ignore_above: 256,
			},
			search: {
				type: 'text',
				index: 'true',
				analyzer: 'ngram_analyzer',
				search_analyzer: 'simple',
			},
			autosuggest: {
				type: 'text',
				index: 'true',
				analyzer: 'autosuggest_analyzer',
				search_analyzer: 'simple',
			},
			english: {
				type: 'text',
				analyzer: 'english',
			},
		},
		analyzer: 'standard',
		search_analyzer: 'standard',
	},
	Long: {
		type: 'long',
	},
	Integer: {
		type: 'integer',
	},
	Double: {
		type: 'double',
	},
	Float: {
		type: 'float',
	},
	Date: {
		type: 'date',
		format: dateFormatMap.date,
	},
	Boolean: {
		type: 'boolean',
	},
	'Geo Point': {
		type: 'geo_point',
	},
	'Geo Shape': {
		type: 'geo_shape',
	},
	Image: {
		type: 'text',
		fields: {
			keyword: {
				type: 'keyword',
				index: 'true',
			},
		},
	},
	Keyword: {
		type: 'keyword',
		ignore_above: 256,
	},
};

const getSortableTypes = () => {
	const sortableTypes = Object.keys(es6mappings).reduce((result, value) => {
		if (['Geo Point', 'Geo Shape', 'Image'].indexOf(value) === -1) {
			result.push(es6mappings[value].type);
		}

		return result;
	}, []);

	return [...sortableTypes, 'string'];
};

const getSortableColumns = properties => {
	const columns = [];
	const sortableTypes = getSortableTypes();

	if (properties) {
		Object.keys(properties).forEach(item => {
			const { type } = properties[item];
			if (type && sortableTypes.indexOf(type) > -1) {
				if (
					properties[item].fields &&
					properties[item].fields.keyword
				) {
					columns.push(`${item}.keyword`);
				}

				if (properties[item].fields && properties[item].fields.raw) {
					columns.push(`${item}.raw`);
				}

				if (
					properties[item].originalFields &&
					properties[item].originalFields.keyword
				) {
					columns.push(`${item}.keyword`);
				}

				if (
					properties[item].originalFields &&
					properties[item].originalFields.raw
				) {
					columns.push(`${item}.raw`);
				}

				columns.push(item);
			}
		});
	}

	return columns;
};

const getTermsAggregationColumns = properties => {
	const columns = [];

	if (properties) {
		Object.keys(properties).forEach(item => {
			const { type } = properties[item];
			if (type === 'string') {
				if (
					(
						properties[item].originalFields ||
						properties[item].fields ||
						{}
					).raw
				) {
					columns.push(`${item}.raw`);
				} else if (
					(
						properties[item].originalFields ||
						properties[item].fields ||
						{}
					).keyword
				) {
					columns.push(`${item}.keyword`);
				} else {
					columns.push(item);
				}
			}

			if (type === 'text') {
				if (
					(
						properties[item].originalFields ||
						properties[item].fields ||
						{}
					).raw
				) {
					columns.push(`${item}.raw`);
				} else if (
					(
						properties[item].originalFields ||
						properties[item].fields ||
						{}
					).keyword
				) {
					columns.push(`${item}.keyword`);
				}
			}

			if (
				[
					es6mappings.Long.type,
					es6mappings.Integer.type,
					es6mappings.Double.type,
					es6mappings.Float.type,
					es6mappings.Date.type,
					es6mappings.Boolean.type,
					es6mappings.Keyword.type,
				].indexOf(type) > -1
			) {
				columns.push(item);
			}
		});
	}

	return columns;
};

const getFieldsTree = (mappings = {}, prefix = null) => {
	let tree = {};
	Object.keys(mappings).forEach(key => {
		if (mappings[key].properties) {
			tree = {
				...tree,
				...getFieldsTree(
					mappings[key].properties,
					`${prefix ? `${prefix}.` : ''}${key}`,
				),
			};
		} else {
			const originalFields = mappings[key].fields;
			tree = {
				...tree,
				[`${prefix ? `${prefix}.` : ''}${key}`]: {
					type: mappings[key].type,
					fields: mappings[key].fields
						? Object.keys(mappings[key].fields)
						: [],
					originalFields: originalFields || {},
				},
			};
		}
	});

	return tree;
};

const getMappingsTree = (mappings = {}) => {
	let tree = {};
	Object.keys(mappings).forEach(key => {
		if (mappings[key].properties) {
			tree = {
				...tree,
				...getFieldsTree(mappings[key].properties, key),
			};
		} else if (mappings[key].type) {
			tree = {
				...tree,
				[key]: mappings[key],
			};
		}
	});

	return tree;
};

const getNestedArrayField = (data, mappings) => {
	const fieldsToBeDeleted = {};
	const parentFields = {};
	const indexTypeMap = {};
	data.forEach(dataItem => {
		Object.keys(mappings).forEach(col => {
			if (!get(dataItem, col) && col.indexOf('.') > -1) {
				const parentPath = col.substring(0, col.lastIndexOf('.'));
				const parentData = get(dataItem, parentPath);
				if (parentData && Array.isArray(parentData)) {
					fieldsToBeDeleted[col] = true;
					parentFields[parentPath] = true;
					indexTypeMap[dataItem._index] = {
						[dataItem._type]: {
							...(indexTypeMap[dataItem._index]
								? indexTypeMap[dataItem._index][
										dataItem._type
								  ] || {}
								: {}),
							[parentPath]: true,
						},
					};
				}
			}
		});
	});

	return { parentFields, fieldsToBeDeleted, indexTypeMap };
};

// function to update mapping of particular type
const updateIndexTypeMapping = (
	currentMapping,
	updatingMap,
	fieldsToBeDeleted,
	fullMap,
) => {
	const newMapping = cloneDeep(currentMapping);
	Object.keys(updatingMap).forEach(index => {
		Object.keys(updatingMap[index]).forEach(type => {
			Object.keys(updatingMap[index][type]).forEach(key => {
				newMapping[index][type][key] = get(
					fullMap.properties,
					key.split('.').join('.properties.'),
				);
			});

			fieldsToBeDeleted.forEach(field => {
				delete newMapping[index][type][field];
			});
		});
	});

	return newMapping;
};

const hasNestedColumns = (originalProperties, nestedProperties) =>
	Object.keys(originalProperties).length !==
	Object.keys(nestedProperties).length;

export {
	extractColumns,
	es6mappings,
	META_FIELDS,
	getSortableTypes,
	getTermsAggregationColumns,
	getMappingsTree,
	getNestedArrayField,
	updateIndexTypeMapping,
	getSortableColumns,
	hasNestedColumns,
};
<commit_msg>fix: text mapping<commit_after>import get from 'lodash/get';
import cloneDeep from 'lodash/cloneDeep';

import { dateFormatMap } from './date';

const extractColumns = (mappings, key) =>
	Object.keys((mappings || {})[key] || []);

const META_FIELDS = ['_index', '_type'];

const es6mappings = {
	'Text: Aggs': {
		type: 'text',
		fields: {
			keyword: {
				type: 'keyword',
				index: 'true',
				ignore_above: 256,
			},
			english: {
				type: 'text',
				analyzer: 'english',
			},
		},
		analyzer: 'standard',
		search_analyzer: 'standard',
	},
	'Text: Search': {
		type: 'text',
		fields: {
			keyword: {
				type: 'keyword',
				index: 'true',
				ignore_above: 256,
			},
			search: {
				type: 'text',
				index: 'true',
				analyzer: 'ngram_analyzer',
				search_analyzer: 'simple',
			},
			autosuggest: {
				type: 'text',
				index: 'true',
				analyzer: 'autosuggest_analyzer',
				search_analyzer: 'simple',
			},
			english: {
				type: 'text',
				analyzer: 'english',
			},
		},
		analyzer: 'standard',
		search_analyzer: 'standard',
	},
	Long: {
		type: 'long',
	},
	Integer: {
		type: 'integer',
	},
	Double: {
		type: 'double',
	},
	Float: {
		type: 'float',
	},
	Date: {
		type: 'date',
		format: dateFormatMap.date,
	},
	Boolean: {
		type: 'boolean',
	},
	'Geo Point': {
		type: 'geo_point',
	},
	'Geo Shape': {
		type: 'geo_shape',
	},
	Image: {
		type: 'text',
		fields: {
			keyword: {
				type: 'keyword',
				index: 'true',
			},
		},
	},
	Keyword: {
		type: 'keyword',
		ignore_above: 256,
	},
};

const getSortableTypes = () => {
	const sortableTypes = Object.keys(es6mappings).reduce((result, value) => {
		if (['Geo Point', 'Geo Shape', 'Image'].indexOf(value) === -1) {
			result.push(es6mappings[value].type);
		}

		return result;
	}, []);

	return [...sortableTypes, 'string'];
};

const getSortableColumns = properties => {
	const columns = [];
	const sortableTypes = getSortableTypes();

	if (properties) {
		Object.keys(properties).forEach(item => {
			const { type } = properties[item];
			if (type && sortableTypes.indexOf(type) > -1) {
				if (
					properties[item].fields &&
					properties[item].fields.keyword
				) {
					columns.push(`${item}.keyword`);
				}

				if (properties[item].fields && properties[item].fields.raw) {
					columns.push(`${item}.raw`);
				}

				if (
					properties[item].originalFields &&
					properties[item].originalFields.keyword
				) {
					columns.push(`${item}.keyword`);
				}

				if (
					properties[item].originalFields &&
					properties[item].originalFields.raw
				) {
					columns.push(`${item}.raw`);
				}

				columns.push(item);
			}
		});
	}

	return columns;
};

const getTermsAggregationColumns = properties => {
	const columns = [];

	if (properties) {
		Object.keys(properties).forEach(item => {
			const { type } = properties[item];
			if (type === 'string') {
				if (
					(
						properties[item].originalFields ||
						properties[item].fields ||
						{}
					).raw
				) {
					columns.push(`${item}.raw`);
				} else if (
					(
						properties[item].originalFields ||
						properties[item].fields ||
						{}
					).keyword
				) {
					columns.push(`${item}.keyword`);
				} else {
					columns.push(item);
				}
			}

			if (type === 'text') {
				if (
					(
						properties[item].originalFields ||
						properties[item].fields ||
						{}
					).raw
				) {
					columns.push(`${item}.raw`);
				} else if (
					(
						properties[item].originalFields ||
						properties[item].fields ||
						{}
					).keyword
				) {
					columns.push(`${item}.keyword`);
				}
			}

			if (
				[
					es6mappings.Long.type,
					es6mappings.Integer.type,
					es6mappings.Double.type,
					es6mappings.Float.type,
					es6mappings.Date.type,
					es6mappings.Boolean.type,
					es6mappings.Keyword.type,
				].indexOf(type) > -1
			) {
				columns.push(item);
			}
		});
	}

	return columns;
};

const getFieldsTree = (mappings = {}, prefix = null) => {
	let tree = {};
	Object.keys(mappings).forEach(key => {
		if (mappings[key].properties) {
			tree = {
				...tree,
				...getFieldsTree(
					mappings[key].properties,
					`${prefix ? `${prefix}.` : ''}${key}`,
				),
			};
		} else {
			const originalFields = mappings[key].fields;
			tree = {
				...tree,
				[`${prefix ? `${prefix}.` : ''}${key}`]: {
					type: mappings[key].type,
					fields: mappings[key].fields
						? Object.keys(mappings[key].fields)
						: [],
					originalFields: originalFields || {},
				},
			};
		}
	});

	return tree;
};

const getMappingsTree = (mappings = {}) => {
	let tree = {};
	Object.keys(mappings).forEach(key => {
		if (mappings[key].properties) {
			tree = {
				...tree,
				...getFieldsTree(mappings[key].properties, key),
			};
		} else if (mappings[key].type) {
			tree = {
				...tree,
				[key]: mappings[key],
			};
		}
	});

	return tree;
};

const getNestedArrayField = (data, mappings) => {
	const fieldsToBeDeleted = {};
	const parentFields = {};
	const indexTypeMap = {};
	data.forEach(dataItem => {
		Object.keys(mappings).forEach(col => {
			if (!get(dataItem, col) && col.indexOf('.') > -1) {
				const parentPath = col.substring(0, col.lastIndexOf('.'));
				const parentData = get(dataItem, parentPath);
				if (parentData && Array.isArray(parentData)) {
					fieldsToBeDeleted[col] = true;
					parentFields[parentPath] = true;
					indexTypeMap[dataItem._index] = {
						[dataItem._type]: {
							...(indexTypeMap[dataItem._index]
								? indexTypeMap[dataItem._index][
										dataItem._type
								  ] || {}
								: {}),
							[parentPath]: true,
						},
					};
				}
			}
		});
	});

	return { parentFields, fieldsToBeDeleted, indexTypeMap };
};

// function to update mapping of particular type
const updateIndexTypeMapping = (
	currentMapping,
	updatingMap,
	fieldsToBeDeleted,
	fullMap,
) => {
	const newMapping = cloneDeep(currentMapping);
	Object.keys(updatingMap).forEach(index => {
		Object.keys(updatingMap[index]).forEach(type => {
			Object.keys(updatingMap[index][type]).forEach(key => {
				newMapping[index][type][key] = get(
					fullMap.properties,
					key.split('.').join('.properties.'),
				);
			});

			fieldsToBeDeleted.forEach(field => {
				delete newMapping[index][type][field];
			});
		});
	});

	return newMapping;
};

const hasNestedColumns = (originalProperties, nestedProperties) =>
	Object.keys(originalProperties).length !==
	Object.keys(nestedProperties).length;

export {
	extractColumns,
	es6mappings,
	META_FIELDS,
	getSortableTypes,
	getTermsAggregationColumns,
	getMappingsTree,
	getNestedArrayField,
	updateIndexTypeMapping,
	getSortableColumns,
	hasNestedColumns,
};
<|endoftext|>


<commit_before>/**
 * Created by yfyuan on 2016/8/12.
 */
'use strict';
cBoard.service('dataService', function ($http, updateService) {

    /**
     * Get raw data from server side.
     * @param datasource
     * @param query
     * @param callback
     */
    this.getData = function (datasource, query, datasetId, callback) {
        $http.post("/dashboard/getData.do", {
            datasourceId: datasource,
            query: angular.toJson(query),
            datasetId: datasetId
        }).success(function (response) {
            callback(response);
        });
    };

    var getDataSeries = function (rawData, chartConfig) {
        var result = [];
        _.each(chartConfig.values, function (v) {
            _.each(v.cols, function (c) {
                var series = configToDataSeries(rawData, c);
                _.each(series, function (s) {
                    if (!_.find(result, function (e) {
                            return JSON.stringify(e) == JSON.stringify(s);
                        })) {
                        result.push(s);
                    }
                });
            });
        });
        return result;
    };

    var configToDataSeries = function (rawData, config) {
        switch (config.type) {
            case 'exp':
                return getExpSeries(rawData, config.exp);
                break;
            default:
                return [{
                    name: config.col,
                    aggregate: config.aggregate_type,
                    index: getHeaderIndex(rawData, [config.col])[0]
                }]
                break;
        }
    };

    var getExpSeries = function (rawData, exp) {
        var result = [];
        exp = exp.trim();
        _.each(exp.match(/(sum|avg|count|max|min)\([\u4e00-\u9fa5_a-zA-Z0-9]+\)/g), function (text) {
            var name = text.substring(text.indexOf('(') + 1, text.indexOf(')'));
            result.push({
                name: name,
                aggregate: text.substring(0, text.indexOf('(')),
                index: getHeaderIndex(rawData, [name])[0]
            });
        });
        return result;
    };

    var getRule = function (cfg, colIdx) {
        switch (cfg.type) {
            case '=':
            case 'eq':
                return function (row) {
                    for (var i = 0; i < cfg.values.length; i++) {
                        if (row[colIdx] == cfg.values[i]) {
                            return true;
                        }
                    }
                    return cfg.values.length == 0;
                };
                break;
            case '≠':
            case 'ne':
                return function (row) {
                    for (var i = 0; i < cfg.values.length; i++) {
                        if (row[colIdx] == cfg.values[i]) {
                            return false;
                        }
                    }
                    return true;
                };
                break;
            case '>':
                var v = cfg.values[0];
                if (!_.isUndefined(v) && row[colIdx] <= v) {
                    return false;
                }
                return true;
                break;
            case '<':
                var v = cfg.values[0];
                if (!_.isUndefined(v) && row[colIdx] >= v) {
                    return false;
                }
                return true;
                break;
            case '≥':
                var v = cfg.values[0];
                if (!_.isUndefined(v) && row[colIdx] < v) {
                    return false;
                }
                return true;
                break;
            case '≤':
                var v = cfg.values[0];
                if (!_.isUndefined(v) && row[colIdx] > v) {
                    return false;
                }
                return true;
                break;
            case '(a,b]':
                var a = cfg.values[0];
                var b = cfg.values[1];
                if (!_.isUndefined(a) && !_.isUndefined(b) && (row[colIdx] <= a || row[colIdx] > b)) {
                    return false;
                }
                return true;
                break;
            case '[a,b)':
                var a = cfg.values[0];
                var b = cfg.values[1];
                if (!_.isUndefined(a) && !_.isUndefined(b) && (row[colIdx] < a || row[colIdx] >= b)) {
                    return false;
                }
                return true;
                break;
            case '(a,b)':
                var a = cfg.values[0];
                var b = cfg.values[1];
                if (!_.isUndefined(a) && !_.isUndefined(b) && (row[colIdx] <= a || row[colIdx] >= b)) {
                    return false;
                }
                return true;
                break;
            case '[a,b]':
                var a = cfg.values[0];
                var b = cfg.values[1];
                if (!_.isUndefined(a) && !_.isUndefined(b) && (row[colIdx] < a || row[colIdx] > b)) {
                    return false;
                }
                return true;
                break;
        }
    };

    this.getRule = getRule;

    var getFilter = function (chartConfig, keysIdx, groupsIdx, filtersIdx) {
        var rules = [];
        _.map(keysIdx, function (v, i) {
            var cfg = chartConfig.keys[i];
            rules.push(getRule(cfg, v));
        });
        _.map(groupsIdx, function (v, i) {
            var cfg = chartConfig.groups[i];
            rules.push(getRule(cfg, v));
        });
        _.map(filtersIdx, function (v, i) {
            var cfg = chartConfig.filters[i];
            rules.push(getRule(cfg, v));
        });
        return function (row) {
            for (var i = 0; i < rules.length; i++) {
                if (!rules[i](row)) {
                    return false;
                }
            }
            return true;
        };
    };

    /**
     * Cast the aggregated raw data into data series
     * @param rawData
     * @param chartConfig
     * @param callback function which is used to transform series data to widgets option
     */
    this.castRawData2Series = function (rawData, chartConfig, callback) {
        updateService.updateConfig(chartConfig);
        var keysIdx = getHeaderIndex(rawData, _.map(chartConfig.keys, function (e) {
            return e.col;
        }));
        var keysSort = _.map(chartConfig.keys, function (e) {
            return e.sort;
        });
        var groupsIdx = getHeaderIndex(rawData, _.map(chartConfig.groups, function (e) {
            return e.col;
        }));
        var groupsSort = _.map(chartConfig.groups, function (e) {
            return e.sort;
        });
        var filtersIdx = getHeaderIndex(rawData, _.map(chartConfig.filters, function (e) {
            return e.col;
        }));
        var dataSeries = getDataSeries(rawData, chartConfig);

        var castedKeys = new Array();
        var castedGroups = new Array();
        var newData = {};

        var filter = getFilter(chartConfig, keysIdx, groupsIdx, filtersIdx);

        for (var i = 1; i < rawData.length; i++) {
            if (!filter(rawData[i])) {
                continue;
            }
            //组合keys
            var newKey = getRowElements(rawData[i], keysIdx);
            var keysInsert = sortInsert(castedKeys, newKey, keysSort);
            if (keysInsert.newKey) {
                _.mapObject(newData, function (g) {
                    _.mapObject(g, function (groupSeries) {
                        _.each(_.keys(groupSeries), function (aggregateType) {
                            groupSeries[aggregateType].splice(keysInsert.idx, 0, undefined)
                        });
                    });
                });
            }
            //组合groups
            var group = getRowElements(rawData[i], groupsIdx);
            sortInsert(castedGroups, group, groupsSort);
            var newGroup = group.join('-');
            // pick the raw values into coordinate cell and then use aggregate function to do calculate
            _.each(dataSeries, function (dSeries) {
                if (_.isUndefined(newData[newGroup])) {
                    newData[newGroup] = {};
                }
                if (_.isUndefined(newData[newGroup][dSeries.name])) {
                    newData[newGroup][dSeries.name] = {};
                }
                if (_.isUndefined(newData[newGroup][dSeries.name][dSeries.aggregate])) {
                    newData[newGroup][dSeries.name][dSeries.aggregate] = [];
                }
                if (_.isUndefined(newData[newGroup][dSeries.name][dSeries.aggregate][keysInsert.idx])) {
                    newData[newGroup][dSeries.name][dSeries.aggregate][keysInsert.idx] = [];
                }
                newData[newGroup][dSeries.name][dSeries.aggregate][keysInsert.idx].push(rawData[i][dSeries.index]);
            });
        }
        // do aggregate
        _.mapObject(newData, function (g) {
            _.mapObject(g, function (groupSeries) {
                _.each(_.keys(groupSeries), function (aggregateType) {
                    for (var i = 0; i < groupSeries[aggregateType].length; i++) {
                        if (groupSeries[aggregateType][i]) {
                            groupSeries[aggregateType][i] = aggregate(groupSeries[aggregateType][i], aggregateType);
                        }
                    }
                });
            });
        });
        var castedAliasSeriesName = new Array();
        var aliasSeriesConfig = {};
        var aliasData = new Array();
        _.each(castedGroups, function (group) {
            _.each(chartConfig.values, function (value, vIdx) {
                _.each(value.cols, function (series) {
                    var seriesName = series.alias ? series.alias : series.col;
                    var newSeriesName = seriesName;
                    if (group && group.length > 0) {
                        var a = [].concat(group);
                        a.push(seriesName);
                        newSeriesName = a.join('-');
                        castedAliasSeriesName.push(a);
                    } else {
                        castedAliasSeriesName.push([seriesName]);
                    }
                    //castedAliasSeriesName.push(newSeriesName);
                    aliasSeriesConfig[newSeriesName] = {type: value.series_type, valueAxisIndex: vIdx};

                    castSeriesData(series, group.join('-'), castedKeys, newData, function (castedData, keyIdx) {
                        if (!aliasData[castedAliasSeriesName.length - 1]) {
                            aliasData[castedAliasSeriesName.length - 1] = new Array();
                        }
                        // Only format decimal
                        aliasData[castedAliasSeriesName.length - 1][keyIdx] = dataFormat(castedData);
                    });
                });
            });
        });
        callback(castedKeys, castedAliasSeriesName, aliasData, aliasSeriesConfig);
    };

    var castSeriesData = function (series, group, castedKeys, newData, iterator) {
        switch (series.type) {
            case 'exp':
                var runExp = compileExp(series.exp);
                for (var i = 0; i < castedKeys.length; i++) {
                    iterator(runExp(newData[group], i), i);
                }
                break;
            default:
                _.each(newData[group][series.col][series.aggregate_type], iterator);
                break;
        }
    };

    var compileExp = function (exp) {
        exp = exp.trim();
        _.each(exp.match(/(sum|avg|count|max|min)\([\u4e00-\u9fa5_a-zA-Z0-9]+\)/g), function (text) {
            var name = text.substring(text.indexOf('(') + 1, text.indexOf(')'));
            var aggregate = text.substring(0, text.indexOf('('));
            exp = exp.replace(text, "groupData['" + name + "']['" + aggregate + "'][keyIdx]");
        });
        return function (groupData, keyIdx) {
            return eval(exp);
        };
    };

    var aggregate = function (data_array, fnc) {
        if (!data_array) {
            return data_array;
        }
        switch (fnc) {
            case 'sum':
                return aggregate_sum(data_array);
            case 'count':
                return aggregate_count(data_array);
            case 'avg':
                return aggregate_avg(data_array);
            case 'max':
                return _.max(data_array, function (f) {
                    return parseFloat(f);
                });
            case 'min':
                return _.min(data_array, function (f) {
                    return parseFloat(f);
                });
        }
    };

    var aggregate_sum = function (data_array) {
        var sum = 0;
        for (var i = 0; i < data_array.length; i++) {
            var f = parseFloat(data_array[i]);
            if (f) {
                sum += f;
            }
        }
        return sum;
    };

    var aggregate_count = function (data_array) {
        return data_array.length;
    };

    var aggregate_avg = function (data_array) {
        var sum = 0;
        var count = 0;
        for (var i = 0; i < data_array.length; i++) {
            var f = parseFloat(data_array[i]);
            if (f) {
                sum += f;
                count++;
            }
        }
        return count == 0 ? 0 : sum / count;
    };

    var getHeaderIndex = function (chartData, col) {
        var result = new Array();
        if (col) {
            for (var j = 0; j < col.length; j++) {
                var idx = _.indexOf(chartData[0], col[j]);
                result.push(idx);
            }
        }
        return result;
    };

    var getRowElements = function (row, elmIdxs) {
        var arr = new Array();
        for (var j = 0; j < elmIdxs.length; j++) {
            var elm = row[elmIdxs[j]];
            arr.push(elm);
        }
        return arr;
    };

    var sortInsert = function (arr, elm, sort) {
        var idx = indexOf(arr, elm);
        if (idx < 0) {
            for (var i = 0; i < arr.length; i++) {
                for (var j = 0; j < arr[i].length; j++) {
                    if (!sort[j] || elm[j] == arr[i][j]) {
                        continue;
                    }
                    var a = Number(elm[j]);
                    var b = Number(arr[i][j]);
                    if (Number.isNaN(a) || Number.isNaN(b)) {
                        a = elm[j];
                        b = arr[i][j];
                    }
                    if ((a > b) ^ (sort[j] != 'asc')) {
                        break;
                    } else {
                        arr.splice(i, 0, elm);
                        return {idx: i, newKey: true};
                    }
                }
            }
            var x = arr.length;
            arr.push(elm);
            return {idx: x, newKey: true};
        } else {
            return {idx: idx, newKey: false};
        }
    };

    var indexOf = function (array, key) {
        var idx = -1;
        outer : for (var i = 0; i < array.length; i++) {
            // if (array[i].length != key.length) {
            //     continue outer;
            // }
            for (var j = 0; j < array[i].length; j++) {
                if (array[i][j] != key[j]) {
                    continue outer;
                }
            }
            idx = i;
            break;
        }
        return idx;
    };
});
<commit_msg>filter for dashboard #14<commit_after>/**
 * Created by yfyuan on 2016/8/12.
 */
'use strict';
cBoard.service('dataService', function ($http, updateService) {

    /**
     * Get raw data from server side.
     * @param datasource
     * @param query
     * @param callback
     */
    this.getData = function (datasource, query, datasetId, callback) {
        $http.post("/dashboard/getData.do", {
            datasourceId: datasource,
            query: angular.toJson(query),
            datasetId: datasetId
        }).success(function (response) {
            callback(response);
        });
    };

    var getDataSeries = function (rawData, chartConfig) {
        var result = [];
        _.each(chartConfig.values, function (v) {
            _.each(v.cols, function (c) {
                var series = configToDataSeries(rawData, c);
                _.each(series, function (s) {
                    if (!_.find(result, function (e) {
                            return JSON.stringify(e) == JSON.stringify(s);
                        })) {
                        result.push(s);
                    }
                });
            });
        });
        return result;
    };

    var configToDataSeries = function (rawData, config) {
        switch (config.type) {
            case 'exp':
                return getExpSeries(rawData, config.exp);
                break;
            default:
                return [{
                    name: config.col,
                    aggregate: config.aggregate_type,
                    index: getHeaderIndex(rawData, [config.col])[0]
                }]
                break;
        }
    };

    var getExpSeries = function (rawData, exp) {
        var result = [];
        exp = exp.trim();
        _.each(exp.match(/(sum|avg|count|max|min)\([\u4e00-\u9fa5_a-zA-Z0-9]+\)/g), function (text) {
            var name = text.substring(text.indexOf('(') + 1, text.indexOf(')'));
            result.push({
                name: name,
                aggregate: text.substring(0, text.indexOf('(')),
                index: getHeaderIndex(rawData, [name])[0]
            });
        });
        return result;
    };

    var getRule = function (cfg, colIdx) {
        switch (cfg.type) {
            case '=':
            case 'eq':
                return function (row) {
                    for (var i = 0; i < cfg.values.length; i++) {
                        if (row[colIdx] == cfg.values[i]) {
                            return true;
                        }
                    }
                    return cfg.values.length == 0;
                };
                break;
            case '≠':
            case 'ne':
                return function (row) {
                    for (var i = 0; i < cfg.values.length; i++) {
                        if (row[colIdx] == cfg.values[i]) {
                            return false;
                        }
                    }
                    return true;
                };
                break;
            case '>':
                return function (row) {
                    var v = cfg.values[0];
                    var params = toNumber(row[colIdx], v);
                    if (!_.isUndefined(v) && params[0] <= params[1]) {
                        return false;
                    }
                    return true;
                };
                break;
            case '<':
                return function (row) {
                    var v = cfg.values[0];
                    var params = toNumber(row[colIdx], v);
                    if (!_.isUndefined(v) && params[0] >= params[1]) {
                        return false;
                    }
                    return true;
                };
                break;
            case '≥':
                return function (row) {
                    var v = cfg.values[0];
                    var params = toNumber(row[colIdx], v);
                    if (!_.isUndefined(v) && params[0] < params[1]) {
                        return false;
                    }
                    return true;
                };
                break;
            case '≤':
                return function (row) {
                    var v = cfg.values[0];
                    var params = toNumber(row[colIdx], v);
                    if (!_.isUndefined(v) && params[0] > params[1]) {
                        return false;
                    }
                    return true;
                };
                break;
            case '(a,b]':
                return function (row) {
                    var a = cfg.values[0];
                    var b = cfg.values[1];
                    var params = toNumber(row[colIdx], a, b);
                    if (!_.isUndefined(a) && !_.isUndefined(b) && (params[0] <= params[1] || params[0] > params[2])) {
                        return false;
                    }
                    return true;
                };
                break;
            case '[a,b)':
                return function (row) {
                    var a = cfg.values[0];
                    var b = cfg.values[1];
                    var params = toNumber(row[colIdx], a, b);
                    if (!_.isUndefined(a) && !_.isUndefined(b) && (params[0] < params[1] || params[0] >= params[2])) {
                        return false;
                    }
                    return true;
                };
                break;
            case '(a,b)':
                return function (row) {
                    var a = cfg.values[0];
                    var b = cfg.values[1];
                    var params = toNumber(row[colIdx], a, b);
                    if (!_.isUndefined(a) && !_.isUndefined(b) && (params[0] <= params[1] || params[0] >= params[2])) {
                        return false;
                    }
                    return true;
                };
                break;
            case '[a,b]':
                return function (row) {
                    var a = cfg.values[0];
                    var b = cfg.values[1];
                    var params = toNumber(row[colIdx], a, b);
                    if (!_.isUndefined(a) && !_.isUndefined(b) && (params[0] < params[1] || params[0] > params[2])) {
                        return false;
                    }
                    return true;
                };
                break;
        }
    };

    var toNumber = function (args) {
        var result = [];
        for (var i = 0; i < arguments.length; i++) {
            var a = Number(arguments[i]);
            if (Number.isNaN(a)) {
                return arguments;
            } else {
                result.push(a);
            }
        }
    };

    this.getRule = getRule;

    var getFilter = function (chartConfig, keysIdx, groupsIdx, filtersIdx) {
        var rules = [];
        _.map(keysIdx, function (v, i) {
            var cfg = chartConfig.keys[i];
            rules.push(getRule(cfg, v));
        });
        _.map(groupsIdx, function (v, i) {
            var cfg = chartConfig.groups[i];
            rules.push(getRule(cfg, v));
        });
        _.map(filtersIdx, function (v, i) {
            var cfg = chartConfig.filters[i];
            rules.push(getRule(cfg, v));
        });
        return function (row) {
            for (var i = 0; i < rules.length; i++) {
                if (!rules[i](row)) {
                    return false;
                }
            }
            return true;
        };
    };

    /**
     * Cast the aggregated raw data into data series
     * @param rawData
     * @param chartConfig
     * @param callback function which is used to transform series data to widgets option
     */
    this.castRawData2Series = function (rawData, chartConfig, callback) {
        updateService.updateConfig(chartConfig);
        var keysIdx = getHeaderIndex(rawData, _.map(chartConfig.keys, function (e) {
            return e.col;
        }));
        var keysSort = _.map(chartConfig.keys, function (e) {
            return e.sort;
        });
        var groupsIdx = getHeaderIndex(rawData, _.map(chartConfig.groups, function (e) {
            return e.col;
        }));
        var groupsSort = _.map(chartConfig.groups, function (e) {
            return e.sort;
        });
        var filtersIdx = getHeaderIndex(rawData, _.map(chartConfig.filters, function (e) {
            return e.col;
        }));
        var dataSeries = getDataSeries(rawData, chartConfig);

        var castedKeys = new Array();
        var castedGroups = new Array();
        var newData = {};

        var filter = getFilter(chartConfig, keysIdx, groupsIdx, filtersIdx);

        for (var i = 1; i < rawData.length; i++) {
            if (!filter(rawData[i])) {
                continue;
            }
            //组合keys
            var newKey = getRowElements(rawData[i], keysIdx);
            var keysInsert = sortInsert(castedKeys, newKey, keysSort);
            if (keysInsert.newKey) {
                _.mapObject(newData, function (g) {
                    _.mapObject(g, function (groupSeries) {
                        _.each(_.keys(groupSeries), function (aggregateType) {
                            groupSeries[aggregateType].splice(keysInsert.idx, 0, undefined)
                        });
                    });
                });
            }
            //组合groups
            var group = getRowElements(rawData[i], groupsIdx);
            sortInsert(castedGroups, group, groupsSort);
            var newGroup = group.join('-');
            // pick the raw values into coordinate cell and then use aggregate function to do calculate
            _.each(dataSeries, function (dSeries) {
                if (_.isUndefined(newData[newGroup])) {
                    newData[newGroup] = {};
                }
                if (_.isUndefined(newData[newGroup][dSeries.name])) {
                    newData[newGroup][dSeries.name] = {};
                }
                if (_.isUndefined(newData[newGroup][dSeries.name][dSeries.aggregate])) {
                    newData[newGroup][dSeries.name][dSeries.aggregate] = [];
                }
                if (_.isUndefined(newData[newGroup][dSeries.name][dSeries.aggregate][keysInsert.idx])) {
                    newData[newGroup][dSeries.name][dSeries.aggregate][keysInsert.idx] = [];
                }
                newData[newGroup][dSeries.name][dSeries.aggregate][keysInsert.idx].push(rawData[i][dSeries.index]);
            });
        }
        // do aggregate
        _.mapObject(newData, function (g) {
            _.mapObject(g, function (groupSeries) {
                _.each(_.keys(groupSeries), function (aggregateType) {
                    for (var i = 0; i < groupSeries[aggregateType].length; i++) {
                        if (groupSeries[aggregateType][i]) {
                            groupSeries[aggregateType][i] = aggregate(groupSeries[aggregateType][i], aggregateType);
                        }
                    }
                });
            });
        });
        var castedAliasSeriesName = new Array();
        var aliasSeriesConfig = {};
        var aliasData = new Array();
        _.each(castedGroups, function (group) {
            _.each(chartConfig.values, function (value, vIdx) {
                _.each(value.cols, function (series) {
                    var seriesName = series.alias ? series.alias : series.col;
                    var newSeriesName = seriesName;
                    if (group && group.length > 0) {
                        var a = [].concat(group);
                        a.push(seriesName);
                        newSeriesName = a.join('-');
                        castedAliasSeriesName.push(a);
                    } else {
                        castedAliasSeriesName.push([seriesName]);
                    }
                    //castedAliasSeriesName.push(newSeriesName);
                    aliasSeriesConfig[newSeriesName] = {type: value.series_type, valueAxisIndex: vIdx};

                    castSeriesData(series, group.join('-'), castedKeys, newData, function (castedData, keyIdx) {
                        if (!aliasData[castedAliasSeriesName.length - 1]) {
                            aliasData[castedAliasSeriesName.length - 1] = new Array();
                        }
                        // Only format decimal
                        aliasData[castedAliasSeriesName.length - 1][keyIdx] = dataFormat(castedData);
                    });
                });
            });
        });
        callback(castedKeys, castedAliasSeriesName, aliasData, aliasSeriesConfig);
    };

    var castSeriesData = function (series, group, castedKeys, newData, iterator) {
        switch (series.type) {
            case 'exp':
                var runExp = compileExp(series.exp);
                for (var i = 0; i < castedKeys.length; i++) {
                    iterator(runExp(newData[group], i), i);
                }
                break;
            default:
                _.each(newData[group][series.col][series.aggregate_type], iterator);
                break;
        }
    };

    var compileExp = function (exp) {
        exp = exp.trim();
        _.each(exp.match(/(sum|avg|count|max|min)\([\u4e00-\u9fa5_a-zA-Z0-9]+\)/g), function (text) {
            var name = text.substring(text.indexOf('(') + 1, text.indexOf(')'));
            var aggregate = text.substring(0, text.indexOf('('));
            exp = exp.replace(text, "groupData['" + name + "']['" + aggregate + "'][keyIdx]");
        });
        return function (groupData, keyIdx) {
            return eval(exp);
        };
    };

    var aggregate = function (data_array, fnc) {
        if (!data_array) {
            return data_array;
        }
        switch (fnc) {
            case 'sum':
                return aggregate_sum(data_array);
            case 'count':
                return aggregate_count(data_array);
            case 'avg':
                return aggregate_avg(data_array);
            case 'max':
                return _.max(data_array, function (f) {
                    return parseFloat(f);
                });
            case 'min':
                return _.min(data_array, function (f) {
                    return parseFloat(f);
                });
        }
    };

    var aggregate_sum = function (data_array) {
        var sum = 0;
        for (var i = 0; i < data_array.length; i++) {
            var f = parseFloat(data_array[i]);
            if (f) {
                sum += f;
            }
        }
        return sum;
    };

    var aggregate_count = function (data_array) {
        return data_array.length;
    };

    var aggregate_avg = function (data_array) {
        var sum = 0;
        var count = 0;
        for (var i = 0; i < data_array.length; i++) {
            var f = parseFloat(data_array[i]);
            if (f) {
                sum += f;
                count++;
            }
        }
        return count == 0 ? 0 : sum / count;
    };

    var getHeaderIndex = function (chartData, col) {
        var result = new Array();
        if (col) {
            for (var j = 0; j < col.length; j++) {
                var idx = _.indexOf(chartData[0], col[j]);
                result.push(idx);
            }
        }
        return result;
    };

    var getRowElements = function (row, elmIdxs) {
        var arr = new Array();
        for (var j = 0; j < elmIdxs.length; j++) {
            var elm = row[elmIdxs[j]];
            arr.push(elm);
        }
        return arr;
    };

    var sortInsert = function (arr, elm, sort) {
        var idx = indexOf(arr, elm);
        if (idx < 0) {
            for (var i = 0; i < arr.length; i++) {
                for (var j = 0; j < arr[i].length; j++) {
                    if (!sort[j] || elm[j] == arr[i][j]) {
                        continue;
                    }
                    var a = Number(elm[j]);
                    var b = Number(arr[i][j]);
                    if (Number.isNaN(a) || Number.isNaN(b)) {
                        a = elm[j];
                        b = arr[i][j];
                    }
                    if ((a > b) ^ (sort[j] != 'asc')) {
                        break;
                    } else {
                        arr.splice(i, 0, elm);
                        return {idx: i, newKey: true};
                    }
                }
            }
            var x = arr.length;
            arr.push(elm);
            return {idx: x, newKey: true};
        } else {
            return {idx: idx, newKey: false};
        }
    };

    var indexOf = function (array, key) {
        var idx = -1;
        outer : for (var i = 0; i < array.length; i++) {
            // if (array[i].length != key.length) {
            //     continue outer;
            // }
            for (var j = 0; j < array[i].length; j++) {
                if (array[i][j] != key[j]) {
                    continue outer;
                }
            }
            idx = i;
            break;
        }
        return idx;
    };
});
<|endoftext|>


<commit_before>import xs from 'xstream';
import Cycle from '@cycle/xstream-run';
import {makeDOMDriver} from '@cycle/dom';
import {html} from 'snabbdom-jsx';

function main(drivers) {
  return {
    DOM: xs.periodic(1000).map(i => i + 1).startWith(0)
      .map(i =>
Seconds elapsed {i}
)
  };
}

const drivers = {
  DOM: makeDOMDriver('#main-container')
};

Cycle.run(main, drivers);
<commit_msg>Change main function variable names (#32)<commit_after>import xs from 'xstream';
import Cycle from '@cycle/xstream-run';
import {makeDOMDriver} from '@cycle/dom';
import {html} from 'snabbdom-jsx';

function main(sources) {
  return {
    DOM: xs.periodic(1000).map(i => i + 1).startWith(0)
      .map(i =>
Seconds elapsed {i}
)
  };
}

const drivers = {
  DOM: makeDOMDriver('#main-container')
};

Cycle.run(main, drivers);
<|endoftext|>


<commit_before>var colors = require("colors");
var TruffleError = require("truffle-error");
var inherits = require("util").inherits;

inherits(CompileError, TruffleError);

function CompileError(message) {
  // Note we trim() because solc likes to add extra whitespace.
  var fancy_message = message.trim() + "\n" + colors.red("Compilation failed. See above.");
  var normal_message = message.trim();

  CompileError.super_.call(this, normal_message);
  this.message = fancy_message;
};

module.exports = CompileError;
<commit_msg>adjust output formatting<commit_after>var colors = require("colors");
var TruffleError = require("truffle-error");
var inherits = require("util").inherits;

inherits(CompileError, TruffleError);

function CompileError(message) {
  // Note we trim() because solc likes to add extra whitespace.
  var fancy_message =
    message.trim() + "\n\n" + colors.red("Compilation failed. See above.");
  var normal_message = message.trim();

  CompileError.super_.call(this, normal_message);
  this.message = fancy_message;
}

module.exports = CompileError;
<|endoftext|>


<commit_before>/**
 * Created by justin on 2014-11-29.
 */

var
    StringStream = require('string-stream'),
    batcher = require('win-common')().batcher;

module.exports = function(config,log) {
  return function (bucketName, provider,promisify) {
    var s = new (function StorageService(){})();
    provider = provider || new AWS.S3({params: {Bucket: bucketName}});

    // technically there is a way to promisfy all in one go, but as can be seen here
    // we do not want all the methods promisified...  (getObject for one...)
    // http://stackoverflow.com/questions/26475486/how-do-i-promisify-the-aws-javascript-sdk
    if(!promisify) {
      provider.deleteBucket = p.promisify(provider.deleteBucket);
      provider.createBucket = p.promisify(provider.createBucket);
      provider.putObject = p.promisify(provider.putObject);
      provider.listBuckets = p.promisify(provider.listBuckets);
      provider.deleteObjects = p.promisify(provider.deleteObjects);
      provider.getSignedUrl = p.promisify(provider.getSignedUrl);
    }

    //provider.getObject = p.promisify(provider.getObject);

    s.destroy = function () {
      return s.emptyBucket().then(function () {
        return provider.deleteBucket().then(function () {
          s._bucketName = null;
        });
      });
    };

    s.emptyBucket = function() {
      return s.ready().then(function () {
        return s.list()
      })
      .then(function (allObjects) {
        log('Deleting:', {
          objectCount: allObjects.length,
          bucketName: bucketName});
        return p.all(batcher.chunk(allObjects, 1000, function (chunk) {
              return provider.deleteObjects({
                Delete: {
                  Objects: _.map(chunk, function (x) {
                    return {Key: x.Key}
                  })
                }
              });
            }
          )
        )
      })
    };

    s.ready = function () {
      if (s._bucketName) {
        return p.resolve(s._bucketName);
      }
      else if (s._async) {
        return s._async;
      }
      else {
        log('Initializing bucket:', bucketName);
        return s._async = provider.createBucket().then(function (data) {
          s._bucketName = bucketName;
          s._async = null;
        });
      }
    };

    s.write = function (params) {
      return s.ready().then(function () {
        var key = params.key || s.genKey(params.suffix);
        return provider.putObject({
          Key: key,
          Body: params.data
        }).then(function () {
          return key;
        });
      });
    };

    s.read = function (key) {
      return s.ready().then(function () {
        return provider.getObject({
          Key: key
        }).createReadStream();
      });
    };

    s.genKey = function (suffix) {
      return new Date().toISOString() + '-' + (suffix || Math.floor(Math.random() * 99999));
    };

    s.listBuckets = function () {
      return provider.listBuckets().then(function (data) {
        return data.Buckets;
      });
    };

    s.readString = function (key) {
      return s.read(key).then(function (fileStream) {
        var deferred = p.defer();
        var ss = new StringStream('');
        fileStream.pipe(ss);
        ss.on('end', function () {
          deferred.resolve(ss.toString());
        });
        fileStream.on('error', function (err) {
          deferred.reject(err);
        });
        return deferred.promise;
      });
    };

    /**
     *
     * @param prefix Only download files that start with this prefix
     * @param marker Only download files after this file (the same thing as s3 api marker.)
     * @param maxCount Will only return up to this amount (it could exceed it by up to 999 at maximum, but no more.)
     * @returns {*}
     */
    s.list = function (prefix, marker, maxCount) {
      return s.ready().then(function () {
        return listAllObjects(prefix, marker, maxCount);
      });
    };

    /***
     * Write the file to S3 if it doesnt already exist.  If file does exist, this does nothing and resolves.
     * @param filePath
     * @param key
     */
    s.writeFile = function(filePath, key) {
      return s.list(key).then(function(results) {
        if (!results || !results.length) {
          return s.write({
            data: fs.createReadStream(filePath),
            key: key
          });
        }
        return key;
      });
    };

    s.save = function(bucket, key, blob) {
      return s.ready().then(function () {
        return p.resolve().then(function() {
          try {
            return JSON.stringify(blob);
          }
          catch (ex) {
            console.log('Failed to stringify body.');
            console.error(ex);
            throw ex;
          }
        })
        .then(function(body) {
          return provider.putObject({
            Key: key,
            Body: body,
            Bucket: bucket
          })
        })
        .then(function () {
          return 's3://'+bucket+'/'+key;
        })
        .catch(function(err) {
          // TODO: check if error is 4xx and if it is just let it bubble up
          // TODO: else if it is 5xx do an exponential backoff retry.
          console.log('Failed to save a file to S3.  Details below:');
          console.log(blob);
          console.error(err);
          throw err;
        });
      });
    };

    s.writeBlobs = function(blobs) {
      return p.map(blobs, function(blob) {
        return s.write(blob);
      });
    };

    s.readBlobs = function(blobs) {
      return p.map(blobs, function(key) {
        return s.readString(key);
      })
      .then(function(data) {
        return _.map(blobs, function(key, idx) {
          return {
            key: key,
            data: data[idx]
          };
        });
      });
    };

    s.getSignedUrl = function(params) {
      // TODO: return signed URL
      //var params = {Bucket: 'bucket', Key: 'key', };
      var s3Params = {
        Key: params.key
      };
      if (params.bucket) s3Params.Bucket = params.bucket;
      if (params.expiryInSecs) s3Params.Expires = params.expiryInSecs;

      return provider.getSignedUrl('getObject', s3Params);
    };

    var partitionKeyCandidates = 'abcdefghijklmnopqrstuvwxyz0123456789'
    var getRandomInt = function() {
      return Math.round(Math.random()*100)
    }

    var getPartitionKey = function(partitionKeySize) {
      var partitionKey = ''
      for(var i =0; i<partitionKeySize; i++) {
        partitionKey += partitionKeyCandidates[getRandomInt()%partitionKeyCandidates.length]
      }
      return partitionKey
    }

    s.generateKey = function(params) {
      params = params || {partitionKeySize: 0}
      params.partitionKeySize = params.partitionKeySize || 0

      var partitionKey = getPartitionKey(params.partitionKeySize)
      var key = ''
      if (partitionKey) key = partitionKey
      return path.join(key,params.path||'')
    }

    function listAllObjects(prefix, marker, maxCount) {
      var allKeys = [], deferred = p.defer();
      maxCount = maxCount || 100000;

      function listAllKeys(marker, prefix) {
        provider.listObjects({Prefix: prefix, Marker: marker, MaxKeys: maxCount}, function (err, data) {
          if (err) {
            deferred.reject(err);
            return;
          }
          allKeys.push(data.Contents);
          if (data.IsTruncated && _.flatten(allKeys).length < maxCount)
            listAllKeys(data.Contents.slice(-1)[0].Key, prefix);
          else
            deferred.resolve(_.flatten(allKeys));
        });
      }

      listAllKeys(marker, prefix);
      return deferred.promise;
    }

    return s;
  };
}
<commit_msg>bugfixes<commit_after>/**
 * Created by justin on 2014-11-29.
 */

var
    StringStream = require('string-stream'),
    batcher = require('win-common')().batcher;

module.exports = function(config,log) {
  return function (bucketName, provider,promisify) {
    var s = new (function StorageService(){})();
    provider = provider || new AWS.S3({params: {Bucket: bucketName}});

    // technically there is a way to promisfy all in one go, but as can be seen here
    // we do not want all the methods promisified...  (getObject for one...)
    // http://stackoverflow.com/questions/26475486/how-do-i-promisify-the-aws-javascript-sdk
    if(!promisify) {
      provider.deleteBucket = p.promisify(provider.deleteBucket);
      provider.createBucket = p.promisify(provider.createBucket);
      provider.putObject = p.promisify(provider.putObject);
      provider.listBuckets = p.promisify(provider.listBuckets);
      provider.deleteObjects = p.promisify(provider.deleteObjects);
      provider.getSignedUrl = p.promisify(provider.getSignedUrl);
    }

    //provider.getObject = p.promisify(provider.getObject);

    s.destroy = function () {
      return s.emptyBucket().then(function () {
        return provider.deleteBucket().then(function () {
          s._bucketName = null;
        });
      });
    };

    s.emptyBucket = function() {
      return s.ready().then(function () {
        return s.list()
      })
      .then(function (allObjects) {
        log('Deleting:', {
          objectCount: allObjects.length,
          bucketName: bucketName});
        return p.all(batcher.chunk(allObjects, 1000, function (chunk) {
              return provider.deleteObjects({
                Delete: {
                  Objects: _.map(chunk, function (x) {
                    return {Key: x.Key}
                  })
                }
              });
            }
          )
        )
      })
    };

    s.ready = function () {
      if (s._bucketName) {
        return p.resolve(s._bucketName);
      }
      else if (s._async) {
        return s._async;
      }
      else {
        log('Initializing bucket:', bucketName);
        return s._async = provider.createBucket().then(function (data) {
          s._bucketName = bucketName;
          s._async = null;
        });
      }
    };

    s.write = function (params) {
      return s.ready().then(function () {
        var key = params.key || s.genKey(params.suffix);
        return provider.putObject({
          Key: key,
          Body: params.data
        }).then(function () {
          return key;
        });
      });
    };

    s.read = function (key) {
      return s.ready().then(function () {
        return provider.getObject({
          Key: key
        }).createReadStream();
      });
    };

    s.genKey = function (suffix) {
      return new Date().toISOString() + '-' + (suffix || Math.floor(Math.random() * 99999));
    };

    s.listBuckets = function () {
      return provider.listBuckets().then(function (data) {
        return data.Buckets;
      });
    };

    s.readString = function (key) {
      console.log('readString()', {key:key})
      return s.read(key).then(function (fileStream) {
        var deferred = p.defer();
        var ss = new StringStream('');
        fileStream.pipe(ss);
        ss.on('end', function () {
          deferred.resolve(ss.toString());
        });
        fileStream.on('error', function (err) {
          deferred.reject(err);
        });
        return deferred.promise;
      });
    };

    /**
     *
     * @param prefix Only download files that start with this prefix
     * @param marker Only download files after this file (the same thing as s3 api marker.)
     * @param maxCount Will only return up to this amount (it could exceed it by up to 999 at maximum, but no more.)
     * @returns {*}
     */
    s.list = function (prefix, marker, maxCount) {
      return s.ready().then(function () {
        return listAllObjects(prefix, marker, maxCount);
      });
    };

    /***
     * Write the file to S3 if it doesnt already exist.  If file does exist, this does nothing and resolves.
     * @param filePath
     * @param key
     */
    s.writeFile = function(filePath, key) {
      return s.list(key).then(function(results) {
        if (!results || !results.length) {
          return s.write({
            data: fs.createReadStream(filePath),
            key: key
          });
        }
        return key;
      });
    };

    s.save = function(bucket, key, blob) {
      return s.ready().then(function () {
        return p.resolve().then(function() {
          try {
            return JSON.stringify(blob);
          }
          catch (ex) {
            console.log('Failed to stringify body.');
            console.error(ex);
            throw ex;
          }
        })
        .then(function(body) {
          return provider.putObject({
            Key: key,
            Body: body,
            Bucket: bucket
          })
        })
        .then(function () {
          return 's3://'+bucket+'/'+key;
        })
        .catch(function(err) {
          // TODO: check if error is 4xx and if it is just let it bubble up
          // TODO: else if it is 5xx do an exponential backoff retry.
          console.log('Failed to save a file to S3.  Details below:');
          console.log(blob);
          console.error(err);
          throw err;
        });
      });
    };

    s.writeBlobs = function(blobs) {
      return p.map(blobs, function(blob) {
        return s.write(blob);
      });
    };

    s.readBlobs = function(blobs) {
      return p.map(blobs, function(key) {
        return s.readString(key);
      })
      .then(function(data) {
        return _.map(blobs, function(key, idx) {
          return {
            key: key,
            data: data[idx]
          };
        });
      });
    };

    s.getSignedUrl = function(params) {
      // TODO: return signed URL
      //var params = {Bucket: 'bucket', Key: 'key', };
      var s3Params = {
        Key: params.key
      };
      if (params.bucket) s3Params.Bucket = params.bucket;
      if (params.expiryInSecs) s3Params.Expires = params.expiryInSecs;

      return provider.getSignedUrl('getObject', s3Params);
    };

    var partitionKeyCandidates = 'abcdefghijklmnopqrstuvwxyz0123456789'
    var getRandomInt = function() {
      return Math.round(Math.random()*100)
    }

    var getPartitionKey = function(partitionKeySize) {
      var partitionKey = ''
      for(var i =0; i<partitionKeySize; i++) {
        partitionKey += partitionKeyCandidates[getRandomInt()%partitionKeyCandidates.length]
      }
      return partitionKey
    }

    s.generateKey = function(params) {
      params = params || {partitionKeySize: 0}
      params.partitionKeySize = params.partitionKeySize || 0

      var partitionKey = getPartitionKey(params.partitionKeySize)
      var key = ''
      if (partitionKey) key = partitionKey
      return path.join(key,params.path||'')
    }

    function listAllObjects(prefix, marker, maxCount) {
      var allKeys = [], deferred = p.defer();
      maxCount = maxCount || 100000;

      function listAllKeys(marker, prefix) {
        provider.listObjects({Prefix: prefix, Marker: marker, MaxKeys: maxCount}, function (err, data) {
          if (err) {
            deferred.reject(err);
            return;
          }
          allKeys.push(data.Contents);
          if (data.IsTruncated && _.flatten(allKeys).length < maxCount)
            listAllKeys(data.Contents.slice(-1)[0].Key, prefix);
          else
            deferred.resolve(_.flatten(allKeys));
        });
      }

      listAllKeys(marker, prefix);
      return deferred.promise;
    }

    return s;
  };
}
<|endoftext|>