<commit_before>import { Component } from 'react';
import PropTypes from 'prop-types';

class RangeSelectorButton extends Component {

  static propTypes = {
    count: PropTypes.number,
    type: PropTypes.string.isRequired,
    update: PropTypes.func, // Provided by ChartProvider
    getChart: PropTypes.func // Provided by ChartProvider
  };

  constructor (props) {
    super(props);
    this.getButtons = this.getButtons.bind(this);
    this.getButtonIndex = this.getButtonIndex.bind(this);
    this.updateRangeSelectorButtons = this.updateRangeSelectorButtons.bind(this);
  }

  componentDidMount () {
    const button = this.getButtonIndex();
    if (!button) {
      const { count, type, children } = this.props;
      const buttons = this.getButtons();
      buttons.push({
        count,
        type,
        text: children
      });
      this.updateRangeSelectorButtons(buttons);
    }
  }

  componentWillUnmount () {
    const button = this.getButtonIndex();
    if (button) {
      const buttons = this.getButtons();
      buttons.splice(button, 1);
      this.updateRangeSelectorButtons(buttons);
    }
  }

  getButtons () {
    const { buttons = [] } = this.props.getChart().options.rangeSelector;
    return buttons;
  }

  getButtonIndex () {
    const { count, type } = this.props;
    this.getButtons().findIndex(b => {
      return (b.count === count && b.type === type);
    });
  }

  updateRangeSelectorButtons (config) {
    this.props.update({
      rangeSelector: {
        buttons: config
      }
    });
  }

  render () {
    return null;
  }
}

export default RangeSelectorButton;
<commit_msg>Fix unmount range selector issue<commit_after>import { Component } from 'react';
import PropTypes from 'prop-types';

class RangeSelectorButton extends Component {

  static propTypes = {
    count: PropTypes.number,
    type: PropTypes.string.isRequired,
    update: PropTypes.func, // Provided by ChartProvider
    getChart: PropTypes.func // Provided by ChartProvider
  };

  constructor (props) {
    super(props);
    this.getButtons = this.getButtons.bind(this);
    this.getButtonIndex = this.getButtonIndex.bind(this);
    this.updateRangeSelectorButtons = this.updateRangeSelectorButtons.bind(this);
  }

  componentDidMount () {
    const button = this.getButtonIndex();
    if (!button) {
      const { count, type, children } = this.props;
      const buttons = this.getButtons();
      buttons.push({
        count,
        type,
        text: children
      });
      this.updateRangeSelectorButtons(buttons);
    }
  }

  componentWillUnmount () {
    const button = this.getButtonIndex();
    if (button) {
      const buttons = this.getButtons();
      buttons.splice(button, 1);
      this.updateRangeSelectorButtons(buttons);
    }
  }

  getButtons () {
    const chart = this.props.getChart()
    if (chart && chart.options) {
        const { buttons = [] } = chart.options.rangeSelector;
        return buttons;
    }

    return [];
  }

  getButtonIndex () {
    const { count, type } = this.props;
    this.getButtons().findIndex(b => {
      return (b.count === count && b.type === type);
    });
  }

  updateRangeSelectorButtons (config) {
    this.props.update({
      rangeSelector: {
        buttons: config
      }
    });
  }

  render () {
    return null;
  }
}

export default RangeSelectorButton;
<|endoftext|>


<commit_before>const assert = require("assert");
const fs = require("fs");
const request = require("request-promise");
const sinon = require("sinon");
const { VersionRange } = require("../../../compilerSupplier/loadingStrategies");
const instance = new VersionRange();
const compilerFileNames = [
  "soljson-v0.4.22+commit.124ca40d.js",
  "soljson-v0.4.23+commit.1534a40d.js",
  "soljson-v0.4.11+commit.124234rd.js"
];

const allVersions = {
  builds: [
    {
      path: "soljson-v0.1.1+commit.6ff4cd6.js",
      version: "0.1.1",
      build: "commit.6ff4cd6",
      longVersion: "0.1.1+commit.6ff4cd6",
      keccak256:
        "0xd8b8c64f4e9de41e6604e6ac30274eff5b80f831f8534f0ad85ec0aff466bb25",
      urls: [
        "bzzr://8f3c028825a1b72645f46920b67dca9432a87fc37a8940a2b2ce1dd6ddc2e29b"
      ]
    },
    {
      path: "soljson-v0.1.2+commit.d0d36e3.js",
      version: "0.1.2",
      build: "commit.d0d36e3",
      longVersion: "0.1.2+commit.d0d36e3",
      keccak256:
        "0xa70b3d4acf77a303efa93c3ddcadd55b8762c7be109fd8f259ec7d6be654f03e",
      urls: [
        "bzzr://e662d71e9b8e1b0311c129b962e678e5dd63487ad9b020ee539d7f74cd7392c9"
      ]
    }
  ],
  releases: {
    "0.5.2": "soljson-v0.5.2+commit.1df8f40c.js",
    "0.5.1": "soljson-v0.5.1+commit.c8a2cb62.js",
    "0.5.0": "soljson-v0.5.0+commit.1d4f565a.js",
    "0.4.25": "soljson-v0.4.25+commit.59dbf8f1.js",
    "0.4.24": "soljson-v0.4.24+commit.e67f0147.js",
    "0.4.23": "soljson-v0.4.23+commit.124ca40d.js",
    "0.4.22": "soljson-v0.4.22+commit.4cb486ee.js"
  },
  latestRelease: "0.5.2"
};

describe("VersionRange loading strategy", () => {
  describe("async getSolcByCommit(commit)", () => {
    describe("when the file is cached", () => {
      beforeEach(() => {
        sinon
          .stub(instance, "getCachedSolcFileName")
          .withArgs("commit.porkBelly")
          .returns("someFile.js");
        sinon.stub(instance, "getCachedSolcByFileName");
      });
      afterEach(() => {
        instance.getCachedSolcFileName.restore();
        instance.getCachedSolcByFileName.restore();
      });

      it("calls getCachedSolcByFileName with the file name", async () => {
        await instance.getSolcByCommit("commit.porkBelly");
        assert(instance.getCachedSolcByFileName.calledWith("someFile.js"));
      });
    });

    describe("when the file is not cached", () => {
      beforeEach(() => {
        // commit string for v 0.5.1
        commitString = "commit.c8a2cb62";
        sinon
          .stub(instance, "getCachedSolcFileName")
          .withArgs(commitString)
          .returns(undefined);
        sinon.stub(request, "get").returns("requestResponse");
        sinon.stub(instance, "addFileToCache");
        sinon.stub(instance, "compilerFromString");
        expectedUrl =
          instance.config.compilerUrlRoot + "soljson-v0.5.1+commit.c8a2cb62.js";
      });
      afterEach(() => {
        instance.getCachedSolcFileName.restore();
        request.get.restore();
        instance.addFileToCache.restore();
        instance.compilerFromString.restore();
      });

      it("eventually calls compilerFromString with request reponse", async () => {
        await instance.getSolcByCommit(commitString);
        assert(instance.compilerFromString.calledWith("requestResponse"));
      });
      it("throws an error when it can't find a match", async () => {
        try {
          await instance.getSolcByCommit("some garbage that will not match");
          assert(false);
        } catch (error) {
          assert(error.message === "No matching version found");
        }
      });
    });
  });
  describe(".getSolcByUrlAndCache()", () => {
    beforeEach(() => {
      sinon
        .stub(request, "get")
        .withArgs("someUrl")
        .returns("requestReturn");
      sinon.stub(instance, "addFileToCache").withArgs("requestReturn");
      sinon
        .stub(instance, "compilerFromString")
        .withArgs("requestReturn")
        .returns("success");
    });
    afterEach(() => {
      request.get.restore();
      instance.addFileToCache.restore();
      instance.compilerFromString.restore();
    });

    it("calls addFileToCache with the response and the file name", async () => {
      result = await instance.getSolcByUrlAndCache("someUrl", "someSolcFile");
      assert(
        instance.addFileToCache.calledWith("requestReturn", "someSolcFile")
      );
      assert(result === "success");
    });
  });

  describe(".findNewestValidVersion(version, allVersions)", () => {
    it("returns the version name of the newest valid version", () => {
      expectedResult = "0.5.2";
      assert(
        instance.findNewestValidVersion("^0.5.0", allVersions) ===
          expectedResult
      );
    });
    it("returns null when the version is invalid", () => {
      assert(instance.findNewestValidVersion("garbageInput") === null);
    });
    it("returns null when there are no valid versions", () => {
      assert(instance.findNewestValidVersion("^0.8.0", allVersions) === null);
    });
  });

  describe("versionIsCached(version)", () => {
    beforeEach(() => {
      sinon.stub(fs, "readdirSync").returns(compilerFileNames);
    });
    afterEach(() => {
      fs.readdirSync.restore();
    });

    describe("when a cached version of the compiler is present", () => {
      beforeEach(() => {
        expectedResult = "v0.4.11+commit.124234rd.js";
      });

      it("returns the file name with the prefix removed", () => {
        assert.equal(instance.versionIsCached("0.4.11"), expectedResult);
      });
    });

    describe("when a cached version of the compiler is not present", () => {
      beforeEach(() => {
        expectedResult = undefined;
      });

      it("returns undefined", () => {
        assert.equal(instance.versionIsCached("0.4.29"), expectedResult);
      });
    });
  });

  describe("getCachedSolcByVersionRange(version)", () => {
    beforeEach(() => {
      expectedResult = "soljson-v0.4.23+commit.1534a40d.js";
      sinon.stub(fs, "readdirSync").returns(compilerFileNames);
      sinon.stub(instance, "getCachedSolcByFileName");
    });
    afterEach(() => {
      fs.readdirSync.restore();
      instance.getCachedSolcByFileName.restore();
    });

    it("returns the compiler when a single version is specified", () => {
      instance.getCachedSolcByVersionRange("0.4.23");
      assert(instance.getCachedSolcByFileName.calledWith(expectedResult));
    });
    it("returns the newest compiler when there are multiple valid ones", () => {
      instance.getCachedSolcByVersionRange("^0.4.1");
      assert(instance.getCachedSolcByFileName.calledWith(expectedResult));
    });
  });
});
<commit_msg>Add tests for load function<commit_after>const assert = require("assert");
const fs = require("fs");
const request = require("request-promise");
const sinon = require("sinon");
const { VersionRange } = require("../../../compilerSupplier/loadingStrategies");
const instance = new VersionRange();
const compilerFileNames = [
  "soljson-v0.4.22+commit.124ca40d.js",
  "soljson-v0.4.23+commit.1534a40d.js",
  "soljson-v0.4.11+commit.124234rd.js"
];

const allVersions = {
  builds: [
    {
      path: "soljson-v0.1.1+commit.6ff4cd6.js",
      version: "0.1.1",
      build: "commit.6ff4cd6",
      longVersion: "0.1.1+commit.6ff4cd6",
      keccak256:
        "0xd8b8c64f4e9de41e6604e6ac30274eff5b80f831f8534f0ad85ec0aff466bb25",
      urls: [
        "bzzr://8f3c028825a1b72645f46920b67dca9432a87fc37a8940a2b2ce1dd6ddc2e29b"
      ]
    },
    {
      path: "soljson-v0.1.2+commit.d0d36e3.js",
      version: "0.1.2",
      build: "commit.d0d36e3",
      longVersion: "0.1.2+commit.d0d36e3",
      keccak256:
        "0xa70b3d4acf77a303efa93c3ddcadd55b8762c7be109fd8f259ec7d6be654f03e",
      urls: [
        "bzzr://e662d71e9b8e1b0311c129b962e678e5dd63487ad9b020ee539d7f74cd7392c9"
      ]
    }
  ],
  releases: {
    "0.5.2": "soljson-v0.5.2+commit.1df8f40c.js",
    "0.5.1": "soljson-v0.5.1+commit.c8a2cb62.js",
    "0.5.0": "soljson-v0.5.0+commit.1d4f565a.js",
    "0.4.25": "soljson-v0.4.25+commit.59dbf8f1.js",
    "0.4.24": "soljson-v0.4.24+commit.e67f0147.js",
    "0.4.23": "soljson-v0.4.23+commit.124ca40d.js",
    "0.4.22": "soljson-v0.4.22+commit.4cb486ee.js"
  },
  latestRelease: "0.5.2"
};

describe("VersionRange loading strategy", () => {
  describe("load(versionRange)", () => {
    beforeEach(() => {
      sinon.stub(instance, "getSolcBySingleVersion");
      sinon.stub(instance, "getSolcByVersionRange");
    });
    afterEach(() => {
      instance.getSolcBySingleVersion.restore();
      instance.getSolcByVersionRange.restore();
    });

    it("calls getSolcBySingleVersion when a single version is specified", () => {
      instance.load("0.5.1");
      assert(instance.getSolcBySingleVersion.called);
    });
    it("calls getSolcByVersionRange when a single version is specified", () => {
      instance.load("^0.5.1");
      assert(instance.getSolcByVersionRange.called);
    });
  });

  describe("async getSolcByCommit(commit)", () => {
    describe("when the file is cached", () => {
      beforeEach(() => {
        sinon
          .stub(instance, "getCachedSolcFileName")
          .withArgs("commit.porkBelly")
          .returns("someFile.js");
        sinon.stub(instance, "getCachedSolcByFileName");
      });
      afterEach(() => {
        instance.getCachedSolcFileName.restore();
        instance.getCachedSolcByFileName.restore();
      });

      it("calls getCachedSolcByFileName with the file name", async () => {
        await instance.getSolcByCommit("commit.porkBelly");
        assert(instance.getCachedSolcByFileName.calledWith("someFile.js"));
      });
    });

    describe("when the file is not cached", () => {
      beforeEach(() => {
        // commit string for v 0.5.1
        commitString = "commit.c8a2cb62";
        sinon
          .stub(instance, "getCachedSolcFileName")
          .withArgs(commitString)
          .returns(undefined);
        sinon.stub(request, "get").returns("requestResponse");
        sinon.stub(instance, "addFileToCache");
        sinon.stub(instance, "compilerFromString");
        expectedUrl =
          instance.config.compilerUrlRoot + "soljson-v0.5.1+commit.c8a2cb62.js";
      });
      afterEach(() => {
        instance.getCachedSolcFileName.restore();
        request.get.restore();
        instance.addFileToCache.restore();
        instance.compilerFromString.restore();
      });

      it("eventually calls compilerFromString with request reponse", async () => {
        await instance.getSolcByCommit(commitString);
        assert(instance.compilerFromString.calledWith("requestResponse"));
      });
      it("throws an error when it can't find a match", async () => {
        try {
          await instance.getSolcByCommit("some garbage that will not match");
          assert(false);
        } catch (error) {
          assert(error.message === "No matching version found");
        }
      });
    });
  });
  describe(".getSolcByUrlAndCache()", () => {
    beforeEach(() => {
      sinon
        .stub(request, "get")
        .withArgs("someUrl")
        .returns("requestReturn");
      sinon.stub(instance, "addFileToCache").withArgs("requestReturn");
      sinon
        .stub(instance, "compilerFromString")
        .withArgs("requestReturn")
        .returns("success");
    });
    afterEach(() => {
      request.get.restore();
      instance.addFileToCache.restore();
      instance.compilerFromString.restore();
    });

    it("calls addFileToCache with the response and the file name", async () => {
      result = await instance.getSolcByUrlAndCache("someUrl", "someSolcFile");
      assert(
        instance.addFileToCache.calledWith("requestReturn", "someSolcFile")
      );
      assert(result === "success");
    });
  });

  describe(".findNewestValidVersion(version, allVersions)", () => {
    it("returns the version name of the newest valid version", () => {
      expectedResult = "0.5.2";
      assert(
        instance.findNewestValidVersion("^0.5.0", allVersions) ===
          expectedResult
      );
    });
    it("returns null when the version is invalid", () => {
      assert(instance.findNewestValidVersion("garbageInput") === null);
    });
    it("returns null when there are no valid versions", () => {
      assert(instance.findNewestValidVersion("^0.8.0", allVersions) === null);
    });
  });

  describe("versionIsCached(version)", () => {
    beforeEach(() => {
      sinon.stub(fs, "readdirSync").returns(compilerFileNames);
    });
    afterEach(() => {
      fs.readdirSync.restore();
    });

    describe("when a cached version of the compiler is present", () => {
      beforeEach(() => {
        expectedResult = "v0.4.11+commit.124234rd.js";
      });

      it("returns the file name with the prefix removed", () => {
        assert.equal(instance.versionIsCached("0.4.11"), expectedResult);
      });
    });

    describe("when a cached version of the compiler is not present", () => {
      beforeEach(() => {
        expectedResult = undefined;
      });

      it("returns undefined", () => {
        assert.equal(instance.versionIsCached("0.4.29"), expectedResult);
      });
    });
  });

  describe("getCachedSolcByVersionRange(version)", () => {
    beforeEach(() => {
      expectedResult = "soljson-v0.4.23+commit.1534a40d.js";
      sinon.stub(fs, "readdirSync").returns(compilerFileNames);
      sinon.stub(instance, "getCachedSolcByFileName");
    });
    afterEach(() => {
      fs.readdirSync.restore();
      instance.getCachedSolcByFileName.restore();
    });

    it("returns the compiler when a single version is specified", () => {
      instance.getCachedSolcByVersionRange("0.4.23");
      assert(instance.getCachedSolcByFileName.calledWith(expectedResult));
    });
    it("returns the newest compiler when there are multiple valid ones", () => {
      instance.getCachedSolcByVersionRange("^0.4.1");
      assert(instance.getCachedSolcByFileName.calledWith(expectedResult));
    });
  });
});
<|endoftext|>


<commit_before>'use strict';

var util = require('util');

var Feeds = function(client) {
    this.client = client;
};

Feeds.prototype.url = function(format) {
    var params = Array.prototype.slice.call(arguments, 1).map(function(param) {
        return encodeURIComponent(param);
    });

    return util.format.apply(this, [format].concat(params));
};

Feeds.prototype.list = function() {
    return this.client.get("/feeds");
};

Feeds.prototype.view = function(id) {
    return this.client.get(this.url("/feeds/%s", id));
};

Feeds.prototype.log = function(id) {
    return this.client.get(this.url("/feeds/%s/log", id));
};

Feeds.prototype.location = function(id) {
    return this.client.get(this.url("/feeds/%s/location", id));
};

Feeds.prototype.updateLocation = function(id, params) {
    return this.client.put(this.url("/feeds/%s/location", id), null, params);
};

Feeds.prototype.streams = function(id) {
    return this.client.get(this.url("/feeds/%s/streams", id));
};

Feeds.prototype.stream = function(id, name) {
    return this.client.get(this.url("/feeds/%s/streams/%s", id, name));
};

Feeds.prototype.streamValues = function(id, name) {
    return this.client.get(this.url("/feeds/%s/streams/%s/values", id, name));
};

Feeds.prototype.updateStream = function(id, name, params) {
    return this.client.put(this.url("/feeds/%s/streams/%s", id, name), null, params);
};

Feeds.prototype.deleteStream = function(id, name) {
    return this.client.del(this.url("/feeds/%s/streams/%s", id, name));
};

Feeds.prototype.keys = function(id) {
    return this.client.get("/keys", { feed: id });
};

Feeds.prototype.createKey = function() {
    // TODO
};

Feeds.prototype.updateKey = function() {
    // TODO
};

module.exports = Feeds;
<commit_msg>Added explanatory comments to Feeds class methods.<commit_after>'use strict';

var util = require('util');

// Wrapper for AT&T M2X Feed API
//
// See https://m2x.att.com/developer/documentation/feed for AT&T M2X
// HTTP Feed API documentation.
var Feeds = function(client) {
    this.client = client;
};

Feeds.prototype.url = function(format) {
    var params = Array.prototype.slice.call(arguments, 1).map(function(param) {
        return encodeURIComponent(param);
    });

    return util.format.apply(this, [format].concat(params));
};

// List all the feeds that belong to the user associated with the
// M2X API key supplied when initializing M2X
Feeds.prototype.list = function() {
    return this.client.get("/feeds");
};

// Return the details of the supplied feed
Feeds.prototype.view = function(id) {
    return this.client.get(this.url("/feeds/%s", id));
};

// Return a list of access log to the supplied feed
Feeds.prototype.log = function(id) {
    return this.client.get(this.url("/feeds/%s/log", id));
};

// Return the current location of the supplied feed
//
// Note that this method can return an empty value (response status
// of 204) if the feed has no location defined.
Feeds.prototype.location = function(id) {
    return this.client.get(this.url("/feeds/%s/location", id));
};

// Update the current location of the feed
Feeds.prototype.updateLocation = function(id, params) {
    return this.client.put(this.url("/feeds/%s/location", id), null, params);
};

// Return a list of the associated streams for the supplied feed
Feeds.prototype.streams = function(id) {
    return this.client.get(this.url("/feeds/%s/streams", id));
};

// Return the details of the supplied stream
Feeds.prototype.stream = function(id, name) {
    return this.client.get(this.url("/feeds/%s/streams/%s", id, name));
};

// Return a list with the latest values from a stream
Feeds.prototype.streamValues = function(id, name) {
    return this.client.get(this.url("/feeds/%s/streams/%s/values", id, name));
};

// Update stream's properties
//
// If the stream doesn't exist it will create it. See
// https://m2x.att.com/developer/documentation/feed#Create-Update-Data-Stream
// for details.
Feeds.prototype.updateStream = function(id, name, params) {
    return this.client.put(this.url("/feeds/%s/streams/%s", id, name), null, params);
};

// Delete the stream (and all its values) from the feed
Feeds.prototype.deleteStream = function(id, name) {
    return this.client.del(this.url("/feeds/%s/streams/%s", id, name));
};

// Returns a list of API keys associated with the feed
Feeds.prototype.keys = function(id) {
    return this.client.get("/keys", { feed: id });
};

// Creates a new API key associated to the feed
//
// If a parameter named `stream` is supplied with a stream name, it
// will create an API key associated with that stream only.
Feeds.prototype.createKey = function() {
    // TODO
};

// Updates an API key properties
Feeds.prototype.updateKey = function() {
    // TODO
};

module.exports = Feeds;
<|endoftext|>


<commit_before>/**
 * @fileOverview The entities base class.
 */
var util = require('util');

var __ = require('lodash');
var Entity = require('../entity');

/**
 * The base Entity Class all entities extend from.
 *
 * @param {mongoose.Model} Model the model that this entity relates to.
 * @param {Object=} optUdo Optionally define the current handling user.
 * @constructor
 * @extends {crude.Entity}
 */
var Entity = module.exports = function(Model, optUdo) {
  Entity.call(this, Model, optUdo);
};
util.inherits(Entity, Entity);

/**
 * Create an entity item.
 *
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.create = function(itemData, done) {
  var item = new this.Model(itemData);
  item.save(done);
};

/**
 * Read one entity item.
 *
 * @param {string|Object} id the item id or an Object to query against.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.readOne = function(id, done) {
  var query = new Object(null);

  if (__.isObject(id)) {
    query = id;
  } else {
    query.id = id;
  }

  this.Model.findOne(query, done);
};

/**
 * Read all items, do practice common sense!
 *
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.readAll = function(done) {
  this.Model.find(done);
};

/**
 * Read a limited set of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {number} skip starting position.
 * @param {number} limit how many records to fetch.
 * @param {Function(ts.error.Abstract=, Array.<mongoose.Document>=)} done callback.
 */
Entity.prototype.readLimit = function(query, skip, limit, done) {
  this.Model.find(query)
    .skip(skip)
    .limit(limit)
    .exec(done);
};

/**
 * Get the count of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {Function(ts.error.Abstract=, number=)} done callback.
 */
Entity.prototype.count = function(query, done) {
  this.Model.count(query).exec(done);
};

/**
 * Update an entity item.
 *
 * @param {string} id the item id.
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.update = function(id, itemData, done) {
  this.Model.findById(id, function(err, doc){
    if (err) {
      return done(err);
    }

    __.forOwn(itemData, function(value, key) {
      doc[key] = value;
    }, this);

    doc.save(done);

  }.bind(this));
};

<commit_msg>update mongoose entity driver<commit_after>/**
 * @fileOverview The entities base class.
 */
var util = require('util');

var __ = require('lodash');
var Entity = require('../entity');

/**
 * The base Entity Class all entities extend from.
 *
 * @param {mongoose.Model} Model the model that this entity relates to.
 * @param {Object=} optUdo Optionally define the current handling user.
 * @constructor
 * @extends {crude.Entity}
 */
var Entity = module.exports = function(Model, optUdo) {
  Entity.call(this, Model, optUdo);
};
util.inherits(Entity, Entity);

/**
 * Create an entity item.
 *
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.create = function(itemData, done) {
  var item = new this.Model(itemData);
  item.save(done);
};

/**
 * Read one entity item.
 *
 * @param {string|Object} id the item id or an Object to query against.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.readOne = function(id, done) {
  var query = new Object(null);

  if (__.isObject(id)) {
    query = id;
  } else {
    query.id = id;
  }

  this.Model.findOne(query, done);
};

/**
 * Read all items, do practice common sense!
 *
 * @param {Object=} optQuery Limit the results.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.read = function(optQuery, done) {
  var query = {};
  if (__.isFunction(optQuery)) {
    done = optQuery;
  } else if (__.isObject(optQuery)) {
    query = optQuery;
  }

  this.Model.find(query).exec(done);
};

/**
 * Read a limited set of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {number} skip starting position.
 * @param {number} limit how many records to fetch.
 * @param {Function(ts.error.Abstract=, Array.<mongoose.Document>=)} done callback.
 */
Entity.prototype.readLimit = function(query, skip, limit, done) {
  this.Model.find(query)
    .skip(skip)
    .limit(limit)
    .exec(done);
};

/**
 * Get the count of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {Function(ts.error.Abstract=, number=)} done callback.
 */
Entity.prototype.count = function(query, done) {
  this.Model.count(query).exec(done);
};

/**
 * Update an entity item.
 *
 * @param {string} id the item id.
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.update = function(id, itemData, done) {
  this.Model.findById(id, function(err, doc){
    if (err) {
      return done(err);
    }

    __.forOwn(itemData, function(value, key) {
      doc[key] = value;
    }, this);

    doc.save(done);

  }.bind(this));
};

<|endoftext|>


<commit_before>/**
 * @fileOverview The entities base class.
 */
var util = require('util');

var __ = require('lodash');
var Entity = require('../entity');

/**
 * The base Entity Class all entities extend from.
 *
 * @param {mongoose.Model} Model the model that this entity relates to.
 * @param {Object=} optUdo Optionally define the current handling user.
 * @constructor
 * @extends {crude.Entity}
 */
var Entity = module.exports = function(Model, optUdo) {
  Entity.call(this, Model, optUdo);
};
util.inherits(Entity, Entity);

/**
 * Create an entity item.
 *
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.create = function(itemData, done) {
  var item = new this.Model(itemData);
  item.save(done);
};

/**
 * Read one entity item.
 *
 * @param {string|Object} id the item id or an Object to query against.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.readOne = function(id, done) {
  var query = new Object(null);

  if (__.isObject(id)) {
    query = id;
  } else {
    query.id = id;
  }

  this.Model.findOne(query, done);
};

/**
 * Read all items, do practice common sense!
 *
 * @param {Object=} optQuery Limit the results.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.read = function(optQuery, done) {
  var query = {};
  if (__.isFunction(optQuery)) {
    done = optQuery;
  } else if (__.isObject(optQuery)) {
    query = optQuery;
  }

  this.Model.find(query).exec(done);
};

/**
 * Read a limited set of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {number} skip starting position.
 * @param {number} limit how many records to fetch.
 * @param {Function(ts.error.Abstract=, Array.<mongoose.Document>=)} done callback.
 */
Entity.prototype.readLimit = function(query, skip, limit, done) {
  this.Model.find(query)
    .skip(skip)
    .limit(limit)
    .exec(done);
};

/**
 * Get the count of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {Function(ts.error.Abstract=, number=)} done callback.
 */
Entity.prototype.count = function(query, done) {
  this.Model.count(query).exec(done);
};

/**
 * Update an entity item.
 *
 * @param {string} id the item id.
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.update = function(id, itemData, done) {
  this.Model.findById(id, function(err, doc){
    if (err) {
      return done(err);
    }

    __.forOwn(itemData, function(value, key) {
      doc[key] = value;
    }, this);

    doc.save(done);

  }.bind(this));
};

<commit_msg>update read docs for mongoose ent<commit_after>/**
 * @fileOverview The entities base class.
 */
var util = require('util');

var __ = require('lodash');
var Entity = require('../entity');

/**
 * The base Entity Class all entities extend from.
 *
 * @param {mongoose.Model} Model the model that this entity relates to.
 * @param {Object=} optUdo Optionally define the current handling user.
 * @constructor
 * @extends {crude.Entity}
 */
var Entity = module.exports = function(Model, optUdo) {
  Entity.call(this, Model, optUdo);
};
util.inherits(Entity, Entity);

/**
 * Create an entity item.
 *
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.create = function(itemData, done) {
  var item = new this.Model(itemData);
  item.save(done);
};

/**
 * Read one entity item.
 *
 * @param {string|Object} id the item id or an Object to query against.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.readOne = function(id, done) {
  var query = new Object(null);

  if (__.isObject(id)) {
    query = id;
  } else {
    query.id = id;
  }

  this.Model.findOne(query, done);
};

/**
 * Read items based on query or if not defined, read all items.
 * Do practice common sense!
 *
 * @param {Object=} optQuery Limit the results.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.read = function(optQuery, done) {
  var query = {};
  if (__.isFunction(optQuery)) {
    done = optQuery;
  } else if (__.isObject(optQuery)) {
    query = optQuery;
  }

  this.Model.find(query).exec(done);
};

/**
 * Read a limited set of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {number} skip starting position.
 * @param {number} limit how many records to fetch.
 * @param {Function(ts.error.Abstract=, Array.<mongoose.Document>=)} done callback.
 */
Entity.prototype.readLimit = function(query, skip, limit, done) {
  this.Model.find(query)
    .skip(skip)
    .limit(limit)
    .exec(done);
};

/**
 * Get the count of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {Function(ts.error.Abstract=, number=)} done callback.
 */
Entity.prototype.count = function(query, done) {
  this.Model.count(query).exec(done);
};

/**
 * Update an entity item.
 *
 * @param {string} id the item id.
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.update = function(id, itemData, done) {
  this.Model.findById(id, function(err, doc){
    if (err) {
      return done(err);
    }

    __.forOwn(itemData, function(value, key) {
      doc[key] = value;
    }, this);

    doc.save(done);

  }.bind(this));
};

<|endoftext|>


<commit_before>/**
 * @file TreeCalculation vendor
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import Util from './Util';

function calDepth(data, path) {

    let list = data,
        depth = 0;

    if (!data || !path) {
        return depth = 0;
    }

    for (let item of path) {
        if (item.index in list) {
            list = list[item.index].children;
            depth++;
        } else {
            return depth;
        }
    }

    if (list && list.length > 0) {
        return depth + 1;
    }

    return depth;

}

function calPath(value, data, props) {

    if (!value || !data) {
        return;
    }

    return traverseData(data, value, props, null);

}

function traverseData(node, value, props, parent, index = 0) {

    if (!node || node.length < 1 || !value) {
        return;
    }

    const {valueField, displayField} = props;

    // find in children
    if (node.children && node.children.length > 0) {

        for (let i = 0, len = node.children.length; i < len; i++) {

            // traverse child node
            const path = traverseData(node.children[i], value, props, node, i);

            // if finded in child node
            if (path) {

                if (!parent) {
                    return path;
                }

                path.unshift({
                    node,
                    index
                });
                return path;

            }

        }
    }

    if (Util.getValueByValueField(node, valueField, displayField)
        === Util.getValueByValueField(value, valueField, displayField)) {
        return [{
            node,
            index
        }];
    }

    return;

}

export default {
    calDepth,
    calPath
};<commit_msg>update TreeCalculation<commit_after>/**
 * @file TreeCalculation vendor
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import Util from './Util';

function calDepth(data, path) {

    let list = data,
        depth = 0;

    if (!data || !path) {
        return depth = 0;
    }

    for (let item of path) {
        if (item.index in list) {
            list = list[item.index].children;
            depth++;
        } else {
            return depth;
        }
    }

    if (list && list.length > 0) {
        return depth + 1;
    }

    return depth;

}

function calPath(value, data, props) {

    if (!value || !data) {
        return;
    }

    return traverseDataCalPath(data, value, props, null);

}

function traverseDataCalPath(node, value, props, parent, index = 0) {

    if (!node || node.length < 1 || !value) {
        return;
    }

    const {valueField, displayField} = props;

    // find in children
    if (node.children && node.children.length > 0) {

        for (let i = 0, len = node.children.length; i < len; i++) {

            // traverse child node
            const path = traverseDataCalPath(node.children[i], value, props, node, i);

            // if finded in child node
            if (path) {

                if (!parent) {
                    return path;
                }

                path.unshift({
                    node,
                    index
                });
                return path;

            }

        }
    }

    if (Util.getValueByValueField(node, valueField, displayField)
        === Util.getValueByValueField(value, valueField, displayField)) {
        return [{
            node,
            index
        }];
    }

    return;

}

function findNodeById(node, id, callback, index = null, parent = null) {

    if (!node) {
        return;
    }

    if (node.id === id) {
        callback && callback(node, index, parent);
        return true;
    }

    if (node.children && node.children.length > 0) {
        for (let i = 0, len = node.children.length; i < len; i++) {
            if (findNodeById(node.children[i], id, callback, i, node)) {
                return;
            }
        }
    }

}

export default {
    calDepth,
    calPath,
    findNodeById
};<|endoftext|>


<commit_before>Anylang = (function() {
  var tables = {};

  function Anylang(langDestination, langOrigin){
    this.origin = langOrigin;
    this.langDestination = langDestination;
    this.table = tables[langDestination][langOrigin];
  };

  Anylang.addLang = function addLang(equivs) {
    tables[equivs.langDestination] = tables[equivs.langDestination] || {};
    tables[equivs.langDestination][equivs.langOrigin] = equivs.table.map(function(eq){
      if (typeof eq.from === "string") {
        eq.from = new RegExp(eq.from, 'g');
        return eq;
      }
      return eq;
    });
  }

  Anylang.prototype.equiv = function equiv(txt) {
    for (var j=0; j<this.table.length; j++) {
        var repl = this.table[j];
        txt = txt.replace(repl.from, repl.to);
    }
    return txt;
  }

  if (typeof document !== "undefined") {
    document.addEventListener("DOMContentLoaded", function(event) {
      var inputs = document.querySelectorAll("input[data-anylang-to]");
      for (var i=0; i<inputs.length; i++) {
        var input = inputs[i];
        var change = (function (input) {
          var data = input.dataset;
          var anylang = new Anylang(data.anylangTo, data.anylangFrom);
          var target = document.getElementById(data.anylangTarget);
          return function(evt){
            var trans = anylang.equiv(input.value);
            data.anylangEquiv = trans;
            if (target !== null) {
              if (target.value !== void 0) {
                target.value = trans;
              } else {
                target.innerHTML = trans;
              }
            }
          }
        })(input);
        input.addEventListener("keyup", change);
        input.addEventListener("change", change);
      }
    });
  }
  return Anylang;
})();
<commit_msg>Add Anylang.attach and Anylang.detach<commit_after>Anylang = (function() {
  var tables = {};

  function Anylang(langDestination, langOrigin){
    this.origin = langOrigin;
    this.langDestination = langDestination;
    this.table = tables[langDestination][langOrigin];
  };

  Anylang.addLang = function addLang(equivs) {
    tables[equivs.langDestination] = tables[equivs.langDestination] || {};
    tables[equivs.langDestination][equivs.langOrigin] = equivs.table.map(function(eq){
      if (typeof eq.from === "string") {
        eq.from = new RegExp(eq.from, 'g');
        return eq;
      }
      return eq;
    });
  }

  Anylang.prototype.equiv = function equiv(txt) {
    for (var j=0; j<this.table.length; j++) {
        var repl = this.table[j];
        txt = txt.replace(repl.from, repl.to);
    }
    return txt;
  }

  if (typeof document !== "undefined") {

    function bindToInput(input) {
      var data = input.dataset;
      var anylang = new Anylang(data.anylangTo, data.anylangFrom);
      var target = document.getElementById(data.anylangTarget);
      var change = function anylang_change(evt){
        var trans = anylang.equiv(input.value);
        data.anylangEquiv = trans;
        if (target !== null) {
          if (target.value !== void 0) {
            target.value = trans;
          } else {
            target.innerHTML = trans;
          }
        }
      }
      input._anylang_update_equiv = change;
      input.addEventListener("keyup", change);
      input.addEventListener("change", change);
    }

    Anylang.attach = bindToInput;
    Anylang.detach = function Anylang_detach(input) {
      input.removeEventListener("keyup", input._anylang_update_equiv);
      input.removeEventListener("change", input._anylang_update_equiv);
    }

    document.addEventListener("DOMContentLoaded", function(event) {
      var inputs = document.querySelectorAll("input[data-anylang-to]");
      for (var i=0; i<inputs.length; i++) {
        bindToInput(inputs[i]);
      }
    });
  }
  return Anylang;
})();
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */
'use strict';

function Call(config) {
  this.traceEvent = report.traceEventAsync('call');
  this.traceEvent({ config: config });

  this.pc1 = new RTCPeerConnection(config);
  this.pc2 = new RTCPeerConnection(config);

  this.pc1.addEventListener('icecandidate', this.onIceCandidate_.bind(this, this.pc2));
  this.pc2.addEventListener('icecandidate', this.onIceCandidate_.bind(this, this.pc1));

  this.iceCandidateFilter_ = Call.noFilter;
}

Call.prototype = {
  establishConnection: function () {
    this.traceEvent({ state: 'start' });
    this.pc1.createOffer(this.gotOffer_.bind(this));
  },

  close: function () {
    this.traceEvent({ state: 'end' });
    this.pc1.close();
    this.pc2.close();
  },

  setIceCandidateFilter: function (filter) {
    this.iceCandidateFilter_ = filter;
  },

  // Constraint max video bitrate by modifying the SDP when creating an answer.
  constrainVideoBitrate: function (maxVideoBitrateKbps) {
    this.constrainVideoBitrateKbps_ = maxVideoBitrateKbps;
  },

  // Remove video FEC if available on the offer.
  disableVideoFec: function () {
    this.constrainOfferToRemoveVideoFec_ = true;
  },

  // When the peerConnection is closed the callback is called once returning
  // with an array of gathered stats.
  gatherStats: function(peerConnection, callback, interval) {
    var stats = [];
    getStats_();

    function getStats_() {
      if (peerConnection.signalingState === 'closed') {
        callback(stats);
        return;
      }
      setTimeout(function() {
        peerConnection.getStats(gotStats_.bind(this));
      }, interval);
    }

    function gotStats_(response) {
      for (var index in response.result()) {
        stats.push(response.result()[index]);
      }
      getStats_();
    }
  },

  gotOffer_: function (offer) {
    if (this.constrainOfferToRemoveVideoFec_) {
      offer.sdp = offer.sdp.replace(/(m=video 1 [^\r]+)(116 117)(\r\n)/g,
                                    '$1\r\n');
      offer.sdp = offer.sdp.replace(/a=rtpmap:116 red\/90000\r\n/g, '');
      offer.sdp = offer.sdp.replace(/a=rtpmap:117 ulpfec\/90000\r\n/g, '');
    }
    this.pc1.setLocalDescription(offer);
    this.pc2.setRemoteDescription(offer);
    this.pc2.createAnswer(this.gotAnswer_.bind(this));
  },

  gotAnswer_: function (answer) {
    if (this.constrainVideoBitrateKbps_) {
      answer.sdp = answer.sdp.replace(
          /a=mid:video\r\n/g,
          'a=mid:video\r\nb=AS:' + this.constrainVideoBitrateKbps_ + '\r\n');
    }
    this.pc2.setLocalDescription(answer);
    this.pc1.setRemoteDescription(answer);
  },

  onIceCandidate_: function (otherPeer) {
    if (event.candidate) {
      var parsed = Call.parseCandidate(event.candidate.candidate);
      if (this.iceCandidateFilter_(parsed)) {
        otherPeer.addIceCandidate(event.candidate);
      }
    }
  }
};

Call.noFilter = function () {
  return true;
};

Call.isRelay = function (candidate) {
  return candidate.type === 'relay';
};

Call.isNotHostCandidate = function (candidate) {
  return candidate.type !== 'host';
};

Call.isIpv6 = function (candidate) {
  return candidate.address.indexOf(':') !== -1;
};

// Parse a 'candidate:' line into a JSON object.
Call.parseCandidate = function (text) {
  var candidateStr = 'candidate:';
  var pos = text.indexOf(candidateStr) + candidateStr.length;
  var fields = text.substr(pos).split(' ');
  return {
    'type': fields[7],
    'protocol': fields[2],
    'address': fields[4],
  };
};

// Ask computeengineondemand to give us TURN server credentials and URIs.
Call.CEOD_URL = 'https://computeengineondemand.appspot.com/turn?username=1234&key=5678';
Call.asyncCreateTurnConfig = function (onSuccess, onError) {
  var xhr = new XMLHttpRequest();
  function onResult() {
    if (xhr.readyState !== 4) {
      return;
    }

    if (xhr.status !== 200) {
      onError('TURN request failed');
      return;
    }

    var response = JSON.parse(xhr.responseText);
    var iceServer = {
      'username': response.username,
      'credential': response.password,
      'urls': response.uris
    };
    onSuccess({ 'iceServers': [ iceServer ] });
  }

  xhr.onreadystatechange = onResult;
  xhr.open('GET', Call.CEOD_URL, true);
  xhr.send();
};
<commit_msg>call.js<commit_after>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */
'use strict';

function Call(config) {
  this.traceEvent = report.traceEventAsync('call');
  this.traceEvent({config: config});

  this.pc1 = new RTCPeerConnection(config);
  this.pc2 = new RTCPeerConnection(config);

  this.pc1.addEventListener('icecandidate', this.onIceCandidate_.bind(this,
      this.pc2));
  this.pc2.addEventListener('icecandidate', this.onIceCandidate_.bind(this,
      this.pc1));

  this.iceCandidateFilter_ = Call.noFilter;
}

Call.prototype = {
  establishConnection: function() {
    this.traceEvent({state: 'start'});
    this.pc1.createOffer(this.gotOffer_.bind(this));
  },

  close: function() {
    this.traceEvent({state: 'end'});
    this.pc1.close();
    this.pc2.close();
  },

  setIceCandidateFilter: function(filter) {
    this.iceCandidateFilter_ = filter;
  },

  // Constraint max video bitrate by modifying the SDP when creating an answer.
  constrainVideoBitrate: function(maxVideoBitrateKbps) {
    this.constrainVideoBitrateKbps_ = maxVideoBitrateKbps;
  },

  // Remove video FEC if available on the offer.
  disableVideoFec: function() {
    this.constrainOfferToRemoveVideoFec_ = true;
  },

  // When the peerConnection is closed the callback is called once returning
  // with an array of gathered stats.
  gatherStats: function(peerConnection, callback, interval) {
    var stats = [];
    getStats_();

    function getStats_() {
      if (peerConnection.signalingState === 'closed') {
        callback(stats);
        return;
      }
      setTimeout(function() {
        peerConnection.getStats(gotStats_.bind(this));
      }, interval);
    }

    function gotStats_(response) {
      for (var index in response.result()) {
        stats.push(response.result()[index]);
      }
      getStats_();
    }
  },

  gotOffer_: function(offer) {
    if (this.constrainOfferToRemoveVideoFec_) {
      offer.sdp = offer.sdp.replace(/(m=video 1 [^\r]+)(116 117)(\r\n)/g,
                                    '$1\r\n');
      offer.sdp = offer.sdp.replace(/a=rtpmap:116 red\/90000\r\n/g, '');
      offer.sdp = offer.sdp.replace(/a=rtpmap:117 ulpfec\/90000\r\n/g, '');
    }
    this.pc1.setLocalDescription(offer);
    this.pc2.setRemoteDescription(offer);
    this.pc2.createAnswer(this.gotAnswer_.bind(this));
  },

  gotAnswer_: function(answer) {
    if (this.constrainVideoBitrateKbps_) {
      answer.sdp = answer.sdp.replace(
          /a=mid:video\r\n/g,
          'a=mid:video\r\nb=AS:' + this.constrainVideoBitrateKbps_ + '\r\n');
    }
    this.pc2.setLocalDescription(answer);
    this.pc1.setRemoteDescription(answer);
  },

  onIceCandidate_: function(otherPeer) {
    if (event.candidate) {
      var parsed = Call.parseCandidate(event.candidate.candidate);
      if (this.iceCandidateFilter_(parsed)) {
        otherPeer.addIceCandidate(event.candidate);
      }
    }
  }
};

Call.noFilter = function() {
  return true;
};

Call.isRelay = function(candidate) {
  return candidate.type === 'relay';
};

Call.isNotHostCandidate = function(candidate) {
  return candidate.type !== 'host';
};

Call.isIpv6 = function(candidate) {
  return candidate.address.indexOf(':') !== -1;
};

// Parse a 'candidate:' line into a JSON object.
Call.parseCandidate = function(text) {
  var candidateStr = 'candidate:';
  var pos = text.indexOf(candidateStr) + candidateStr.length;
  var fields = text.substr(pos).split(' ');
  return {
    'type': fields[7],
    'protocol': fields[2],
    'address': fields[4]
  };
};

// Ask computeengineondemand to give us TURN server credentials and URIs.
Call.CEOD_URL =
    'https://computeengineondemand.appspot.com/turn?username=1234&key=5678';
Call.asyncCreateTurnConfig = function(onSuccess, onError) {
  var xhr = new XMLHttpRequest();
  function onResult() {
    if (xhr.readyState !== 4) {
      return;
    }

    if (xhr.status !== 200) {
      onError('TURN request failed');
      return;
    }

    var response = JSON.parse(xhr.responseText);
    var iceServer = {
      'username': response.username,
      'credential': response.password,
      'urls': response.uris
    };
    onSuccess({'iceServers': [iceServer]});
  }

  xhr.onreadystatechange = onResult;
  xhr.open('GET', Call.CEOD_URL, true);
  xhr.send();
};
<|endoftext|>


<commit_before>var express = require('express');
var pg = require('pg');
var db_info = require('./db_info.js')
var app = express();
var pool = new pg.Pool(db_info.config);

app.get('/', function (req, res) {
  res.jsonp('Hello World!');
});

/****************************************************
* /path     /checkout/:id/:person/:qty
* /params   id
*           person
*           qty
* /brief    Route to remove some :qty from inventory
*
* /author   Luke?
****************************************************/
app.get('/checkout/:id/:person/:qty', function(req, res) {
    transaction(req.params.id, req.params.person, -req.params.qty, errResultHandler, res);
});

/****************************************************
* /path     /checkin/:id/:person/:qty
* /params   id
*           person
*           qty
* /brief    Route to add item back into inventory
*
* /author   Luke
****************************************************/
app.get('/checkin/:id/:person/:qty', function(req, res) {
    transaction(req.params.id, req.params.person, req.params.qty, errResultHandler, res);
});

/****************************************************
* /path     N/A
* /brief    Helper function for checkin route
*
* /author   Luke
****************************************************/
var transaction = function(id, person, qty, retFunc, res) {

    pool.connect(function(err, client, done) {
        if(err) {
            return console.error('error fetching client from pool', err);
        }

         client.query('INSERT INTO transactions(item_id, person, qty_changed) VALUES ($1, $2, $3)', [id, person, qty], function(err, result) {
            //call `done()` to release the client back to the pool
            done();

            if(err) {
                console.error('error running query', err);
                retFunc(err, null, res);
            } else {
                retFunc(null, 'Transaction Completed Successfully', res);
            }
        });
    });
}

/****************************************************
* /path     /view
* /params   null
* /brief    Display all entries in the items table
*
* /author   <insert name>
****************************************************/
app.get('/view', function(req, res){
  //first query the database
  //then return the results to the user

      pool.connect(function(err, client, done) {
        if(err) {
            return console.error('error fetching client from pool', err);
        }
        client.query('SELECT item_id, item_name AS name, description, quantity FROM items', [], function(err, result) {
            //call `done()` to release the client back to the pool
            done();
            errResultHandler(err, result.rows, res);
        });
    });
});

/****************************************************
* /path     /add/:name/:desc/:price/:thresh
* /params
*
* /brief    Add new item api route, used to insert rows into
*
* /author   Austen & Luke
* /date     2/7/2017
****************************************************/
app.get('/add/:name/:desc/:price/:thresh', function(req, res){
  //first query the database
  //then return the results to the user

      pool.connect(function(err, client, done) {
        if(err) {
            return console.error('error fetching client from pool', err);
        }
        client.query('INSERT INTO items(item_name, description, price, threshold) VALUES ($1, $2, $3, $4)',
        [req.params.name, req.params.desc, req.params.price, req.params.thresh], function(err, result) {
            //call `done()` to release the client back to the pool
            done();
            errResultHandler(err, 'Item Added Successfully', res);
        });
    });
});

/****************************************************
* /path     /shoppinglist
* /params   null
* /brief    Returns all items with quantity less than threshold
*
* /author   Luke
****************************************************/
app.get('/shoppinglist', function(req, res){
  //first query the database
  //then return the results to the user

      pool.connect(function(err, client, done) {
        if(err) {
            return console.error('error fetching client from pool', err);
        }
        client.query('SELECT item_name AS name, description, price FROM items WHERE quantity < threshold', [], function(err, result) {
            //call `done()` to release the client back to the pool
            done();
            errResultHandler(err, result.rows, res);
        });
    });
});

/****************************************************
* /path     /stats/:id
* /params
*
*
* /brief    Route to pull satistics for an item
*           should probably be renamed to be more specific
*
* /author   Andrew McCann
* /date     2/3/2017
****************************************************/
app.get('/stats/:id', function(err, client, done) {
    pool.connect(function(err, client, done) {
        if(err) {
            return console.error('Error fetching client from pool', err);
        }
        /*
        client.query('INSERT INTO transactions(item_id, person, qty_changed) VALUES ($1, $2, $3)', [id, person, qty], function(err, result) {
        client.query('SELECT item_name, quantity, blahbalh
        client.query('SELECT * FROM transactions WHERE item_name = id', [], function(err, result) {
            done();

            if(err)
                return console.error('Error returned from DB', err);

            res.jsonp(result.rows);
        }*/
    });
});

/****************************************************
* /path     /stats/range/:start_date/:end_date
* /params   :start_date - Beginning of time frame
*           :end_date - End of time frame
*
* /brief    Route to pull all stats from a date_range
*
* /author   Andrew McCann
* /date     2/3/2017
****************************************************/
app.get('/stats/range/:start_date/:end_date', function(err, client, done) {
    pool.connect(function(err, client, done) {
        if(err) {
            return console.error('Error fetching client from pool', err);
        }
        /*
        client.query('SELECT * FROM transactions WHERE date <= end_date AND date >= start_date', [], function(err, result) {
            done();
            if(err) {
                return console.error('Error resulting from query', err);
            }
        } */
    });

});

/****************************************************
* /path     /stats/range/:start_date/:end_date
* /params   :start_date - Beginning of time frame
*           :end_date - End of time frame
*
* /brief    Responds with a meaningful status and returns the results
*
* /author   Luke
* /date     2/7/2017
****************************************************/
var errResultHandler = function(err, result, res) {
    if (err) {
      res.status(500);
      res.jsonp('Database Error');
    } else {
      res.status(200);
      res.jsonp(result);
    }
}

app.listen(3000, function () {
  console.log('Listening on port 3000');
});
<commit_msg>Add API route for tagging items<commit_after>var express = require('express');
var pg = require('pg');
var db_info = require('./db_info.js')
var app = express();
var pool = new pg.Pool(db_info.config);

app.get('/', function (req, res) {
  res.jsonp('Hello World!');
});

/****************************************************
* /path     /checkout/:id/:person/:qty
* /params   id
*           person
*           qty
* /brief    Route to remove some :qty from inventory
*
* /author   Luke?
****************************************************/
app.get('/checkout/:id/:person/:qty', function(req, res) {
    transaction(req.params.id, req.params.person, -req.params.qty, errResultHandler, res);
});

/****************************************************
* /path     /checkin/:id/:person/:qty
* /params   id
*           person
*           qty
* /brief    Route to add quantity to an existing item in the inventory
*
* /author   Luke
****************************************************/
app.get('/checkin/:id/:person/:qty', function(req, res) {
    transaction(req.params.id, req.params.person, req.params.qty, errResultHandler, res);
});

/****************************************************
* /path     N/A
* /brief    Helper function for checkin route
*
* /author   Luke
****************************************************/
var transaction = function(id, person, qty, retFunc, res) {

    pool.connect(function(err, client, done) {
        if(err) {
            return console.error('error fetching client from pool', err);
        }

         client.query('INSERT INTO transactions(item_id, person, qty_changed) VALUES ($1, $2, $3)', [id, person, qty], function(err, result) {
            //call `done()` to release the client back to the pool
            done();

            if(err) {
                console.error('error running query', err);
                retFunc(err, null, res);
            } else {
                retFunc(null, 'Transaction Completed Successfully', res);
            }
        });
    });
}

/****************************************************
* /path     /view
* /params   null
* /brief    Display all entries in the items table
*
* /author   <insert name>
****************************************************/
app.get('/view', function(req, res){
  //first query the database
  //then return the results to the user

      pool.connect(function(err, client, done) {
        if(err) {
            return console.error('error fetching client from pool', err);
        }
        client.query('SELECT item_id, item_name AS name, description, quantity FROM items', [], function(err, result) {
            //call `done()` to release the client back to the pool
            done();
            errResultHandler(err, result.rows, res);
        });
    });
});

/****************************************************
* /path     /add/:name/:desc/:price/:thresh
* /params   name - the name of the item
*           desc - the item description
*           price - the price of the item in decimal form
*           thresh - the threshold to notify the admin if the quantity drops below
*
* /brief    Add new item api route, used to insert rows into
*
* /author   Austen & Luke
* /date     2/7/2017
****************************************************/
app.get('/add/:name/:desc/:price/:thresh', function(req, res){
  //first query the database
  //then return the results to the user

      pool.connect(function(err, client, done) {
        if(err) {
            return console.error('error fetching client from pool', err);
        }
        client.query('INSERT INTO items(item_name, description, price, threshold) VALUES ($1, $2, $3, $4)',
        [req.params.name, req.params.desc, req.params.price, req.params.thresh], function(err, result) {
            //call `done()` to release the client back to the pool
            done();
            errResultHandler(err, 'Item Added Successfully', res);
        });
    });
});

/****************************************************
* /path     /tagitem/:id/:tag
* /params   :id - The id of the item to tag
*           :tag - the name of the tag to give the item
*
* /brief    Add a tag to an item given its id
*
* /author   Luke
* /date     2/7/2017
****************************************************/
app.get('/tagitem/:id/:tag', function(req, res){
  //first query the database
  //then return the results to the user

      pool.connect(function(err, client, done) {
        if(err) {
            return console.error('error fetching client from pool', err);
        }
        client.query('INSERT INTO tags VALUES ($1, $2)',
                    [req.params.tag, req.params.id], function(err, result) {
            //call `done()` to release the client back to the pool
            done();
            errResultHandler(err, 'Tag Added Successfully', res);
        });
    });
});

/****************************************************
* /path     /shoppinglist
* /params   null
* /brief    Returns all items with quantity less than threshold
*
* /author   Luke
****************************************************/
app.get('/shoppinglist', function(req, res){
  //first query the database
  //then return the results to the user

      pool.connect(function(err, client, done) {
        if(err) {
            return console.error('error fetching client from pool', err);
        }
        client.query('SELECT item_name AS name, description, price FROM items WHERE quantity < threshold', [], function(err, result) {
            //call `done()` to release the client back to the pool
            done();
            errResultHandler(err, result.rows, res);
        });
    });
});

/****************************************************
* /path     /stats/:id
* /params
*
*
* /brief    Route to pull satistics for an item
*           should probably be renamed to be more specific
*
* /author   Andrew McCann
* /date     2/3/2017
****************************************************/
app.get('/stats/:id', function(err, client, done) {
    pool.connect(function(err, client, done) {
        if(err) {
            return console.error('Error fetching client from pool', err);
        }
        /*
        client.query('INSERT INTO transactions(item_id, person, qty_changed) VALUES ($1, $2, $3)', [id, person, qty], function(err, result) {
        client.query('SELECT item_name, quantity, blahbalh
        client.query('SELECT * FROM transactions WHERE item_name = id', [], function(err, result) {
            done();

            if(err)
                return console.error('Error returned from DB', err);

            res.jsonp(result.rows);
        }*/
    });
});

/****************************************************
* /path     /stats/range/:start_date/:end_date
* /params   :start_date - Beginning of time frame
*           :end_date - End of time frame
*
* /brief    Route to pull all stats from a date_range
*
* /author   Andrew McCann
* /date     2/3/2017
****************************************************/
app.get('/stats/range/:start_date/:end_date', function(err, client, done) {
    pool.connect(function(err, client, done) {
        if(err) {
            return console.error('Error fetching client from pool', err);
        }
        /*
        client.query('SELECT * FROM transactions WHERE date <= end_date AND date >= start_date', [], function(err, result) {
            done();
            if(err) {
                return console.error('Error resulting from query', err);
            }
        } */
    });

});

/****************************************************
* /path     /stats/range/:start_date/:end_date
* /params   :err - the error that occured, null if none
*           :result - the result of the database query
                      (either the rows returned or success message)
            :res - the function to handle the responding the result
*
* /brief    Responds with a meaningful status and returns the results
*
* /author   Luke
* /date     2/7/2017
****************************************************/
var errResultHandler = function(err, result, res) {
    if (err) {
      res.status(500);
      res.jsonp('Database Error');
    } else {
      res.status(200);
      res.jsonp(result);
    }
}

app.listen(3000, function () {
  console.log('Listening on port 3000');
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.logger',
  name: 'DiscardLogger',
  extends: 'foam.nanos.logger.ProxyLogger',
  requires: [
    'foam.nanos.logger.LogLevel',
  ],
  properties: [
    {
      class: 'Object',
      name: 'lastUniqueObject',
      value: null
    },
    {
      class: 'Int',
      name: 'repeatCount',
      value: 0
    },
    {
      class: 'Enum',
      of: 'foam.nanos.logger.LogLevel',
      name: 'lastLogLevel',
      factory: function() { return foam.nanos.logger.LogLevel.INFO; }
    }
  ],

  methods: [
    {
        name: 'newLogHandler',
        args: [
          {
          name: 'logLevelName',
          javaType: 'String'
          },
          {
            name: 'setLastLogLevel',
            javaType: 'Boolean'
          },
          {
            name: 'args',
            javaType: 'Object...',
          },

        ],
        javaReturns: 'void',
        javaCode: `
        switch ( logLevelName ) {
          case "debug": {
              setRepeatCount(1);
              setLastUniqueObject(args);
              getDelegate().debug(args);
              if (setLastLogLevel){
                setLastLogLevel(LogLevel.DEBUG);
              break;
          }
              }
              case "info":  {
                setRepeatCount(1);
                setLastUniqueObject(args);
                getDelegate().info(args);
                if (setLastLogLevel){
                  setLastLogLevel(LogLevel.INFO);
                }
                break;
              }
              case "warning":  {
                setRepeatCount(1);
                setLastUniqueObject(args);
                getDelegate().warning(args);
                if (setLastLogLevel){
                  setLastLogLevel(LogLevel.WARNING);
                }
                break;

                }
                case "error":  {
                  setRepeatCount(1);
                  setLastUniqueObject(args);
                  getDelegate().error(args);
                  if (setLastLogLevel){
                    setLastLogLevel(LogLevel.ERROR);
                  }
                break;

                }
              }
    `
    },

    {
      name: 'repeatLogConstructor',
      args: [
        {
        name: 'logLevelName',
        javaType: 'String'
        },
        {
          name: 'args',
          javaType: 'Object...',
        }
      ],
      javaReturns: 'void',
      javaCode: `
        if (! getLastLogLevel().toString().equalsIgnoreCase(logLevelName)){
              if (getRepeatCount() > 1){

                switch ( getLastLogLevel() ) {
                  case DEBUG: {
                    getDelegate().debug("previous count repeated " + getRepeatCount() +" times");
                    break;
                  }
                  case INFO:  {
                    getDelegate().info("previous count repeated " + getRepeatCount() +" times");
                    break;
                  }
                  case WARNING:  {
                    getDelegate().warning("previous count repeated " + getRepeatCount() +" times");
                    break;
                  }
                  case ERROR:  {
                    getDelegate().error("previous count repeated " + getRepeatCount() +" times");
                    break;
                  }
                }

              }

              newLogHandler(logLevelName,true,args);
              return;
              // ;
            };

        if ( getLastUniqueObject() == null){
          newLogHandler(logLevelName,false,args);
          }
            else {

                Object[] o = (Object[]) getLastUniqueObject();
                if ( ! (args.length == o.length ) ){
                  // Different Message
                  if (getRepeatCount() > 1){
                    getDelegate().info("previous count repeated " + getRepeatCount() +" times");
                  }
                  newLogHandler(logLevelName,false,args);
                }

               else{
                  for ( int i = 0; i < args.length; i ++) {
                    if  ( ! ( args[i].equals(o[i]) && !(args[i] instanceof Exception) )  ) {
                      if (getRepeatCount() > 1){
                        getDelegate().info("previous count repeated " + getRepeatCount() +" times");
                      }
                      newLogHandler(logLevelName,false,args);
                    return;
                    }
                  }
                  setRepeatCount(getRepeatCount()+1);
                }
              }

            `

    },
    {
      name: 'debug',
      args:[
        {
          name: 'args',
          javaType: 'Object...',
        }
      ],
      javaReturns: 'void',
      javaCode: `
      String logLevelName = new String("debug");
      repeatLogConstructor(logLevelName,args);
      `

    },
    {
      name: 'info',
      args:[
        {
          name: 'args',
          javaType: 'Object...',
        }
      ],
      javaReturns: 'void',
      javaCode: `
      String logLevelName = new String("info");
      repeatLogConstructor(logLevelName,args);
      `

    },

    {
      name: 'warning',
      args:[
        {
          name: 'args',
          javaType: 'Object...',
        }
      ],
      javaReturns: 'void',
      javaCode: `
      String logLevelName = new String("warning");
      repeatLogConstructor(logLevelName,args);
      `

    },
    {
      name: 'error',
      args:[
        {
          name: 'args',
          javaType: 'Object...',
        }
      ],
      javaReturns: 'void',
      javaCode: `
      String logLevelName = new String("error");
      repeatLogConstructor(logLevelName,args);
      `
    }

  ]
});

// abstract out logic for when a new error/ old error is encountered
// implement hashcode to check instead of equals<commit_msg>abstract out logging of counts of previous message<commit_after>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.logger',
  name: 'DiscardLogger',
  extends: 'foam.nanos.logger.ProxyLogger',
  requires: [
    'foam.nanos.logger.LogLevel',
  ],
  properties: [
    {
      class: 'Object',
      name: 'lastUniqueObject',
      value: null
    },
    {
      class: 'Int',
      name: 'repeatCount',
      value: 0
    },
    {
      class: 'Enum',
      of: 'foam.nanos.logger.LogLevel',
      name: 'lastLogLevel',
      factory: function() { return foam.nanos.logger.LogLevel.INFO; }
    }
  ],

  methods: [
    {
        name: 'newLogHandler',
        args: [
          {
          name: 'logLevelName',
          javaType: 'String'
          },
          {
            name: 'setLastLogLevel',
            javaType: 'Boolean'
          },
          {
            name: 'args',
            javaType: 'Object...',
          },

        ],
        javaReturns: 'void',
        javaCode: `
        switch ( logLevelName ) {
          case "debug": {
              setRepeatCount(1);
              setLastUniqueObject(args);
              getDelegate().debug(args);
              if (setLastLogLevel){
                setLastLogLevel(LogLevel.DEBUG);
              break;
          }
              }
              case "info":  {
                setRepeatCount(1);
                setLastUniqueObject(args);
                getDelegate().info(args);
                if (setLastLogLevel){
                  setLastLogLevel(LogLevel.INFO);
                }
                break;
              }
              case "warning":  {
                setRepeatCount(1);
                setLastUniqueObject(args);
                getDelegate().warning(args);
                if (setLastLogLevel){
                  setLastLogLevel(LogLevel.WARNING);
                }
                break;

                }
                case "error":  {
                  setRepeatCount(1);
                  setLastUniqueObject(args);
                  getDelegate().error(args);
                  if (setLastLogLevel){
                    setLastLogLevel(LogLevel.ERROR);
                  }
                break;
                }
              }
    `
    },
    {
      name: 'logLastLogRepeats',

      javaReturns: 'void',
      javaCode:
      `
      switch ( getLastLogLevel() ) {
        case DEBUG: {
          getDelegate().debug("The last log was repeated " + getRepeatCount() + " times" );
          break;
        }
        case INFO:  {
          getDelegate().info("The last log was repeated "+ getRepeatCount()  + " times" );
          break;
        }
        case WARNING:  {
          getDelegate().warning("The last log was repeated "+ getRepeatCount()  + " times" );
          break;
        }
        case ERROR:  {
          getDelegate().error("The last log was repeated " + getRepeatCount() + " times" );
          break;
        }
      }
      `

    },

    {
      name: 'repeatLogConstructor',
      args: [
        {
        name: 'logLevelName',
        javaType: 'String'
        },
        {
          name: 'args',
          javaType: 'Object...',
        }
      ],
      javaReturns: 'void',
      javaCode: `
        if (! getLastLogLevel().toString().equalsIgnoreCase(logLevelName)){
              if (getRepeatCount() > 1){
                logLastLogRepeats();
              }
              newLogHandler(logLevelName,true,args);
              return;
            };

        if ( getLastUniqueObject() == null){
          newLogHandler(logLevelName,false,args);
          }
            else {
                Object[] o = (Object[]) getLastUniqueObject();
                if ( ! (args.length == o.length ) ){
                  // Different Message
                  if (getRepeatCount() > 1){
                    logLastLogRepeats();
                  }
                  newLogHandler(logLevelName,false,args);
                }

               else{
                  for ( int i = 0; i < args.length; i ++) {
                    if  ( ! ( args[i].equals(o[i]) && !(args[i] instanceof Exception) )  ) {
                      if (getRepeatCount() > 1){
                        logLastLogRepeats();
                      }
                      newLogHandler(logLevelName,false,args);
                    return;
                    }
                  }
                  setRepeatCount(getRepeatCount()+1);
                }
              }
            `
    },
    {
      name: 'debug',
      args:[
        {
          name: 'args',
          javaType: 'Object...',
        }
      ],
      javaReturns: 'void',
      javaCode: `
      String logLevelName = new String("debug");
      repeatLogConstructor(logLevelName,args);
      `

    },
    {
      name: 'info',
      args:[
        {
          name: 'args',
          javaType: 'Object...',
        }
      ],
      javaReturns: 'void',
      javaCode: `
      String logLevelName = new String("info");
      repeatLogConstructor(logLevelName,args);
      `

    },

    {
      name: 'warning',
      args:[
        {
          name: 'args',
          javaType: 'Object...',
        }
      ],
      javaReturns: 'void',
      javaCode: `
      String logLevelName = new String("warning");
      repeatLogConstructor(logLevelName,args);
      `
    },
    {
      name: 'error',
      args:[
        {
          name: 'args',
          javaType: 'Object...',
        }
      ],
      javaReturns: 'void',
      javaCode: `
      String logLevelName = new String("error");
      repeatLogConstructor(logLevelName,args);
      `
    }
  ]
});

// abstract out logic for when a new error/ old error is encountered
// implement hashcode to check instead of equals<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'UnstyledTableView',
  extends: 'foam.u2.Element',

  implements: [
    'foam.mlang.Expressions'
  ],

  requires: [
    'foam.u2.md.OverlayDropdown',
    'foam.u2.view.EditColumnsView'
  ],

  exports: [
    'columns',
    'selection',
    'hoverSelection'
  ],

  imports: [
    'dblclick?',
    'editRecord?',
    'selection? as importSelection'
  ],

  properties: [
    {
      class: 'Class',
      name: 'of'
    },
    {
      class: 'foam.dao.DAOProperty',
      name: 'data',
      postSet: function(_, data) {
        if ( ! this.of && data ) this.of = data.of;
      }
    },
    {
      class: 'foam.dao.DAOProperty',
      name: 'orderedDAO',
      expression: function(data, order) {
        return data ? data.orderBy(order) : foam.dao.NullDAO.create();
      }
    },
    {
      name: 'order'
    },
    {
      name: 'columns_',
      expression: function(columns, of) {
        var of = this.of;
        if ( ! of ) return [];

        return columns.map(function(p) {
          var c = typeof p == 'string' ?
            of.getAxiomByName(p) :
            p;

           if ( ! c ) {
             console.error('Unknown table column: ', p);
           }

          return c;
        }).filter(function(c) { return c; });
      }
    },
    {
      name: 'columns',
      expression: function(of) {
        var of = this.of;
        if ( ! of ) return [];

        var tableColumns = of.getAxiomByName('tableColumns');

        if ( tableColumns ) return tableColumns.columns;

        return of.getAxiomsByClass(foam.core.Property).
            filter(function(p) { return p.tableCellFormatter && ! p.hidden; }).
            map(foam.core.Property.NAME.f);
      }
    },
    {
      class: 'FObjectArray',
      of: 'foam.core.Action',
      name: 'contextMenuActions',
      documentation: `
        Each table row has a context menu that contains actions you can perform
        on the object in that row. The actions used to populate that menu come
        from two different sources. The first source is this property. If you
        want a context menu action to do something in the view, then you should
        write the code for that action in the view model and pass it to the
        table view via this property. The second source of actions is from the
        model of the object being shown in the table.
      `
    },
    {
      class: 'Boolean',
      name: 'editColumnsEnabled',
      value: true,
      documentation: 'Set this to true to let the user select columns.'
    },
    {
      class: 'Boolean',
      name: 'disableUserSelection',
      value: false,
      documentation: 'Ignores selection by user.'
    },
    {
      name: 'ascIcon',
      documentation: 'HTML entity representing unicode Up-Pointing Triangle',
      factory: function() {
        return this.Entity.create({ name: '#9650' });
      }
    },
    {
      name: 'descIcon',
      documentation: 'HTML entity representing unicode Down-Pointing Triangle',
      factory: function() {
        return this.Entity.create({ name: '#9660' });
      }
    },
    {
      name: 'vertMenuIcon',
      documentation: 'HTML entity representing unicode Vertical Ellipsis',
      factory: function() {
        return this.Entity.create({ name: '#8942' });
      }
    },
    {
      name: 'selection',
      expression: function(importSelection) { return importSelection || null; },
    },
    'hoverSelection',
    'dropdownOrigin',
    'overlayOrigin'
  ],

  methods: [
    function sortBy(column) {
      this.order = this.order === column ?
        this.DESC(column) :
        column;
    },

    function createColumnSelection() {
      var editor = this.EditColumnsView.create({
        columns: this.columns,
        columns_$: this.columns_$,
        table: this.of
      });

      return this.OverlayDropdown.create().add(editor);
    },

    /** Adds offset for edit columns overlay dropdown
     * OverlayDropdown adds element to top right of parent container.
     * We want the table dropdown to appear below the dropdown icon.
     */
    function positionOverlayDropdown(overlay) {
      // Dynamic position calculation
      var origin  = this.dropdownOrigin.el();
      var current = this.overlayOrigin.el();

      var boundingBox = origin.getBoundingClientRect();
      var dropdownMenu = current.getBoundingClientRect();

      overlay.style({ top: boundingBox.top - dropdownMenu.top + 'px' });
    },

    function initE() {
      var view = this;
      var columnSelectionE;

      this.start('div', null, this.overlayOrigin$)
        .callIf(view.editColumnsEnabled, function() {
          columnSelectionE = view.createColumnSelection();
          this.add(columnSelectionE);
        })
      .end();

      this.
        addClass(this.myClass()).
        addClass(this.myClass(this.of.id.replace(/\./g, '-'))).
        setNodeName('table').
        start('thead').
          add(this.slot(function(columns_) {
            return this.E('tr').
              forEach(columns_, function(column) {
                this.start('th').
                  addClass(view.myClass('th-' + column.name)).
                  callIf(column.tableWidth, function() {
                    this.style({ width: column.tableWidth });
                  }).
                  on('click', function(e) { view.sortBy(column); }).
                  call(column.tableHeaderFormatter, [column]).
                  add(' ', this.slot(function(order) {
                    return column === order ? view.ascIcon :
                        (view.Desc.isInstance(order) && order.arg1 === column) ? view.descIcon : ''
                  }, view.order$)).
                end();
              }).
              call(function() {
                this.start('th').
                  callIf(view.editColumnsEnabled, function() {
                    this.addClass(view.myClass('th-editColumns')).
                    on('click', function(e) {
                      view.positionOverlayDropdown(columnSelectionE);
                      columnSelectionE.open();
                    }).
                    add(' ', view.vertMenuIcon).
                    addClass(view.myClass('vertDots')).
                    addClass(view.myClass('noselect'));
                  }).
                  tag('div', null, view.dropdownOrigin$).
                end();
              });
          })).
          add(this.slot(function(columns_) {
            return this.
              E('tbody').
              select(this.orderedDAO$proxy, function(obj) {
                return this.E('tr').
                  on('mouseover', function() { view.hoverSelection = obj; }).
                  callIf(view.dblclick && ! view.disableUserSelection, function() {
                    this.on('dblclick', function() {
                      view.dblclick && view.dblclick(obj);
                    });
                  }).
                  callIf( ! view.disableUserSelection, function() {
                    this.on('click', function(evt) {
                      // If we're clicking somewhere to close the context menu,
                      // don't do anything.
                      if (
                        evt.target.nodeName === 'DROPDOWN-OVERLAY' ||
                        evt.target.classList.contains(view.myClass('vertDots'))
                      ) return;

                      view.selection = obj;
                      if ( view.importSelection$ ) view.importSelection = obj;
                      if ( view.editRecord$ ) view.editRecord(obj);
                    });
                  }).
                  addClass(view.slot(function(selection) {
                    return selection && foam.util.equals(obj.id, selection.id) ?
                        view.myClass('selected') : '';
                  })).
                  addClass(view.myClass('row')).
                  forEach(columns_, function(column) {
                    this.
                      start('td').
                        callOn(column.tableCellFormatter, 'format', [
                          column.f ? column.f(obj) : null, obj, column
                        ]).
                      end();
                  }).
                  call(function() {
                    var modelActions = view.of.getAxiomsByClass(foam.core.Action);
                    var allActions = Array.isArray(view.contextMenuActions) ?
                      view.contextMenuActions.concat(modelActions) :
                      modelActions;
                    var actions = allActions.filter(function(action) {
                      return action.isAvailableFor(obj);
                    });

                    // Show the context menu in a disabled state if there are
                    // no available actions.
                    if ( actions.length === 0 ) {
                      return this.start('td').
                        style({ 'text-align': 'right' }).
                        start('span').
                          addClass(view.myClass('vertDots')).
                          addClass(view.myClass('noselect')).
                          addClass('disabled').
                          add(view.vertMenuIcon).
                        end().
                      end();
                    }

                    var overlay = view.OverlayDropdown.create();
                    overlay.forEach(actions, function(action) {
                      this.start()
                        .addClass(view.myClass('context-menu-item'))
                        .add(action.label)
                        .call(function() {
                          if ( action.isEnabledFor(obj) ) {
                            this.on('click', function(evt) {
                              action.maybeCall(view.__subContext__, obj);
                            });
                          } else {
                            this.addClass('disabled');
                          }
                        })
                        .end();
                    });

                    return this.start('td').
                      add(overlay).
                      style({ 'text-align': 'right' }).
                      start('span').
                        addClass(view.myClass('vertDots')).
                        addClass(view.myClass('noselect')).
                        add(view.vertMenuIcon).
                        on('click', function(evt) {
                          view.positionOverlayDropdown(overlay);
                          overlay.open();
                        }).
                      end().
                    end();
                  });
              });
          }));
    }
  ]
});
<commit_msg>Put everything inline to avoid duplication<commit_after>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2.view',
  name: 'UnstyledTableView',
  extends: 'foam.u2.Element',

  implements: [
    'foam.mlang.Expressions'
  ],

  requires: [
    'foam.u2.md.OverlayDropdown',
    'foam.u2.view.EditColumnsView'
  ],

  exports: [
    'columns',
    'selection',
    'hoverSelection'
  ],

  imports: [
    'dblclick?',
    'editRecord?',
    'selection? as importSelection'
  ],

  properties: [
    {
      class: 'Class',
      name: 'of'
    },
    {
      class: 'foam.dao.DAOProperty',
      name: 'data',
      postSet: function(_, data) {
        if ( ! this.of && data ) this.of = data.of;
      }
    },
    {
      class: 'foam.dao.DAOProperty',
      name: 'orderedDAO',
      expression: function(data, order) {
        return data ? data.orderBy(order) : foam.dao.NullDAO.create();
      }
    },
    {
      name: 'order'
    },
    {
      name: 'columns_',
      expression: function(columns, of) {
        var of = this.of;
        if ( ! of ) return [];

        return columns.map(function(p) {
          var c = typeof p == 'string' ?
            of.getAxiomByName(p) :
            p;

           if ( ! c ) {
             console.error('Unknown table column: ', p);
           }

          return c;
        }).filter(function(c) { return c; });
      }
    },
    {
      name: 'columns',
      expression: function(of) {
        var of = this.of;
        if ( ! of ) return [];

        var tableColumns = of.getAxiomByName('tableColumns');

        if ( tableColumns ) return tableColumns.columns;

        return of.getAxiomsByClass(foam.core.Property).
            filter(function(p) { return p.tableCellFormatter && ! p.hidden; }).
            map(foam.core.Property.NAME.f);
      }
    },
    {
      class: 'FObjectArray',
      of: 'foam.core.Action',
      name: 'contextMenuActions',
      documentation: `
        Each table row has a context menu that contains actions you can perform
        on the object in that row. The actions used to populate that menu come
        from two different sources. The first source is this property. If you
        want a context menu action to do something in the view, then you should
        write the code for that action in the view model and pass it to the
        table view via this property. The second source of actions is from the
        model of the object being shown in the table.
      `
    },
    {
      class: 'Boolean',
      name: 'editColumnsEnabled',
      value: true,
      documentation: 'Set this to true to let the user select columns.'
    },
    {
      class: 'Boolean',
      name: 'disableUserSelection',
      value: false,
      documentation: 'Ignores selection by user.'
    },
    {
      name: 'ascIcon',
      documentation: 'HTML entity representing unicode Up-Pointing Triangle',
      factory: function() {
        return this.Entity.create({ name: '#9650' });
      }
    },
    {
      name: 'descIcon',
      documentation: 'HTML entity representing unicode Down-Pointing Triangle',
      factory: function() {
        return this.Entity.create({ name: '#9660' });
      }
    },
    {
      name: 'vertMenuIcon',
      documentation: 'HTML entity representing unicode Vertical Ellipsis',
      factory: function() {
        return this.Entity.create({ name: '#8942' });
      }
    },
    {
      name: 'selection',
      expression: function(importSelection) { return importSelection || null; },
    },
    'hoverSelection',
    'dropdownOrigin',
    'overlayOrigin'
  ],

  methods: [
    function sortBy(column) {
      this.order = this.order === column ?
        this.DESC(column) :
        column;
    },

    function createColumnSelection() {
      var editor = this.EditColumnsView.create({
        columns: this.columns,
        columns_$: this.columns_$,
        table: this.of
      });

      return this.OverlayDropdown.create().add(editor);
    },

    /** Adds offset for edit columns overlay dropdown
     * OverlayDropdown adds element to top right of parent container.
     * We want the table dropdown to appear below the dropdown icon.
     */
    function positionOverlayDropdown(overlay) {
      // Dynamic position calculation
      var origin  = this.dropdownOrigin.el();
      var current = this.overlayOrigin.el();

      var boundingBox = origin.getBoundingClientRect();
      var dropdownMenu = current.getBoundingClientRect();

      overlay.style({ top: boundingBox.top - dropdownMenu.top + 'px' });
    },

    function initE() {
      var view = this;
      var columnSelectionE;

      this.start('div', null, this.overlayOrigin$)
        .callIf(view.editColumnsEnabled, function() {
          columnSelectionE = view.createColumnSelection();
          this.add(columnSelectionE);
        })
      .end();

      this.
        addClass(this.myClass()).
        addClass(this.myClass(this.of.id.replace(/\./g, '-'))).
        setNodeName('table').
        start('thead').
          add(this.slot(function(columns_) {
            return this.E('tr').
              forEach(columns_, function(column) {
                this.start('th').
                  addClass(view.myClass('th-' + column.name)).
                  callIf(column.tableWidth, function() {
                    this.style({ width: column.tableWidth });
                  }).
                  on('click', function(e) { view.sortBy(column); }).
                  call(column.tableHeaderFormatter, [column]).
                  add(' ', this.slot(function(order) {
                    return column === order ? view.ascIcon :
                        (view.Desc.isInstance(order) && order.arg1 === column) ? view.descIcon : ''
                  }, view.order$)).
                end();
              }).
              call(function() {
                this.start('th').
                  callIf(view.editColumnsEnabled, function() {
                    this.addClass(view.myClass('th-editColumns')).
                    on('click', function(e) {
                      view.positionOverlayDropdown(columnSelectionE);
                      columnSelectionE.open();
                    }).
                    add(' ', view.vertMenuIcon).
                    addClass(view.myClass('vertDots')).
                    addClass(view.myClass('noselect'));
                  }).
                  tag('div', null, view.dropdownOrigin$).
                end();
              });
          })).
          add(this.slot(function(columns_) {
            return this.
              E('tbody').
              select(this.orderedDAO$proxy, function(obj) {
                return this.E('tr').
                  on('mouseover', function() { view.hoverSelection = obj; }).
                  callIf(view.dblclick && ! view.disableUserSelection, function() {
                    this.on('dblclick', function() {
                      view.dblclick && view.dblclick(obj);
                    });
                  }).
                  callIf( ! view.disableUserSelection, function() {
                    this.on('click', function(evt) {
                      // If we're clicking somewhere to close the context menu,
                      // don't do anything.
                      if (
                        evt.target.nodeName === 'DROPDOWN-OVERLAY' ||
                        evt.target.classList.contains(view.myClass('vertDots'))
                      ) return;

                      view.selection = obj;
                      if ( view.importSelection$ ) view.importSelection = obj;
                      if ( view.editRecord$ ) view.editRecord(obj);
                    });
                  }).
                  addClass(view.slot(function(selection) {
                    return selection && foam.util.equals(obj.id, selection.id) ?
                        view.myClass('selected') : '';
                  })).
                  addClass(view.myClass('row')).
                  forEach(columns_, function(column) {
                    this.
                      start('td').
                        callOn(column.tableCellFormatter, 'format', [
                          column.f ? column.f(obj) : null, obj, column
                        ]).
                      end();
                  }).
                  call(function() {
                    var modelActions = view.of.getAxiomsByClass(foam.core.Action);
                    var allActions = Array.isArray(view.contextMenuActions) ?
                      view.contextMenuActions.concat(modelActions) :
                      modelActions;
                    var actions = allActions.filter(function(action) {
                      return action.isAvailableFor(obj);
                    });
                    var overlay = view.OverlayDropdown.create();
                    return this.start('td').
                      callIf(actions.length > 0, function() {
                        overlay.forEach(actions, function(action) {
                          this.
                            start().
                              addClass(view.myClass('context-menu-item')).
                              add(action.label).
                              call(function() {
                                if ( action.isEnabledFor(obj) ) {
                                  this.on('click', function(evt) {
                                    action.maybeCall(view.__subContext__, obj);
                                  });
                                } else {
                                  this.addClass('disabled');
                                }
                              }).
                            end();
                        });
                        this.add(overlay);
                      }).
                      style({ 'text-align': 'right' }).
                      start('span').
                        addClass(view.myClass('vertDots')).
                        addClass(view.myClass('noselect')).
                        enableClass('disabled', actions.length === 0).
                        callIf(actions.length > 0, function() {
                          this.on('click', function(evt) {
                            view.positionOverlayDropdown(overlay);
                            overlay.open();
                          });
                        }).
                        add(view.vertMenuIcon).
                      end().
                    end();
                  });
              });
          }));
    }
  ]
});
<|endoftext|>


<commit_before>'use strict';

const OPERATOR_REGEX = /^(-|\+|\*{1,2}|\\|\/|#|&|!|_|\?|'*<=*|'*>=*|'*\[|'*\]{1,2}|\(|\)|'*=|'|\${1,2}|\^|,|:)/;
const STRING_REGEX = /^("+)/;
const CHARACTER_REGEX = /^([A-Za-z0-9\.]+)/;

class AbstractSyntaxTree {
    constructor(tokens) {
        this.tokens = tokens;
        this.generate();
    }
    generate() {
    }
}

module.exports = AbstractSyntaxTree;
<commit_msg>Remove unused global regexes<commit_after>'use strict';

class AbstractSyntaxTree {
    constructor(tokens) {
        this.tokens = tokens;
        this.generate();
    }
    generate() {
    }
}

module.exports = AbstractSyntaxTree;
<|endoftext|>