<commit_before>/*jslint indent: 2, nomen: true, maxlen: 100, white: true  plusplus: true */
/*global beforeEach, afterEach */
/*global describe, it, expect */
/*global window, eb, loadFixtures, document */
/*global $, _, d3*/
/*global NodeShaper*/

////////////////////////////////////////////////////////////////////////////////
/// @brief Graph functionality
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

(function () {
  "use strict";

  describe('Node Shaper', function () {
    var svg;

    beforeEach(function () {
      svg = document.createElement("svg");
      document.body.appendChild(svg);
    });

    afterEach(function () {
      document.body.removeChild(svg);
    });

    it('should be able to draw a node', function () {
      var node = [{"id": 1}],
        shaper = new NodeShaper(d3.select("svg"));
      shaper.drawNodes(node);
      expect($("svg .node").length).toEqual(1);
      expect($("svg .node")[0]).toBeDefined();
    });

    it('should be able to draw many nodes', function () {
      var nodes = [{"id": 1}, {"id": 2}, {"id": 3}],
        shaper = new NodeShaper(d3.select("svg"));
      shaper.drawNodes(nodes);
      expect($("svg .node").length).toEqual(3);
    });

    it('should be able to add a click event', function () {
      var nodes = [{"id": 1}, {"id": 2}, {"id": 3}],
      clicked = [false, false, false],
      click = function (node) {
        clicked[node.id-1] = !clicked[node.id-1];
      },
      shaper = new NodeShaper(d3.select("svg")),
      first,
      third;

      shaper.on("click", click);
      shaper.drawNodes(nodes);
      first = $("#1").get(0);
      third = $("#3").get(0);
      first.__onclick();
      third.__onclick();

      expect($("svg .node").length).toEqual(3);
      expect(clicked[0]).toBeTruthy();
      expect(clicked[2]).toBeTruthy();
      expect(clicked[1]).toBeFalsy();
    });

    describe('configured for circle', function () {
      var shaper;

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"), {"shape": NodeShaper.shapes.CIRCLE});
      });

      it('should draw circle elements', function () {
        var node = [{"id": 1}];
        shaper.drawNodes(node);
        expect($("svg .node")[0]).toBeDefined();
        expect($("svg .node").length).toEqual(1);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg circle")[0]).toBeDefined();
        expect($("svg circle").length).toEqual(1);
        expect($("svg .node circle")[0]).toBeDefined();
        expect($("svg .node circle").length).toEqual(1);
      });

      it('should be able to use a fixed radius', function() {
        shaper = new NodeShaper(d3.select("svg"),
        {
          "shape": NodeShaper.shapes.CIRCLE,
          "size": 15
        });
        var nodes = [
          {"id": 1},
          {"id": 2},
          {"id": 3},
          {"id": 4},
          {"id": 5}
        ];
        shaper.drawNodes(nodes);
        expect($("svg #1 circle")[0].attributes.r.value).toEqual("15");
        expect($("svg #2 circle")[0].attributes.r.value).toEqual("15");
        expect($("svg #3 circle")[0].attributes.r.value).toEqual("15");
        expect($("svg #4 circle")[0].attributes.r.value).toEqual("15");
        expect($("svg #5 circle")[0].attributes.r.value).toEqual("15");
      });

      it('should be able to use a function to determine the radius', function() {
        var radiusFunction = function (node) {
          return 10 + node.id;
        },
        nodes = [
          {"id": 1},
          {"id": 2},
          {"id": 3},
          {"id": 4},
          {"id": 5}
        ];
        shaper = new NodeShaper(d3.select("svg"),
        {
          "shape": NodeShaper.shapes.CIRCLE,
          "size": radiusFunction
        });
        shaper.drawNodes(nodes);
        expect($("svg #1 circle")[0].attributes.r.value).toEqual("11");
        expect($("svg #2 circle")[0].attributes.r.value).toEqual("12");
        expect($("svg #3 circle")[0].attributes.r.value).toEqual("13");
        expect($("svg #4 circle")[0].attributes.r.value).toEqual("14");
        expect($("svg #5 circle")[0].attributes.r.value).toEqual("15");

      });

    });

    describe('configured for rectangle', function () {
      var shaper;

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"), {"shape": NodeShaper.shapes.RECT});
      });

      it('should draw rect elements', function () {
        var node = [{"id": 1}];
        shaper.drawNodes(node);
        expect($("svg .node")[0]).toBeDefined();
        expect($("svg .node").length).toEqual(1);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg rect")[0]).toBeDefined();
        expect($("svg rect").length).toEqual(1);
        expect($("svg .node rect")[0]).toBeDefined();
        expect($("svg .node rect").length).toEqual(1);
      });

      it('should be able to use a fixed size', function() {
        shaper = new NodeShaper(d3.select("svg"),
        {
          "shape": NodeShaper.shapes.RECT,
          "width": 15,
          "height": 10
        });
        var nodes = [
          {"id": 1},
          {"id": 2},
          {"id": 3},
          {"id": 4},
          {"id": 5}
        ];
        shaper.drawNodes(nodes);
        expect($("svg #1 rect")[0].attributes.width.value).toEqual("15");
        expect($("svg #2 rect")[0].attributes.width.value).toEqual("15");
        expect($("svg #3 rect")[0].attributes.width.value).toEqual("15");
        expect($("svg #4 rect")[0].attributes.width.value).toEqual("15");
        expect($("svg #5 rect")[0].attributes.width.value).toEqual("15");

        expect($("svg #1 rect")[0].attributes.height.value).toEqual("10");
        expect($("svg #2 rect")[0].attributes.height.value).toEqual("10");
        expect($("svg #3 rect")[0].attributes.height.value).toEqual("10");
        expect($("svg #4 rect")[0].attributes.height.value).toEqual("10");
        expect($("svg #5 rect")[0].attributes.height.value).toEqual("10");

      });

      it('should be able to use a function to determine the size', function() {
        var widthFunction = function (node) {
          return 10 + node.id;
        },
        heightFunction = function (node) {
          return 10 - node.id;
        },
        nodes = [
          {"id": 1},
          {"id": 2},
          {"id": 3},
          {"id": 4},
          {"id": 5}
        ];
        shaper = new NodeShaper(d3.select("svg"),
        {
          "shape": NodeShaper.shapes.RECT,
          "width": widthFunction,
          "height": heightFunction
        });
        shaper.drawNodes(nodes);
        expect($("svg #1 rect")[0].attributes.width.value).toEqual("11");
        expect($("svg #2 rect")[0].attributes.width.value).toEqual("12");
        expect($("svg #3 rect")[0].attributes.width.value).toEqual("13");
        expect($("svg #4 rect")[0].attributes.width.value).toEqual("14");
        expect($("svg #5 rect")[0].attributes.width.value).toEqual("15");

        expect($("svg #1 rect")[0].attributes.height.value).toEqual("9");
        expect($("svg #2 rect")[0].attributes.height.value).toEqual("8");
        expect($("svg #3 rect")[0].attributes.height.value).toEqual("7");
        expect($("svg #4 rect")[0].attributes.height.value).toEqual("6");
        expect($("svg #5 rect")[0].attributes.height.value).toEqual("5");

      });

    });

    describe('configured for label', function () {
      var shaper;

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"), {
          "label": "label"
        });
      });

      it('should add a text element', function () {
        var node = [{"id": 1, "label": "MyLabel"}];
        shaper.drawNodes(node);
        expect($("svg .node")[0]).toBeDefined();
        expect($("svg .node").length).toEqual(1);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg text")[0]).toBeDefined();
        expect($("svg text").length).toEqual(1);
        expect($("svg .node text")[0]).toBeDefined();
        expect($("svg .node text").length).toEqual(1);
        expect($("svg .node text")[0].textContent).toEqual("MyLabel");
      });

      it('should ignore other attributes', function () {
        var nodes = [
          {"id": 1, "label": "correct"},
          {"id": 2, "alt": "incorrect"},
          {"id": 3, "alt": "incorrect"},
          {"id": 4, "label": "correct", "alt": "incorrect"}];
        shaper.drawNodes(nodes);
        expect($("svg #1 text")[0].textContent).toEqual("correct");
        expect($("svg #2 text")[0].textContent).toEqual("");
        expect($("svg #3 text")[0].textContent).toEqual("");
        expect($("svg #4 text")[0].textContent).toEqual("correct");
      });

      it('should also print "0" as a label', function() {
        var node = [{"id": 1, "label": 0}];
        shaper.drawNodes(node);
        expect($("svg .node text")[0]).toBeDefined();
        expect($("svg .node text").length).toEqual(1);
        expect($("svg .node text")[0].textContent).toEqual("0");
      });

    });

    describe('using a function for labels', function () {
      var shaper,
      labelFunction = function (node) {
        if (node.id === 4) {
          return "correct";
        }
        if (node.label) {
          return node.label;
        }
        if (node.alt) {
          return node.alt;
        }
        return "default";
      };

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"), {
          "label": labelFunction
        });
      });

      it('should display the correct labels according to the function', function () {
        var nodes = [
          {"id": 1, "label": "correct"},
          {"id": 2, "alt": "correct"},
          {"id": 3, "label": "correct", "alt": "incorrect"},
          {"id": 4, "label": "incorrect", "alt": "incorrect"},
          {"id": 5}
        ];
        shaper.drawNodes(nodes);
        expect($("text").length).toEqual(5);
        expect($("#1 text")[0].textContent).toEqual("correct");
        expect($("#2 text")[0].textContent).toEqual("correct");
        expect($("#3 text")[0].textContent).toEqual("correct");
        expect($("#4 text")[0].textContent).toEqual("correct");
        expect($("#5 text")[0].textContent).toEqual("default");
      });

    });

    describe('that has already drawn some nodes', function () {

      var shaper, nodes;

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"));
        nodes = [{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}];
        shaper.drawNodes(nodes);
      });

      it('should be able to draw more nodes', function () {
        nodes.push({"id": 6});
        nodes.push({"id": 7});
        nodes.push({"id": 8});

        shaper.drawNodes(nodes);
        expect($("svg .node").length).toEqual(8);
      });

      it('should be able to remove nodes', function () {
        nodes.splice(1, 1);
        nodes.splice(3, 1);
        shaper.drawNodes(nodes);
        expect($("svg .node").length).toEqual(3);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg #3")[0]).toBeDefined();
        expect($("svg #4")[0]).toBeDefined();

        expect($("svg #2")[0]).toBeUndefined();
        expect($("svg #5")[0]).toBeUndefined();
      });

      it('should be able to add some nodes and remove other nodes', function () {
        nodes.splice(1, 1);
        nodes.splice(3, 1);
        nodes.push({"id": 6});
        nodes.push({"id": 7});
        nodes.push({"id": 8});
        shaper.drawNodes(nodes);
        expect($("svg .node").length).toEqual(6);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg #3")[0]).toBeDefined();
        expect($("svg #4")[0]).toBeDefined();
        expect($("svg #6")[0]).toBeDefined();
        expect($("svg #7")[0]).toBeDefined();
        expect($("svg #8")[0]).toBeDefined();

        expect($("svg #2")[0]).toBeUndefined();
        expect($("svg #5")[0]).toBeUndefined();
      });

    });

    describe('that has an other parent then body.svg', function () {

      it('should draw nodes in the correct position', function () {
        var internalObject = d3.select("svg")
          .append("g")
          .append("svg")
          .append("g"),
          node = [{"id": 1}],
          shaper = new NodeShaper(internalObject);

        shaper.drawNodes(node);

        expect($("svg g svg g .node").length).toEqual(1);
      });
    });

    describe('configured for circle with label', function () {
      var shaper;

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"),
            {
              "shape": NodeShaper.shapes.CIRCLE,
              "label": "label"
            }
          );
      });

      it('should draw circle elements', function () {
        var node = [{
          "id": 1,
          "label": "correct"
        }];
        shaper.drawNodes(node);
        expect($("svg .node").length).toEqual(1);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg circle")[0]).toBeDefined();
        expect($("svg circle").length).toEqual(1);
        expect($("svg .node circle")[0]).toBeDefined();
        expect($("svg .node circle").length).toEqual(1);

        expect($("svg text").length).toEqual(1);
        expect($("svg .node text").length).toEqual(1);
        expect($("svg .node text")[0].textContent).toEqual("correct");
      });

    });

  });

}());<commit_msg>Fix in NodeShaper spec<commit_after>/*jslint indent: 2, nomen: true, maxlen: 100, white: true  plusplus: true */
/*global beforeEach, afterEach */
/*global describe, it, expect */
/*global window, eb, loadFixtures, document */
/*global $, _, d3*/
/*global NodeShaper*/

////////////////////////////////////////////////////////////////////////////////
/// @brief Graph functionality
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Michael Hackstein
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

(function () {
  "use strict";

  describe('Node Shaper', function () {
    var svg;

    beforeEach(function () {
      svg = document.createElement("svg");
      document.body.appendChild(svg);
    });

    afterEach(function () {
      document.body.removeChild(svg);
    });

    it('should be able to draw a node', function () {
      var node = [{_id: 1}],
        shaper = new NodeShaper(d3.select("svg"));
      shaper.drawNodes(node);
      expect($("svg .node").length).toEqual(1);
      expect($("svg .node")[0]).toBeDefined();
    });

    it('should be able to draw many nodes', function () {
      var nodes = [{_id: 1}, {_id: 2}, {_id: 3}],
        shaper = new NodeShaper(d3.select("svg"));
      shaper.drawNodes(nodes);
      expect($("svg .node").length).toEqual(3);
    });

    it('should be able to add a click event', function () {
      var nodes = [{_id: 1}, {_id: 2}, {_id: 3}],
      clicked = [false, false, false],
      click = function (node) {
        clicked[node._id-1] = !clicked[node._id-1];
      },
      shaper = new NodeShaper(d3.select("svg")),
      first,
      third;

      shaper.on("click", click);
      shaper.drawNodes(nodes);
      first = $("#1").get(0);
      third = $("#3").get(0);
      first.__onclick();
      third.__onclick();

      expect($("svg .node").length).toEqual(3);
      expect(clicked[0]).toBeTruthy();
      expect(clicked[2]).toBeTruthy();
      expect(clicked[1]).toBeFalsy();
    });

    describe('configured for circle', function () {
      var shaper;

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"), {"shape": NodeShaper.shapes.CIRCLE});
      });

      it('should draw circle elements', function () {
        var node = [{_id: 1}];
        shaper.drawNodes(node);
        expect($("svg .node")[0]).toBeDefined();
        expect($("svg .node").length).toEqual(1);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg circle")[0]).toBeDefined();
        expect($("svg circle").length).toEqual(1);
        expect($("svg .node circle")[0]).toBeDefined();
        expect($("svg .node circle").length).toEqual(1);
      });

      it('should be able to use a fixed radius', function() {
        shaper = new NodeShaper(d3.select("svg"),
        {
          "shape": NodeShaper.shapes.CIRCLE,
          "size": 15
        });
        var nodes = [
          {_id: 1},
          {_id: 2},
          {_id: 3},
          {_id: 4},
          {_id: 5}
        ];
        shaper.drawNodes(nodes);
        expect($("svg #1 circle")[0].attributes.r.value).toEqual("15");
        expect($("svg #2 circle")[0].attributes.r.value).toEqual("15");
        expect($("svg #3 circle")[0].attributes.r.value).toEqual("15");
        expect($("svg #4 circle")[0].attributes.r.value).toEqual("15");
        expect($("svg #5 circle")[0].attributes.r.value).toEqual("15");
      });

      it('should be able to use a function to determine the radius', function() {
        var radiusFunction = function (node) {
          return 10 + node._id;
        },
        nodes = [
          {_id: 1},
          {_id: 2},
          {_id: 3},
          {_id: 4},
          {_id: 5}
        ];
        shaper = new NodeShaper(d3.select("svg"),
        {
          "shape": NodeShaper.shapes.CIRCLE,
          "size": radiusFunction
        });
        shaper.drawNodes(nodes);
        expect($("svg #1 circle")[0].attributes.r.value).toEqual("11");
        expect($("svg #2 circle")[0].attributes.r.value).toEqual("12");
        expect($("svg #3 circle")[0].attributes.r.value).toEqual("13");
        expect($("svg #4 circle")[0].attributes.r.value).toEqual("14");
        expect($("svg #5 circle")[0].attributes.r.value).toEqual("15");

      });

    });

    describe('configured for rectangle', function () {
      var shaper;

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"), {"shape": NodeShaper.shapes.RECT});
      });

      it('should draw rect elements', function () {
        var node = [{_id: 1}];
        shaper.drawNodes(node);
        expect($("svg .node")[0]).toBeDefined();
        expect($("svg .node").length).toEqual(1);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg rect")[0]).toBeDefined();
        expect($("svg rect").length).toEqual(1);
        expect($("svg .node rect")[0]).toBeDefined();
        expect($("svg .node rect").length).toEqual(1);
      });

      it('should be able to use a fixed size', function() {
        shaper = new NodeShaper(d3.select("svg"),
        {
          "shape": NodeShaper.shapes.RECT,
          "width": 15,
          "height": 10
        });
        var nodes = [
          {_id: 1},
          {_id: 2},
          {_id: 3},
          {_id: 4},
          {_id: 5}
        ];
        shaper.drawNodes(nodes);
        expect($("svg #1 rect")[0].attributes.width.value).toEqual("15");
        expect($("svg #2 rect")[0].attributes.width.value).toEqual("15");
        expect($("svg #3 rect")[0].attributes.width.value).toEqual("15");
        expect($("svg #4 rect")[0].attributes.width.value).toEqual("15");
        expect($("svg #5 rect")[0].attributes.width.value).toEqual("15");

        expect($("svg #1 rect")[0].attributes.height.value).toEqual("10");
        expect($("svg #2 rect")[0].attributes.height.value).toEqual("10");
        expect($("svg #3 rect")[0].attributes.height.value).toEqual("10");
        expect($("svg #4 rect")[0].attributes.height.value).toEqual("10");
        expect($("svg #5 rect")[0].attributes.height.value).toEqual("10");

      });

      it('should be able to use a function to determine the size', function() {
        var widthFunction = function (node) {
          return 10 + node._id;
        },
        heightFunction = function (node) {
          return 10 - node._id;
        },
        nodes = [
          {_id: 1},
          {_id: 2},
          {_id: 3},
          {_id: 4},
          {_id: 5}
        ];
        shaper = new NodeShaper(d3.select("svg"),
        {
          "shape": NodeShaper.shapes.RECT,
          "width": widthFunction,
          "height": heightFunction
        });
        shaper.drawNodes(nodes);
        expect($("svg #1 rect")[0].attributes.width.value).toEqual("11");
        expect($("svg #2 rect")[0].attributes.width.value).toEqual("12");
        expect($("svg #3 rect")[0].attributes.width.value).toEqual("13");
        expect($("svg #4 rect")[0].attributes.width.value).toEqual("14");
        expect($("svg #5 rect")[0].attributes.width.value).toEqual("15");

        expect($("svg #1 rect")[0].attributes.height.value).toEqual("9");
        expect($("svg #2 rect")[0].attributes.height.value).toEqual("8");
        expect($("svg #3 rect")[0].attributes.height.value).toEqual("7");
        expect($("svg #4 rect")[0].attributes.height.value).toEqual("6");
        expect($("svg #5 rect")[0].attributes.height.value).toEqual("5");

      });

    });

    describe('configured for label', function () {
      var shaper;

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"), {
          "label": "label"
        });
      });

      it('should add a text element', function () {
        var node = [{_id: 1, "label": "MyLabel"}];
        shaper.drawNodes(node);
        expect($("svg .node")[0]).toBeDefined();
        expect($("svg .node").length).toEqual(1);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg text")[0]).toBeDefined();
        expect($("svg text").length).toEqual(1);
        expect($("svg .node text")[0]).toBeDefined();
        expect($("svg .node text").length).toEqual(1);
        expect($("svg .node text")[0].textContent).toEqual("MyLabel");
      });

      it('should ignore other attributes', function () {
        var nodes = [
          {_id: 1, "label": "correct"},
          {_id: 2, "alt": "incorrect"},
          {_id: 3, "alt": "incorrect"},
          {_id: 4, "label": "correct", "alt": "incorrect"}];
        shaper.drawNodes(nodes);
        expect($("svg #1 text")[0].textContent).toEqual("correct");
        expect($("svg #2 text")[0].textContent).toEqual("");
        expect($("svg #3 text")[0].textContent).toEqual("");
        expect($("svg #4 text")[0].textContent).toEqual("correct");
      });

      it('should also print "0" as a label', function() {
        var node = [{_id: 1, "label": 0}];
        shaper.drawNodes(node);
        expect($("svg .node text")[0]).toBeDefined();
        expect($("svg .node text").length).toEqual(1);
        expect($("svg .node text")[0].textContent).toEqual("0");
      });

    });

    describe('using a function for labels', function () {
      var shaper,
      labelFunction = function (node) {
        if (node._id === 4) {
          return "correct";
        }
        if (node.label) {
          return node.label;
        }
        if (node.alt) {
          return node.alt;
        }
        return "default";
      };

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"), {
          "label": labelFunction
        });
      });

      it('should display the correct labels according to the function', function () {
        var nodes = [
          {_id: 1, "label": "correct"},
          {_id: 2, "alt": "correct"},
          {_id: 3, "label": "correct", "alt": "incorrect"},
          {_id: 4, "label": "incorrect", "alt": "incorrect"},
          {_id: 5}
        ];
        shaper.drawNodes(nodes);
        expect($("text").length).toEqual(5);
        expect($("#1 text")[0].textContent).toEqual("correct");
        expect($("#2 text")[0].textContent).toEqual("correct");
        expect($("#3 text")[0].textContent).toEqual("correct");
        expect($("#4 text")[0].textContent).toEqual("correct");
        expect($("#5 text")[0].textContent).toEqual("default");
      });

    });

    describe('that has already drawn some nodes', function () {

      var shaper, nodes;

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"));
        nodes = [{_id: 1}, {_id: 2}, {_id: 3}, {_id: 4}, {_id: 5}];
        shaper.drawNodes(nodes);
      });

      it('should be able to draw more nodes', function () {
        nodes.push({_id: 6});
        nodes.push({_id: 7});
        nodes.push({_id: 8});

        shaper.drawNodes(nodes);
        expect($("svg .node").length).toEqual(8);
      });

      it('should be able to remove nodes', function () {
        nodes.splice(1, 1);
        nodes.splice(3, 1);
        shaper.drawNodes(nodes);
        expect($("svg .node").length).toEqual(3);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg #3")[0]).toBeDefined();
        expect($("svg #4")[0]).toBeDefined();

        expect($("svg #2")[0]).toBeUndefined();
        expect($("svg #5")[0]).toBeUndefined();
      });

      it('should be able to add some nodes and remove other nodes', function () {
        nodes.splice(1, 1);
        nodes.splice(3, 1);
        nodes.push({_id: 6});
        nodes.push({_id: 7});
        nodes.push({_id: 8});
        shaper.drawNodes(nodes);
        expect($("svg .node").length).toEqual(6);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg #3")[0]).toBeDefined();
        expect($("svg #4")[0]).toBeDefined();
        expect($("svg #6")[0]).toBeDefined();
        expect($("svg #7")[0]).toBeDefined();
        expect($("svg #8")[0]).toBeDefined();

        expect($("svg #2")[0]).toBeUndefined();
        expect($("svg #5")[0]).toBeUndefined();
      });

    });

    describe('that has an other parent then body.svg', function () {

      it('should draw nodes in the correct position', function () {
        var internalObject = d3.select("svg")
          .append("g")
          .append("svg")
          .append("g"),
          node = [{_id: 1}],
          shaper = new NodeShaper(internalObject);

        shaper.drawNodes(node);

        expect($("svg g svg g .node").length).toEqual(1);
      });
    });

    describe('configured for circle with label', function () {
      var shaper;

      beforeEach(function () {
        shaper = new NodeShaper(d3.select("svg"),
            {
              "shape": NodeShaper.shapes.CIRCLE,
              "label": "label"
            }
          );
      });

      it('should draw circle elements', function () {
        var node = [{
          _id: 1,
          "label": "correct"
        }];
        shaper.drawNodes(node);
        expect($("svg .node").length).toEqual(1);
        expect($("svg #1")[0]).toBeDefined();
        expect($("svg circle")[0]).toBeDefined();
        expect($("svg circle").length).toEqual(1);
        expect($("svg .node circle")[0]).toBeDefined();
        expect($("svg .node circle").length).toEqual(1);

        expect($("svg text").length).toEqual(1);
        expect($("svg .node text").length).toEqual(1);
        expect($("svg .node text")[0].textContent).toEqual("correct");
      });

    });

  });

}());<|endoftext|>


<commit_before>/*jshint browser: true */
/*jshint unused: false */
/*global describe, beforeEach, afterEach, it, spyOn, expect*/
/*global arangoHelper*/

(function () {
    "use strict";

    describe("The document view", function () {

        var model, view, div;

        beforeEach(function () {
            div = document.createElement("div");
            div.id = "content";
            document.body.appendChild(div);

            model = new window.arangoDocument({
                _key: "123",
                _id: "v/123",
                _rev: "123",
                name: "alice"
            });

            view = new window.DocumentView({
                collection: new window.arangoDocument()
            });

            view.collection.add(model);
            view.render();
        });

        afterEach(function () {
            document.body.removeChild(div);
        });

        it("assert the basics", function () {
            expect(view.colid).toEqual(0);
            expect(view.colid).toEqual(0);
            expect(view.events).toEqual({
                "click #saveDocumentButton": "saveDocument",
                "click #deleteDocumentButton" : "deleteDocumentModal",
                "click #confirmDeleteDocument" : "deleteDocument",
                "click #document-from" : "navigateToDocument",
                "click #document-to" : "navigateToDocument",
                "dblclick #documentEditor tr" : "addProperty"
            });
        });

        it("should copy a model into editor", function () {
            spyOn(view.editor, "set");
            view.fillEditor();
            expect(view.editor.set).toHaveBeenCalled();
        });

        it("should save type document", function () {
            view.type = 'document';
            spyOn(view.collection, "saveDocument").andReturn(true);
            view.saveDocument();
            expect(view.collection.saveDocument).toHaveBeenCalled();
        });

        it("should save type edge", function () {
            view.type = 'edge';
            spyOn(view.collection, "saveEdge").andReturn(true);
            view.saveDocument();
            expect(view.collection.saveEdge).toHaveBeenCalled();
        });

        it("should save type edge and return error", function () {
            view.type = 'edge';
            spyOn(view.collection, "saveEdge").andReturn(false);
            spyOn(arangoHelper, "arangoError");
            view.saveDocument();
            expect(arangoHelper.arangoError).toHaveBeenCalled();
        });

        it("should save type document and return error", function () {
            view.type = 'document';
            spyOn(view.collection, "saveDocument").andReturn(false);
            spyOn(arangoHelper, "arangoError");
            view.saveDocument();
            expect(arangoHelper.arangoError).toHaveBeenCalled();
        });

        it("check document view type check positive", function () {
            view.collection.add(model);
            spyOn(view, "fillEditor");

            spyOn(view.collection, "getEdge").andReturn(true);
            spyOn(view.collection, "getDocument").andReturn(true);
            var result = view.typeCheck('edge');
            expect(result).toEqual(true);
            expect(view.collection.getEdge).toHaveBeenCalled();
            result = view.typeCheck('document');
            expect(view.collection.getDocument).toHaveBeenCalled();
            expect(result).toEqual(true);
        });

        it("check document view type check negative", function () {
            view.collection.add(model);
            spyOn(view, "fillEditor");

            var result = view.typeCheck('easddge');
            expect(result).not.toEqual(true);

            result = view.typeCheck(false);
            expect(result).not.toEqual(true);

            result = view.typeCheck(123);
            expect(result).not.toEqual(true);
        });

        it("should remove readonly keys", function () {
            var object = {
                    hello: 123,
                    wrong: true,
                    _key: "123",
                    _rev: "adasda",
                    _id: "paosdjfp1321"
                },
                shouldObject = {
                    hello: 123,
                    wrong: true
                },
                result = view.removeReadonlyKeys(object);

            expect(result).toEqual(shouldObject);
        });

        it("should modify the breadcrumb", function () {
            var bar = document.createElement("div"),
                emptyBar = document.createElement("div");
            bar.id = 'transparentHeader';

            view.breadcrumb();
            expect(emptyBar).not.toBe(bar);
        });

        it("escaped", function () {
            expect(view.escaped('&<>"\'')).toEqual("&<>"'");
        });

        it("should addProperty in existing json document", function () {

            var eDummy = {
                    currentTarget :  {
                        cells : [
                            "",
                            "",
                            {
                                childNodes : [
                                    {
                                        childNodes : [
                                            {
                                                childNodes : [
                                                    {
                                                        childNodes : [
                                                            "",
                                                            {
                                                                childNodes : [
                                                                    {
                                                                        textContent : "bla"

                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                }, editorDummy  = {

                node : {
                    search : function () {

                    }
                }

            }, nodeDummy1 =  {elem : "value", node : {_onInsertAfter : function () {}}},
            nodeDummy2 =  {elem : "field", node : {_onInsertAfter : function () {}}} ;
            spyOn(editorDummy.node, "search").andReturn([
                nodeDummy1,
                nodeDummy2,
                nodeDummy1
            ]);
            spyOn(nodeDummy1.node, "_onInsertAfter");
            spyOn(nodeDummy2.node, "_onInsertAfter");
            view.editor = editorDummy;

            view.addProperty(eDummy);

            expect(editorDummy.node.search).toHaveBeenCalledWith("bla");
            expect(nodeDummy1.node._onInsertAfter).not.toHaveBeenCalled();
            expect(nodeDummy2.node._onInsertAfter).toHaveBeenCalledWith(
                undefined, undefined, "auto");

        });

        it("should addProperty in existing json document in first position", function () {

            var eDummy = {
                    currentTarget :  {
                        cells : [
                            "",
                            "",
                            {
                                childNodes : [
                                    {
                                        childNodes : [
                                            {
                                                childNodes : [
                                                    {
                                                        childNodes : [
                                                            "",
                                                            {
                                                                childNodes : [
                                                                    {
                                                                        textContent : "object"

                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                }, editorDummy  = {

                    node : {
                        search : function () {

                        },
                        childs : [
                            {
                                focus : function () {},
                                _onInsertBefore : function () {

                                }
                            }
                        ]
                    },
                    get : function () {

                    },
                    set : function () {

                    }

                }, nodeDummy1 =  {elem : "value", _onInsertAfter : function () {}},
                nodeDummy2 =  {elem : "value", _onInsertAfter : function () {}} ;
            spyOn(editorDummy.node, "search").andReturn([
                nodeDummy1,
                nodeDummy2,
                nodeDummy1
            ]);
            spyOn(nodeDummy1, "_onInsertAfter");
            spyOn(nodeDummy2, "_onInsertAfter");

            spyOn(editorDummy, "get").andReturn([
                nodeDummy1,
                nodeDummy2,
                nodeDummy1
            ]);

            spyOn(editorDummy, "set");
            spyOn(editorDummy.node.childs[0], "_onInsertBefore");
            spyOn(editorDummy.node.childs[0], "focus");

            view.editor = editorDummy;

            view.addProperty(eDummy);

            expect(editorDummy.node.search).not.toHaveBeenCalled();
            expect(editorDummy.node.childs[0].focus).not.toHaveBeenCalled();
            expect(editorDummy.node.childs[0]._onInsertBefore).toHaveBeenCalledWith(
                undefined, undefined, "auto");
            expect(editorDummy.get).toHaveBeenCalled();
            expect(editorDummy.set).not.toHaveBeenCalled();

        });

        it("should addProperty in new json document in first position", function () {

            var eDummy = {
                    currentTarget :  {
                        cells : [
                            "",
                            "",
                            {
                                childNodes : [
                                    {
                                        childNodes : [
                                            {
                                                childNodes : [
                                                    {
                                                        childNodes : [
                                                            "",
                                                            {
                                                                childNodes : [
                                                                    {
                                                                        textContent : "object"

                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                }, editorDummy  = {

                    node : {
                        search : function () {

                        },
                        childs : [
                            {
                                focus : function () {},
                                _onInsertBefore : function () {

                                }
                            }
                        ]
                    },
                    get : function () {

                    },
                    set : function () {

                    }

                }, nodeDummy1 =  {elem : "value", _onInsertAfter : function () {}},
                nodeDummy2 =  {elem : "value", _onInsertAfter : function () {}} ;
            spyOn(editorDummy.node, "search").andReturn([
                nodeDummy1,
                nodeDummy2,
                nodeDummy1
            ]);
            spyOn(nodeDummy1, "_onInsertAfter");
            spyOn(nodeDummy2, "_onInsertAfter");

            spyOn(editorDummy, "get").andReturn(undefined);

            spyOn(editorDummy, "set");
            spyOn(editorDummy.node.childs[0], "_onInsertBefore");
            spyOn(editorDummy.node.childs[0], "focus");

            view.editor = editorDummy;

            view.addProperty(eDummy);

            expect(editorDummy.node.search).not.toHaveBeenCalled();
            expect(editorDummy.node.childs[0].focus).toHaveBeenCalledWith("field");
            expect(editorDummy.node.childs[0]._onInsertBefore).not.toHaveBeenCalled();
            expect(editorDummy.get).toHaveBeenCalled();
            expect(editorDummy.set).toHaveBeenCalledWith({
                "": ""
            });

        });

    });

}());
<commit_msg>Fixed frontend test<commit_after>/*jshint browser: true */
/*jshint unused: false */
/*global describe, beforeEach, afterEach, it, spyOn, expect*/
/*global arangoHelper*/

(function () {
    "use strict";

    describe("The document view", function () {

        var model, view, div;

        beforeEach(function () {
            div = document.createElement("div");
            div.id = "content";
            document.body.appendChild(div);

            model = new window.arangoDocument({
                _key: "123",
                _id: "v/123",
                _rev: "123",
                name: "alice"
            });

            view = new window.DocumentView({
                collection: new window.arangoDocument()
            });

            view.collection.add(model);
            view.render();
        });

        afterEach(function () {
            document.body.removeChild(div);
        });

        it("assert the basics", function () {
            expect(view.colid).toEqual(0);
            expect(view.colid).toEqual(0);
            expect(view.events).toEqual({
                "click #saveDocumentButton": "saveDocument",
                "click #deleteDocumentButton" : "deleteDocumentModal",
                "click #confirmDeleteDocument" : "deleteDocument",
                "click #document-from" : "navigateToDocument",
                "click #document-to" : "navigateToDocument",
                "dblclick #documentEditor tr" : "addProperty",
                "focusout .ace_editor": "parseInvalidJson"
            });
        });

        it("should copy a model into editor", function () {
            spyOn(view.editor, "set");
            view.fillEditor();
            expect(view.editor.set).toHaveBeenCalled();
        });

        it("should save type document", function () {
            view.type = 'document';
            spyOn(view.collection, "saveDocument").andReturn(true);
            view.saveDocument();
            expect(view.collection.saveDocument).toHaveBeenCalled();
        });

        it("should save type edge", function () {
            view.type = 'edge';
            spyOn(view.collection, "saveEdge").andReturn(true);
            view.saveDocument();
            expect(view.collection.saveEdge).toHaveBeenCalled();
        });

        it("should save type edge and return error", function () {
            view.type = 'edge';
            spyOn(view.collection, "saveEdge").andReturn(false);
            spyOn(arangoHelper, "arangoError");
            view.saveDocument();
            expect(arangoHelper.arangoError).toHaveBeenCalled();
        });

        it("should save type document and return error", function () {
            view.type = 'document';
            spyOn(view.collection, "saveDocument").andReturn(false);
            spyOn(arangoHelper, "arangoError");
            view.saveDocument();
            expect(arangoHelper.arangoError).toHaveBeenCalled();
        });

        it("check document view type check positive", function () {
            view.collection.add(model);
            spyOn(view, "fillEditor");

            spyOn(view.collection, "getEdge").andReturn(true);
            spyOn(view.collection, "getDocument").andReturn(true);
            var result = view.typeCheck('edge');
            expect(result).toEqual(true);
            expect(view.collection.getEdge).toHaveBeenCalled();
            result = view.typeCheck('document');
            expect(view.collection.getDocument).toHaveBeenCalled();
            expect(result).toEqual(true);
        });

        it("check document view type check negative", function () {
            view.collection.add(model);
            spyOn(view, "fillEditor");

            var result = view.typeCheck('easddge');
            expect(result).not.toEqual(true);

            result = view.typeCheck(false);
            expect(result).not.toEqual(true);

            result = view.typeCheck(123);
            expect(result).not.toEqual(true);
        });

        it("should remove readonly keys", function () {
            var object = {
                    hello: 123,
                    wrong: true,
                    _key: "123",
                    _rev: "adasda",
                    _id: "paosdjfp1321"
                },
                shouldObject = {
                    hello: 123,
                    wrong: true
                },
                result = view.removeReadonlyKeys(object);

            expect(result).toEqual(shouldObject);
        });

        it("should modify the breadcrumb", function () {
            var bar = document.createElement("div"),
                emptyBar = document.createElement("div");
            bar.id = 'transparentHeader';

            view.breadcrumb();
            expect(emptyBar).not.toBe(bar);
        });

        it("escaped", function () {
            expect(view.escaped('&<>"\'')).toEqual("&<>"'");
        });

        it("should addProperty in existing json document", function () {

            var eDummy = {
                    currentTarget :  {
                        cells : [
                            "",
                            "",
                            {
                                childNodes : [
                                    {
                                        childNodes : [
                                            {
                                                childNodes : [
                                                    {
                                                        childNodes : [
                                                            "",
                                                            {
                                                                childNodes : [
                                                                    {
                                                                        textContent : "bla"

                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                }, editorDummy  = {

                node : {
                    search : function () {

                    }
                }

            }, nodeDummy1 =  {elem : "value", node : {_onInsertAfter : function () {}}},
            nodeDummy2 =  {elem : "field", node : {_onInsertAfter : function () {}}} ;
            spyOn(editorDummy.node, "search").andReturn([
                nodeDummy1,
                nodeDummy2,
                nodeDummy1
            ]);
            spyOn(nodeDummy1.node, "_onInsertAfter");
            spyOn(nodeDummy2.node, "_onInsertAfter");
            view.editor = editorDummy;

            view.addProperty(eDummy);

            expect(editorDummy.node.search).toHaveBeenCalledWith("bla");
            expect(nodeDummy1.node._onInsertAfter).not.toHaveBeenCalled();
            expect(nodeDummy2.node._onInsertAfter).toHaveBeenCalledWith(
                undefined, undefined, "auto");

        });

        it("should addProperty in existing json document in first position", function () {

            var eDummy = {
                    currentTarget :  {
                        cells : [
                            "",
                            "",
                            {
                                childNodes : [
                                    {
                                        childNodes : [
                                            {
                                                childNodes : [
                                                    {
                                                        childNodes : [
                                                            "",
                                                            {
                                                                childNodes : [
                                                                    {
                                                                        textContent : "object"

                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                }, editorDummy  = {

                    node : {
                        search : function () {

                        },
                        childs : [
                            {
                                focus : function () {},
                                _onInsertBefore : function () {

                                }
                            }
                        ]
                    },
                    get : function () {

                    },
                    set : function () {

                    }

                }, nodeDummy1 =  {elem : "value", _onInsertAfter : function () {}},
                nodeDummy2 =  {elem : "value", _onInsertAfter : function () {}} ;
            spyOn(editorDummy.node, "search").andReturn([
                nodeDummy1,
                nodeDummy2,
                nodeDummy1
            ]);
            spyOn(nodeDummy1, "_onInsertAfter");
            spyOn(nodeDummy2, "_onInsertAfter");

            spyOn(editorDummy, "get").andReturn([
                nodeDummy1,
                nodeDummy2,
                nodeDummy1
            ]);

            spyOn(editorDummy, "set");
            spyOn(editorDummy.node.childs[0], "_onInsertBefore");
            spyOn(editorDummy.node.childs[0], "focus");

            view.editor = editorDummy;

            view.addProperty(eDummy);

            expect(editorDummy.node.search).not.toHaveBeenCalled();
            expect(editorDummy.node.childs[0].focus).not.toHaveBeenCalled();
            expect(editorDummy.node.childs[0]._onInsertBefore).toHaveBeenCalledWith(
                undefined, undefined, "auto");
            expect(editorDummy.get).toHaveBeenCalled();
            expect(editorDummy.set).not.toHaveBeenCalled();

        });

        it("should addProperty in new json document in first position", function () {

            var eDummy = {
                    currentTarget :  {
                        cells : [
                            "",
                            "",
                            {
                                childNodes : [
                                    {
                                        childNodes : [
                                            {
                                                childNodes : [
                                                    {
                                                        childNodes : [
                                                            "",
                                                            {
                                                                childNodes : [
                                                                    {
                                                                        textContent : "object"

                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                }, editorDummy  = {

                    node : {
                        search : function () {

                        },
                        childs : [
                            {
                                focus : function () {},
                                _onInsertBefore : function () {

                                }
                            }
                        ]
                    },
                    get : function () {

                    },
                    set : function () {

                    }

                }, nodeDummy1 =  {elem : "value", _onInsertAfter : function () {}},
                nodeDummy2 =  {elem : "value", _onInsertAfter : function () {}} ;
            spyOn(editorDummy.node, "search").andReturn([
                nodeDummy1,
                nodeDummy2,
                nodeDummy1
            ]);
            spyOn(nodeDummy1, "_onInsertAfter");
            spyOn(nodeDummy2, "_onInsertAfter");

            spyOn(editorDummy, "get").andReturn(undefined);

            spyOn(editorDummy, "set");
            spyOn(editorDummy.node.childs[0], "_onInsertBefore");
            spyOn(editorDummy.node.childs[0], "focus");

            view.editor = editorDummy;

            view.addProperty(eDummy);

            expect(editorDummy.node.search).not.toHaveBeenCalled();
            expect(editorDummy.node.childs[0].focus).toHaveBeenCalledWith("field");
            expect(editorDummy.node.childs[0]._onInsertBefore).not.toHaveBeenCalled();
            expect(editorDummy.get).toHaveBeenCalled();
            expect(editorDummy.set).toHaveBeenCalledWith({
                "": ""
            });

        });

    });

}());
<|endoftext|>


<commit_before>
(function() {

cdb.admin.forms = {};

var polygon_stroke = {
     name: 'Polygon Stroke',
     form: {
        'line-width': { type: 'width', value: 1 },
        'line-color': { type: 'color' , value: '#00FF00' },
        'line-opacity': { type: 'opacity', value: 0.6 }
    }
};

var label_text = {
     name: 'Label Text',
     form: {
      'text-name': { type: 'select' }  /* value is filled by wizard */
     }
};

var label_text_properties = {
    name: 'Label Font',
    form: {
      'text-face-name': {
        type: 'select',
        value: "Open Sans Regular",
        extra: ["Open Sans Regular","Open Sans Bold", "Open Sans Italic"]
      },
      'text-size': { type: 'number', value: 10, min: 1 },
      'text-fill': { type: 'color' , value: '#000' }
    }
};

var label_halo_properties = {
  name: 'Label Halo',
  form: {
    'text-halo-fill':  { type: 'color' , value: '#AAA' },
    'text-halo-radius': { type: 'number', value: 1, min: 0}
  }
};

/*
 *
 * text-face-name:@sans_bold;
  text-placement:point;
  text-fill:@country_text;
  text-halo-fill: @country_halo;
  text-halo-radius: 1;
  */

cdb.admin.forms.simple_form = [
    {
       name: 'Marker Fill',
       form: {
          'marker-fill': { type: 'color' , value: '#00FF00' },
          'marker-opacity': { type: 'opacity' , value: 0.6 },
          'marker-allow-overlap': { type: 'hidden', value: true }
      }
    },
    {
       name: 'Marker Stroke',
       form: {
          'marker-line-width': { type: 'width', value: 1 },
          'marker-line-color': { type: 'color' , value: '#00FF00' },
          'marker-line-opacity': { type: 'opacity', value: 0.6 }
      }
    },
    {
       name: 'Polygon Fill',
       form: {
          'polygon-fill': { type: 'color' , value: '#00FF00' },
          'polygon-opacity': { type: 'opacity' , value: 0.6 }
      }
    },
    polygon_stroke,
    label_text,
    label_text_properties,
    label_halo_properties
];

cdb.admin.forms.bubble_form = [
  {
     name: 'Column',
     form: { 'property': { type: 'select' } } /* value is filled by wizard */
  },
  {
     name: 'Radius',
     title: 'Radius (min-max)',
     form: {
       'radius_min': { type: 'number', value: 1 },
       'radius_max': { type: 'number', value: 10 }
     },
     text: '- to -'
  },
  {
     name: 'Bubble fill',
     form: {
       'marker-fill': { type: 'color', value: '#00FF00' },
       'marker-opacity': { type: 'opacity', value: 0.9 }
     }
  },
  {
     name: 'Bubble stroke',
     form: {
       'marker-line-width': { type: 'number', value: 1 },
       'marker-line-color': { type: 'color', value: '#00FF00' },
       'marker-line-opacity': { type: 'opacity', value: 0.9 }
     }
  }
];

cdb.admin.forms.choroplet = [
  {
     name: 'column',
     form: { 'property': { type: 'select' } } /* value is filled by wizard */
  },
  {
     name: 'Method',
     form: {
       'method': { type: 'select', value: 'Quantiles', extra: ['Quantiles'] }
     }
  },
  {
     name: 'Buckets',
     form: {
       'method': { type: 'select', value: '5 Buckets', extra: ['3 Buckets', '5 Buckets', '7 Buckets'] }
     }
  },

  {
     name: 'Color Ramp',
     form: {
       'color_ramp': { type: 'select', value: 'red', extra:['pink', 'red', 'black', 'green', 'blue'] },
       'polygon-opacity': { type: 'opacity', value: 0.9 }
     }
  },

  polygon_stroke
];

cdb.admin.forms.density = [
  {
     name: 'Method',
     form: {
       'method': { type: 'select', value: 'Hexagons', extra: ['Hexagons', 'rectangles'] }
     }
  },
  {
     name: 'Buckets',
     form: {
       'method': { type: 'select', value: '5 Buckets', extra: ['3 Buckets', '5 Buckets', '7 Buckets'] }
     }
  },

  {
     name: 'color ramp',
     form: {
       'color_ramp': { type: 'select', value: 'red', extra:['pink', 'red', 'black', 'green', 'blue'] },
       'polygon-opacity': { type: 'opacity', value: 0.9 }
     }
  },

  polygon_stroke,
  {
    name: 'Polygon size',
    form: {
      'polygon-size': { type: 'number', value: 15, min: 1, max: 100 },
    }
  }
];

})();
<commit_msg>added marker radius to wizard<commit_after>
(function() {

cdb.admin.forms = {};

var polygon_stroke = {
     name: 'Polygon Stroke',
     form: {
        'line-width': { type: 'width', value: 1 },
        'line-color': { type: 'color' , value: '#00FF00' },
        'line-opacity': { type: 'opacity', value: 0.6 }
    }
};

var label_text = {
     name: 'Label Text',
     form: {
      'text-name': { type: 'select' }  /* value is filled by wizard */
     }
};

var label_text_properties = {
    name: 'Label Font',
    form: {
      'text-face-name': {
        type: 'select',
        value: "Open Sans Regular",
        extra: ["Open Sans Regular","Open Sans Bold", "Open Sans Italic"]
      },
      'text-size': { type: 'number', value: 10, min: 1 },
      'text-fill': { type: 'color' , value: '#000' }
    }
};

var label_halo_properties = {
  name: 'Label Halo',
  form: {
    'text-halo-fill':  { type: 'color' , value: '#AAA' },
    'text-halo-radius': { type: 'number', value: 1, min: 0}
  }
};

cdb.admin.forms.simple_form = [
    {
       name: 'Marker Fill',
       form: {
          'marker-fill': { type: 'color' , value: '#00FF00' },
          'marker-opacity': { type: 'opacity' , value: 0.6 },
          'marker-allow-overlap': { type: 'hidden', value: true }
      }
    },
    {
       name: 'Marker Radius',
       form: {
          'marker-width': { type: 'width', value: 4 }
       }
    },
    {
       name: 'Marker Stroke',
       form: {
          'marker-line-width': { type: 'width', value: 1 },
          'marker-line-color': { type: 'color' , value: '#00FF00' },
          'marker-line-opacity': { type: 'opacity', value: 0.6 }
      }
    },
    {
       name: 'Polygon Fill',
       form: {
          'polygon-fill': { type: 'color' , value: '#00FF00' },
          'polygon-opacity': { type: 'opacity' , value: 0.6 }
      }
    },
    polygon_stroke,
    label_text,
    label_text_properties,
    label_halo_properties
];

cdb.admin.forms.bubble_form = [
  {
     name: 'Column',
     form: { 'property': { type: 'select' } } /* value is filled by wizard */
  },
  {
     name: 'Radius',
     title: 'Radius (min-max)',
     form: {
       'radius_min': { type: 'number', value: 1 },
       'radius_max': { type: 'number', value: 10 }
     },
     text: '- to -'
  },
  {
     name: 'Bubble fill',
     form: {
       'marker-fill': { type: 'color', value: '#00FF00' },
       'marker-opacity': { type: 'opacity', value: 0.9 }
     }
  },
  {
     name: 'Bubble stroke',
     form: {
       'marker-line-width': { type: 'number', value: 1 },
       'marker-line-color': { type: 'color', value: '#00FF00' },
       'marker-line-opacity': { type: 'opacity', value: 0.9 }
     }
  }
];

cdb.admin.forms.choroplet = [
  {
     name: 'column',
     form: { 'property': { type: 'select' } } /* value is filled by wizard */
  },
  {
     name: 'Method',
     form: {
       'method': { type: 'select', value: 'Quantiles', extra: ['Quantiles'] }
     }
  },
  {
     name: 'Buckets',
     form: {
       'method': { type: 'select', value: '5 Buckets', extra: ['3 Buckets', '5 Buckets', '7 Buckets'] }
     }
  },

  {
     name: 'Color Ramp',
     form: {
       'color_ramp': { type: 'select', value: 'red', extra:['pink', 'red', 'black', 'green', 'blue'] },
       'polygon-opacity': { type: 'opacity', value: 0.9 }
     }
  },

  polygon_stroke
];

cdb.admin.forms.density = [
  {
     name: 'Method',
     form: {
       'method': { type: 'select', value: 'Hexagons', extra: ['Hexagons', 'rectangles'] }
     }
  },
  {
     name: 'Buckets',
     form: {
       'method': { type: 'select', value: '5 Buckets', extra: ['3 Buckets', '5 Buckets', '7 Buckets'] }
     }
  },

  {
     name: 'color ramp',
     form: {
       'color_ramp': { type: 'select', value: 'red', extra:['pink', 'red', 'black', 'green', 'blue'] },
       'polygon-opacity': { type: 'opacity', value: 0.9 }
     }
  },

  polygon_stroke,
  {
    name: 'Polygon size',
    form: {
      'polygon-size': { type: 'number', value: 15, min: 1, max: 100 },
    }
  }
];

})();
<|endoftext|>


<commit_before>var Backbone = require('backbone');

var TYPE_TO_ANALYSIS_DEFINITION_MODEL_MAP = {
  'source': require('./analysis-definitions/analysis-source-definition-model'),
  'trade-area': require('./analysis-definitions/analysis-trade-area-definition-model')
};
var SOURCE_ID_REGEX = /^([a-zA-Z]+)(\d+)$/;

/**
 * Collection of analysis definitions
 */
module.exports = Backbone.Collection.extend({

  model: function (d, opts) {
    var self = opts.collection;
    // var Klass = TYPE_TO_ANALYSIS_DEFINITION_MODEL_MAP[d.type] || cdb.core.Model;
    var Klass = TYPE_TO_ANALYSIS_DEFINITION_MODEL_MAP[d.type];
    if (!Klass) throw new Error('no analysis definition class found for type ' + d.type);
    var m = new Klass(d, {
      parse: true, // make sure data is structured as expected
      collection: self,
      configModel: self._configModel
    });

    return m;
  },

  initialize: function (models, options) {
    if (!options.configModel) throw new Error('configModel is required');

    this._configModel = options.configModel;
  },

  /**
   * Get next id in sequence of given source id.
   * @param {String} sourceId e.g. 'B2'
   * @return {String} e.g. 'B3'
   */
  nextId: function (sourceId) {
    if (!sourceId || !sourceId.match) throw new Error('invalid sourceId');
    var matches = sourceId.match(SOURCE_ID_REGEX);
    if (!matches || matches.length < 3) throw new Error('invalid sourceId');

    var letters = matches[1];
    var nextNumber = parseInt(matches[2], 10) + 1;

    return letters + nextNumber;
  }

});
<commit_msg>Remove unnecessary comment<commit_after>var Backbone = require('backbone');

var TYPE_TO_ANALYSIS_DEFINITION_MODEL_MAP = {
  'source': require('./analysis-definitions/analysis-source-definition-model'),
  'trade-area': require('./analysis-definitions/analysis-trade-area-definition-model')
};
var SOURCE_ID_REGEX = /^([a-zA-Z]+)(\d+)$/;

/**
 * Collection of analysis definitions
 */
module.exports = Backbone.Collection.extend({

  model: function (d, opts) {
    var self = opts.collection;
    var Klass = TYPE_TO_ANALYSIS_DEFINITION_MODEL_MAP[d.type];
    if (!Klass) throw new Error('no analysis definition class found for type ' + d.type);
    var m = new Klass(d, {
      parse: true, // make sure data is structured as expected
      collection: self,
      configModel: self._configModel
    });

    return m;
  },

  initialize: function (models, options) {
    if (!options.configModel) throw new Error('configModel is required');

    this._configModel = options.configModel;
  },

  /**
   * Get next id in sequence of given source id.
   * @param {String} sourceId e.g. 'B2'
   * @return {String} e.g. 'B3'
   */
  nextId: function (sourceId) {
    if (!sourceId || !sourceId.match) throw new Error('invalid sourceId');
    var matches = sourceId.match(SOURCE_ID_REGEX);
    if (!matches || matches.length < 3) throw new Error('invalid sourceId');

    var letters = matches[1];
    var nextNumber = parseInt(matches[2], 10) + 1;

    return letters + nextNumber;
  }

});
<|endoftext|>


<commit_before>/**
 * Task
 *
 * @module      ::  Model
 * @description ::  Model represents single task on taskboard. Tasks are attached to specified user story, phase,
 *                  type and user.
 */
var jQuery = require("jquery");
var async = require("async");
var moment = require("moment-timezone");

module.exports = {
    schema: true,
    attributes: {
        // Relation to Story model
        storyId: {
            type:       'integer',
            required:   true
        },
        // Relation to User model
        userId: {
            type:       'integer',
            defaultsTo: 0
        },
        // Relation to Phase model
        phaseId: {
            type:       'integer',
            required:   true,
            defaultsTo: 0
        },
        // Relation to Type model
        typeId: {
            type:       'integer',
            required:   true,
            defaultsTo: 1
        },
        title: {
            type:       'string',
            required:   true,
            minLength:  5
        },
        description: {
            type:       'text',
            defaultsTo: ''
        },
        isDone: {
            type:       'boolean',
            required:   true,
            defaultsTo: 0
        },
        timeStart: {
            type:       'datetime'
        },
        timeEnd: {
            type:       'datetime'
        },

        objectTitle: function() {
            return this.title;
        },
        createdAtObject: function () {
            return (this.createdAt && this.createdAt != '0000-00-00')
                ? DateService.convertDateObjectToUtc(this.createdAt) : null;
        },
        updatedAtObject: function () {
            return (this.updatedAt && this.updatedAt != '0000-00-00')
                ? DateService.convertDateObjectToUtc(this.updatedAt) : null;
        },
        timeStartObject: function() {
            return (this.timeStart && this.timeStart != '0000-00-00 00:00:00')
                ? DateService.convertDateObjectToUtc(this.timeStart) : null;
        },
        timeEndObject: function() {
            return (this.timeEnd && this.timeEnd != '0000-00-00 00:00:00')
                ? DateService.convertDateObjectToUtc(this.timeEnd) : null;
        },
        timeDuration: function() {
            var output;

            if (moment.isMoment(this.timeStartObject()) && moment.isMoment(this.timeEndObject())) {
                output = this.timeEndObject().diff(this.timeStartObject(), 'seconds');
            } else {
                output = 0;
            }

            return output;
        },
        timeDurationHuman: function() {
            var output;

            if (moment.isMoment(this.timeStartObject()) && this.timeStartObject().isValid()
                && moment.isMoment(this.timeEndObject()) && this.timeEndObject().isValid()
            ) {
                output = this.timeStartObject().from(this.timeEndObject(), true);
            } else {
                output = "";
            }

            return output;
        }
    },

    // Lifecycle Callbacks

    /**
     * Before create callback. Basically we just want to make sure that isDone bit is set to false.
     *
     * @param   {sails.model.task}  values
     * @param   {Function}          cb
     */
    beforeCreate: function(values, cb) {
        values.isDone = false;

        cb();
    },

    /**
     * Before update callback we want to check desired phase id isDone bit and
     * update task data with that.
     *
     * @param   {sails.model.task}  values
     * @param   {Function}          cb
     */
    beforeUpdate: function(values, cb) {
        if (values.phaseId) {
            async.parallel(
                {
                    // Fetch phase data
                    phase: function(callback) {
                        DataService.getPhase(values.phaseId, callback);
                    },

                    // Fetch task data
                    task: function(callback) {
                        DataService.getTask(values.id, callback);
                    }
                },
                function (error, data) {
                    if (error) {
                        cb(error);
                    } else {
                        values.isDone = data.phase.isDone;
                        values.timeEnd = values.isDone ? new Date() : null;

                        // We can assume that this update is from the board, so set start time if needed
                        if (values.phaseId !== data.task.phaseId
                            && (!data.task.timeStart || data.task.timeStart == '0000-00-00 00:00:00')
                        ) {
                            values.timeStart = new Date();
                        }

                        cb();
                    }
                }
            );
        } else {
            cb();
        }
    },

    /**
     * Before destroy callback. In this we want to check 'isDone' bit for all task which
     * are attached to same user story as task which is going to be deleted.
     *
     * If all task are done (isDone === true) we can update current story as done. Note
     * that if story hasn't any task it cannot be "done".
     *
     * @param   {Number}    taskId
     * @param   {Function}  cb
     */
    beforeDestroy: function(taskId, cb) {
        Task
            .findOne(taskId)
            .done(function(error, /** sails.model.task */task) {
                if (error) {
                    cb(error)
                } else {
                    HistoryService.remove('Task', task.id);

                    Task
                        .find()
                        .where({storyId: task.storyId})
                        .where({id: {'!': task.id}})
                        .done(function(error, /** sails.model.task[] */tasks) {
                            var isDone = true;
                            var timeEnd = null;

                            if (_.size(tasks) > 0) {
                                // Iterate story tasks
                                jQuery.each(tasks, function(key, /** sails.model.task */task) {
                                    if (!task.isDone) {
                                        isDone = false;
                                    }
                                });
                            } else { // If there are no tasks, story cannot be done
                                isDone = false;
                            }

                            if (isDone) {
                                timeEnd = new Date();
                            }

                            // Update story data
                            Story
                                .update(
                                    {id: task.storyId},
                                    {isDone: isDone, timeEnd: timeEnd},
                                    function(error, /** sails.model.story[] */stories) {
                                        if (error) {
                                            cb(error);
                                        } else {
                                            _.each(stories, function(story) {
                                                Story.publishUpdate(story.id, story.toJSON());
                                            });

                                            cb();
                                        }
                                });
                        });
                }
            });
    },

    /**
     * After task creation we can set current story automatic to not done status (isDone = false).
     *
     * @param   {sails.model.task}  values
     * @param   {Function}          cb
     */
    afterCreate: function(values, cb) {
        HistoryService.write('Task', values);

        // Update story data
        Story
            .update(
                {id: values.storyId},
                {isDone: 0, timeEnd: null},
                function(error, /** sails.model.story[] */stories) {
                    if (error) {
                        cb(error);
                    } else {
                        _.each(stories, function(story) {
                            Story.publishUpdate(story.id, story.toJSON());
                        });

                        cb();
                    }
            });
    },

    /**
     * After update callback. In this we want to check 'isDone' bit for all task which
     * are attached to same user story as updated.
     *
     * If all task are done (isDone === true) we can update current story as done.
     *
     * @param   {sails.model.task}  values
     * @param   {Function}          cb
     */
    afterUpdate: function(values, cb) {
        HistoryService.write('Task', values);

        async.parallel(
            {
                // Fetch phase data
                story: function(callback) {
                    DataService.getStory(values.storyId, callback);
                },

                // Fetch task data
                task: function(callback) {
                    DataService.getTask(values.id, callback);
                },

                tasks: function(callback) {
                    DataService.getTasks({storyId: values.storyId}, callback);
                }
            },
            function (error, data) {
                if (error) {
                    cb(error);
                } else {
                    var isDone = true;
                    var timeEnd = new Date();

                    _.each(data.tasks, function(task) {
                        if (!task.isDone) {
                            isDone = false;
                            timeEnd = null;
                        }
                    });

                    var where = {id: data.story.id};
                    var updateData = {
                        isDone: isDone,
                        timeEnd: timeEnd
                    };

                    if ((!data.story.timeStart || data.story.timeStart == '0000-00-00 00:00:00')
                        && data.task.timeStart && data.task.timeStart != '0000-00-00 00:00:00') {
                        updateData['timeStart'] = new Date();
                    }

                    Story
                        .update(where, updateData, function(error, stories) {
                            if (error) {
                                cb(error);
                            } else {
                                _.each(stories, function(story) {
                                    Story.publishUpdate(story.id, story.toJSON());
                                });

                                cb();
                            }
                        });
                }
            }
        );
    }
};
<commit_msg>Implemented task and story start time reset if task is moved back to first phase.<commit_after>/**
 * Task
 *
 * @module      ::  Model
 * @description ::  Model represents single task on taskboard. Tasks are attached to specified user story, phase,
 *                  type and user.
 */
var jQuery = require("jquery");
var async = require("async");
var moment = require("moment-timezone");

module.exports = {
    schema: true,
    attributes: {
        // Relation to Story model
        storyId: {
            type:       'integer',
            required:   true
        },
        // Relation to User model
        userId: {
            type:       'integer',
            defaultsTo: 0
        },
        // Relation to Phase model
        phaseId: {
            type:       'integer',
            required:   true,
            defaultsTo: 0
        },
        // Relation to Type model
        typeId: {
            type:       'integer',
            required:   true,
            defaultsTo: 1
        },
        title: {
            type:       'string',
            required:   true,
            minLength:  5
        },
        description: {
            type:       'text',
            defaultsTo: ''
        },
        isDone: {
            type:       'boolean',
            required:   true,
            defaultsTo: 0
        },
        timeStart: {
            type:       'datetime'
        },
        timeEnd: {
            type:       'datetime'
        },

        objectTitle: function() {
            return this.title;
        },
        createdAtObject: function () {
            return (this.createdAt && this.createdAt != '0000-00-00')
                ? DateService.convertDateObjectToUtc(this.createdAt) : null;
        },
        updatedAtObject: function () {
            return (this.updatedAt && this.updatedAt != '0000-00-00')
                ? DateService.convertDateObjectToUtc(this.updatedAt) : null;
        },
        timeStartObject: function() {
            return (this.timeStart && this.timeStart != '0000-00-00 00:00:00')
                ? DateService.convertDateObjectToUtc(this.timeStart) : null;
        },
        timeEndObject: function() {
            return (this.timeEnd && this.timeEnd != '0000-00-00 00:00:00')
                ? DateService.convertDateObjectToUtc(this.timeEnd) : null;
        },
        timeDuration: function() {
            var output;

            if (moment.isMoment(this.timeStartObject()) && moment.isMoment(this.timeEndObject())) {
                output = this.timeEndObject().diff(this.timeStartObject(), 'seconds');
            } else {
                output = 0;
            }

            return output;
        },
        timeDurationHuman: function() {
            var output;

            if (moment.isMoment(this.timeStartObject()) && this.timeStartObject().isValid()
                && moment.isMoment(this.timeEndObject()) && this.timeEndObject().isValid()
            ) {
                output = this.timeStartObject().from(this.timeEndObject(), true);
            } else {
                output = "";
            }

            return output;
        }
    },

    // Lifecycle Callbacks

    /**
     * Before create callback. Basically we just want to make sure that isDone bit is set to false.
     *
     * @param   {sails.model.task}  values
     * @param   {Function}          cb
     */
    beforeCreate: function(values, cb) {
        values.isDone = false;

        cb();
    },

    /**
     * Before update callback we want to check desired phase id isDone bit and
     * update task data with that.
     *
     * @param   {sails.model.task}  values
     * @param   {Function}          cb
     */
    beforeUpdate: function(values, cb) {
        if (values.phaseId) {
            async.parallel(
                {
                    // Fetch phase data
                    phase: function(callback) {
                        DataService.getPhase(values.phaseId, callback);
                    },

                    // Fetch task data
                    task: function(callback) {
                        DataService.getTask(values.id, callback);
                    }
                },
                function (error, data) {
                    if (error) {
                        cb(error);
                    } else {
                        values.isDone = data.phase.isDone;
                        values.timeEnd = values.isDone ? new Date() : null;

                        // Task is updated to first phase, so set start and end times to null
                        if (data.phase.order === 0) {
                            values.timeStart = null;
                            values.timeEnd = null;
                        } else if (values.phaseId !== data.task.phaseId // We can assume that this update is from the board, so set start time if needed
                            && (!data.task.timeStart || data.task.timeStart == '0000-00-00 00:00:00')
                        ) {
                            values.timeStart = new Date();
                        }

                        cb();
                    }
                }
            );
        } else {
            cb();
        }
    },

    /**
     * Before destroy callback. In this we want to check 'isDone' bit for all task which
     * are attached to same user story as task which is going to be deleted.
     *
     * If all task are done (isDone === true) we can update current story as done. Note
     * that if story hasn't any task it cannot be "done".
     *
     * @param   {Number}    taskId
     * @param   {Function}  cb
     */
    beforeDestroy: function(taskId, cb) {
        Task
            .findOne(taskId)
            .done(function(error, /** sails.model.task */task) {
                if (error) {
                    cb(error)
                } else {
                    HistoryService.remove('Task', task.id);

                    Task
                        .find()
                        .where({storyId: task.storyId})
                        .where({id: {'!': task.id}})
                        .done(function(error, /** sails.model.task[] */tasks) {
                            var isDone = true;
                            var timeEnd = null;

                            if (_.size(tasks) > 0) {
                                // Iterate story tasks
                                jQuery.each(tasks, function(key, /** sails.model.task */task) {
                                    if (!task.isDone) {
                                        isDone = false;
                                    }
                                });
                            } else { // If there are no tasks, story cannot be done
                                isDone = false;
                            }

                            if (isDone) {
                                timeEnd = new Date();
                            }

                            // Update story data
                            Story
                                .update(
                                    {id: task.storyId},
                                    {isDone: isDone, timeEnd: timeEnd},
                                    function(error, /** sails.model.story[] */stories) {
                                        if (error) {
                                            cb(error);
                                        } else {
                                            _.each(stories, function(story) {
                                                Story.publishUpdate(story.id, story.toJSON());
                                            });

                                            cb();
                                        }
                                });
                        });
                }
            });
    },

    /**
     * After task creation we can set current story automatic to not done status (isDone = false).
     *
     * @param   {sails.model.task}  values
     * @param   {Function}          cb
     */
    afterCreate: function(values, cb) {
        HistoryService.write('Task', values);

        // Update story data
        Story
            .update(
                {id: values.storyId},
                {isDone: 0, timeEnd: null},
                function(error, /** sails.model.story[] */stories) {
                    if (error) {
                        cb(error);
                    } else {
                        _.each(stories, function(story) {
                            Story.publishUpdate(story.id, story.toJSON());
                        });

                        cb();
                    }
            });
    },

    /**
     * After update callback. In this we want to check 'isDone' bit for all task which
     * are attached to same user story as updated.
     *
     * If all task are done (isDone === true) we can update current story as done.
     *
     * @param   {sails.model.task}  values
     * @param   {Function}          cb
     */
    afterUpdate: function(values, cb) {
        HistoryService.write('Task', values);

        async.parallel(
            {
                // Fetch phase data
                story: function(callback) {
                    DataService.getStory(values.storyId, callback);
                },

                // Fetch task data
                task: function(callback) {
                    DataService.getTask(values.id, callback);
                },

                // Fetch tasks that are attached to same story
                tasks: function(callback) {
                    DataService.getTasks({storyId: values.storyId}, callback);
                },

                // Fetch phases
                phases: function(callback) {
                    DataService.getPhases({}, callback);
                }
            },
            function (error, data) {
                if (error) {
                    cb(error);
                } else {
                    var isDone = true;
                    var timeEnd = new Date();
                    var taskPhases = [];

                    _.each(data.tasks, function(task) {
                        if (!task.isDone) {
                            isDone = false;
                            timeEnd = null;
                        }

                        taskPhases.push(task.phaseId);
                    });

                    taskPhases = _.uniq(taskPhases);

                    var updateData = {
                        isDone: isDone,
                        timeEnd: timeEnd
                    };

                    if (taskPhases.length === 1) {
                        DataService.getPhase(taskPhases[0], function(error, phase) {
                            if (error) {
                                cb(error);
                            } else if (phase.order == 0) {
                                updateData['timeStart'] = null;
                            }

                            updateStory(data, updateData);
                        });
                    } else if ((!data.story.timeStart || data.story.timeStart == '0000-00-00 00:00:00')
                        && data.task.timeStart && data.task.timeStart != '0000-00-00 00:00:00') {
                        updateData['timeStart'] = new Date();

                        updateStory(data, updateData);
                    } else {
                        updateStory(data, updateData);
                    }
                }
            }
        );

        function updateStory(data, updateData) {
            var where = {id: data.story.id};

            Story
                .update(where, updateData, function(error, stories) {
                    if (error) {
                        cb(error);
                    } else {
                        _.each(stories, function(story) {
                            Story.publishUpdate(story.id, story.toJSON());
                        });

                        cb();
                    }
                });
        }
    }
};
<|endoftext|>