<commit_before>/**
 * Mixins dynamic segments replacing the `:segment_name` parts with provide
 * values
 * @param {String} url – URL
 * @param {Object} dynamicSegments – dynamic segments
 * @returns {String} – URL
 */
function mixinDynamicSegmentsValues (url, dynamicSegments) {
  let aggregator = url
  for (let [key, value] of dynamicSegments.entries()) {
    aggregator = aggregator.replace(`:${key}`, value)
  }
  return aggregator
}

/**
 * Adds query params string to url
 * @param {string} url – URL
 * @param {Array} queryParams – query params
 * @returns {String} – URL
 */
function addQueryParams (url, queryParams) {
  if (queryParams.size === 0)
    return url
  const chanks = [queryParams.lenght]
  for (let [key, value] of queryParams.entries()) {
    chanks.push(`${key}=${value}`)
  }
  return url + '?' + chanks.join('&')
}

/**
 * Adds headers to xmlhttp object
 * @param {Object} xmlhttp – XMLHttpRequest
 * @param {Object} headers – HTTP headers key-value collection
 * @returns {Object} – XMLHttpRequest
 */
function addHeaders (xmlhttp, headers) {
  for (let [key, value] of headers.entries()) {
    xmlhttp.setRequestHeader(key, value)
  }
  return xmlhttp
}

/**
 * Sets XMLHttpRequest response type
 * @param {Object} xmlhttp – XMLHttpRequest
 * @param {String} responseType – response type
 * @returns {Object} – XMLHttpRequest
 */
function setResponseType (xmlhttp, responseType) {
  if (!responseType) return xmlhttp
  xmlhttp.responseType = responseType
  return xmlhttp
}

/**
 * Executes if xmlhttp request succeed
 * @param {fulfillCallback} fulfill – fulfill callback
 * @param {Object} http – HTTP object
 * @param {Object} xmlhttp – XMLHttpRequest
 */
function onSucceed (fulfill, http, xmlhttp) {
  fulfill({
    status: xmlhttp.status,
    response: http.responseType ? xmlhttp.response : xmlhttp.responseText,
    headers: xmlhttp.getAllResponseHeaders()
  })
}

/**
 * Executes if xmlhttp request failed
 * @param {rejectCallback} reject - reject
 * @param {Object} http – HTTP object
 * @param {Object} xmlhttp – XMLHttpRequest
 */
function onFailed (reject, http, xmlhttp) {
  reject({
    status: xmlhttp.status,
    response: xmlhttp.response,
    headers: xmlhttp.getAllResponseHeaders()
  })
}

/**
 * Checks if status code is in range 200…299 to enshure response is in Ok state
 * @param {Number} statusCode - HTTP status code
 * @return {Boolean} true id status OK-like
 */
function isStatusOkLike (statusCode) {
  const delta = statusCode - 200
  const isOk = delta >= 0
  return isOk && delta < 100
}

/**
 * Cunstructs XmlHttpRequest object
 * @param {fulfillCallback} fulfill – fulfill callback
 * @param {rejectCallback} reject – reject callback
 * @returns {Object} XMLHttpRequest – XMLHttpRequest
 */
function getXmlHttp (fulfill, reject) {
  const xmlhttp = new XMLHttpRequest()
  xmlhttp.onreadystatechange = () => {
    if (xmlhttp.readyState !== 4)
      return
    if (isStatusOkLike(xmlhttp.status)) {
      fulfill(xmlhttp)
    } else {
      reject(xmlhttp)
    }
  }
  return xmlhttp
}

/**
 * Executes any submit type request
 * @param {Object} http – HTTP object
 * @returns {Object} - Promise
 */
function submit (http) {
  return new Promise((fulfill, reject) => {
    const xmlhttp = getXmlHttp(
      onSucceed.bind(this, fulfill, http),
      onFailed.bind(this, reject, http)
    )

    let url = mixinDynamicSegmentsValues(http.url(), http.dynamicSegments)
    url = addQueryParams(url, http.queryParams)

    xmlhttp.open(http.method(), url, true)
    setResponseType(xmlhttp, http.responseType)
    addHeaders(xmlhttp, http.headers)
    const body = http.bodyProcessor(http.body)
    xmlhttp.send(body)
  })
}

/**
 * Executes GET request
 * @param {Object} http – HTTP object
 * @returns {Object} - Promise
 */
function get (http) {
  return new Promise((fulfill, reject) => {
    const xmlhttp = getXmlHttp(
      onSucceed.bind(this, fulfill, http),
      onFailed.bind(this, reject, http)
    )

    let url = mixinDynamicSegmentsValues(http.url, http.dynamicSegments)
    url = addQueryParams(url, http.queryParams)

    xmlhttp.open('GET', url, true)
    addHeaders(xmlhttp, http.headers)
    setResponseType(xmlhttp, http.responseType)

    xmlhttp.send(null)
  })
}

const methodsHandlerMap = {
  GET: get,
  POST: submit,
  PUT: submit,
  DELETE: submit
}

/**
 * Executes validated http request
 * @param {Object} http – HTTP object
 * @returns {Object} – Promise
 */
function exec (http) {
  const handler = methodsHandlerMap[http.method]
  if (!handler)
    throw `Method ${http.method} is not supported`
  return handler(http)
}

export default exec
<commit_msg>functions -> getters<commit_after>/**
 * Mixins dynamic segments replacing the `:segment_name` parts with provide
 * values
 * @param {String} url – URL
 * @param {Object} dynamicSegments – dynamic segments
 * @returns {String} – URL
 */
function mixinDynamicSegmentsValues (url, dynamicSegments) {
  let aggregator = url
  for (let [key, value] of dynamicSegments.entries()) {
    aggregator = aggregator.replace(`:${key}`, value)
  }
  return aggregator
}

/**
 * Adds query params string to url
 * @param {string} url – URL
 * @param {Array} queryParams – query params
 * @returns {String} – URL
 */
function addQueryParams (url, queryParams) {
  if (queryParams.size === 0)
    return url
  const chanks = [queryParams.lenght]
  for (let [key, value] of queryParams.entries()) {
    chanks.push(`${key}=${value}`)
  }
  return url + '?' + chanks.join('&')
}

/**
 * Adds headers to xmlhttp object
 * @param {Object} xmlhttp – XMLHttpRequest
 * @param {Object} headers – HTTP headers key-value collection
 * @returns {Object} – XMLHttpRequest
 */
function addHeaders (xmlhttp, headers) {
  for (let [key, value] of headers.entries()) {
    xmlhttp.setRequestHeader(key, value)
  }
  return xmlhttp
}

/**
 * Sets XMLHttpRequest response type
 * @param {Object} xmlhttp – XMLHttpRequest
 * @param {String} responseType – response type
 * @returns {Object} – XMLHttpRequest
 */
function setResponseType (xmlhttp, responseType) {
  if (!responseType) return xmlhttp
  xmlhttp.responseType = responseType
  return xmlhttp
}

/**
 * Executes if xmlhttp request succeed
 * @param {fulfillCallback} fulfill – fulfill callback
 * @param {Object} http – HTTP object
 * @param {Object} xmlhttp – XMLHttpRequest
 */
function onSucceed (fulfill, http, xmlhttp) {
  fulfill({
    status: xmlhttp.status,
    response: http.responseType ? xmlhttp.response : xmlhttp.responseText,
    headers: xmlhttp.getAllResponseHeaders()
  })
}

/**
 * Executes if xmlhttp request failed
 * @param {rejectCallback} reject - reject
 * @param {Object} http – HTTP object
 * @param {Object} xmlhttp – XMLHttpRequest
 */
function onFailed (reject, http, xmlhttp) {
  reject({
    status: xmlhttp.status,
    response: xmlhttp.response,
    headers: xmlhttp.getAllResponseHeaders()
  })
}

/**
 * Checks if status code is in range 200…299 to enshure response is in Ok state
 * @param {Number} statusCode - HTTP status code
 * @return {Boolean} true id status OK-like
 */
function isStatusOkLike (statusCode) {
  const delta = statusCode - 200
  const isOk = delta >= 0
  return isOk && delta < 100
}

/**
 * Cunstructs XmlHttpRequest object
 * @param {fulfillCallback} fulfill – fulfill callback
 * @param {rejectCallback} reject – reject callback
 * @returns {Object} XMLHttpRequest – XMLHttpRequest
 */
function getXmlHttp (fulfill, reject) {
  const xmlhttp = new XMLHttpRequest()
  xmlhttp.onreadystatechange = () => {
    if (xmlhttp.readyState !== 4)
      return
    if (isStatusOkLike(xmlhttp.status)) {
      fulfill(xmlhttp)
    } else {
      reject(xmlhttp)
    }
  }
  return xmlhttp
}

/**
 * Executes any submit type request
 * @param {Object} http – HTTP object
 * @returns {Object} - Promise
 */
function submit (http) {
  return new Promise((fulfill, reject) => {
    const xmlhttp = getXmlHttp(
      onSucceed.bind(this, fulfill, http),
      onFailed.bind(this, reject, http)
    )

    let url = mixinDynamicSegmentsValues(http.url, http.dynamicSegments)
    url = addQueryParams(url, http.queryParams)

    xmlhttp.open(http.method, url, true)
    setResponseType(xmlhttp, http.responseType)
    addHeaders(xmlhttp, http.headers)
    const body = http.bodyProcessor(http.body)
    xmlhttp.send(body)
  })
}

/**
 * Executes GET request
 * @param {Object} http – HTTP object
 * @returns {Object} - Promise
 */
function get (http) {
  return new Promise((fulfill, reject) => {
    const xmlhttp = getXmlHttp(
      onSucceed.bind(this, fulfill, http),
      onFailed.bind(this, reject, http)
    )

    let url = mixinDynamicSegmentsValues(http.url, http.dynamicSegments)
    url = addQueryParams(url, http.queryParams)

    xmlhttp.open('GET', url, true)
    addHeaders(xmlhttp, http.headers)
    setResponseType(xmlhttp, http.responseType)

    xmlhttp.send(null)
  })
}

const methodsHandlerMap = {
  GET: get,
  POST: submit,
  PUT: submit,
  DELETE: submit
}

/**
 * Executes validated http request
 * @param {Object} http – HTTP object
 * @returns {Object} – Promise
 */
function exec (http) {
  const handler = methodsHandlerMap[http.method]
  if (!handler)
    throw `Method ${http.method} is not supported`
  return handler(http)
}

export default exec
<|endoftext|>


<commit_before>import {Validator, ValidationEngine} from 'aurelia-validatejs';

/***
 * Some functionalities are desired in a view model of a form. Responsibilites
 * include validation and submit.
 *
 * This class is optional and serves as a convenience class.
 *
 * - creates a messages property for storing error strings
 * - allows you to set the model which automaticall
 * - automatically triggers validation
 * - convenient methods that can be overwritten to perform action on submit and
 *   change
 */
export class Form {

  messages = {}

  /***
   * Used to get access to onSubmit and model changes could also wrap the
   * change and submit methods instead
   */
  onChange() {}
  onSubmit() {}

  constructor() {
    this.__defineSetter__('model', (model) => {
      this.onChange(model, this.model);
      this.__defineGetter__('model', () => model);
      this.observer && this.observer.dispose();
      this.validator = new Validator(model);
      this.reporter  = ValidationEngine.getValidationReporter(model);
      this.observer  = this.reporter.subscribe(validationErrors => {
        this.messages = validationErrors.reduce( (errors, error) => {
          errors[error.propertyName] = error.message;
          return errors;
        }, {});
      });
    });
  }

  validate() {
    this.validator.validate();
  }

  detached() {
    this.observer.dispose();
  }

  submit() {
    this.onSubmit(this.model);
    this.validate();
  }

  change() {
    this.onChange(this.model);
    this.validate();
  }

}
<commit_msg>feat(form): isValid property on Form<commit_after>import {Validator, ValidationEngine} from 'aurelia-validatejs';

/***
 * Some functionalities are desired in a view model of a form. Responsibilites
 * include validation and submit.
 *
 * This class is optional and serves as a convenience class.
 *
 * - creates a messages property for storing error strings
 * - allows you to set the model which automaticall
 * - automatically triggers validation
 * - convenient methods that can be overwritten to perform action on submit and
 *   change
 */
export class Form {

  messages = {}

  isValid

  /***
   * Used to get access to onSubmit and model changes could also wrap the
   * change and submit methods instead
   */
  onChange() {}
  onSubmit() {}

  constructor() {
    this.__defineSetter__('model', (model) => {
      this.onChange(model, this.model);
      this.__defineGetter__('model', () => model);
      this.observer && this.observer.dispose();
      this.validator = new Validator(model);
      this.reporter  = ValidationEngine.getValidationReporter(model);
      this.observer  = this.reporter.subscribe(validationErrors => {
        this.isValid = Object.keys(validationErrors).length === 0;
        this.messages = validationErrors.reduce((errors, error) => {
          errors[error.propertyName] = error.message;
          return errors;
        }, {});
      });
    });
  }

  validate() {
    this.validator.validate();
  }

  detached() {
    this.observer.dispose();
  }

  submit() {
    this.validate();
    this.onSubmit(this.model);
  }

  change() {
    this.validate();
    this.onChange(this.model);
  }

}
<|endoftext|>


<commit_before>(function() {
  var Game = Backbone.Model.extend({
    defaults: {
      "players": [],
      "currentTurn": 0,
      "scenario": undefined,
      "numberOfTurns": 0
    }
  });

  window.Game = Game;
}());
<commit_msg>Mock out state flow for game<commit_after>(function() {

  // Set up State enum
  var states = [ "Uninitialized",
                 "PlayerSetup",
                 "ShowScenarioChoices",
                 "PreTurn",
                 "MidTurn",
                 "PostTurn",
                 "OpinionPhase",
                 "VotingPhase",
                 "FinalChoice",
                 "GameEnd"
               ];

  var State = {};
  for (var i = 0; i < states; i++) {
    var stateName = states[ i ];
    Game.State[ stateName ] = stateName;
  }

  var Game = Backbone.Model.extend({
    defaults: {
      "players": [],
      "numberOfTurns": 0,
      "currentTurn": -1,
      "scenario": undefined,
      "cardsOnBoard": [],
      "state": State.Uninitialized
    },

    beginPlayerSetup: function() {
      this.set( "state", Game.State.PlayerSetup );
    },

    finishPlayerSetup: function( numberOfPlayers ) {
      // TODO: Generate players and scenario
      this.beginNextTurn();
    },

    beginNextTurn: function() {
      var turn = this.get( "currentTurn" ) + 1;
      this.set( "turn", turn );

      if ( turn < this.get( "numberOfTurns" )) {
        this.beginPreTurn();
      } else {
        this.beginOpinionPhase();
      }
    }

    beginPreTurn: function() {
      var turn = this.get( "turn" );
      var players = this.get( "players" );
      var currentPlayerIndex = turn % players.length;

      var currentPlayer = players[ currentPlayerIndex ];
      console.log( "*** Starting turn:", turn);
      console.log( "Player", currentPlayer.name, "take the screen! Everyone else look away!" );

      this.set( "state", Game.State.PreTurn );
    },

    beginMidTurn: function() {
      // Not sure that we need anything else here
      this.set( "state", Game.Start.MidTurn );
    },

    beginPostTurn: function( player, sharedCard, cardsOnBoard ) {
      player.shareCard( sharedCard );
      this.set( "cardsOnBoard", cardsOnBoard );
      this.set( "state", Game.State.PostTurn );
    },

    beginOpinionPhase: function() {
      this.set( "state", Game.State.OpinionPhase );
    },

    beginVotingPhase: function() {
      this.set( "state", Game.State.VotingPhase );
    },

    beginFinalChoice: function() {
      this.set( "state", Game.State.FinalChoice );
    },

    lockInDecision: function( choice ) {
      this.set( "state", Game.State.GameEnd );
    }
  });

  Game.State = State;
  window.Game = Game;
}());
<|endoftext|>


<commit_before>/*
  backgrid
  http://github.com/wyuenho/backgrid

  Copyright (c) 2013 Jimmy Yuen Ho Wong
  Licensed under the MIT @license.
*/

/**
   Grid represents a data grid that has a header, body and an optional footer.

   By default, a Grid treats each model in a collection as a row, and each
   attribute in a model as a column. To render a grid you must provide a list of
   column metadata and a collection to the Grid constructor. Just like any
   Backbone.View class, the grid is rendered as a DOM node fragment when you
   call render().

       var grid = Backgrid.Grid({
         columns: [{ name: "id", label: "ID", type: "string" },
          // ...
         ],
         collections: books
       });

       $("#table-container").append(grid.render().el);

   Optionally, if you want to customize the rendering of the grid's header and
   footer, you may choose to extend Backgrid.Header and Backgrid.Footer, and
   then supply that class or an instance of that class to the Grid constructor.
   See the documentation for Header and Footer for further details.

       var grid = Backgrid.Grid({
         columns: [{ name: "id", label: "ID", type: "string" }],
         collections: books,
         header: Backgrid.Header.extend({
              //...
         }),
         footer: Backgrid.Paginator
       });

   Finally, if you want to override how the rows are rendered in the table body,
   you can supply a Body subclass as the `body` attribute that uses a different
   Row class.

   @class Backgrid.Grid
   @extends Backbone.View

   See:

   - Backgrid.Column
   - Backgrid.Header
   - Backgrid.Body
   - Backgrid.Row
   - Backgrid.Footer
*/
var Grid = Backgrid.Grid = Backbone.View.extend({

  /** @property */
  tagName: "table",

  /** @property */
  className: "backgrid",

  /** @property */
  header: Header,

  /** @property */
  body: Body,

  /** @property */
  footer: null,

  /**
     Initializes a Grid instance.

     @param {Object} options
     @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
     @param {Backbone.Collection} options.collection The collection of tabular model data to display.
     @param {Backgrid.Header} [options.header=Backgrid.Header] An optional Header class to override the default.
     @param {Backgrid.Body} [options.body=Backgrid.Body] An optional Body class to override the default.
     @param {Backgrid.Row} [options.row=Backgrid.Row] An optional Row class to override the default.
     @param {Backgrid.Footer} [options.footer=Backgrid.Footer] An optional Footer class.
   */
  initialize: function (options) {
    requireOptions(options, ["columns", "collection"]);

    // Convert the list of column objects here first so the subviews don't have
    // to.
    if (!(options.columns instanceof Backbone.Collection)) {
      options.columns = new Columns(options.columns);
    }
    this.columns = options.columns;

    this.header = options.header || this.header;
    this.header = new this.header(options);

    this.body = options.body || this.body;
    this.body = new this.body(options);

    this.footer = options.footer || this.footer;
    if (this.footer) {
      this.footer = new this.footer(options);
    }

    this.listenTo(this.columns, "reset", function () {
      this.header = new (this.header.remove().constructor)(options);
      this.body = new (this.body.remove().constructor)(options);
      if (this.footer) this.footer = new (this.footer.remove().constructor)(options);
      this.render();
    });
  },

  /**
     Delegates to Backgrid.Body#insertRow.
   */
  insertRow: function (model, collection, options) {
    return this.body.insertRow(model, collection, options);
  },

  /**
     Delegates to Backgrid.Body#removeRow.
   */
  removeRow: function (model, collection, options) {
    return this.body.removeRow(model, collection, options);
  },

  /**
     Delegates to Backgrid.Columns#add for adding a column. Subviews can listen
     to the `add` event from their internal `columns` if rerendering needs to
     happen.

     @param {Object} [options] Options for `Backgrid.Columns#add`.
     @param {boolean} [options.render=true] Whether to render the column
     immediately after insertion.

     @chainable
   */
  insertColumn: function (column, options) {
    var self = this;
    options = options || {render: true};
    self.columns.add(column, options);
    return self;
  },

  /**
     Delegates to Backgrid.Columns#remove for removing a column. Subviews can
     listen to the `remove` event from the internal `columns` if rerendering
     needs to happen.

     @param {Object} [options] Options for `Backgrid.Columns#remove`.

     @chainable
   */
  removeColumn: function (column, options) {
    var self = this;
    self.columns.remove(column, options);
    return self;
  },

  /**
     Renders the grid's header, then footer, then finally the body.
   */
  render: function () {
    this.$el.empty();

    this.$el.append(this.header.render().$el);

    if (this.footer) {
      this.$el.append(this.footer.render().$el);
    }

    this.$el.append(this.body.render().$el);

    /**
       Backbone event. Fired when the grid has been successfully rendered.

       @event rendered
     */
    this.trigger("rendered");

    return this;
  },

  /**
     Clean up this grid and its subviews.

     @chainable
   */
  remove: function () {
    this.header.remove.apply(this.header, arguments);
    this.body.remove.apply(this.body, arguments);
    this.footer && this.footer.remove.apply(this.footer, arguments);
    return Backbone.View.prototype.remove.apply(this, arguments);
  }

});
<commit_msg>Change self back to this<commit_after>/*
  backgrid
  http://github.com/wyuenho/backgrid

  Copyright (c) 2013 Jimmy Yuen Ho Wong
  Licensed under the MIT @license.
*/

/**
   Grid represents a data grid that has a header, body and an optional footer.

   By default, a Grid treats each model in a collection as a row, and each
   attribute in a model as a column. To render a grid you must provide a list of
   column metadata and a collection to the Grid constructor. Just like any
   Backbone.View class, the grid is rendered as a DOM node fragment when you
   call render().

       var grid = Backgrid.Grid({
         columns: [{ name: "id", label: "ID", type: "string" },
          // ...
         ],
         collections: books
       });

       $("#table-container").append(grid.render().el);

   Optionally, if you want to customize the rendering of the grid's header and
   footer, you may choose to extend Backgrid.Header and Backgrid.Footer, and
   then supply that class or an instance of that class to the Grid constructor.
   See the documentation for Header and Footer for further details.

       var grid = Backgrid.Grid({
         columns: [{ name: "id", label: "ID", type: "string" }],
         collections: books,
         header: Backgrid.Header.extend({
              //...
         }),
         footer: Backgrid.Paginator
       });

   Finally, if you want to override how the rows are rendered in the table body,
   you can supply a Body subclass as the `body` attribute that uses a different
   Row class.

   @class Backgrid.Grid
   @extends Backbone.View

   See:

   - Backgrid.Column
   - Backgrid.Header
   - Backgrid.Body
   - Backgrid.Row
   - Backgrid.Footer
*/
var Grid = Backgrid.Grid = Backbone.View.extend({

  /** @property */
  tagName: "table",

  /** @property */
  className: "backgrid",

  /** @property */
  header: Header,

  /** @property */
  body: Body,

  /** @property */
  footer: null,

  /**
     Initializes a Grid instance.

     @param {Object} options
     @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
     @param {Backbone.Collection} options.collection The collection of tabular model data to display.
     @param {Backgrid.Header} [options.header=Backgrid.Header] An optional Header class to override the default.
     @param {Backgrid.Body} [options.body=Backgrid.Body] An optional Body class to override the default.
     @param {Backgrid.Row} [options.row=Backgrid.Row] An optional Row class to override the default.
     @param {Backgrid.Footer} [options.footer=Backgrid.Footer] An optional Footer class.
   */
  initialize: function (options) {
    requireOptions(options, ["columns", "collection"]);

    // Convert the list of column objects here first so the subviews don't have
    // to.
    if (!(options.columns instanceof Backbone.Collection)) {
      options.columns = new Columns(options.columns);
    }
    this.columns = options.columns;

    this.header = options.header || this.header;
    this.header = new this.header(options);

    this.body = options.body || this.body;
    this.body = new this.body(options);

    this.footer = options.footer || this.footer;
    if (this.footer) {
      this.footer = new this.footer(options);
    }

    this.listenTo(this.columns, "reset", function () {
      this.header = new (this.header.remove().constructor)(options);
      this.body = new (this.body.remove().constructor)(options);
      if (this.footer) this.footer = new (this.footer.remove().constructor)(options);
      this.render();
    });
  },

  /**
     Delegates to Backgrid.Body#insertRow.
   */
  insertRow: function (model, collection, options) {
    return this.body.insertRow(model, collection, options);
  },

  /**
     Delegates to Backgrid.Body#removeRow.
   */
  removeRow: function (model, collection, options) {
    return this.body.removeRow(model, collection, options);
  },

  /**
     Delegates to Backgrid.Columns#add for adding a column. Subviews can listen
     to the `add` event from their internal `columns` if rerendering needs to
     happen.

     @param {Object} [options] Options for `Backgrid.Columns#add`.
     @param {boolean} [options.render=true] Whether to render the column
     immediately after insertion.

     @chainable
   */
  insertColumn: function (column, options) {
    options = options || {render: true};
    this.columns.add(column, options);
    return this;
  },

  /**
     Delegates to Backgrid.Columns#remove for removing a column. Subviews can
     listen to the `remove` event from the internal `columns` if rerendering
     needs to happen.

     @param {Object} [options] Options for `Backgrid.Columns#remove`.

     @chainable
   */
  removeColumn: function (column, options) {
    this.columns.remove(column, options);
    return this;
  },

  /**
     Renders the grid's header, then footer, then finally the body.
   */
  render: function () {
    this.$el.empty();

    this.$el.append(this.header.render().$el);

    if (this.footer) {
      this.$el.append(this.footer.render().$el);
    }

    this.$el.append(this.body.render().$el);

    /**
       Backbone event. Fired when the grid has been successfully rendered.

       @event rendered
     */
    this.trigger("rendered");

    return this;
  },

  /**
     Clean up this grid and its subviews.

     @chainable
   */
  remove: function () {
    this.header.remove.apply(this.header, arguments);
    this.body.remove.apply(this.body, arguments);
    this.footer && this.footer.remove.apply(this.footer, arguments);
    return Backbone.View.prototype.remove.apply(this, arguments);
  }

});
<|endoftext|>


<commit_before>import Promise from 'bluebird';
import fs from 'fs';
import exec from './exec.js';
import Handlebars from 'handlebars';
import Pool from './pool.js';
import Apache from './service/Apache.js';

const writeFile = Promise.promisify(fs.writeFile);
const readFile  = Promise.promisify(fs.readFile);
const unlink    = Promise.promisify(fs.unlink);

async function enableVhost(hostname) {
    await exec('a2ensite {{hostname}}', {
        hostname: hostname
    });
}

async function disableVhost(hostname) {
    await exec('a2dissite {{hostname}}', {
        hostname: hostname
    });
}

async function createVhostFile(hostname, data) {
    await writeFile('/etc/apache2/sites-available/' + hostname + '.conf', data);
}

async function removeVhostFile(hostname) {
    await unlink('/etc/apache2/sites-available/' + hostname + '.conf');
}

async function createVhostFolder(customer, name) {
    await exec('mkdir -p /var/www/{{customer}}/{{name}}', {
        name: name,
        customer: customer
    });
    await exec('chown -R {{customer}}:{{customer}} /var/www/{{customer}}/{{name}}', {
        name: name,
        customer: customer
    });
}

async function removeVhostFolder(customer, name) {
    await exec('rm -fr /var/www/{{customer}}/{{name}}', {
        name: name,
        customer: customer
    });
}

async function addPool(host) {
    await (new Pool(host)).create();
}

async function removePool(host) {
    await (new Pool(host)).remove();
}

// load and compile vhost template
const loadTemplate = readFile(__dirname + '/templates/vhost.hbs', 'utf-8')
    .then(function(template) {
        return Handlebars.compile(template);
    });

class Host {
    constructor(customer, name) {
        this.customer = customer;
        this.name = name;
    }

    async create() {
        let template = await loadTemplate;
        let data = template(this);
        await createVhostFile(this.name, data);
        await createVhostFolder(this.customer.name, this.name);
        await enableVhost(this.name);
        await addPool(this);
        await Apache.restart();
    }

    async remove() {
        await disableVhost(this.name);
        await removeVhostFile(this.name);
        await removeVhostFolder(this.customer.name, this.name);
        await removePool(this);
        await Apache.restart();
    }
}

export default Host;
<commit_msg>code style<commit_after>import Promise from 'bluebird';
import fs from 'fs';
import exec from './exec.js';
import Handlebars from 'handlebars';
import Pool from './pool.js';
import Apache from './service/Apache.js';

const writeFile = Promise.promisify(fs.writeFile);
const readFile  = Promise.promisify(fs.readFile);
const unlink    = Promise.promisify(fs.unlink);

const enableVhost = async (hostname) => {
    await exec('a2ensite {{hostname}}', { hostname });
};

const disableVhost = async (hostname) => {
    await exec('a2dissite {{hostname}}', { hostname });
};

const createVhostFile = async (hostname, data) => {
    await writeFile(`/etc/apache2/sites-available/${hostname}.conf`, data);
};

const removeVhostFile = async (hostname) => {
    await unlink(`/etc/apache2/sites-available/${hostname}.conf`);
};

const createVhostFolder = async (customer, name) => {
    await exec('mkdir -p /var/www/{{customer}}/{{name}}', { name, customer });
    await exec('chown -R {{customer}}:{{customer}} /var/www/{{customer}}/{{name}}', { name, customer });
};

const removeVhostFolder = async (customer, name) => {
    await exec('rm -fr /var/www/{{customer}}/{{name}}', { name, customer });
};

const addPool = async (host) => {
    await (new Pool(host)).create();
};

const removePool = async (host) => {
    await (new Pool(host)).remove();
};

// load and compile vhost template
const loadTemplate = readFile(__dirname + '/templates/vhost.hbs', 'utf-8')
    .then(function(template) {
        return Handlebars.compile(template);
    });

class Host {
    constructor(customer, name) {
        this.customer = customer;
        this.name = name;
    }

    async create() {
        let template = await loadTemplate;
        let data = template(this);
        await createVhostFile(this.name, data);
        await createVhostFolder(this.customer.name, this.name);
        await enableVhost(this.name);
        await addPool(this);
        await Apache.restart();
    }

    async remove() {
        await disableVhost(this.name);
        await removeVhostFile(this.name);
        await removeVhostFolder(this.customer.name, this.name);
        await removePool(this);
        await Apache.restart();
    }
}

export default Host;
<|endoftext|>


<commit_before>/**
 * @fileoverview Bootstrap for the Treesaver library.
 */

/**
 * @preserve Copyright 2011 Filipe Fortes ( www.fortes.com ).
 * Version: 0.1.
 *
 * Licensed under MIT and GPLv2.
 */

goog.provide('treesaver');

goog.require('treesaver.boot');
goog.require('treesaver.capabilities');
goog.require('treesaver.constants');
goog.require('treesaver.debug');
goog.require('treesaver.history');
goog.require('treesaver.html5');

// Begin loading
if (treesaver.capabilities.SUPPORTS_TREESAVER) {
  treesaver.boot.load();
}
else {
  treesaver.debug.warn('Treesaver not supported');
}

/**
 * The version number of the code used to build a production
 * bundle.
 *
 * @define {string}
 */
treesaver.VERSION = 'dev';

goog.exportSymbol('treesaver.VERSION', treesaver.VERSION, window);

/**
 * A global configuration object. Use only as a last resort.
 */
treesaver.config = {};

goog.exportSymbol('treesaver.config', treesaver.config, window);
<commit_msg>Remove old configuration object.<commit_after>/**
 * @fileoverview Bootstrap for the Treesaver library.
 */

/**
 * @preserve Copyright 2011 Filipe Fortes ( www.fortes.com ).
 * Version: 0.1.
 *
 * Licensed under MIT and GPLv2.
 */

goog.provide('treesaver');

goog.require('treesaver.boot');
goog.require('treesaver.capabilities');
goog.require('treesaver.constants');
goog.require('treesaver.debug');
goog.require('treesaver.history');
goog.require('treesaver.html5');

// Begin loading
if (treesaver.capabilities.SUPPORTS_TREESAVER) {
  treesaver.boot.load();
}
else {
  treesaver.debug.warn('Treesaver not supported');
}

/**
 * The version number of the code used to build a production
 * bundle.
 *
 * @define {string}
 */
treesaver.VERSION = 'dev';

goog.exportSymbol('treesaver.VERSION', treesaver.VERSION, window);
<|endoftext|>


<commit_before>import config from './config'
import { warn } from './utils'
import set from './set'
import autoTracking from './track/autoTracking'
import loadScript from 'load-script'

export default function (router, callback) {
  if (config.manual) {
    return
  }

  if (!config.id || !config.id.length) {
    const url = 'https://github.com/MatteoGabriele/vue-analytics#usage'
    warn('Please enter a Google Analaytics tracking ID', url)
    return
  }

  const options = config.userId || {}
  const debugSource = config.debug.enabled ? '_debug' : ''
  const source = `https://www.google-analytics.com/analytics${debugSource}.js`

  loadScript(source, function (error, script) {
    if (error) {
      warn('Ops! Could\'t load the Google Analytics script')
      return
    }

    if (callback && typeof callback === 'function') {
      callback()
    }

    const poll = setInterval(function () {
      if (!window.ga) {
        return
      }

      clearInterval(poll)

      if (config.debug.enabled) {
        window.ga_debug = {
          trace: config.debug.trace
        }
      }

      [].concat(config.id).forEach(function (id) {
        options['name'] = id.replace(/-/g, '')
        window.ga('create', id, 'auto', options)
      })

      if (!config.debug.sendHitTask) {
        set('sendHitTask', null)
      }

      window.ga('send', 'pageview')

      autoTracking(router)
    }, 10)
  })
}
<commit_msg>refactor(init): move the callback after ga create, before the first hit<commit_after>import config from './config'
import { warn } from './utils'
import set from './set'
import autoTracking from './track/autoTracking'
import loadScript from 'load-script'

export default function (router, callback) {
  if (config.manual) {
    return
  }

  if (!config.id || !config.id.length) {
    const url = 'https://github.com/MatteoGabriele/vue-analytics#usage'
    warn('Please enter a Google Analaytics tracking ID', url)
    return
  }

  const options = config.userId || {}
  const debugSource = config.debug.enabled ? '_debug' : ''
  const source = `https://www.google-analytics.com/analytics${debugSource}.js`

  loadScript(source, function (error, script) {
    if (error) {
      warn('Ops! Could\'t load the Google Analytics script')
      return
    }

    const poll = setInterval(function () {
      if (!window.ga) {
        return
      }

      clearInterval(poll)

      if (config.debug.enabled) {
        window.ga_debug = {
          trace: config.debug.trace
        }
      }

      [].concat(config.id).forEach(function (id) {
        options['name'] = id.replace(/-/g, '')
        window.ga('create', id, 'auto', options)
      })

      if (callback && typeof callback === 'function') {
        callback()
      }

      if (!config.debug.sendHitTask) {
        set('sendHitTask', null)
      }

      window.ga('send', 'pageview')

      autoTracking(router)
    }, 10)
  })
}
<|endoftext|>


<commit_before>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import { UIDatabase } from '../../database';

import { sortDataBy } from '../../utilities';
import { recordKeyExtractor } from './utilities';
import getColumns from './getColumns';
import getPageInfoColumns from './getPageInfoColumns';

import { ROUTES } from '../../navigation/constants';

/**
 * Gets data for initialising a customer invoice page from an associated transaction.
 *
 * @param    {Transaction}  transaction
 * @returns  {object}
 */
export const customerInvoiceInitialiser = transaction => {
  const { items: backingData } = transaction;

  const sortedData = backingData.sorted('item.name').slice();

  return {
    pageObject: transaction,
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['item.name', 'item.code'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    modalValue: null,
    hasSelection: false,
    route: ROUTES.CUSTOMER_INVOICE,
    columns: getColumns(ROUTES.CUSTOMER_INVOICE),
    getPageInfoColumns: getPageInfoColumns(ROUTES.CUSTOMER_INVOICE),
  };
};

/**
 * Gets data for initialising a customer invoices page.
 * Invoices shown initially are unfinalised and sorted by serial number.
 *
 * @returns  {object}
 */
export const customerInvoicesInitialiser = () => {
  const backingData = UIDatabase.objects('CustomerInvoice');
  const filteredData = backingData.filtered('status != $0', 'finalised').slice();
  const sortedData = sortDataBy(filteredData, 'serialNumber', false);

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['otherParty.name'],
    sortBy: 'serialNumber',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    route: ROUTES.CUSTOMER_INVOICES,
    columns: getColumns(ROUTES.CUSTOMER_INVOICES),
    getPageInfoColumns: getPageInfoColumns(ROUTES.CUSTOMER_INVOICES),
  };
};

/**
 * Gets data for initialising a customer requisition page from an associated requisition.
 *
 * @param    {Requisition}  requisition
 * @returns  {object}
 */
const customerRequisitionInitialiser = requisition => {
  const { items: backingData } = requisition;
  const sortedData = backingData.sorted('item.name').slice();

  return {
    pageObject: requisition,
    backingData: requisition.items,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['item.name', 'item.code'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    modalValue: null,
    route: ROUTES.CUSTOMER_REQUISITION,
    columns: getColumns(ROUTES.CUSTOMER_REQUISITION),
    getPageInfoColumns: getPageInfoColumns(ROUTES.CUSTOMER_REQUISITION),
  };
};

/**
 * Gets data for initialising a customer requisitions page.
 *
 * @returns  {object}
 */
const customerRequisitionsInitialiser = () => {
  const backingData = UIDatabase.objects('ResponseRequisition');

  const filteredData = backingData.filtered('status != $0', 'finalised');
  const sortedData = sortDataBy(filteredData.slice(), 'serialNumber', false);

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    searchTerm: '',
    filterDataKeys: ['serialNumber'],
    sortBy: 'serialNumber',
    isAscending: false,
    route: ROUTES.CUSTOMER_REQUISITIONS,
    columns: getColumns(ROUTES.CUSTOMER_REQUISITIONS),
    getPageInfoColumns: getPageInfoColumns(ROUTES.CUSTOMER_REQUISITIONS),
  };
};

/**
 * Gets data for initialising a stock page.
 *
 * @returns  {object}
 */
const stockInitialiser = () => {
  const backingData = UIDatabase.objects('Item').sorted('name');

  return {
    backingData,
    data: backingData.slice(),
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['name', 'code'],
    sortBy: 'name',
    isAscending: true,
    selectedRow: null,
    route: ROUTES.STOCK,
    columns: getColumns(ROUTES.STOCK),
    getPageInfoColumns: getPageInfoColumns(ROUTES.STOCK),
  };
};

/**
 * Gets data for initialising a stocktakes page.
 * Initial data is unfinalised stocktakes, sorted by creation date.
 *
 * @returns  {object}
 */
const stocktakesInitialiser = () => {
  const backingData = UIDatabase.objects('Stocktake');

  const filteredData = backingData.filtered('status != $0', 'finalised');
  const sortedData = filteredData.sorted('createdDate', true).slice();

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['name', 'serialNumber'],
    sortBy: 'createdDate',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    route: ROUTES.STOCKTAKES,
    columns: getColumns(ROUTES.STOCKTAKES),
    getPageInfoColumns: getPageInfoColumns(ROUTES.STOCKTAKES),
  };
};

/**
 * Gets data for initialising a stocktake batch page from an associated stocktake item.
 *
 * @param    {StocktakeItem}  stocktakeItem
 * @returns  {object}
 */
const stocktakeBatchInitialiser = stocktakeItem => ({
  pageObject: stocktakeItem,
  backingData: stocktakeItem.batches,
  data: stocktakeItem.batches.slice(),
  keyExtractor: recordKeyExtractor,
  dataState: new Map(),
  sortBy: 'itemName',
  isAscending: true,
  modalKey: '',
  modalValue: null,
  columns: getColumns(ROUTES.CUSTOMER_INVOICE),
  getPageInfoColumns: getPageInfoColumns(ROUTES.CUSTOMER_INVOICE),
});

/**
 * Gets data for initialising a manage stocktake page from an associated stocktake item.
 *
 * @param    {Stocktake}  stocktake
 * @returns  {object}
 */
const stocktakeManagerInitialiser = stocktake => {
  const backingData = UIDatabase.objects('Item');

  return {
    stocktake,
    backingData,
    data: backingData.sorted('name').slice(),
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['name', 'code'],
    name: stocktake ? stocktake.name : '',
    sortBy: 'name',
    isAscending: true,
    hasSelection: false,
    allSelected: false,
    showAll: true,
    route: ROUTES.STOCKTAKE_MANAGER,
    columns: getColumns(ROUTES.STOCKTAKE_MANAGER),
    getPageInfoColumns: getPageInfoColumns(ROUTES.STOCKTAKE_MANAGER),
  };
};

/**
 * Gets data for initialising an edit stocktake page from an associated stocktake item.
 *
 * @param    {Stocktake}  stocktake
 * @returns  {object}
 */
const stocktakeEditorInitialiser = stocktake => {
  const { items: backingData } = stocktake;
  const sortedData = backingData.sorted('item.name').slice();

  const hasNegativeAdjustmentReasons = UIDatabase.objects('NegativeAdjustmentReason').length > 0;
  const hasPositiveAdjustmentReasons = UIDatabase.objects('PositiveAdjustmentReason').length > 0;
  const usesReasons = hasNegativeAdjustmentReasons && hasPositiveAdjustmentReasons;

  const route = usesReasons ? ROUTES.STOCKTAKE_EDITOR_WITH_REASONS : ROUTES.STOCKTAKE_EDITOR;

  return {
    pageObject: stocktake,
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['item.name', 'item.code'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    modalValue: null,
    route,
    columns: getColumns(route),
    getPageInfoColumns: getPageInfoColumns(route),
  };
};

/**
 * Gets data for initialising an edit stocktake page when reasons
 * are defined from an associated stocktake.
 *
 * @param    {Stocktake}  stocktake
 * @returns  {object}
 */
const stocktakeEditorWithReasonsInitialiser = stocktake => {
  const { items: backingData } = stocktake;
  const sortedData = backingData.sorted('item.name').slice();

  return {
    pageObject: stocktake,
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['item.name', 'item.code'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    modalValue: null,
    route: ROUTES.STOCKTAKE_EDITOR_WITH_REASONS,
    columns: getColumns(ROUTES.STOCKTAKE_EDITOR_WITH_REASONS),
    getPageInfoColumns: getPageInfoColumns(ROUTES.STOCKTAKE_EDITOR_WITH_REASONS),
  };
};

/**
 * Gets data for initialising a supplier invoice page from an associated transaction item.
 *
 * @param    {Transaction}  transaction
 * @returns  {object}
 */
const supplierInvoiceInitialiser = transaction => {
  const backingData = transaction.getTransactionBatches(UIDatabase);

  const sortedData = backingData.sorted('itemName').slice();

  return {
    pageObject: transaction,
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['itemName'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    modalValue: null,
    hasSelection: false,
    route: ROUTES.SUPPLIER_INVOICE,
    columns: getColumns(ROUTES.SUPPLIER_INVOICE),
    getPageInfoColumns: getPageInfoColumns(ROUTES.SUPPLIER_INVOICE),
  };
};

/**
 * Gets data for initialising a supplier invoices page.
 * Data is initially unfinalised and sorted by serial number.
 *
 * @returns  {object}
 */
const supplierInvoicesInitialiser = () => {
  const backingData = UIDatabase.objects('SupplierInvoice');

  const filteredData = backingData.filtered('status != $0', 'finalised').slice();
  const sortedData = sortDataBy(filteredData, 'serialNumber', false);

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['serialNumber'],
    sortBy: 'serialNumber',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    route: ROUTES.SUPPLIER_INVOICES,
    columns: getColumns(ROUTES.SUPPLIER_INVOICES),
    getPageInfoColumns: getPageInfoColumns(ROUTES.SUPPLIER_INVOICES),
  };
};

/**
 * Gets data for initialising a supplier requisition page from an associated requisition.
 *
 * @param    {Requisition}  requisition
 * @returns  {object}
 */
const supplierRequisitionInitialiser = requisition => {
  const { program, items: backingData } = requisition;

  const usingPrograms = !!program;
  const route = program ? ROUTES.SUPPLIER_REQUISITION_WITH_PROGRAM : ROUTES.SUPPLIER_REQUISITION;

  const sortedData = backingData.sorted('item.name').slice();
  const filteredData = usingPrograms
    ? sortedData.filter(item => item.isLessThanThresholdMOS)
    : sortedData;

  return {
    pageObject: requisition,
    backingData,
    data: filteredData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['item.name', 'item.code'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    hasSelection: false,
    modalValue: null,
    showAll: !usingPrograms,
    route: ROUTES.SUPPLIER_REQUISITION,
    columns: getColumns(route),
    getPageInfoColumns: getPageInfoColumns(route),
  };
};

/**
 * Gets data for initialising a supplier requisitions page.
 * Initial data are unfinalised requisitions, sorted by serial number.
 *
 * @returns  {object}
 */
const supplierRequisitionsInitialiser = () => {
  const backingData = UIDatabase.objects('RequestRequisition');

  const filteredData = backingData.filtered('status != $0', 'finalised').slice();
  const sortedData = sortDataBy(filteredData, 'serialNumber', false);

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['serialNumber'],
    sortBy: 'serialNumber',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    route: ROUTES.SUPPLIER_REQUISITIONS,
    columns: getColumns(ROUTES.SUPPLIER_REQUISITIONS),
    getPageInfoColumns: getPageInfoColumns(ROUTES.SUPPLIER_REQUISITIONS),
  };
};

const pageInitialisers = {
  customerInvoice: customerInvoiceInitialiser,
  customerInvoices: customerInvoicesInitialiser,
  customerRequisition: customerRequisitionInitialiser,
  customerRequisitions: customerRequisitionsInitialiser,
  stock: stockInitialiser,
  stocktakeBatchEditModal: stocktakeBatchInitialiser,
  stocktakeBatchEditModalWithReasons: stocktakeBatchInitialiser,
  stocktakeEditor: stocktakeEditorInitialiser,
  stocktakeEditorWithReasons: stocktakeEditorWithReasonsInitialiser,
  stocktakeManager: stocktakeManagerInitialiser,
  stocktakes: stocktakesInitialiser,
  supplierInvoice: supplierInvoiceInitialiser,
  supplierInvoices: supplierInvoicesInitialiser,
  supplierRequisition: supplierRequisitionInitialiser,
  supplierRequisitions: supplierRequisitionsInitialiser,
};

/**
 * A wrapper for mapping pages to initialisation functions.
 *
 * @param    {object}    A mapper from page names to initialisation functions.
 * @returns  {Function}  A lookup function for retrieving page initialisers.
 */
const getPageInitialiser = pageToInitialiser => page => pageToInitialiser[page];

export default getPageInitialiser(pageInitialisers);
<commit_msg>Add prescriptions page state initialiser<commit_after>/**
 * mSupply Mobile
 * Sustainable Solutions (NZ) Ltd. 2019
 */

import { UIDatabase } from '../../database';

import { sortDataBy } from '../../utilities';
import { recordKeyExtractor } from './utilities';
import getColumns from './getColumns';
import getPageInfoColumns from './getPageInfoColumns';

import { ROUTES } from '../../navigation/constants';

/**
 * Gets data for initialising a customer invoice page from an associated transaction.
 *
 * @param    {Transaction}  transaction
 * @returns  {object}
 */
export const customerInvoiceInitialiser = transaction => {
  const { items: backingData } = transaction;

  const sortedData = backingData.sorted('item.name').slice();

  return {
    pageObject: transaction,
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['item.name', 'item.code'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    modalValue: null,
    hasSelection: false,
    route: ROUTES.CUSTOMER_INVOICE,
    columns: getColumns(ROUTES.CUSTOMER_INVOICE),
    getPageInfoColumns: getPageInfoColumns(ROUTES.CUSTOMER_INVOICE),
  };
};

/**
 * Gets data for initialising a customer invoices page.
 * Invoices shown initially are unfinalised and sorted by serial number.
 *
 * @returns  {object}
 */
export const customerInvoicesInitialiser = () => {
  const backingData = UIDatabase.objects('CustomerInvoice');
  const filteredData = backingData.filtered('status != $0', 'finalised').slice();
  const sortedData = sortDataBy(filteredData, 'serialNumber', false);

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['otherParty.name'],
    sortBy: 'serialNumber',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    route: ROUTES.CUSTOMER_INVOICES,
    columns: getColumns(ROUTES.CUSTOMER_INVOICES),
    getPageInfoColumns: getPageInfoColumns(ROUTES.CUSTOMER_INVOICES),
  };
};

/**
 * Gets data for initialising a customer requisition page from an associated requisition.
 *
 * @param    {Requisition}  requisition
 * @returns  {object}
 */
const customerRequisitionInitialiser = requisition => {
  const { items: backingData } = requisition;
  const sortedData = backingData.sorted('item.name').slice();

  return {
    pageObject: requisition,
    backingData: requisition.items,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['item.name', 'item.code'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    modalValue: null,
    route: ROUTES.CUSTOMER_REQUISITION,
    columns: getColumns(ROUTES.CUSTOMER_REQUISITION),
    getPageInfoColumns: getPageInfoColumns(ROUTES.CUSTOMER_REQUISITION),
  };
};

/**
 * Gets data for initialising a customer requisitions page.
 *
 * @returns  {object}
 */
const customerRequisitionsInitialiser = () => {
  const backingData = UIDatabase.objects('ResponseRequisition');

  const filteredData = backingData.filtered('status != $0', 'finalised');
  const sortedData = sortDataBy(filteredData.slice(), 'serialNumber', false);

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    searchTerm: '',
    filterDataKeys: ['serialNumber'],
    sortBy: 'serialNumber',
    isAscending: false,
    route: ROUTES.CUSTOMER_REQUISITIONS,
    columns: getColumns(ROUTES.CUSTOMER_REQUISITIONS),
    getPageInfoColumns: getPageInfoColumns(ROUTES.CUSTOMER_REQUISITIONS),
  };
};

/**
 * Gets data for initialising a stock page.
 *
 * @returns  {object}
 */
const stockInitialiser = () => {
  const backingData = UIDatabase.objects('Item').sorted('name');

  return {
    backingData,
    data: backingData.slice(),
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['name', 'code'],
    sortBy: 'name',
    isAscending: true,
    selectedRow: null,
    route: ROUTES.STOCK,
    columns: getColumns(ROUTES.STOCK),
    getPageInfoColumns: getPageInfoColumns(ROUTES.STOCK),
  };
};

/**
 * Gets data for initialising a stocktakes page.
 * Initial data is unfinalised stocktakes, sorted by creation date.
 *
 * @returns  {object}
 */
const stocktakesInitialiser = () => {
  const backingData = UIDatabase.objects('Stocktake');

  const filteredData = backingData.filtered('status != $0', 'finalised');
  const sortedData = filteredData.sorted('createdDate', true).slice();

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['name', 'serialNumber'],
    sortBy: 'createdDate',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    route: ROUTES.STOCKTAKES,
    columns: getColumns(ROUTES.STOCKTAKES),
    getPageInfoColumns: getPageInfoColumns(ROUTES.STOCKTAKES),
  };
};

/**
 * Gets data for initialising a stocktake batch page from an associated stocktake item.
 *
 * @param    {StocktakeItem}  stocktakeItem
 * @returns  {object}
 */
const stocktakeBatchInitialiser = stocktakeItem => ({
  pageObject: stocktakeItem,
  backingData: stocktakeItem.batches,
  data: stocktakeItem.batches.slice(),
  keyExtractor: recordKeyExtractor,
  dataState: new Map(),
  sortBy: 'itemName',
  isAscending: true,
  modalKey: '',
  modalValue: null,
  columns: getColumns(ROUTES.CUSTOMER_INVOICE),
  getPageInfoColumns: getPageInfoColumns(ROUTES.CUSTOMER_INVOICE),
});

/**
 * Gets data for initialising a manage stocktake page from an associated stocktake item.
 *
 * @param    {Stocktake}  stocktake
 * @returns  {object}
 */
const stocktakeManagerInitialiser = stocktake => {
  const backingData = UIDatabase.objects('Item');

  return {
    stocktake,
    backingData,
    data: backingData.sorted('name').slice(),
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['name', 'code'],
    name: stocktake ? stocktake.name : '',
    sortBy: 'name',
    isAscending: true,
    hasSelection: false,
    allSelected: false,
    showAll: true,
    route: ROUTES.STOCKTAKE_MANAGER,
    columns: getColumns(ROUTES.STOCKTAKE_MANAGER),
    getPageInfoColumns: getPageInfoColumns(ROUTES.STOCKTAKE_MANAGER),
  };
};

/**
 * Gets data for initialising an edit stocktake page from an associated stocktake item.
 *
 * @param    {Stocktake}  stocktake
 * @returns  {object}
 */
const stocktakeEditorInitialiser = stocktake => {
  const { items: backingData } = stocktake;
  const sortedData = backingData.sorted('item.name').slice();

  const hasNegativeAdjustmentReasons = UIDatabase.objects('NegativeAdjustmentReason').length > 0;
  const hasPositiveAdjustmentReasons = UIDatabase.objects('PositiveAdjustmentReason').length > 0;
  const usesReasons = hasNegativeAdjustmentReasons && hasPositiveAdjustmentReasons;

  const route = usesReasons ? ROUTES.STOCKTAKE_EDITOR_WITH_REASONS : ROUTES.STOCKTAKE_EDITOR;

  return {
    pageObject: stocktake,
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['item.name', 'item.code'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    modalValue: null,
    route,
    columns: getColumns(route),
    getPageInfoColumns: getPageInfoColumns(route),
  };
};

/**
 * Gets data for initialising an edit stocktake page when reasons
 * are defined from an associated stocktake.
 *
 * @param    {Stocktake}  stocktake
 * @returns  {object}
 */
const stocktakeEditorWithReasonsInitialiser = stocktake => {
  const { items: backingData } = stocktake;
  const sortedData = backingData.sorted('item.name').slice();

  return {
    pageObject: stocktake,
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['item.name', 'item.code'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    modalValue: null,
    route: ROUTES.STOCKTAKE_EDITOR_WITH_REASONS,
    columns: getColumns(ROUTES.STOCKTAKE_EDITOR_WITH_REASONS),
    getPageInfoColumns: getPageInfoColumns(ROUTES.STOCKTAKE_EDITOR_WITH_REASONS),
  };
};

/**
 * Gets data for initialising a supplier invoice page from an associated transaction item.
 *
 * @param    {Transaction}  transaction
 * @returns  {object}
 */
const supplierInvoiceInitialiser = transaction => {
  const backingData = transaction.getTransactionBatches(UIDatabase);

  const sortedData = backingData.sorted('itemName').slice();

  return {
    pageObject: transaction,
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['itemName'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    modalValue: null,
    hasSelection: false,
    route: ROUTES.SUPPLIER_INVOICE,
    columns: getColumns(ROUTES.SUPPLIER_INVOICE),
    getPageInfoColumns: getPageInfoColumns(ROUTES.SUPPLIER_INVOICE),
  };
};

/**
 * Gets data for initialising a supplier invoices page.
 * Data is initially unfinalised and sorted by serial number.
 *
 * @returns  {object}
 */
const supplierInvoicesInitialiser = () => {
  const backingData = UIDatabase.objects('SupplierInvoice');

  const filteredData = backingData.filtered('status != $0', 'finalised').slice();
  const sortedData = sortDataBy(filteredData, 'serialNumber', false);

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['serialNumber'],
    sortBy: 'serialNumber',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    route: ROUTES.SUPPLIER_INVOICES,
    columns: getColumns(ROUTES.SUPPLIER_INVOICES),
    getPageInfoColumns: getPageInfoColumns(ROUTES.SUPPLIER_INVOICES),
  };
};

/**
 * Gets data for initialising a supplier requisition page from an associated requisition.
 *
 * @param    {Requisition}  requisition
 * @returns  {object}
 */
const supplierRequisitionInitialiser = requisition => {
  const { program, items: backingData } = requisition;

  const usingPrograms = !!program;
  const route = program ? ROUTES.SUPPLIER_REQUISITION_WITH_PROGRAM : ROUTES.SUPPLIER_REQUISITION;

  const sortedData = backingData.sorted('item.name').slice();
  const filteredData = usingPrograms
    ? sortedData.filter(item => item.isLessThanThresholdMOS)
    : sortedData;

  return {
    pageObject: requisition,
    backingData,
    data: filteredData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['item.name', 'item.code'],
    sortBy: 'itemName',
    isAscending: true,
    modalKey: '',
    hasSelection: false,
    modalValue: null,
    showAll: !usingPrograms,
    route: ROUTES.SUPPLIER_REQUISITION,
    columns: getColumns(route),
    getPageInfoColumns: getPageInfoColumns(route),
  };
};

/**
 * Gets data for initialising a supplier requisitions page.
 * Initial data are unfinalised requisitions, sorted by serial number.
 *
 * @returns  {object}
 */
const supplierRequisitionsInitialiser = () => {
  const backingData = UIDatabase.objects('RequestRequisition');

  const filteredData = backingData.filtered('status != $0', 'finalised').slice();
  const sortedData = sortDataBy(filteredData, 'serialNumber', false);

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['serialNumber'],
    sortBy: 'serialNumber',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    route: ROUTES.SUPPLIER_REQUISITIONS,
    columns: getColumns(ROUTES.SUPPLIER_REQUISITIONS),
    getPageInfoColumns: getPageInfoColumns(ROUTES.SUPPLIER_REQUISITIONS),
  };
};

const prescriptionsInitialiser = () => {
  const backingData = UIDatabase.objects('Prescription');
  const filteredData = backingData.filtered('status != $0', 'finalised').slice();
  const sortedData = sortDataBy(filteredData, 'serialNumber', false);

  return {
    backingData,
    data: sortedData,
    keyExtractor: recordKeyExtractor,
    dataState: new Map(),
    searchTerm: '',
    filterDataKeys: ['otherParty.name'],
    sortBy: 'serialNumber',
    isAscending: false,
    modalKey: '',
    hasSelection: false,
    route: ROUTES.PRESCRIPTIONS,
    columns: getColumns(ROUTES.PRESCRIPTIONS),
    getPageInfoColumns: getPageInfoColumns(ROUTES.PRESCRIPTIONS),
  };
};

const pageInitialisers = {
  customerInvoice: customerInvoiceInitialiser,
  customerInvoices: customerInvoicesInitialiser,
  customerRequisition: customerRequisitionInitialiser,
  customerRequisitions: customerRequisitionsInitialiser,
  stock: stockInitialiser,
  stocktakeBatchEditModal: stocktakeBatchInitialiser,
  stocktakeBatchEditModalWithReasons: stocktakeBatchInitialiser,
  stocktakeEditor: stocktakeEditorInitialiser,
  stocktakeEditorWithReasons: stocktakeEditorWithReasonsInitialiser,
  stocktakeManager: stocktakeManagerInitialiser,
  stocktakes: stocktakesInitialiser,
  supplierInvoice: supplierInvoiceInitialiser,
  supplierInvoices: supplierInvoicesInitialiser,
  supplierRequisition: supplierRequisitionInitialiser,
  supplierRequisitions: supplierRequisitionsInitialiser,
  prescriptions: prescriptionsInitialiser,
};

/**
 * A wrapper for mapping pages to initialisation functions.
 *
 * @param    {object}    A mapper from page names to initialisation functions.
 * @returns  {Function}  A lookup function for retrieving page initialisers.
 */
const getPageInitialiser = pageToInitialiser => page => pageToInitialiser[page];

export default getPageInitialiser(pageInitialisers);
<|endoftext|>


<commit_before>var React = require('react');
var Footer = require('../../components/footer.js');
var ContentContainer = require('../../components/content-container.js');
import StickyContainer from '../../components/sticky-container.js';

module.exports = React.createClass({
  onButtonClick: function() {
    window.location.href = '/encrypt-hard-drive/thank-you/?action=user_encrypted';
  },
  getPosition: function() {
    if (!this.refs.stickyContainer) {
      return 0;
    }
    return this.refs.stickyContainer.getClientRects()[0].top + this.refs.stickyContent.offsetHeight + window.scrollY - window.innerHeight;
  },
  render: function() {
    return (

          <ContentContainer className="center-align encrypt-hard-drive-header">

Mozilla

Encrypt Your Hard Drive

Check out the step by step guides:

          </ContentContainer>
          <ContentContainer className="main-container">

Mac: Turn on FileVault

From the Apple menu, choose System Preferences.

Click the Security & Privacy icon in the System Preferences window.

Click the FileVault tab.

Click the lock icon and enter an administrator name and password.

Click the "Turn On FileVault" button.

Remember to keep your recovery key and password safe.

PC: Turn on BitLocker

Go to Control Panel

Choose System and Security

Click the BitLocker Drive Encryption (In Windows 8, you can search Bitlocker.)

In the BitLocker menu, turn on BitLocker next to the drive(s) you wish to encrypt.

Remember to keep your recovery key and password safe.

          </ContentContainer>

          <ContentContainer className="faq-container center-align">

FAQ Troubleshooting

                FileVault Entire hard drive

                BitLocker

                Selected drives

          </ContentContainer>

          <ContentContainer className="button-container center-align">

              <StickyContainer className="sticky-button" initialState={true} stickyTo={this.getPosition}>

Did this information help you install this software?

                  <button className="button" onClick={this.onButtonClick}>Yes, I did it!</button>

              </StickyContainer>

          </ContentContainer>

    );
  }
});
<commit_msg>updates to copyy<commit_after>var React = require('react');
var Footer = require('../../components/footer.js');
var ContentContainer = require('../../components/content-container.js');
import StickyContainer from '../../components/sticky-container.js';

module.exports = React.createClass({
  onButtonClick: function() {
    window.location.href = '/encrypt-hard-drive/thank-you/?action=user_encrypted';
  },
  getPosition: function() {
    if (!this.refs.stickyContainer) {
      return 0;
    }
    return this.refs.stickyContainer.getClientRects()[0].top + this.refs.stickyContent.offsetHeight + window.scrollY - window.innerHeight;
  },
  render: function() {
    return (

          <ContentContainer className="center-align encrypt-hard-drive-header">

Mozilla

Encrypt Your Hard Drive

Check out these step-by-step guides:

          </ContentContainer>
          <ContentContainer className="main-container">

Mac: Turn on FileVault

From the Apple menu, choose System Preferences.

Click the Security & Privacy icon in the System Preferences window.

Click the FileVault tab.

Click the lock icon and enter an administrator name and password.

Click the Turn On FileVault button.

Remember to keep your recovery key and password safe.

PC: Turn on BitLocker

Go to Control Panel

Choose System and Security

Click the BitLocker Drive Encryption (In Windows 8, you can search BitLocker.)

In the BitLocker menu, turn on BitLocker next to the drive(s) you wish to encrypt.

Remember to keep your recovery key and password safe.

          </ContentContainer>

          <ContentContainer className="faq-container center-align">

FAQ and Troubleshooting

                FileVault

                BitLocker

                Selected drives

          </ContentContainer>

          <ContentContainer className="button-container center-align">

              <StickyContainer className="sticky-button" initialState={true} stickyTo={this.getPosition}>

Did this information help you install the software?

                  <button className="button" onClick={this.onButtonClick}>Yes, it did!</button>

              </StickyContainer>

          </ContentContainer>

    );
  }
});
<|endoftext|>


<commit_before>
var GS = require("../getsource.js");

var RG  = GS.getSource(["RG"], "./src/rg.js");
RG.Object = GS.getSource(["RG", "Object"], "./src/object.js");
RG.Component = GS.getSource(["RG", "Component"], "./src/component.js");

//---------------------------------------------------------------------------
// ITEMS
//---------------------------------------------------------------------------

RG.Item = {};

/** Models an item. Each item is ownable by someone. During game, there are no
 * items with null owners. Ownership shouldn't be ever set to null. */
RG.Item.Base = function(name) {
    RG.Object.Ownable.call(this, null);
    RG.Entity.call(this);
    this.setPropType(RG.TYPE_ITEM);

    var _name = name;
    var _weight = 1;
    var _value = 1;
    var _p = {}; // Stores all extra properties

    this.count = 1; // Number of items

    this.setName = function(name) {_name = name;};
    this.getName = function() {return _name;};

    this.hasProp = function(propName) {
        return _p.hasOwnProperty(propName);
    };

    this.getProp = function(propName) {
        if (_p.hasOwnProperty(propName)) {
            return _p[propName];
        }
        else {
            return null;
        }
    };

    this.setWeight = function(weight) {_weight = weight;};
    this.getWeight = function() {return _weight;};
    this.setValue = function(value) {_value = value;};
    this.getValue = function() {return _value;};

};
RG.Item.Base.prototype.toString = function() {
    var txt = this.getName() + ", " + this.getType() + ", ";
    txt += this.getWeight() * this.count + "kg";
    if (this.hasOwnProperty("count")) {
        txt = this.count + " x " + txt;
    }
    return txt;
};

RG.Item.Base.prototype.equals = function(item) {
    var res = this.getName() === item.getName();
    res = res && (this.getType() === item.getType());
    return res;
};

RG.Item.Base.prototype.copy = function(rhs) {
    this.setName(rhs.getName());
    this.setType(rhs.getType());
    this.setWeight(rhs.getWeight());
    this.setValue(rhs.getValue());
};

RG.Item.Base.prototype.clone = function() {
    var newItem = new RG.Item.Base(this.getName());
    newItem.copy(this);
    return newItem;
};

RG.extend2(RG.Item.Base, RG.Object.Ownable);

/** Object representing food items in the game.*/
RG.Item.Food = function(name) {
    RG.Item.Base.call(this, name);
    this.setType("food");

    var _energy = 0; // per 0.1 kg

    this.setEnergy = function(energy) {_energy = energy;};
    this.getEnergy = function() {return _energy;};

    /** Uses (eats) the food item.*/
    this.useItem = function(obj) {
        if (obj.hasOwnProperty("target")) {
            var target = obj.target;
            if (target.has("Hunger")) {
                var totalEnergy = Math.round(this.getWeight() * _energy);
                target.get("Hunger").addEnergy(totalEnergy);
                if (this.count === 1) {
                    var msg = {item: this};
                    RG.POOL.emitEvent(RG.EVT_DESTROY_ITEM, msg);
                }
                else {
                    this.count -= 1;
                }
            }
        }
        else {
            RG.err("ItemFood", "useItem", "No target given in obj.");
        }
    };

};
RG.extend2(RG.Item.Food, RG.Item.Base);

/** Corpse object dropped by killed actors.*/
RG.Item.Corpse = function(name) {
    RG.Item.Base.call(this, name);
    this.setType("corpse");
};
RG.extend2(RG.Item.Corpse, RG.Item.Base);

/** Base object for all weapons.*/
RG.Item.Weapon = function(name) {
    RG.Item.Base.call(this, name);
    RG.Object.Damage.call(this);
    this.setType("weapon");
};

RG.Item.Weapon.prototype.toString = function() {
    var msg = RG.Item.Base.prototype.toString.call(this);
    msg += RG.Object.Damage.prototype.toString.call(this);
    return msg;

};

RG.Item.Weapon.prototype.clone = function() {
    var weapon = new RG.Item.Weapon(this.getName());
    weapon.copy(this);
    return weapon;
};

RG.Item.Weapon.prototype.copy = function(rhs) {
    RG.Item.Base.prototype.copy.call(this, rhs);
    RG.Object.Damage.prototype.copy.call(this, rhs);

};

RG.Item.Weapon.prototype.equals = function(rhs) {
    var res = RG.Item.Base.prototype.equals.call(this, rhs);
    res = res && RG.Object.Damage.prototype.equals.call(this, rhs);
    return res;

};

RG.extend2(RG.Item.Weapon, RG.Item.Base);
RG.extend2(RG.Item.Weapon, RG.Object.Damage);

/** Base object for armour.*/
RG.Item.Armour = function(name) {
    RG.Item.Base.call(this, name);
    RG.Object.Defense.call(this);
    this.setType("armour");

    var _armourType = null;

    this.setArmourType = function(type) {_armourType = type;};
    this.getArmourType = function() {return _armourType;};

};

RG.Item.Armour.prototype.clone = function() {
    var armour = new RG.Item.Armour(this.getName());
    armour.copy(this);
    return armour;
};

RG.Item.Armour.prototype.copy = function(rhs) {
    RG.Item.Base.prototype.copy.call(this, rhs);
    RG.Object.Defense.prototype.copy.call(this, rhs);
    this.setArmourType(rhs.getArmourType());
};

RG.Item.Armour.prototype.equals = function(rhs) {
    var res = RG.Item.Base.prototype.equals.call(this, rhs);
    res = res && RG.Object.Defense.prototype.equals.call(this, rhs);
    return res;
};

RG.extend2(RG.Item.Armour, RG.Item.Base);
RG.extend2(RG.Item.Armour, RG.Object.Defense);

/** Potion object which restores hit points .*/
RG.Item.Potion = function(name) {
    RG.Item.Base.call(this, name);
    this.setType("potion");

    this.useItem = function(obj) {
        if (obj.hasOwnProperty("target")) {
            var target = obj.target;
            var die = new RG.Die(1, 10, 2);
            var pt = die.roll();
            if (target.has("Health")) {
                target.get("Health").addHP(pt);
                if (this.count === 1) {
                    var msg = {item: this};
                    RG.POOL.emitEvent(RG.EVT_DESTROY_ITEM, msg);
                }
                else {
                    this.count -= 1;
                }
            }
        }
        else {
            RG.err("ItemPotion", "useItem", "No target given in obj.");
        }
    };

};
RG.extend2(RG.Item.Potion, RG.Item.Base);

/** Models an object which is used as a missile.*/
RG.Item.Missile = function(name) {
    RG.Item.Base.call(this, name);
    RG.Object.Damage.call(this);
    this.setType("missile");

};

RG.Item.Missile.prototype.clone = function() {
    var weapon = new RG.Item.Missile(this.getName());
    weapon.copy(this);
    return weapon;
};

RG.Item.Missile.prototype.copy = function(rhs) {
    RG.Item.Base.prototype.copy.call(this, rhs);
    RG.Object.Damage.prototype.copy.call(this, rhs);

};

RG.Item.Missile.prototype.equals = function(rhs) {
    var res = RG.Item.Base.prototype.equals.call(this, rhs);
    res = res && RG.Object.Damage.prototype.equals.call(this, rhs);
    return res;

};

RG.extend2(RG.Item.Missile, RG.Item.Base);
RG.extend2(RG.Item.Missile, RG.Object.Damage);
RG.extend2(RG.Item.Missile, RG.Entity);

/** Models an item container. Can hold a number of items.*/
RG.Item.Container = function(owner) {
    RG.Item.Base.call(this, "container");
    this.setOwner(owner);

    var _items = [];
    var _iter  = 0;

    var _removedItem = null; // Last removed item

    this._addItem = function(item) {
        var matchFound = false;
        for (var i = 0; i < _items.length; i++) {
            if (_items[i].equals(item)) {
                if (_items[i].hasOwnProperty("count")) {
                    if (item.hasOwnProperty("count")) {
                        _items[i].count += item.count;
                    }
                    else {
                        _items[i].count += 1;
                    }
                }
                else {
                    if (item.hasOwnProperty("count")) {
                        _items[i].count = 1 + item.count;
                    }
                    else {
                        _items[i].count = 2;
                    }
                }
                matchFound = true;
                break;
            }
        }

        if (!matchFound) {
            item.setOwner(this);
            _items.push(item);
        }
    };

    /** Returns the total weight of the container.*/
    this.getWeight = function() {
        var sum = 0;
        for (var i = 0; i < _items.length; i++) {
            sum += _items[i].getWeight() * _items[i].count;
        }
        return sum;
    };

    /** Adds an item. Container becomes item's owner.*/
    this.addItem = function(item) {
        if (item.getType() === "container") {
            if (this.getOwner() !== item) {
                this._addItem(item);
            }
            else {
                RG.err("Item", "addItem", "Added item is container's owner. Impossible.");
            }
        }
        else {
            this._addItem(item);
        }
    };

    this.getItems = function() {return _items;};

    /** Check by pure obj ref. Returns true if contains item ref.*/
    this.hasItemRef = function(item) {
        var index = _items.indexOf(item);
        if (index !== -1) return true;
        return false;
    };

    /** Used for stacking/equip purposes only.*/
    this.hasItem = function(item) {
        if (this.hasItemRef(item)) return true;
        var index = _getMatchingItemIndex(item);
        return index >= 0;
    };

    /** Tries to remove an item. Returns true on success, false otherwise.*/
    this.removeItem = function(item) {
        if (this.hasItem(item)) {
            return _removeItem(item);
        }
        _removedItem = null;
        return false;
    };

    var _getMatchingItemIndex = function(item) {
        for (var i = 0; i < _items.length; i++) {
            if (item.equals(_items[i])) return i;
        }
        return -1;
    };

    var _removeItem = function(item) {
        var i = _getMatchingItemIndex(item);

        if (i === -1) {
            RG.err("ItemContainer", "_removeItem",
                "Negative index found. Horribly wrong.");
            return false;
        }

        if (_items[i].hasOwnProperty("count")) {
            _removedItem = RG.removeStackedItems(_items[i], 1);
            if (_items[i].count === 0) _items.splice(i, 1);
        }
        else {
            _removedItem = item;
            _items.splice(i, 1);
        }
        return true;
    };

    /** Returns last removed item if removeItem returned true.*/
    this.getRemovedItem = function() {
        return _removedItem;
    };

    /** Removes N items from the inventory of given type.*/
    this.removeNItems = function(item, n) {
        var count = 0;
        while ((count < n) && this.removeItem(item)) {
            ++count;
        }

        if (_removedItem !== null) {
            _removedItem.count = count;
        }
        else {
            RG.err("ItemContainer", "removeNItems",
                "_removedItem was null. It should be a valid item.");
            return false;
        }

        if (count > 0) return true;
        return false;
    };

    /** Returns first item or null for empty container.*/
    this.first = function() {
        if (_items.length > 0) {
            _iter = 1;
            return _items[0];
        }
        return null;
    };

    /** Returns next item from container or null if there are no more items.*/
    this.next = function() {
        if (_iter < _items.length) {
            return _items[_iter++];
        }
        return null;
    };

    this.last = function() {
        return _items[_items.length - 1];

    };

    /** Returns true for empty container.*/
    this.isEmpty = function() {
        return _items.length === 0;
    };

};
RG.extend2(RG.Item.Container, RG.Item.Base);

/** Spirit items are wearables which can have powerful use abilities as well.*/
RG.Item.Spirit = function(name) {
    RG.Item.Base.call(this, name);
    this.setType("spirit");

    this.getArmourType = function() {return "spirit";};

    var stats = new RG.Component.Stats();
    this.add("Stats", stats);

    var _brain = new RG.Brain.Spirit(this);

    this.add("Action", new RG.Component.Stats());

    this.isPlayer = function() {return false;};

    /** Get next action for this spirit.*/
    this.nextAction = function(obj) {
        var cb = _brain.decideNextAction(obj);
        var action = null;

        if (cb !== null) {
            var speed = this.get("Stats").getSpeed();
            var duration = parseInt(RG.BASE_SPEED/speed * RG.ACTION_DUR);
            action = new RG.RogueAction(duration, cb, {});
        }
        else {
            action = new RG.RogueAction(0, function(){}, {});
        }
        return action;
    };

};

RG.Item.Spirit.prototype.toString = function() {
    var txt = this.getName() + ", " + this.getType() + ", ";
    txt += this.get("Stats").toString();
    return txt;
};

RG.Item.Spirit.prototype.equals = function(item) {
    var res = RG.Item.Base.prototype.equals.call(this, item);
    res = res && (this.getType() === item.getType());
    return res;
};

RG.Item.Spirit.prototype.copy = function(rhs) {
    this.get("Stats").copy(rhs.get("Stats"));
};

RG.Item.Spirit.prototype.clone = function() {
    var newSpirit = new RG.Item.Spirit(this.getName());
    newSpirit.copy(this);
    return newSpirit;
};

RG.extend2(RG.Item.Spirit, RG.Item.Base);

if (typeof module !== "undefined" && typeof exports !== "undefined") {
    GS.exportSource(module, exports, ["RG", "Item"], [RG, RG.Item]);
}
else {
    GS.exportSource(undefined, undefined, ["RG", "Item"], [RG, RG.Item]);
}
<commit_msg>Added Physical comp. Added SpiritGem.<commit_after>
var GS = require("../getsource.js");

var RG  = GS.getSource(["RG"], "./src/rg.js");
RG.Object = GS.getSource(["RG", "Object"], "./src/object.js");
RG.Component = GS.getSource(["RG", "Component"], "./src/component.js");

//---------------------------------------------------------------------------
// ITEMS
//---------------------------------------------------------------------------

RG.Item = {};

/** Models an item. Each item is ownable by someone. During game, there are no
 * items with null owners. Ownership shouldn't be ever set to null. */
RG.Item.Base = function(name) {
    RG.Object.Ownable.call(this, null);
    RG.Entity.call(this);
    this.setPropType(RG.TYPE_ITEM);

    var _name = name;
    var _value = 1;

    this.add("Physical", new RG.Component.Physical());

    this.count = 1; // Number of items

    this.setName = function(name) {_name = name;};
    this.getName = function() {return _name;};

    this.setWeight = function(weight) {this.get("Physical").setWeight(weight);};
    this.getWeight = function() {return this.get("Physical").getWeight();};

    this.setValue = function(value) {_value = value;};
    this.getValue = function() {return _value;};

};
RG.Item.Base.prototype.toString = function() {
    var txt = this.getName() + ", " + this.getType() + ", ";
    txt += this.getWeight() * this.count + "kg";
    if (this.hasOwnProperty("count")) {
        txt = this.count + " x " + txt;
    }
    return txt;
};

RG.Item.Base.prototype.equals = function(item) {
    var res = this.getName() === item.getName();
    res = res && (this.getType() === item.getType());
    return res;
};

RG.Item.Base.prototype.copy = function(rhs) {
    this.setName(rhs.getName());
    this.setType(rhs.getType());
    this.setWeight(rhs.getWeight());
    this.setValue(rhs.getValue());
};

RG.Item.Base.prototype.clone = function() {
    var newItem = new RG.Item.Base(this.getName());
    newItem.copy(this);
    return newItem;
};

RG.extend2(RG.Item.Base, RG.Object.Ownable);

/** Object representing food items in the game.*/
RG.Item.Food = function(name) {
    RG.Item.Base.call(this, name);
    this.setType("food");

    var _energy = 0; // per 0.1 kg

    this.setEnergy = function(energy) {_energy = energy;};
    this.getEnergy = function() {return _energy;};

    /** Uses (eats) the food item.*/
    this.useItem = function(obj) {
        if (obj.hasOwnProperty("target")) {
            var cell = obj.target;
            if (cell.hasActors()) {
                var target = cell.getProp("actors")[0];
                if (target.has("Hunger")) {
                    var totalEnergy = Math.round(this.getWeight() * _energy);
                    target.get("Hunger").addEnergy(totalEnergy);
                    if (this.count === 1) {
                        var msg = {item: this};
                        RG.POOL.emitEvent(RG.EVT_DESTROY_ITEM, msg);
                        RG.gameMsg(target.getName() + " + consumes " + this.getName());
                    }
                    else {
                        this.count -= 1;
                    }
                }
                else {
                    RG.gameWarn(target.getName() + " is not interested in eating.");
                }
            }
            else {
                RG.gameWarn("There's no one to give food to.");
            }
        }
        else {
            RG.err("ItemFood", "useItem", "No target given in obj.");
        }
    };

};
RG.extend2(RG.Item.Food, RG.Item.Base);

/** Corpse object dropped by killed actors.*/
RG.Item.Corpse = function(name) {
    RG.Item.Base.call(this, name);
    this.setType("corpse");
};
RG.extend2(RG.Item.Corpse, RG.Item.Base);

/** Base object for all weapons.*/
RG.Item.Weapon = function(name) {
    RG.Item.Base.call(this, name);
    RG.Object.Damage.call(this);
    this.setType("weapon");
};

RG.Item.Weapon.prototype.toString = function() {
    var msg = RG.Item.Base.prototype.toString.call(this);
    msg += RG.Object.Damage.prototype.toString.call(this);
    return msg;
};

RG.Item.Weapon.prototype.clone = function() {
    var weapon = new RG.Item.Weapon(this.getName());
    weapon.copy(this);
    return weapon;
};

RG.Item.Weapon.prototype.copy = function(rhs) {
    RG.Item.Base.prototype.copy.call(this, rhs);
    RG.Object.Damage.prototype.copy.call(this, rhs);
};

RG.Item.Weapon.prototype.equals = function(rhs) {
    var res = RG.Item.Base.prototype.equals.call(this, rhs);
    res = res && RG.Object.Damage.prototype.equals.call(this, rhs);
    return res;
};

RG.extend2(RG.Item.Weapon, RG.Item.Base);
RG.extend2(RG.Item.Weapon, RG.Object.Damage);

/** Base object for armour.*/
RG.Item.Armour = function(name) {
    RG.Item.Base.call(this, name);
    RG.Object.Defense.call(this);
    this.setType("armour");

    var _armourType = null;

    this.setArmourType = function(type) {_armourType = type;};
    this.getArmourType = function() {return _armourType;};

};

RG.Item.Armour.prototype.clone = function() {
    var armour = new RG.Item.Armour(this.getName());
    armour.copy(this);
    return armour;
};

RG.Item.Armour.prototype.copy = function(rhs) {
    RG.Item.Base.prototype.copy.call(this, rhs);
    RG.Object.Defense.prototype.copy.call(this, rhs);
    this.setArmourType(rhs.getArmourType());
};

RG.Item.Armour.prototype.equals = function(rhs) {
    var res = RG.Item.Base.prototype.equals.call(this, rhs);
    res = res && RG.Object.Defense.prototype.equals.call(this, rhs);
    return res;
};

RG.extend2(RG.Item.Armour, RG.Item.Base);
RG.extend2(RG.Item.Armour, RG.Object.Defense);

/** Potion object which restores hit points .*/
RG.Item.Potion = function(name) {
    RG.Item.Base.call(this, name);
    this.setType("potion");

    this.useItem = function(obj) {
        if (obj.hasOwnProperty("target")) {
            var cell = obj.target;
            if (cell.hasActors()) {
                var target = cell.getProp("actors")[0];
                var die = new RG.Die(1, 10, 2);
                var pt = die.roll();
                if (target.has("Health")) {
                    target.get("Health").addHP(pt);
                    if (this.count === 1) {
                        var msg = {item: this};
                        RG.POOL.emitEvent(RG.EVT_DESTROY_ITEM, msg);
                        RG.gameMsg(target.getName() + " drinks " + this.getName());
                    }
                    else {
                        this.count -= 1;
                    }
                }
            }
            else {
                RG.gameWarn("Cannot see anyone there for using the potion.");
            }
        }
        else {
            RG.err("ItemPotion", "useItem", "No target given in obj.");
        }
    };

};
RG.extend2(RG.Item.Potion, RG.Item.Base);

/** Models an object which is used as a missile.*/
RG.Item.Missile = function(name) {
    RG.Item.Base.call(this, name);
    RG.Object.Damage.call(this);
    this.setType("missile");

};

RG.Item.Missile.prototype.clone = function() {
    var weapon = new RG.Item.Missile(this.getName());
    weapon.copy(this);
    return weapon;
};

RG.Item.Missile.prototype.copy = function(rhs) {
    RG.Item.Base.prototype.copy.call(this, rhs);
    RG.Object.Damage.prototype.copy.call(this, rhs);

};

RG.Item.Missile.prototype.equals = function(rhs) {
    var res = RG.Item.Base.prototype.equals.call(this, rhs);
    res = res && RG.Object.Damage.prototype.equals.call(this, rhs);
    return res;

};

RG.extend2(RG.Item.Missile, RG.Item.Base);
RG.extend2(RG.Item.Missile, RG.Object.Damage);
RG.extend2(RG.Item.Missile, RG.Entity);

/** Models an item container. Can hold a number of items.*/
RG.Item.Container = function(owner) {
    RG.Item.Base.call(this, "container");
    this.setOwner(owner);

    var _items = [];
    var _iter  = 0;

    var _removedItem = null; // Last removed item

    this._addItem = function(item) {
        var matchFound = false;
        for (var i = 0; i < _items.length; i++) {
            if (_items[i].equals(item)) {
                if (_items[i].hasOwnProperty("count")) {
                    if (item.hasOwnProperty("count")) {
                        _items[i].count += item.count;
                    }
                    else {
                        _items[i].count += 1;
                    }
                }
                else {
                    if (item.hasOwnProperty("count")) {
                        _items[i].count = 1 + item.count;
                    }
                    else {
                        _items[i].count = 2;
                    }
                }
                matchFound = true;
                break;
            }
        }

        if (!matchFound) {
            item.setOwner(this);
            _items.push(item);
        }
    };

    /** Returns the total weight of the container.*/
    this.getWeight = function() {
        var sum = 0;
        for (var i = 0; i < _items.length; i++) {
            sum += _items[i].getWeight() * _items[i].count;
        }
        return sum;
    };

    /** Adds an item. Container becomes item's owner.*/
    this.addItem = function(item) {
        if (item.getType() === "container") {
            if (this.getOwner() !== item) {
                this._addItem(item);
            }
            else {
                RG.err("Item", "addItem", "Added item is container's owner. Impossible.");
            }
        }
        else {
            this._addItem(item);
        }
    };

    this.getItems = function() {return _items;};

    /** Check by pure obj ref. Returns true if contains item ref.*/
    this.hasItemRef = function(item) {
        var index = _items.indexOf(item);
        if (index !== -1) return true;
        return false;
    };

    /** Used for stacking/equip purposes only.*/
    this.hasItem = function(item) {
        if (this.hasItemRef(item)) return true;
        var index = _getMatchingItemIndex(item);
        return index >= 0;
    };

    /** Tries to remove an item. Returns true on success, false otherwise.*/
    this.removeItem = function(item) {
        if (this.hasItem(item)) {
            return _removeItem(item);
        }
        _removedItem = null;
        return false;
    };

    var _getMatchingItemIndex = function(item) {
        for (var i = 0; i < _items.length; i++) {
            if (item.equals(_items[i])) return i;
        }
        return -1;
    };

    var _removeItem = function(item) {
        var i = _getMatchingItemIndex(item);

        if (i === -1) {
            RG.err("ItemContainer", "_removeItem",
                "Negative index found. Horribly wrong.");
            return false;
        }

        if (_items[i].hasOwnProperty("count")) {
            _removedItem = RG.removeStackedItems(_items[i], 1);
            if (_items[i].count === 0) _items.splice(i, 1);
        }
        else {
            _removedItem = item;
            _items.splice(i, 1);
        }
        return true;
    };

    /** Returns last removed item if removeItem returned true.*/
    this.getRemovedItem = function() {
        return _removedItem;
    };

    /** Removes N items from the inventory of given type.*/
    this.removeNItems = function(item, n) {
        var count = 0;
        while ((count < n) && this.removeItem(item)) {
            ++count;
        }

        if (_removedItem !== null) {
            _removedItem.count = count;
        }
        else {
            RG.err("ItemContainer", "removeNItems",
                "_removedItem was null. It should be a valid item.");
            return false;
        }

        if (count > 0) return true;
        return false;
    };

    /** Returns first item or null for empty container.*/
    this.first = function() {
        if (_items.length > 0) {
            _iter = 1;
            return _items[0];
        }
        return null;
    };

    /** Returns next item from container or null if there are no more items.*/
    this.next = function() {
        if (_iter < _items.length) {
            return _items[_iter++];
        }
        return null;
    };

    this.last = function() {
        return _items[_items.length - 1];

    };

    /** Returns true for empty container.*/
    this.isEmpty = function() {
        return _items.length === 0;
    };

};
RG.extend2(RG.Item.Container, RG.Item.Base);

/** Spirit gems can capture spirits inside them.*/
RG.Item.SpiritGem = function(name) {
    RG.Item.Base.call(this, name);
    this.setType("spiritgem");

    var _spirit = null;

    this.setSpirit = function(spirit) {};
    this.getSpirit = function() {_return spirit;};

    /** Used for capturing the spirits inside the gem.*/
    this.useItem = function(obj) {
        if (_spirit === null) {

        }
        else {

        }
    };

};
RG.extend2(RG.Item.SpiritGem, RG.Item.Base);

/** Spirit items are wearables which can have powerful use abilities as well.*/
RG.Item.Spirit = function(name) {
    RG.Item.Base.call(this, name);
    this.setType("spirit");

    this.getArmourType = function() {return "spirit";};

    var stats = new RG.Component.Stats();
    this.add("Stats", stats);

    var _brain = new RG.Brain.Spirit(this);

    this.add("Action", new RG.Component.Stats());

    this.isPlayer = function() {return false;};

    /** Get next action for this spirit.*/
    this.nextAction = function(obj) {
        var cb = _brain.decideNextAction(obj);
        var action = null;

        if (cb !== null) {
            var speed = this.get("Stats").getSpeed();
            var duration = parseInt(RG.BASE_SPEED/speed * RG.ACTION_DUR);
            action = new RG.RogueAction(duration, cb, {});
        }
        else {
            action = new RG.RogueAction(0, function(){}, {});
        }
        return action;
    };

};

RG.Item.Spirit.prototype.toString = function() {
    var txt = this.getName() + ", " + this.getType() + ", ";
    txt += this.get("Stats").toString();
    return txt;
};

RG.Item.Spirit.prototype.equals = function(item) {
    var res = RG.Item.Base.prototype.equals.call(this, item);
    res = res && (this.getType() === item.getType());
    return res;
};

RG.Item.Spirit.prototype.copy = function(rhs) {
    this.get("Stats").copy(rhs.get("Stats"));
};

RG.Item.Spirit.prototype.clone = function() {
    var newSpirit = new RG.Item.Spirit(this.getName());
    newSpirit.copy(this);
    return newSpirit;
};

RG.extend2(RG.Item.Spirit, RG.Item.Base);

if (typeof module !== "undefined" && typeof exports !== "undefined") {
    GS.exportSource(module, exports, ["RG", "Item"], [RG, RG.Item]);
}
else {
    GS.exportSource(undefined, undefined, ["RG", "Item"], [RG, RG.Item]);
}
<|endoftext|>