<commit_before>/*
 * This file is part of the GOsa project -  http://gosa-project.org
 *
 * Copyright:
 *    (C) 2010-2017 GONICUS GmbH, Germany, http://www.gonicus.de
 *
 * License:
 *    LGPL-2.1: http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * See the LICENSE file in the project's top-level directory for details.
 */

qx.Class.define("gosa.proxy.Object", {

  extend: qx.core.Object,

  construct: function(data){

    // Call parent contructor
    this.base(arguments);
    this._setAttributes(data);
    this._listeners = new qx.data.Array();
    this._listeners.push(gosa.io.Sse.getInstance().addListener("objectModified", this._objectEvent, this));
    this._listeners.push(gosa.io.Sse.getInstance().addListener("objectRemoved", this._objectEvent, this));
    this._listeners.push(gosa.io.Sse.getInstance().addListener("objectMoved", this._objectEvent, this));
    this._listeners.push(gosa.io.Sse.getInstance().addListener("objectClosing", this._objectClosingEvent, this));
  },

  destruct : function(){

    // Stop listening for object changes
    this._listeners.forEach(function(listener) {
      gosa.io.Sse.getInstance().removeListenerById(listener);
    }, this);
    this.__listeners = null;

    // Remove every listener that was attached to us.
    // This allows us to set attribute values to null without
    // notifying gui widgets or other things.
    qx.event.Registration.removeAllListeners(this);
    for(var item in this.attributes){
      this.set(this.attributes[item], null);
    }
  },

  properties: {

    // Bound to the gui-editing widget
    uiBound: {
      check: "Boolean",
      init: false
    },

    /**
     * Title to identify this object, usually the first part of the DN
     */
    $$title: {
      check: "String",
      init: "",
      event: "changedTitle"
    },

    /**
     * Optional Icon to identify this object (used in the upper toolbar that shows the open objects)
     */
    $$icon: {
      check: "String",
      nullable: true
    },

    /**
     * Must be true if the object shall write updates to the backend.
     */
    writeAttributeUpdates : {
      check : "Boolean",
      init : true
    }
  },

  events: {
    "foundDifferencesDuringReload": "qx.event.type.Data",
    "propertyUpdateOnServer": "qx.event.type.Data",
    "updatedAttributeValues": "qx.event.type.Data",
    "moved": "qx.event.type.Data",
    "removed": "qx.event.type.Event",
    "closing": "qx.event.type.Data"
  },

  members: {

    _closed: false,
    _listeners: null,
    initialized: null,
    is_reloading: false,
    _updateLastChanged: null,
    skipEvents: false,

    isClosed: function(){
      return(this.isDisposed() || this._closed);
    },

    setClosed : function(value) {
      qx.core.Assert.assertBoolean(value);
      this._closed = value;
    },

    _objectClosingEvent: function(e) {
      // Skip event processing while committing, removing, etc
      if(this.skipEvents){
        return;
      }
      var data = e.getData();
      // Skip events that are not for us
      if(data.uuid != this.uuid) {
        return;
      }
      this.fireDataEvent("closing", data);
    },

    _objectEvent: function(e){

      // Skip event processing while committing, removing, etc
      if(this.skipEvents){
        return;
      }

      // Skip events that are not for us
      var data = e.getData();
      if(data.uuid !== this.uuid){
        return;
      }

      // Act on the event type
      if(data.changeType === "remove") {
        this.fireEvent("removed");
      } else if (data.changeType === "move") {
        this.reload();
        this.fireDataEvent("moved", data.dn);
      } else if(data.changeType === "update"){
        if(!this.is_reloading){

          if(!this.isUiBound()){
            this.reload();
          } else {
            this.mergeChanges();
          }
        }
      }
    },

    /* Helper method that sets attribute values using the
     * json-rpc response
     * */
    _setAttributes: function(data){

      // Initialize object values
      this.initialized = false;
      this.instance_uuid = data.__jsonclass__[1][1];
      this.dn = data.__jsonclass__[1][2];
      this.uuid = data.uuid;

      for(var item in this.attributes){
        var val;
        if(this.attributes[item] in data){

          if(this.attribute_data[this.attributes[item]].multivalue){
            val = new qx.data.Array(data[this.attributes[item]]);
          }else{
            var value = data[this.attributes[item]];
            val = new qx.data.Array();
            if(value !== null){
              val.push(value);
            }
          }

          this.set(this.attributes[item], val);
        }
      }

      // Initialization is done (Start sending attribute modifications to the backend)
      this.initialized = true;
    },

    /* Setter method for object values
     * */
    setAttribute: function(name, value){
      if (this.initialized && this.isWriteAttributeUpdates()) {

        // Do nothing..
        if (value === null || value === undefined) {
          return;
        }

        var rpc = gosa.io.Rpc.getInstance();
        var rpc_value = null;
        if (this.attribute_data[name].multivalue) {
          rpc_value = value.toArray();
        } else {
          if(value.getLength()){
            rpc_value = value.toArray()[0];
          }
        }
        rpc.cA("setObjectProperty", this.instance_uuid, name, rpc_value).bind(this)
        .then(function() {
          this.fireDataEvent("propertyUpdateOnServer", {success: true, error: null, property: name});
        })
        .catch(function(error) {
          this.fireDataEvent("propertyUpdateOnServer", {success: false, error: error, property: name});
        }, this);
      }
    },

    /**
     * Closes the current object
     * @return {qx.Promise}
     */
    close : function(){

      // Skip events now.
      this.skipEvents = true;

      this.setClosed(true);
      this.dispose();
      return gosa.io.Rpc.getInstance().cA("closeObject", this.instance_uuid);
    },

    /**
     * If this object is bound to a gui, then send a merge event to that
     * gui, it will then handle merging.
     */
    mergeChanges: function(){
      return gosa.io.Rpc.getInstance().cA("diffObject", this.instance_uuid)
      .then(qx.lang.Function.curry(this.fireDataEvent, "foundDifferencesDuringReload"), this);
    },

    /**
     *  Reload attribute values from the backend
     * @return {qx.Promise}
     */
    reload: function(){
      if(this.is_reloading){
        return;
      }
      this.is_reloading = true;
      var rpc = gosa.io.Rpc.getInstance();
      return rpc.cA("reloadObject", this.instance_uuid)
      .then(function(data) {
        this._setAttributes(data);
        this.is_reloading = false;
      }, this)
      .catch(gosa.ui.dialogs.Error.show, this);
    },

    /**
     * Updates attribute values by fetching them from the server.
     *
     * @param skipValueUpdate {Boolean}
     * @return {qx.Promise}
     */
    refreshAttributeInformation: function(skipValueUpdate){

      if(!skipValueUpdate){
        skipValueUpdate = false;
      }

      var compare = function(a, b){
          if(a.length != b.length){
            return(false);
          }
          for(var i=0; i<a.length; i++){
            if(a[i] != b[i]){
              return(false);
            }
          }
          return(true);
        };

      var rpc = gosa.io.Rpc.getInstance();
      return rpc.cA("dispatchObjectMethod", this.instance_uuid, "get_attribute_values")
      .then(function(data) {
        for (var item in data.value) {

          if (data.values[item]) {
            var attr = this.attribute_data;
            if (attr[item]) {
              attr[item].values = data.values[item];
            }
            this.fireDataEvent("updatedAttributeValues", {
              item   : item,
              values : data.values[item]
            });
          }

          // Do not update the property-value
          if (!skipValueUpdate) {
            var value = null;
            if (data.value[item] === null) {
              var attrData = this.attribute_data[item];
              if (attrData.mandatory && attrData.values && attrData.values.length > 0) {
                value = [attrData.values[0]];
                this.setAttribute(item, new qx.data.Array(value));
              }
              else {
                value = [];
              }
            }
            else {
              if (!(this.attribute_data[item].multivalue)) {
                value = [data.value[item]];
              }
              else {
                value = data.value[item];
              }
            }

            // Update modified attributes but skip RPC requests ...
            if (!compare(this.get(item).toArray(), value)) {

              // Skip RPC actions for this set
              this.initialized = false;
              this.set(item, new qx.data.Array(value));
              this.initialized = true;
            }
          }
        }
        return null;
      }, this);
    },

    /**
     * Reloads the current extension status.
     * @return {qx.Promise}
     */
    refreshMetaInformation : function()
    {
      var rpc = gosa.io.Rpc.getInstance();
      return rpc.cA("dispatchObjectMethod", this.instance_uuid, "get_object_info", this.locale)
      .then(function(data) {
        this.baseType = data.base;
        this.extensionTypes = data.extensions;
      }, this);
    },

    /**
     * Wrapper method for object calls
     *
     * @param method {String} name of the method to call
     * @return {qx.Promise}
     */
    callMethod: function(method){

      // Skip events while saving
      if(method === "commit" || method === "remove"){
        this.skipEvents = true;
      }

      var rpc = gosa.io.Rpc.getInstance();
      var args = ["dispatchObjectMethod", this.instance_uuid, method].concat(Array.prototype.slice.call(arguments, 1));
      return rpc.cA.apply(rpc, args)
      .then(function(result) {
        if (method === "remove") {
          this.close();
          this.skipEvents = false;
        }
        return result;
      }, this);
    }
  }
});
<commit_msg>debounce object change events<commit_after>/*
 * This file is part of the GOsa project -  http://gosa-project.org
 *
 * Copyright:
 *    (C) 2010-2017 GONICUS GmbH, Germany, http://www.gonicus.de
 *
 * License:
 *    LGPL-2.1: http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * See the LICENSE file in the project's top-level directory for details.
 */

qx.Class.define("gosa.proxy.Object", {

  extend: qx.core.Object,

  construct: function(data){

    // Call parent contructor
    this.base(arguments);
    this._setAttributes(data);
    this._listeners = new qx.data.Array();
    this._listeners.push(gosa.io.Sse.getInstance().addListener("objectModified", this._objectEvent, this));
    this._listeners.push(gosa.io.Sse.getInstance().addListener("objectRemoved", this._objectEvent, this));
    this._listeners.push(gosa.io.Sse.getInstance().addListener("objectMoved", this._objectEvent, this));
    this._listeners.push(gosa.io.Sse.getInstance().addListener("objectClosing", this._objectClosingEvent, this));

    this.debouncedMergeChanges = qx.util.Function.debounce(this.mergeChanges, 250, false);
  },

  destruct : function(){

    // Stop listening for object changes
    this._listeners.forEach(function(listener) {
      gosa.io.Sse.getInstance().removeListenerById(listener);
    }, this);
    this.__listeners = null;

    // Remove every listener that was attached to us.
    // This allows us to set attribute values to null without
    // notifying gui widgets or other things.
    qx.event.Registration.removeAllListeners(this);
    for(var item in this.attributes){
      this.set(this.attributes[item], null);
    }
  },

  properties: {

    // Bound to the gui-editing widget
    uiBound: {
      check: "Boolean",
      init: false
    },

    /**
     * Title to identify this object, usually the first part of the DN
     */
    $$title: {
      check: "String",
      init: "",
      event: "changedTitle"
    },

    /**
     * Optional Icon to identify this object (used in the upper toolbar that shows the open objects)
     */
    $$icon: {
      check: "String",
      nullable: true
    },

    /**
     * Must be true if the object shall write updates to the backend.
     */
    writeAttributeUpdates : {
      check : "Boolean",
      init : true
    }
  },

  events: {
    "foundDifferencesDuringReload": "qx.event.type.Data",
    "propertyUpdateOnServer": "qx.event.type.Data",
    "updatedAttributeValues": "qx.event.type.Data",
    "moved": "qx.event.type.Data",
    "removed": "qx.event.type.Event",
    "closing": "qx.event.type.Data"
  },

  members: {

    _closed: false,
    _listeners: null,
    initialized: null,
    is_reloading: false,
    _updateLastChanged: null,
    skipEvents: false,

    isClosed: function(){
      return(this.isDisposed() || this._closed);
    },

    setClosed : function(value) {
      qx.core.Assert.assertBoolean(value);
      this._closed = value;
    },

    _objectClosingEvent: function(e) {
      // Skip event processing while committing, removing, etc
      if(this.skipEvents){
        return;
      }
      var data = e.getData();
      // Skip events that are not for us
      if(data.uuid != this.uuid) {
        return;
      }
      this.fireDataEvent("closing", data);
    },

    _objectEvent: function(e){

      // Skip event processing while committing, removing, etc
      if(this.skipEvents){
        return;
      }

      // Skip events that are not for us
      var data = e.getData();
      if(data.uuid !== this.uuid){
        return;
      }

      // Act on the event type
      if(data.changeType === "remove") {
        this.fireEvent("removed");
      } else if (data.changeType === "move") {
        this.reload();
        this.fireDataEvent("moved", data.dn);
      } else if(data.changeType === "update"){
        if(!this.is_reloading){

          if(!this.isUiBound()){
            this.reload();
          } else {
            this.debouncedMergeChanges();
          }
        }
      }
    },

    /* Helper method that sets attribute values using the
     * json-rpc response
     * */
    _setAttributes: function(data){

      // Initialize object values
      this.initialized = false;
      this.instance_uuid = data.__jsonclass__[1][1];
      this.dn = data.__jsonclass__[1][2];
      this.uuid = data.uuid;

      for(var item in this.attributes){
        var val;
        if(this.attributes[item] in data){

          if(this.attribute_data[this.attributes[item]].multivalue){
            val = new qx.data.Array(data[this.attributes[item]]);
          }else{
            var value = data[this.attributes[item]];
            val = new qx.data.Array();
            if(value !== null){
              val.push(value);
            }
          }

          this.set(this.attributes[item], val);
        }
      }

      // Initialization is done (Start sending attribute modifications to the backend)
      this.initialized = true;
    },

    /* Setter method for object values
     * */
    setAttribute: function(name, value){
      if (this.initialized && this.isWriteAttributeUpdates()) {

        // Do nothing..
        if (value === null || value === undefined) {
          return;
        }

        var rpc = gosa.io.Rpc.getInstance();
        var rpc_value = null;
        if (this.attribute_data[name].multivalue) {
          rpc_value = value.toArray();
        } else {
          if(value.getLength()){
            rpc_value = value.toArray()[0];
          }
        }
        rpc.cA("setObjectProperty", this.instance_uuid, name, rpc_value).bind(this)
        .then(function() {
          this.fireDataEvent("propertyUpdateOnServer", {success: true, error: null, property: name});
        })
        .catch(function(error) {
          this.fireDataEvent("propertyUpdateOnServer", {success: false, error: error, property: name});
        }, this);
      }
    },

    /**
     * Closes the current object
     * @return {qx.Promise}
     */
    close : function(){

      // Skip events now.
      this.skipEvents = true;

      this.setClosed(true);
      this.dispose();
      return gosa.io.Rpc.getInstance().cA("closeObject", this.instance_uuid);
    },

    /**
     * If this object is bound to a gui, then send a merge event to that
     * gui, it will then handle merging.
     */
    mergeChanges: function(){
      return gosa.io.Rpc.getInstance().cA("diffObject", this.instance_uuid)
      .then(qx.lang.Function.curry(this.fireDataEvent, "foundDifferencesDuringReload"), this);
    },

    /**
     *  Reload attribute values from the backend
     * @return {qx.Promise}
     */
    reload: function(){
      if(this.is_reloading){
        return;
      }
      this.is_reloading = true;
      var rpc = gosa.io.Rpc.getInstance();
      return rpc.cA("reloadObject", this.instance_uuid)
      .then(function(data) {
        this._setAttributes(data);
        this.is_reloading = false;
      }, this)
      .catch(gosa.ui.dialogs.Error.show, this);
    },

    /**
     * Updates attribute values by fetching them from the server.
     *
     * @param skipValueUpdate {Boolean}
     * @return {qx.Promise}
     */
    refreshAttributeInformation: function(skipValueUpdate){

      if(!skipValueUpdate){
        skipValueUpdate = false;
      }

      var compare = function(a, b){
          if(a.length != b.length){
            return(false);
          }
          for(var i=0; i<a.length; i++){
            if(a[i] != b[i]){
              return(false);
            }
          }
          return(true);
        };

      var rpc = gosa.io.Rpc.getInstance();
      return rpc.cA("dispatchObjectMethod", this.instance_uuid, "get_attribute_values")
      .then(function(data) {
        for (var item in data.value) {

          if (data.values[item]) {
            var attr = this.attribute_data;
            if (attr[item]) {
              attr[item].values = data.values[item];
            }
            this.fireDataEvent("updatedAttributeValues", {
              item   : item,
              values : data.values[item]
            });
          }

          // Do not update the property-value
          if (!skipValueUpdate) {
            var value = null;
            if (data.value[item] === null) {
              var attrData = this.attribute_data[item];
              if (attrData.mandatory && attrData.values && attrData.values.length > 0) {
                value = [attrData.values[0]];
                this.setAttribute(item, new qx.data.Array(value));
              }
              else {
                value = [];
              }
            }
            else {
              if (!(this.attribute_data[item].multivalue)) {
                value = [data.value[item]];
              }
              else {
                value = data.value[item];
              }
            }

            // Update modified attributes but skip RPC requests ...
            if (!compare(this.get(item).toArray(), value)) {

              // Skip RPC actions for this set
              this.initialized = false;
              this.set(item, new qx.data.Array(value));
              this.initialized = true;
            }
          }
        }
        return null;
      }, this);
    },

    /**
     * Reloads the current extension status.
     * @return {qx.Promise}
     */
    refreshMetaInformation : function()
    {
      var rpc = gosa.io.Rpc.getInstance();
      return rpc.cA("dispatchObjectMethod", this.instance_uuid, "get_object_info", this.locale)
      .then(function(data) {
        this.baseType = data.base;
        this.extensionTypes = data.extensions;
      }, this);
    },

    /**
     * Wrapper method for object calls
     *
     * @param method {String} name of the method to call
     * @return {qx.Promise}
     */
    callMethod: function(method){

      // Skip events while saving
      if(method === "commit" || method === "remove"){
        this.skipEvents = true;
      }

      var rpc = gosa.io.Rpc.getInstance();
      var args = ["dispatchObjectMethod", this.instance_uuid, method].concat(Array.prototype.slice.call(arguments, 1));
      return rpc.cA.apply(rpc, args)
      .then(function(result) {
        if (method === "remove") {
          this.close();
          this.skipEvents = false;
        }
        return result;
      }, this);
    }
  }
});
<|endoftext|>


<commit_before>'use strict';

import { Entity } from 'draft-js';
import { ENTITY } from '../CONSTANT';
import Alignment from './block-alignment-wrapper';
import EmbeddedCodeBlock from '../embedded-code/embedded-code-block';
import ImageBlock from '../image/image-block';
import ImageDiffBlock from '../image-diff/Image-diff-block';
import React from 'react';
import SlideshowBlock from '../slideshow/slideshow-block';

class AtomicBlock extends React.Component {
    constructor(props) {
        super(props);
        this.alignLeft = this._alignLeft.bind(this);
        this.alignCenter = this._alignCenter.bind(this);
        this.alignRight = this._alignRight.bind(this);
    }

    _alignLeft() {
        this.props.align('left');
    }

    _alignCenter() {
        this.props.align('center');
    }

    _alignRight() {
        this.props.align('right');
    }

    render() {
        const entityKey = this.props.block.getEntityAt(0);
        const type =  entityKey ? Entity.get(entityKey).getType(): null;

        const Buttons = (

                    L

                    C

                    R

        );

        const { alignment } = this.props;
        let className = alignment;
        let BlockComponent;

        switch (type) {
            case ENTITY.embeddedCode.type:
                BlockComponent = EmbeddedCodeBlock;
                break;
            case ENTITY.image.type:
                BlockComponent = ImageBlock;
                break;
            case ENTITY.slideshow.type:
                BlockComponent = SlideshowBlock;
                break;
            case ENTITY.imageDiff.type:
                BlockComponent = ImageDiffBlock;
                break;
            default:
                return;
        }

        return (
            <BlockComponent
                {...this.props}
                className={className}
                >
                {Buttons}
            </BlockComponent>
        );
    }
}

export default Alignment(AtomicBlock);
<commit_msg>code fix<commit_after>'use strict';

import { Entity } from 'draft-js';
import { ENTITY } from '../CONSTANT';
import Alignment from './block-alignment-wrapper';
import EmbeddedCodeBlock from '../embedded-code/embedded-code-block';
import ImageBlock from '../image/image-block';
import ImageDiffBlock from '../image-diff/image-diff-block';
import React from 'react';
import SlideshowBlock from '../slideshow/slideshow-block';

class AtomicBlock extends React.Component {
    constructor(props) {
        super(props);
        this.alignLeft = this._alignLeft.bind(this);
        this.alignCenter = this._alignCenter.bind(this);
        this.alignRight = this._alignRight.bind(this);
    }

    _alignLeft() {
        this.props.align('left');
    }

    _alignCenter() {
        this.props.align('center');
    }

    _alignRight() {
        this.props.align('right');
    }

    render() {
        const entityKey = this.props.block.getEntityAt(0);
        const type =  entityKey ? Entity.get(entityKey).getType(): null;

        const Buttons = (

                    L

                    C

                    R

        );

        const { alignment } = this.props;
        let className = alignment;
        let BlockComponent;

        switch (type) {
            case ENTITY.embeddedCode.type:
                BlockComponent = EmbeddedCodeBlock;
                break;
            case ENTITY.image.type:
                BlockComponent = ImageBlock;
                break;
            case ENTITY.slideshow.type:
                BlockComponent = SlideshowBlock;
                break;
            case ENTITY.imageDiff.type:
                BlockComponent = ImageDiffBlock;
                break;
            default:
                return;
        }

        return (
            <BlockComponent
                {...this.props}
                className={className}
                >
                {Buttons}
            </BlockComponent>
        );
    }
}

export default Alignment(AtomicBlock);
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict'

const path = require('path')
const pkg = require('../package.json')
const cosmiconfig = require('cosmiconfig')(pkg.name)
const <%= camelAppName %> = require('<%= appName %>')

require('update-notifier')({pkg}).notify()

const cli = require('meow')({
  pkg,
  help: require('fs').readFileSync(path.join(__dirname, 'help.txt'), 'utf8'),
  flags: {
    cwd: {
      default: process.cwd()
    }
  }
})

;(async () => {
  const { cwd } = cli.flags
  const { config } = await cosmiconfig.search(cwd) || {}
  const input = config.url || cli.input[0]
  const flags = { ...config, ...cli.flags }
  if (!input) cli.showHelp()

  const output = <%= camelAppName %>(flags)
  console.log(output)
})()
<commit_msg>Update _index.js<commit_after>#!/usr/bin/env node
'use strict'

const path = require('path')
const pkg = require('../package.json')
const cosmiconfig = require('cosmiconfig').cosmiconfig(pkg.name)
const <%= camelAppName %> = require('<%= appName %>')

require('update-notifier')({pkg}).notify()

const cli = require('meow')({
  pkg,
  help: require('fs').readFileSync(path.join(__dirname, 'help.txt'), 'utf8'),
  flags: {
    cwd: {
      default: process.cwd()
    }
  }
})

;(async () => {
  const { cwd } = cli.flags
  const { config } = await cosmiconfig.search(cwd) || {}
  const input = config.url || cli.input[0]
  const flags = { ...config, ...cli.flags }
  if (!input) cli.showHelp()

  const output = <%= camelAppName %>(flags)
  console.log(output)
})()
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';

const styles = {
  button: {
    padding: '5px 20px',
    marginRight: '10px',
    fontSize: '14px',
  },
};

const Controls = ({
  onRemove,
  onRemoveAll,
  onRestore,
  onRotate,
  onShuffle,
  numOfCurrentItems,
  numOfTotalItems,
}) => (

    <button
      onClick={() => onRemove()}
      style={styles.button}
      disabled={numOfCurrentItems === 0}
    >
      Remove 1 Item
    </button>

    <button
      onClick={() => onRemoveAll()}
      style={styles.button}
      disabled={numOfCurrentItems === 0}
    >
      Remove All Items
    </button>

    <button
      onClick={() => onRestore()}
      style={styles.button}
      disabled={numOfCurrentItems === numOfTotalItems}
    >
      Restore Items
    </button>

    <button onClick={() => onShuffle()} style={styles.button}>
      Shuffle Items
    </button>

    <button onClick={() => onRotate()} style={styles.button}>
      Rotate Items
    </button>

);

Controls.propTypes = {
  onRemove: PropTypes.func.isRequired,
  onRemoveAll: PropTypes.func.isRequired,
  onRestore: PropTypes.func.isRequired,
  onRotate: PropTypes.func.isRequired,
  onShuffle: PropTypes.func.isRequired,
  numOfCurrentItems: PropTypes.number.isRequired,
  numOfTotalItems: PropTypes.number.isRequired,
};

export default Controls;
<commit_msg>Update Controls in storybook to avoid shuffling empty lists<commit_after>import React, { PropTypes } from 'react';

const styles = {
  button: {
    padding: '5px 20px',
    marginRight: '10px',
    fontSize: '14px',
  },
};

const Controls = ({
  onRemove,
  onRemoveAll,
  onRestore,
  onRotate,
  onShuffle,
  numOfCurrentItems,
  numOfTotalItems,
}) => (

    <button
      onClick={() => onRemove()}
      style={styles.button}
      disabled={numOfCurrentItems === 0}
    >
      Remove 1 Item
    </button>

    <button
      onClick={() => onRemoveAll()}
      style={styles.button}
      disabled={numOfCurrentItems === 0}
    >
      Remove All Items
    </button>

    <button
      onClick={() => onRestore()}
      style={styles.button}
      disabled={numOfCurrentItems === numOfTotalItems}
    >
      Restore Items
    </button>

    <button
      onClick={() => onShuffle()}
      style={styles.button}
      disabled={numOfCurrentItems === 0}
    >
      Shuffle Items
    </button>

    <button
      onClick={() => onRotate()}
      style={styles.button}
      disabled={numOfCurrentItems === 0}
    >
      Rotate Items
    </button>

);

Controls.propTypes = {
  onRemove: PropTypes.func.isRequired,
  onRemoveAll: PropTypes.func.isRequired,
  onRestore: PropTypes.func.isRequired,
  onRotate: PropTypes.func.isRequired,
  onShuffle: PropTypes.func.isRequired,
  numOfCurrentItems: PropTypes.number.isRequired,
  numOfTotalItems: PropTypes.number.isRequired,
};

export default Controls;
<|endoftext|>


<commit_before>
/**
  The address extractor is responsible for cloning documents where a valid address
  data exists.

  The hasValidAddress() function examines the address property which was populated
  earier in the pipeline by the osm.tag.mapper stream and therefore MUST come after
  that stream in the pipeline or it will fail to find any address information.

  There are a few different outcomes for this stream depending on the data contained
  in each individual document, the result can be, 0, 1 or 2 documents being emitted.

  In the case of the document missing a valid doc.name.default string then it is not
  considered to be a point-of-interest in it's own right, it will be discarded.

  In the case where the document contains BOTH a valid house number & street name we
  consider this record to be an address in it's own right and we clone that record,
  duplicating the data across to the new doc instance while adjusting it's id and type.

  In a rare case it is possible that the record contains neither a valid name nor a valid
  address. If this case in encountered then the parser should be modified so these records
  are no longer passed down the pipeline; as they will simply be discarded because they are
  not searchable.
**/

var through = require('through2'),
    isObject = require('is-object'),
    extend = require('extend'),
    Document = require('pelias-model').Document,
    idOrdinal = 0; // used for addresses lacking an id (to keep them unique)

function hasValidAddress( doc ){
  if( !isObject( doc ) ){ return false; }
  if( !isObject( doc.address ) ){ return false; }
  if( 'string' !== typeof doc.address.number ){ return false; }
  if( 'string' !== typeof doc.address.street ){ return false; }
  if( !doc.address.number.length ){ return false; }
  if( !doc.address.street.length ){ return false; }
  return true;
}

module.exports = function(){

  var stream = through.obj( function( doc, enc, next ) {

    var isNamedPoi = !!doc.getName('default');

    try {

      // create a new record for street addresses
      if( hasValidAddress( doc ) ){
        var type = isNamedPoi ? 'poi-address' : 'address';

        // copy data to new document
        var record = new Document( 'osmaddress', type + '-' + doc.getType() + '-' + (doc.getId() || ++idOrdinal) );

        record
          .setName( 'default', doc.address.number + ' ' + doc.address.street )
          .setCentroid( doc.getCentroid() );

        // copy address info
        record.address = doc.address;

        // copy admin data
        if( doc.alpha3 ){ record.setAlpha3( doc.alpha3 ); }
        if( doc.admin0 ){ record.setAdmin( 'admin0', doc.admin0 ); }
        if( doc.admin1 ){ record.setAdmin( 'admin1', doc.admin1 ); }
        if( doc.admin1_abbr ){ record.setAdmin( 'admin1_abbr', doc.admin1_abbr ); }
        if( doc.admin2 ){ record.setAdmin( 'admin2', doc.admin2 ); }
        if( doc.local_admin ){ record.setAdmin( 'local_admin', doc.local_admin ); }
        if( doc.locality ){ record.setAdmin( 'locality', doc.locality ); }
        if( doc.neighborhood ){ record.setAdmin( 'neighborhood', doc.neighborhood ); }

        // copy meta data (but maintain the id & type assigned above)
        record._meta = extend( true, {}, doc._meta, { id: record.getId(), type: record.getType() } );

        this.push( record );
      }

    }

    catch( e ){
      console.error( 'address_extractor error' );
      console.error( e.stack );
      console.error( JSON.stringify( doc, null, 2 ) );
    }

    // forward doc downstream is it's a POI in it's own right
    // note: this MUST be below the address push()
    if( isNamedPoi ){
      this.push( doc );
    }

    return next();

  });

  // catch stream errors
  stream.on( 'error', console.error.bind( console, __filename ) );

  return stream;
};

// export for testing
module.exports.hasValidAddress = hasValidAddress;<commit_msg>Reduce scope of try/catch.<commit_after>
/**
  The address extractor is responsible for cloning documents where a valid address
  data exists.

  The hasValidAddress() function examines the address property which was populated
  earier in the pipeline by the osm.tag.mapper stream and therefore MUST come after
  that stream in the pipeline or it will fail to find any address information.

  There are a few different outcomes for this stream depending on the data contained
  in each individual document, the result can be, 0, 1 or 2 documents being emitted.

  In the case of the document missing a valid doc.name.default string then it is not
  considered to be a point-of-interest in it's own right, it will be discarded.

  In the case where the document contains BOTH a valid house number & street name we
  consider this record to be an address in it's own right and we clone that record,
  duplicating the data across to the new doc instance while adjusting it's id and type.

  In a rare case it is possible that the record contains neither a valid name nor a valid
  address. If this case in encountered then the parser should be modified so these records
  are no longer passed down the pipeline; as they will simply be discarded because they are
  not searchable.
**/

var through = require('through2'),
    isObject = require('is-object'),
    extend = require('extend'),
    Document = require('pelias-model').Document,
    idOrdinal = 0; // used for addresses lacking an id (to keep them unique)

function hasValidAddress( doc ){
  if( !isObject( doc ) ){ return false; }
  if( !isObject( doc.address ) ){ return false; }
  if( 'string' !== typeof doc.address.number ){ return false; }
  if( 'string' !== typeof doc.address.street ){ return false; }
  if( !doc.address.number.length ){ return false; }
  if( !doc.address.street.length ){ return false; }
  return true;
}

module.exports = function(){

  var stream = through.obj( function( doc, enc, next ) {
    var isNamedPoi = !!doc.getName('default');

    // create a new record for street addresses
    if( hasValidAddress( doc ) ){
      var type = isNamedPoi ? 'poi-address' : 'address';
      var record;

      try {
        // copy data to new document
        record = new Document( 'osmaddress', type + '-' + doc.getType() + '-' + (doc.getId() || ++idOrdinal) )
          .setName( 'default', doc.address.number + ' ' + doc.address.street )
          .setCentroid( doc.getCentroid() );

        // copy address info
        record.address = doc.address;

        // copy admin data
        if( doc.alpha3 ){ record.setAlpha3( doc.alpha3 ); }
        if( doc.admin0 ){ record.setAdmin( 'admin0', doc.admin0 ); }
        if( doc.admin1 ){ record.setAdmin( 'admin1', doc.admin1 ); }
        if( doc.admin1_abbr ){ record.setAdmin( 'admin1_abbr', doc.admin1_abbr ); }
        if( doc.admin2 ){ record.setAdmin( 'admin2', doc.admin2 ); }
        if( doc.local_admin ){ record.setAdmin( 'local_admin', doc.local_admin ); }
        if( doc.locality ){ record.setAdmin( 'locality', doc.locality ); }
        if( doc.neighborhood ){ record.setAdmin( 'neighborhood', doc.neighborhood ); }
      }
      catch( e ){
        console.error( 'address_extractor error' );
        console.error( e.stack );
        console.error( JSON.stringify( doc, null, 2 ) );
      }

      if( record !== undefined ){
        // copy meta data (but maintain the id & type assigned above)
        record._meta = extend( true, {}, doc._meta, { id: record.getId(), type: record.getType() } );
        this.push( record );
      }
    }

    // forward doc downstream is it's a POI in it's own right
    // note: this MUST be below the address push()
    if( isNamedPoi ){
      this.push( doc );
    }

    return next();

  });

  // catch stream errors
  stream.on( 'error', console.error.bind( console, __filename ) );

  return stream;
};

// export for testing
module.exports.hasValidAddress = hasValidAddress;
<|endoftext|>


<commit_before>var defaultRoutes = {
	"*page": "page"
};

// NOTE i chose to to pass router.root and set in router
// instead of using Backbone.history.start({ root: }) because
// then history.navigate has to be called with the path without the root.
// one could remove the root from the href in a.nav click event, but that seems a little
// annoying

module.exports = Backbone.Router.extend({
	initialize: function(options) {
		options = options || {};

		var _router = this;

		_.extend(_router, _.pick(options, [ 'app', 'root' ]));

		if(_router.root) {
			// ensure trailing '/' in root
			if(!/\/$/.test(_router.root))
				_router.root = _router.root + '/';
		} else
			_router.root = '/';

		_.each(_.extend(defaultRoutes, options.routes), function(value, path) {
			_router.route(_router.root.slice(1) + path, value);
		});
	},

	page: function(page, index) {
		var _router = this;

		page = page || '';

		$.getJSON(_router.root + page)
			.fail(function(xhr) {
				_.each(xhr.responseJSON.compiled, _router.app.dust.loadSource);
				_router.app.navigate(xhr.responseJSON);
			}).done(function(res, txt, xhr) {
				if(res.data && res.data.page && res.data.page.path.slice(1) !== page) {
					_router.navigate(res.data.page.path, { trigger: true, replace: true });
				} else {
					_.each(res.compiled, _router.app.dust.loadSource);
					_router.app.navigate(res);
				}
			});
	}
});
<commit_msg>Small fix that enables handling of root paths.<commit_after>var defaultRoutes = {
	"*page": "page"
};

// NOTE i chose to to pass router.root and set in router
// instead of using Backbone.history.start({ root: }) because
// then history.navigate has to be called with the path without the root.
// one could remove the root from the href in a.nav click event, but that seems a little
// annoying

module.exports = Backbone.Router.extend({
	initialize: function(options) {
		options = options || {};

		var _router = this;

		_.extend(_router, _.pick(options, [ 'app', 'root' ]));

		if(_router.root) {
			// ensure trailing '/' in root
			if(!/\/$/.test(_router.root))
				_router.root = _router.root + '/';
		} else
			_router.root = '/';

		_.each(_.extend(defaultRoutes, options.routes), function(value, path) {
			_router.route(_router.root.slice(1) + path, value);
		});
	},

	page: function(page, index) {
		var _router = this;

		var path = _router.root + (page || '');

		$.getJSON(path)
			.fail(function(xhr) {
				_.each(xhr.responseJSON.compiled, _router.app.dust.loadSource);
				_router.app.navigate(xhr.responseJSON);
			}).done(function(res, txt, xhr) {
				if(res.data && res.data.page && res.data.page.path !== path) {
					_router.navigate(res.data.page.path, { trigger: true, replace: true });
				} else {
					_.each(res.compiled, _router.app.dust.loadSource);
					_router.app.navigate(res);
				}
			});
	}
});
<|endoftext|>


<commit_before>const exec = require('child_process').exec;

const speaker = require('./speech/amazon-polly-speaker');
const requestHelper = require('./util/request_helper');
const articleExtractor = require('./util/article_extractor');
const serialHandler = require('./util/serial_handler');
var skanetrafiken = require('./util/skanetrafiken');
const moment = require('moment');
const ip = require('ip');
const hue = require('./util/hue');

module.exports = (app, mirrorSocket) => {
  app.get('/api/brightness/:val', (req, res) => {
    console.log(req.params.val);
    if (req.params.cmd) serialHandler.writeString('brightness:' + req.params.val);
    res.json({
      success: true,
    });
  });

  app.get('/api/brightnessUp', (req, res) => {
    serialHandler.writeString('brightnessUp:');
    res.json({
      success: true,
    });
  });

  app.get('/api/brightnessDown', (req, res) => {
    serialHandler.writeString('brightnessDown:');
    res.json({
      success: true,
    });
  });

  app.get('/api/serial/:command', (req, res) => {
    let serialCommand, hour, min;
    let command = req.params.command;
    if (command.includes('time')) {
      serialCommand = command.split(':time=')[0];
      const hhmm = command.split(':time=')[1];
      hour = hhmm.split(':')[0];
      min = hhmm.split(':')[1];
      let now = moment(new Date());
      let future = moment(new Date())
        .hour(hour)
        .minute(min);
      let diff = future.diff(now);
      if (diff < 0) {
        future.add(1, 'day');
      }
      diff = future.diff(now);
      setTimeout(() => {
        serialHandler.writeString(serialCommand);
      }, diff);
    } else {
      serialHandler.writeString(req.params.command);
    }
    res.json({
      success: true,
    });
  });

  app.post('/api/serial', (req, res) => {
    if (req.body.mode) {
      serialHandler.writeString('mode:' + req.body.mode + ':' + req.body.speed);
    } else {
      const side = req.body.side;
      const rgb = req.body.rgb;
      if (side === 'all') {
        serialHandler.writeString('rgb:' + rgb.r + ':' + rgb.g + ':' + rgb.b);
      } else {
        serialHandler.writeString('side:' + side + ':' + rgb.r + ':' + rgb.g + ':' + rgb.b);
      }
    }
    res.json({
      success: true,
    });
  });

  app.get('/api/speak/:text', (req, res) => {
    if (req.params.text) speaker.speak(req.params.text);
    res.json({
      success: true,
    });
  });

  app.get('/api/hide', (req, res) => {
    mirrorSocket.sendToClient('visibility', { component: 'forecasts', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'news', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'article', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'tasks', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'weather', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'clock', visible: false });
    res.json({
      success: true,
    });
  });

  app.get('/api/hide/:component', (req, res) => {
    mirrorSocket.sendToClient('visibility', { component: req.params.component, visible: false });
    res.json({
      success: true,
    });
  });

  app.get('/api/show/:component', (req, res) => {
    mirrorSocket.sendToClient('visibility', { component: req.params.component, visible: true });
    res.json({
      success: true,
    });
  });

  app.get('/api/show', (req, res) => {
    mirrorSocket.sendToClient('visibility', { component: 'forecasts', visible: true });
    mirrorSocket.sendToClient('visibility', { component: 'news', visible: true });
    mirrorSocket.sendToClient('visibility', { component: 'article', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'tasks', visible: true });
    mirrorSocket.sendToClient('visibility', { component: 'weather', visible: true });
    mirrorSocket.sendToClient('visibility', { component: 'clock', visible: true });

    res.json({
      success: true,
    });
  });

  app.get('/api/tasks', (req, res) => {
    requestHelper.getTasks(tasks => {
      res.json({
        tasks: tasks,
      });
      return;
    });
  });

  app.get('/api/demo/:action', (req, res) => {
    if (req.params.action === 'dry') {
      requestHelper.logMoistureLevel(20);
      res.json({
        success: true,
      });
    } else if (req.params.action === 'water') {
      requestHelper.logMoistureLevel(95);
      res.json({
        success: true,
      });
    } else {
      res.json({
        success: false,
      });
    }
  });

  app.get('/api/moisture/latest', (req, res) => {
    requestHelper.getLatestMoistureLevel(moisture => {
      return res.json({
        moisture: moisture,
      });
    });
  });

  app.get('/api/tasks/create/:title', (req, res) => {
    if (req.params.title) {
      requestHelper.createTask(req.params.title);
      res.json({
        success: true,
      });
    } else {
      res.json({
        success: false,
      });
    }
  });

  app.get('/api/articles', (req, res) => {
    articleExtractor.getArticles(articles => {
      res.json({
        articles,
      });
      return;
    });
  });

  app.get('/api/temperatures7days', (req, res) => {
    requestHelper.getTemperatures(temps => {
      res.json({
        temperatures: temps,
      });
      return;
    });
  });

  app.get('/api/temperatures7days/:source', (req, res) => {
    requestHelper.getTemperaturesFromSource(req.params.source, temps => {
      res.json({
        temperatures: temps,
      });
      return;
    });
  });

  app.get('/api/shutdown', (req, res) => {
    exec('sudo shutdown -h now');
    res.json({
      success: true,
    });
  });

  app.get('/api/sleep', (req, res) => {
    exec('sudo tvservice -o');
    res.json({
      success: true,
    });
  });

  app.get('/api/wakeup', (req, res) => {
    exec('sudo tvservice -p; sudo chvt 6; sudo chvt 7;');
    res.json({
      success: true,
    });
  });

  app.get('/api/reboot', (req, res) => {
    exec('sudo reboot');
  });

  app.get('/api/next', (req, res) => {
    mirrorSocket.sendToClient('command', { component: 'article', action: 'next' });
    res.json({
      success: true,
    });
  });

  app.get('/api/spotify/current', (req, res) => {
    requestHelper.getCurrentlyPlayingSpotify(playing => {
      if (!playing) return res.status(500).send({ error: 'Token to old, queries new. Please try again.' });
      res.json({
        currentPlaying: playing,
      });
    });
  });

  app.get('/api/forecast', (req, res) => {
    requestHelper.getForecast(forecast => {
      res.json({
        forecast: forecast,
      });
      return;
    });
  });

  app.get('/api/journey', (req, res) => {
    skanetrafiken
      .getJourneysUsingConfig()
      .then(results => {
        return res.json({
          routes: results,
        });
      })
      .catch(err => {
        res.json({ error: 'Could not featch bus/trains' });
      });
  });

  app.get('/api/localip', (req, res) => {
    res.json({
      success: true,
      ip: ip.address(),
    });
  });

  app.get('/api/localip', (req, res) => {
    res.json({
      success: true,
      ip: ip.address(),
    });
  });

  app.post('/api/hue', (req, res) => {
    if (!req.body.name || !req.body.options) {
      return res.json({
        success: false,
        message: 'Must specify hue light name and options'
      });
    }

    if (hue.light(req.body.name, req.body.options)) {
      return res.json({
        success: true,
      });
    } else {
      return res.json({
        success: false,
        message: 'Light not found. Hue bridge lights are refreshed every 10 min. Try again later or check the name.'
      });
    }
  });

};
<commit_msg>Create tasks using post instead of get<commit_after>const exec = require('child_process').exec;

const speaker = require('./speech/amazon-polly-speaker');
const requestHelper = require('./util/request_helper');
const articleExtractor = require('./util/article_extractor');
const serialHandler = require('./util/serial_handler');
var skanetrafiken = require('./util/skanetrafiken');
const moment = require('moment');
const ip = require('ip');
const hue = require('./util/hue');

module.exports = (app, mirrorSocket) => {
  app.get('/api/brightness/:val', (req, res) => {
    console.log(req.params.val);
    if (req.params.cmd) serialHandler.writeString('brightness:' + req.params.val);
    res.json({
      success: true,
    });
  });

  app.get('/api/brightnessUp', (req, res) => {
    serialHandler.writeString('brightnessUp:');
    res.json({
      success: true,
    });
  });

  app.get('/api/brightnessDown', (req, res) => {
    serialHandler.writeString('brightnessDown:');
    res.json({
      success: true,
    });
  });

  app.get('/api/serial/:command', (req, res) => {
    let serialCommand, hour, min;
    let command = req.params.command;
    if (command.includes('time')) {
      serialCommand = command.split(':time=')[0];
      const hhmm = command.split(':time=')[1];
      hour = hhmm.split(':')[0];
      min = hhmm.split(':')[1];
      let now = moment(new Date());
      let future = moment(new Date())
        .hour(hour)
        .minute(min);
      let diff = future.diff(now);
      if (diff < 0) {
        future.add(1, 'day');
      }
      diff = future.diff(now);
      setTimeout(() => {
        serialHandler.writeString(serialCommand);
      }, diff);
    } else {
      serialHandler.writeString(req.params.command);
    }
    res.json({
      success: true,
    });
  });

  app.post('/api/serial', (req, res) => {
    if (req.body.mode) {
      serialHandler.writeString('mode:' + req.body.mode + ':' + req.body.speed);
    } else {
      const side = req.body.side;
      const rgb = req.body.rgb;
      if (side === 'all') {
        serialHandler.writeString('rgb:' + rgb.r + ':' + rgb.g + ':' + rgb.b);
      } else {
        serialHandler.writeString('side:' + side + ':' + rgb.r + ':' + rgb.g + ':' + rgb.b);
      }
    }
    res.json({
      success: true,
    });
  });

  app.get('/api/speak/:text', (req, res) => {
    if (req.params.text) speaker.speak(req.params.text);
    res.json({
      success: true,
    });
  });

  app.get('/api/hide', (req, res) => {
    mirrorSocket.sendToClient('visibility', { component: 'forecasts', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'news', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'article', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'tasks', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'weather', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'clock', visible: false });
    res.json({
      success: true,
    });
  });

  app.get('/api/hide/:component', (req, res) => {
    mirrorSocket.sendToClient('visibility', { component: req.params.component, visible: false });
    res.json({
      success: true,
    });
  });

  app.get('/api/show/:component', (req, res) => {
    mirrorSocket.sendToClient('visibility', { component: req.params.component, visible: true });
    res.json({
      success: true,
    });
  });

  app.get('/api/show', (req, res) => {
    mirrorSocket.sendToClient('visibility', { component: 'forecasts', visible: true });
    mirrorSocket.sendToClient('visibility', { component: 'news', visible: true });
    mirrorSocket.sendToClient('visibility', { component: 'article', visible: false });
    mirrorSocket.sendToClient('visibility', { component: 'tasks', visible: true });
    mirrorSocket.sendToClient('visibility', { component: 'weather', visible: true });
    mirrorSocket.sendToClient('visibility', { component: 'clock', visible: true });

    res.json({
      success: true,
    });
  });

  app.get('/api/tasks', (req, res) => {
    requestHelper.getTasks(tasks => {
      res.json({
        tasks: tasks,
      });
      return;
    });
  });

  app.get('/api/demo/:action', (req, res) => {
    if (req.params.action === 'dry') {
      requestHelper.logMoistureLevel(20);
      res.json({
        success: true,
      });
    } else if (req.params.action === 'water') {
      requestHelper.logMoistureLevel(95);
      res.json({
        success: true,
      });
    } else {
      res.json({
        success: false,
      });
    }
  });

  app.get('/api/moisture/latest', (req, res) => {
    requestHelper.getLatestMoistureLevel(moisture => {
      return res.json({
        moisture: moisture,
      });
    });
  });

  app.post('/api/tasks', (req, res) => {
    if (req.body.title) {
      requestHelper.createTask(req.body.title);
      res.json({
        success: true,
      });
    } else {
      res.json({
        success: false,
      });
    }
  });

  app.get('/api/articles', (req, res) => {
    articleExtractor.getArticles(articles => {
      res.json({
        articles,
      });
      return;
    });
  });

  app.get('/api/temperatures7days', (req, res) => {
    requestHelper.getTemperatures(temps => {
      res.json({
        temperatures: temps,
      });
      return;
    });
  });

  app.get('/api/temperatures7days/:source', (req, res) => {
    requestHelper.getTemperaturesFromSource(req.params.source, temps => {
      res.json({
        temperatures: temps,
      });
      return;
    });
  });

  app.get('/api/shutdown', (req, res) => {
    exec('sudo shutdown -h now');
    res.json({
      success: true,
    });
  });

  app.get('/api/sleep', (req, res) => {
    exec('sudo tvservice -o');
    res.json({
      success: true,
    });
  });

  app.get('/api/wakeup', (req, res) => {
    exec('sudo tvservice -p; sudo chvt 6; sudo chvt 7;');
    res.json({
      success: true,
    });
  });

  app.get('/api/reboot', (req, res) => {
    exec('sudo reboot');
  });

  app.get('/api/next', (req, res) => {
    mirrorSocket.sendToClient('command', { component: 'article', action: 'next' });
    res.json({
      success: true,
    });
  });

  app.get('/api/spotify/current', (req, res) => {
    requestHelper.getCurrentlyPlayingSpotify(playing => {
      if (!playing) return res.status(500).send({ error: 'Token to old, queries new. Please try again.' });
      res.json({
        currentPlaying: playing,
      });
    });
  });

  app.get('/api/forecast', (req, res) => {
    requestHelper.getForecast(forecast => {
      res.json({
        forecast: forecast,
      });
      return;
    });
  });

  app.get('/api/journey', (req, res) => {
    skanetrafiken
      .getJourneysUsingConfig()
      .then(results => {
        return res.json({
          routes: results,
        });
      })
      .catch(err => {
        res.json({ error: 'Could not featch bus/trains' });
      });
  });

  app.get('/api/localip', (req, res) => {
    res.json({
      success: true,
      ip: ip.address(),
    });
  });

  app.get('/api/localip', (req, res) => {
    res.json({
      success: true,
      ip: ip.address(),
    });
  });

  app.post('/api/hue', (req, res) => {
    if (!req.body.name || !req.body.options) {
      return res.json({
        success: false,
        message: 'Must specify hue light name and options'
      });
    }

    if (hue.light(req.body.name, req.body.options)) {
      return res.json({
        success: true,
      });
    } else {
      return res.json({
        success: false,
        message: 'Light not found. Hue bridge lights are refreshed every 10 min. Try again later or check the name.'
      });
    }
  });

};
<|endoftext|>


<commit_before>/**
 * sinter - routes.js
**/

/**
 * Modules dependencies.
**/
var site = require('./controllers/site');
var sign = require('./controllers/sign')
module.exports = function (app) {
	app.get('/', site.index);
	app.get('/index',site.index);
	app.post('/login',sign.login);
	app.post('/logout',sign.logout);
};<commit_msg>add savename<commit_after>/**
 * sinter - routes.js
**/

/**
 * Modules dependencies.
**/
var site = require('./controllers/site');
var sign = require('./controllers/sign')
module.exports = function (app) {
	app.get('/', site.index);
	app.get('/index',site.index);
	app.post('/login',sign.login);
	app.post('/logout',sign.logout);
	app.post('/saveName',sign.saveName);
};<|endoftext|>


<commit_before>let prepare = require('./utils/prepare');
let generateFramework = require('./generators/framework/generateFramework');
let generateTemplateEngine = require('./generators/template-engine/generateTemplateEngine');
let generateCssFramework = require('./generators/css-framework/generateCssFramework');
let generateCssPreprocessor = require('./generators/css-preprocessor/generateCssPreprocessor');
let generateCssBuildOptions = require('./generators/css-build-options/generateCssBuildOptions');
let generateDatabase = require('./generators/database/generateDatabase');
let generateAuthentication = require('./generators/authentication/generateAuthentication');
let generateJsFramework = require('./generators/js-framework/generateJsFramework');
//let cleanup = require('./utils/cleanup');
let walkAndRemoveComments = require('./utils/walkAndRemoveComments');

async function download(req, res) {
  let params = await prepare(req.body);
  try {
    await generateFramework(params);
    await generateTemplateEngine(params);
    await generateCssFramework(params);
    await generateCssPreprocessor(params);
    await generateCssBuildOptions(params);
    await generateDatabase(params);
    await generateAuthentication(params);
    await generateJsFramework(params);
    await walkAndRemoveComments(params);
  } catch (e) {
    throw Error(e);
  }
  res.end();
}

module.exports = {
  download: download
};
<commit_msg>ES6 import/expore routes<commit_after>import { prepare } from './generators/utils';

import generateFramework from './generators/framework/generateFramework';
import generateTemplateEngine from './generators/template-engine/generateTemplateEngine';
import generateCssFramework from './generators/css-framework/generateCssFramework';
import generateCssPreprocessor from './generators/css-preprocessor/generateCssPreprocessor';
import generateCssBuildOptions from './generators/css-build-options/generateCssBuildOptions';
import generateDatabase from './generators/database/generateDatabase';
import generateAuthentication from './generators/authentication/generateAuthentication';
import generateJsFramework from './generators/js-framework/generateJsFramework';
import { walkAndRemoveComments, cleanup } from './generators/utils';

export async function download(req, res) {
  let params = await prepare(req.body);
  try {
    await generateFramework(params);
    await generateTemplateEngine(params);
    await generateCssFramework(params);
    await generateCssPreprocessor(params);
    await generateCssBuildOptions(params);
    await generateDatabase(params);
    await generateAuthentication(params);
    await generateJsFramework(params);
    await walkAndRemoveComments(params);
  } catch (e) {
    throw Error(e);
  }
  res.end();
}<|endoftext|>


<commit_before>var fs = require('fs')
var haml = require('haml')
var clutch = require('clutch')
var querystring = require('querystring')
var models = require('./models')

db = process.db

if (!db.find('streamName', 'alerts')[0]) {
  new models.Stream('alerts')
}

var header = haml(fs.readFileSync('views/layouts/header.haml', 'utf8'))
var application = haml(fs.readFileSync('views/layouts/application.haml', 'utf8'))

function tails(req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'})
  res.end(header({ yield: application() }))
}

function favicon(req, res) {
  res.writeHead(200, {'Content-Type': 'image/gif'})
  res.end()
}

function getStatic(req, res, dir, file) {
  fs.readFile('./public/' + dir + '/' + file, function (err, data) {
    if (err) {
      res.writeHead(404, {'Content-Type': 'text/plain'})
    } else {
      switch (dir) {
        case 'scripts':
          res.writeHead(200, {'Content-Type': 'text/javascript'})
          break
        case 'stylesheets':
          res.writeHead(200, {'Content-Type': 'text/css'})
          break
        case 'images':
          res.writeHead(200, {'Content-Type': 'image/png'})
          break
        default:
          res.writeHead(200, {'Content-Type': 'text/html'})
      }
      res.write(data)
    }
    res.end()
  })
}

function createStream(req, res) {
  var requestString = ''
  req.on('data', function(chunk) {
    requestString += chunk
  })
  req.on('end', function() {
    var name = querystring.parse(requestString).name
    if (name) {
      var stream = db.find('streamName', name).pop()
      if (!stream || stream.streamEnabled == false) {
        new models.Stream(name)
        res.writeHead(201, {'Content-Type': 'text/plain'})
        res.write(name)
      } else {
        res.writeHead(409, 'Stream already exists', {'Content-Type': 'text/plain'})
      }
    } else {
      res.writeHead(400, 'Missing field - name', {'Content-Type': 'text/plain'})
    }
    res.end()
  })
}

function getStreams(req, res) {
  var streams = db.find('streamEnabled', true)
  var result = {}
  for (var i in streams) {
    var stream = streams[i]
    result[stream.streamName] = {
      name: stream.streamName,
      terms: stream.streamTerms,
      forwarding: {
        enabled: stream.streamForwarding,
        token: stream.streamLogglyToken
      }
    }
  }
  res.writeHead(200, {'Content-Type': 'application/json'})
  res.end(JSON.stringify(result))
}

function removeStream(req, res, name) {
  var stream = db.find('streamName', name).pop()
  if (stream && stream.streamEnabled == true) {
    stream.disable()
    res.writeHead(204)
  } else {
    res.writeHead(404, 'Stream does not exist', {'Content-Type': 'text/plain'})
  }
  res.end()
}

function createTerm(req, res, name) {
  var requestString = ''
  req.on('data', function(chunk) {
    requestString += chunk
  })
  req.on('end', function() {
    var term = querystring.parse(requestString).term
    if (term) {
      var stream = db.find('streamName', name).pop()
      if (stream) {
        if (stream.streamTerms.indexOf(term) == -1) {
          stream.createTerm(term)
          res.writeHead(201, {'Content-Type': 'text/plain'})
	} else {
          res.writeHead(409, 'Term already exists', {'Content-Type': 'text/plain'})
	}
      } else {
        res.writeHead(404, 'Stream does not exist', {'Content-Type': 'text/plain'})
      }
    } else {
      res.writeHead(400, 'Missing field - term', {'Content-Type': 'text/plain'})
    }
    res.end()
  })
}

function removeTerm(req, res, name, term) {
  var stream = db.find('streamName', name).pop()
  if (stream) {
    stream.removeTerm(term)
    res.writeHead(204)
  } else {
    res.writeHead(404, 'Stream does not exist', {'Content-Type': 'text/plain'})
  }
  res.end()
}

function toggleForwarding(req, res, name) {
  var requestString = ''
  req.on('data', function(chunk) {
    requestString += chunk
  })
  req.on('end', function() {
    var token = querystring.parse(requestString).token
    var stream = db.find('streamName', name).pop()
    if (stream) {
      if (token) {
        stream.toggleForwarding(token)
        res.writeHead(200, {'Content-Type': 'text/plain'})
        res.write(stream.streamForwarding.toString())
      } else {
        res.writeHead(400, 'Missing field - token', {'Content-Type': 'text/plain'})
      }
    } else {
      res.writeHead(404, 'Stream does not exist', {'Content-Type': 'text/plain'})
    }
    res.end()
  })
}

exports.urls = clutch.route404([['GET /$', tails],
				['GET /favicon.ico', favicon],
				['POST /streams$', createStream],
				['POST /streams/(.*)/terms$', createTerm],
				['POST /streams/(.*)/forwarding$', toggleForwarding],
				['GET /streams$', getStreams],
				['DELETE /streams/(.*)/terms/(.*)$', removeTerm],
				['DELETE /streams/(.*)$', removeStream],
				['GET /(.*)/(.*)$', getStatic]])
<commit_msg>clean up repo<commit_after><|endoftext|>


<commit_before>/**
 * rowcol - a library for row-column data manipulation
 * @module rowcol
 * @author Samuel Rouse <samuel.rouse@gmail.com>
 * @license MIT http://opensource.org/licenses/MIT
 */

(function() {
    "use strict";

    /*--------------------------------------------------------------------------*/
    /*
     * Constants and basic settings
     * Structure and code from Lo-Dash 2.4.1 <http://lodash.com/>
     */

    var version = "0.2.5";

    /** Used to determine if values are of the language type Object */
    var objectTypes = {
        'function': true,
        'object': true
    };

    /** Used as a reference to the global object */
    var root = (objectTypes[typeof window] && window) || this;

    /** Detect free variable `exports` */
    var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;

    /** Detect free variable `module` */
    var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;

	/** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
	var freeGlobal = freeExports && freeModule && typeof global === 'object' && global;
	if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
		root = freeGlobal;
	}

    /** Detect the popular CommonJS extension `module.exports` */
    var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;

    /*--------------------------------------------------------------------------*/

    /* Functions */

    /**
     * Indicates if the passed object is an array
     * @param {*} obj
     * @returns {boolean}
     */
    function isArray(obj){
        return Object.prototype.toString.call(obj) === '[object Array]';
    }

    /**
     * Returns an array of indexes that match a filter string or function.
     * @param {Array} array Array of values to match
     * @param {Function|String} filter Function or String to match array values.
     * @returns {Array} Array of indexes that match the filter.
     */
	function getIndexes (array, filter) {
		var indexes = [],
			len = array.length,
			i;

		if (typeof filter === 'function') {
			for (i = 0; i < len; i++) {
				if ( filter(i, array[i]) ) {
					indexes.push(i);
				}
			}
		} else {
			for (i = 0; i < len; i++) {
				if ( array[i] === filter ) {
					indexes.push(i);
				}
			}
		}
		return indexes;
	}

    /**
     * Returns the elements of an array using a list of selected indexes.
     * @param {Array} array
     * @param {Array} indexes
     * @returns {Array}
     */
    function getByIndexes (array, indexes) {
        var len = indexes.length,
            data = [];

        for (;len;) {
            data[len] = array[indexes[--len]];
        }
        return data;
    }

    /**
     * Performs the rotation for an unlimited (regular) rotation
     * @param {Array} arr
     * @param {Object} result
     * @returns {Object}
     */
    function arrayRotateUnlimited (arr, result) {
        var obj, att, i = arr.length;

        for (;i;) {
            obj = arr[--i];

            // All variables submit to for-in loops
            for (att in obj) {
                if ( obj.hasOwnProperty(att) ) {
                    if ( result[att] === undefined ) {
                        result[att] = [];
                    }
                    result[att][i] = obj[att];
                }
            }
        }

        return result;
    }

    /**
     * Performs the rotation for a limited (partial) rotation
     * @param {Array} arr
     * @param {Object} result
     * @param {Array|boolean} limited
     * @returns {Object}
     */
    function arrayRotateLimited (arr, result, limited) {
        var objKeys, keyLen, obj, att, i, j;

        // Is limited the list of keys?
        if (isArray(limited)) {
            objKeys = limited;
        } else {
            // Get the keys for limited rotate
            objKeys = Object.keys(result);
        }

        keyLen = objKeys.length;

        // One pass to create any missing arrays
        for (att in objKeys) {
            if (!isArray(result[att])) {
                result[att] = [];
            }
        }

        i = arr.length;

        for (;i;) {
            obj = arr[--i];

            // All variables submit to for-in loops
            // JSHint hates it, but Object.keys
            for (j = 0; j < keyLen; j++) {

                att = objKeys[j];
                result[att][i] = obj[att];
            }

        }

        return result;
    }

    /**
     * Rotate an array of row-data into a column-data object
     * @param {Array} arr
     * @param {Object} [result] Result object to use
     * @param {boolean} [limited] Only update keys passed on the result object, allowing a limited rotation
     * @returns {Object}
     */
    function arrayRotate (arr, result, limited) {

        // Not an array? Send it back.
        if ( !isArray(arr) ) {
            throw new TypeError("RC: Argument is not an array");
        }

        if ( !result || typeof result !== 'object' ) {
            if ( limited ) {
                throw new TypeError("RC: Must pass a result object when 'limited' is true");
            } else {
                result = {};
            }
        }

        // Explicit check: you could pass [0], limited could be falsy.
        if (limited !== undefined && limited !== false) {
            return arrayRotateLimited(arr, result, limited);

        }

        return arrayRotateUnlimited(arr, result);
    }

    /**
     * Filter a column-data object for a particular field.
     * @param {Object} obj
     * @param {String} field
     * @param {Function|String} filter
     * @returns {*}
     */
    function objectFilter (obj, field, filter) {
        return filterMerge(obj, filterIndexes(obj, field, filter));
    }

    /**
     *
     * @param obj
     * @param field
     * @param filter
     * @returns {Array}
     */
    function filterIndexes (obj, field, filter) {
        var indexes = [];

        if ( obj.hasOwnProperty(field) ) {
            indexes = getIndexes(obj[field], filter);
        }
        return indexes;
    }

    /**
     * Filters all properties in a column-data object using an array of indexes.
     * @param {Object} obj
     * @param {Array} indexes
     * @returns {Object}
     */
    function filterMerge(obj, indexes) {
        var result = {},
            att;

        // Don't waste time if tehre are no indexes to merge.
        if (indexes === undefined || !indexes.length) {
            return result;
        }

        for (att in obj) {
            if ( obj.hasOwnProperty(att) ) {
                result[att] = getByIndexes(obj[att], indexes);
            }
        }
        return result;
    }

    /**
     * Finds the longest length of any property in a column-data object.
     * @param {Object} obj
     * @returns {number}
     */
    function objectLength (obj) {
        var att, len = 0;

        // Get the longest length of all properties
        for (att in obj) {
            if ( obj.hasOwnProperty(att) ) {
                len = Math.max(len, obj[att].length);
            }
        }

        return len;
    }

    /**
     * Rotates column-data to row-data and optionally adds it to an existing array.
     * @param {Object} obj
     * @param {Array} [result] Optional array init which we should place rotated data.
     * @param {Boolean} [clearUndef]
     * @returns {Array}
     */
    function objectRotate (obj, result, clearUndef) {
        var att, i, resultIndex, len, resultOffset;

        // Not an array? Send it back.
        if ( typeof obj !== 'object' ) {
            throw new TypeError("RC: Argument is not an object");
        }

        if ( result === undefined ) {
            result = [];
        } else if ( !isArray(result) ) {
            throw new TypeError("RC: Result argument is not an array");
        }

        // Get the existing result array length
        resultOffset = result.length;

        len = objectLength(obj);

        for (i = 0; i < len; i++) {
            resultIndex = i + resultOffset;
            result[resultIndex] = {};

            /** Because of resultOffset, there is no way for the error condition to execute
            if ( result[resultIndex] === undefined ) {
                result[resultIndex] = {};
            } else if ( typeof result[resultIndex] !== 'object' ) {
                throw new TypeError("RC: Result contains incorrect type at index " + i);
            }
             **/

            for (att in obj) {
                if ( obj.hasOwnProperty(att) && ( !clearUndef || obj[att][i] !== undefined ) ) {
                    result[resultIndex][att] = obj[att][i];
                }
            }
        }

        return result;
    }

    /**
     * Create a
     * @param {Object} obj
     * @param {number} index
     * @param {Boolean} [clearUndef]
     * @param {Object} [result]
     * @returns {*}
     */
    function objFromIndex (obj, index, clearUndef, result) {
        var att;

        // Check for a passed result object, used by Proxy/objFromIndex
        if ( result === undefined ) {
            result = {};
        }

        for ( att in obj ) {
            if ( obj.hasOwnProperty(att) && ( !clearUndef || obj[att][index] !== undefined ) ) {
                result[att] = obj[att][index];
            }
        }

        return result;
    }

    /**
     * Create a proxy
     * @param obj
     * @param index
     * @param clearUndef
     */
    function proxyFromIndex (obj, index, clearUndef) {
        return new Proxy(obj, index, clearUndef);
    }

    /**
     * A generic rotate function that accepts row or column data to rotate.
     * @param {Object|Array} obj
     * @returns {Array|Object}
     */
    function rotate(obj) {
        // Generic, which directs to the appropriate array/object rotate
        if (typeof obj !== 'object') throw new TypeError("RC: rotate requires an object or an array");

        if ( isArray(obj) ) {
            return arrayRotate.apply(null, arguments);
        } else {
            return objectRotate.apply(null, arguments);
        }
    }

    /**
     * Increment over column-data like it was array data, making a "read-only" object for each index.
     * Does not prevent modification of values with complex data types (objects, arrays).
     * @param {Object} obj
     * @param {Function} fn
     */
    function readEach(obj, fn) {
        var len = objectLength(obj),
            i = 0;

        for (;i<len;i++) {
            fn(objFromIndex(obj, i));
        }
    }

    /**
     * Increment over column-data like it was array data, making a proxy object for each index.
	 * @param {Object} obj
     * @param {Function} fn
     */
    function objEach(obj, fn) {
        var len = objectLength(obj),
            i = 0,
            prox;

        for (;i<len;i++) {
            prox = new Proxy(obj, i);

            fn(prox, i);

            prox.finalize();
        }
    }

    /**
     * Create an object and add a .commit() prototype to place the values back into the original.
     * Useful for moving simple data types around. Objects and arrays will be automatically referenced.
     * @constructor
     * @param {Object} obj - A columnar object
     * @param {number} index - The index to convert into a row-based object
     * @param {Boolean} [clearUndef] - Clear undefined attributes when copying the object.
     * @example
     * var proxyRow = new Proxy(colData, index);
     */
    var Proxy = (function() {
        var __obj = [],
            __idx = [],
            __clr = [],
            __this = [],
            guid = 0;

        /**
         * Uses a private array to locate the same object, so the proxy doesn't expose itself to modification.
         * We compare the passed object against an array of existing Proxy objects; basically pointer comparison.
         * @param {Proxy} proxy
         * @returns {number} The proxy ID to allow commit and destroy to locate the correct element
         * @private
         */
        function __getId(proxy) {
            var i = __this.length, pid;

            // Most likely to be at the end, so start there
            for (;i;) {
                i--;
                if (__this[i] === proxy) {
                    pid = i;
                    break;
                }
            }

            if (pid === undefined) {
                throw new ReferenceError("Proxy is finalized and cannot be used again.");
            }
            return pid;
        }

        /**
         * The actual Proxy constructor.
         * @param {Object} obj
         * @param {number} index
         * @param {Boolean} [clearUndef]
         * @constructor
         */
        function Proxy (obj, index, clearUndef) {

            // Increment the guid
            ++guid;

            // Set the private data.
            __obj[guid] = obj;
            __idx[guid] = index;
            __clr[guid] = clearUndef;
            __this[guid] = this;

            // Call reusable code for objFromIndex
            objFromIndex(obj, index, clearUndef, this);
        }

        // Defined inside the constructor to give it access to the originating object and parameters

        /**
         * Commits the changes from the proxy to the original.
         */
        Proxy.prototype.commit = function(){
            var pid = __getId(this),
                obj = __obj[pid],
                index = __idx[pid],
                clearUndef = __clr[pid],
                att;

            for ( att in this ) {
                if ( att !== '__rcProxyId' && this.hasOwnProperty(att) && ( !clearUndef || this[att] !== undefined ) ) {
                    obj[att][index] = this[att];
                }
            }
        };

        /**
         * Removes the proxy to prevent memory leaks
         */
        Proxy.prototype.destroy = function() {
            var pid = __getId(this);
            delete __this[pid];
            delete __obj[pid];
            delete __idx[pid];
            delete __clr[pid];
        };

        /**
         * Commit and destroy the proxy, as a single step
         */
		Proxy.prototype.finalize = function() {
			this.commit();
			this.destroy();
		};

		return Proxy;
	}());

	/*--------------------------------------------------------------------------*/

	var rowcol = {
		rotate: rotate,
		proxy: proxyFromIndex,
		array: {
			getIndexes: getIndexes,
			getByIndexes: getByIndexes,
			rotate: arrayRotate
		},
		object: {
			filter: objectFilter,
			filterIndexes: filterIndexes,
			filterMerge: filterMerge,
			rotate: objectRotate,
			objFromIndex: objFromIndex,
			proxy: proxyFromIndex,
			readEach: readEach,
			each: objEach,
			objLength: objectLength
		},
		VERSION: version,
        test: {
            isArray: isArray
        }
	};

	/*--------------------------------------------------------------------------*/

	// some AMD build optimizers like r.js check for condition patterns like the following:
	if (typeof define === 'function' && define.amd && typeof define.amd === 'object') {
	  // Expose to the global object even when an AMD loader is present in
	  // case RowCol is loaded with a RequireJS shim config.
	  // See http://requirejs.org/docs/api.html#config-shim
	  root.rowcol = rowcol;

	  // define as an anonymous module so, through path mapping, it can be
	  // referenced as the "underscore" module
	  define(function() {
		return rowcol;
	  });
	}
	// check for `exports` after `define` in case a build optimizer adds an `exports` object
	else if (freeExports && freeModule) {
	  // in Node.js or RingoJS
	  if (moduleExports) {
		(freeModule.exports = rowcol).rowcol = rowcol;
	  }
	  // in Narwhal or Rhino -require
	  else {
		freeExports.rowcol = rowcol;
	  }
	}
	else {
	  // in a browser or Rhino
	  root.rowcol = rowcol;
	}

}());
<commit_msg>Fix getByIndexes<commit_after>/**
 * rowcol - a library for row-column data manipulation
 * @module rowcol
 * @author Samuel Rouse <samuel.rouse@gmail.com>
 * @license MIT http://opensource.org/licenses/MIT
 */

(function() {
    "use strict";

    /*--------------------------------------------------------------------------*/
    /*
     * Constants and basic settings
     * Structure and code from Lo-Dash 2.4.1 <http://lodash.com/>
     */

    var version = "0.2.5";

    /** Used to determine if values are of the language type Object */
    var objectTypes = {
        'function': true,
        'object': true
    };

    /** Used as a reference to the global object */
    var root = (objectTypes[typeof window] && window) || this;

    /** Detect free variable `exports` */
    var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;

    /** Detect free variable `module` */
    var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;

	/** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
	var freeGlobal = freeExports && freeModule && typeof global === 'object' && global;
	if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
		root = freeGlobal;
	}

    /** Detect the popular CommonJS extension `module.exports` */
    var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;

    /*--------------------------------------------------------------------------*/

    /* Functions */

    /**
     * Indicates if the passed object is an array
     * @param {*} obj
     * @returns {boolean}
     */
    function isArray(obj){
        return Object.prototype.toString.call(obj) === '[object Array]';
    }

    /**
     * Returns an array of indexes that match a filter string or function.
     * @param {Array} array Array of values to match
     * @param {Function|String} filter Function or String to match array values.
     * @returns {Array} Array of indexes that match the filter.
     */
	function getIndexes (array, filter) {
		var indexes = [],
			len = array.length,
			i;

		if (typeof filter === 'function') {
			for (i = 0; i < len; i++) {
				if ( filter(i, array[i]) ) {
					indexes.push(i);
				}
			}
		} else {
			for (i = 0; i < len; i++) {
				if ( array[i] === filter ) {
					indexes.push(i);
				}
			}
		}
		return indexes;
	}

    /**
     * Returns the elements of an array using a list of selected indexes.
     * @param {Array} array
     * @param {Array} indexes
     * @returns {Array}
     */
    function getByIndexes (array, indexes) {
        var i,
            len = indexes.length,
            data = [];

        for (i = 0; i < len; i++) {
            data.push(array[indexes[i]]);
        }
        return data;
    }

    /**
     * Performs the rotation for an unlimited (regular) rotation
     * @param {Array} arr
     * @param {Object} result
     * @returns {Object}
     */
    function arrayRotateUnlimited (arr, result) {
        var obj, att, i = arr.length;

        for (;i;) {
            obj = arr[--i];

            // All variables submit to for-in loops
            for (att in obj) {
                if ( obj.hasOwnProperty(att) ) {
                    if ( result[att] === undefined ) {
                        result[att] = [];
                    }
                    result[att][i] = obj[att];
                }
            }
        }

        return result;
    }

    /**
     * Performs the rotation for a limited (partial) rotation
     * @param {Array} arr
     * @param {Object} result
     * @param {Array|boolean} limited
     * @returns {Object}
     */
    function arrayRotateLimited (arr, result, limited) {
        var objKeys, keyLen, obj, att, i, j;

        // Is limited the list of keys?
        if (isArray(limited)) {
            objKeys = limited;
        } else {
            // Get the keys for limited rotate
            objKeys = Object.keys(result);
        }

        keyLen = objKeys.length;

        // One pass to create any missing arrays
        for (att in objKeys) {
            if (!isArray(result[att])) {
                result[att] = [];
            }
        }

        i = arr.length;

        for (;i;) {
            obj = arr[--i];

            // All variables submit to for-in loops
            // JSHint hates it, but Object.keys
            for (j = 0; j < keyLen; j++) {

                att = objKeys[j];
                result[att][i] = obj[att];
            }

        }

        return result;
    }

    /**
     * Rotate an array of row-data into a column-data object
     * @param {Array} arr
     * @param {Object} [result] Result object to use
     * @param {boolean} [limited] Only update keys passed on the result object, allowing a limited rotation
     * @returns {Object}
     */
    function arrayRotate (arr, result, limited) {

        // Not an array? Send it back.
        if ( !isArray(arr) ) {
            throw new TypeError("RC: Argument is not an array");
        }

        if ( !result || typeof result !== 'object' ) {
            if ( limited ) {
                throw new TypeError("RC: Must pass a result object when 'limited' is true");
            } else {
                result = {};
            }
        }

        // Explicit check: you could pass [0], limited could be falsy.
        if (limited !== undefined && limited !== false) {
            return arrayRotateLimited(arr, result, limited);

        }

        return arrayRotateUnlimited(arr, result);
    }

    /**
     * Filter a column-data object for a particular field.
     * @param {Object} obj
     * @param {String} field
     * @param {Function|String} filter
     * @returns {*}
     */
    function objectFilter (obj, field, filter) {
        return filterMerge(obj, filterIndexes(obj, field, filter));
    }

    /**
     *
     * @param obj
     * @param field
     * @param filter
     * @returns {Array}
     */
    function filterIndexes (obj, field, filter) {
        var indexes = [];

        if ( obj.hasOwnProperty(field) ) {
            indexes = getIndexes(obj[field], filter);
        }
        return indexes;
    }

    /**
     * Filters all properties in a column-data object using an array of indexes.
     * @param {Object} obj
     * @param {Array} indexes
     * @returns {Object}
     */
    function filterMerge(obj, indexes) {
        var result = {},
            att;

        // Don't waste time if tehre are no indexes to merge.
        if (indexes === undefined || !indexes.length) {
            return result;
        }

        for (att in obj) {
            if ( obj.hasOwnProperty(att) ) {
                result[att] = getByIndexes(obj[att], indexes);
            }
        }
        return result;
    }

    /**
     * Finds the longest length of any property in a column-data object.
     * @param {Object} obj
     * @returns {number}
     */
    function objectLength (obj) {
        var att, len = 0;

        // Get the longest length of all properties
        for (att in obj) {
            if ( obj.hasOwnProperty(att) ) {
                len = Math.max(len, obj[att].length);
            }
        }

        return len;
    }

    /**
     * Rotates column-data to row-data and optionally adds it to an existing array.
     * @param {Object} obj
     * @param {Array} [result] Optional array init which we should place rotated data.
     * @param {Boolean} [clearUndef]
     * @returns {Array}
     */
    function objectRotate (obj, result, clearUndef) {
        var att, i, resultIndex, len, resultOffset;

        // Not an array? Send it back.
        if ( typeof obj !== 'object' ) {
            throw new TypeError("RC: Argument is not an object");
        }

        if ( result === undefined ) {
            result = [];
        } else if ( !isArray(result) ) {
            throw new TypeError("RC: Result argument is not an array");
        }

        // Get the existing result array length
        resultOffset = result.length;

        len = objectLength(obj);

        for (i = 0; i < len; i++) {
            resultIndex = i + resultOffset;
            result[resultIndex] = {};

            /** Because of resultOffset, there is no way for the error condition to execute
            if ( result[resultIndex] === undefined ) {
                result[resultIndex] = {};
            } else if ( typeof result[resultIndex] !== 'object' ) {
                throw new TypeError("RC: Result contains incorrect type at index " + i);
            }
             **/

            for (att in obj) {
                if ( obj.hasOwnProperty(att) && ( !clearUndef || obj[att][i] !== undefined ) ) {
                    result[resultIndex][att] = obj[att][i];
                }
            }
        }

        return result;
    }

    /**
     * Create a
     * @param {Object} obj
     * @param {number} index
     * @param {Boolean} [clearUndef]
     * @param {Object} [result]
     * @returns {*}
     */
    function objFromIndex (obj, index, clearUndef, result) {
        var att;

        // Check for a passed result object, used by Proxy/objFromIndex
        if ( result === undefined ) {
            result = {};
        }

        for ( att in obj ) {
            if ( obj.hasOwnProperty(att) && ( !clearUndef || obj[att][index] !== undefined ) ) {
                result[att] = obj[att][index];
            }
        }

        return result;
    }

    /**
     * Create a proxy
     * @param obj
     * @param index
     * @param clearUndef
     */
    function proxyFromIndex (obj, index, clearUndef) {
        return new Proxy(obj, index, clearUndef);
    }

    /**
     * A generic rotate function that accepts row or column data to rotate.
     * @param {Object|Array} obj
     * @returns {Array|Object}
     */
    function rotate(obj) {
        // Generic, which directs to the appropriate array/object rotate
        if (typeof obj !== 'object') throw new TypeError("RC: rotate requires an object or an array");

        if ( isArray(obj) ) {
            return arrayRotate.apply(null, arguments);
        } else {
            return objectRotate.apply(null, arguments);
        }
    }

    /**
     * Increment over column-data like it was array data, making a "read-only" object for each index.
     * Does not prevent modification of values with complex data types (objects, arrays).
     * @param {Object} obj
     * @param {Function} fn
     */
    function readEach(obj, fn) {
        var len = objectLength(obj),
            i = 0;

        for (;i<len;i++) {
            fn(objFromIndex(obj, i));
        }
    }

    /**
     * Increment over column-data like it was array data, making a proxy object for each index.
	 * @param {Object} obj
     * @param {Function} fn
     */
    function objEach(obj, fn) {
        var len = objectLength(obj),
            i = 0,
            prox;

        for (;i<len;i++) {
            prox = new Proxy(obj, i);

            fn(prox, i);

            prox.finalize();
        }
    }

    /**
     * Create an object and add a .commit() prototype to place the values back into the original.
     * Useful for moving simple data types around. Objects and arrays will be automatically referenced.
     * @constructor
     * @param {Object} obj - A columnar object
     * @param {number} index - The index to convert into a row-based object
     * @param {Boolean} [clearUndef] - Clear undefined attributes when copying the object.
     * @example
     * var proxyRow = new Proxy(colData, index);
     */
    var Proxy = (function() {
        var __obj = [],
            __idx = [],
            __clr = [],
            __this = [],
            guid = 0;

        /**
         * Uses a private array to locate the same object, so the proxy doesn't expose itself to modification.
         * We compare the passed object against an array of existing Proxy objects; basically pointer comparison.
         * @param {Proxy} proxy
         * @returns {number} The proxy ID to allow commit and destroy to locate the correct element
         * @private
         */
        function __getId(proxy) {
            var i = __this.length, pid;

            // Most likely to be at the end, so start there
            for (;i;) {
                i--;
                if (__this[i] === proxy) {
                    pid = i;
                    break;
                }
            }

            if (pid === undefined) {
                throw new ReferenceError("Proxy is finalized and cannot be used again.");
            }
            return pid;
        }

        /**
         * The actual Proxy constructor.
         * @param {Object} obj
         * @param {number} index
         * @param {Boolean} [clearUndef]
         * @constructor
         */
        function Proxy (obj, index, clearUndef) {

            // Increment the guid
            ++guid;

            // Set the private data.
            __obj[guid] = obj;
            __idx[guid] = index;
            __clr[guid] = clearUndef;
            __this[guid] = this;

            // Call reusable code for objFromIndex
            objFromIndex(obj, index, clearUndef, this);
        }

        // Defined inside the constructor to give it access to the originating object and parameters

        /**
         * Commits the changes from the proxy to the original.
         */
        Proxy.prototype.commit = function(){
            var pid = __getId(this),
                obj = __obj[pid],
                index = __idx[pid],
                clearUndef = __clr[pid],
                att;

            for ( att in this ) {
                if ( att !== '__rcProxyId' && this.hasOwnProperty(att) && ( !clearUndef || this[att] !== undefined ) ) {
                    obj[att][index] = this[att];
                }
            }
        };

        /**
         * Removes the proxy to prevent memory leaks
         */
        Proxy.prototype.destroy = function() {
            var pid = __getId(this);
            delete __this[pid];
            delete __obj[pid];
            delete __idx[pid];
            delete __clr[pid];
        };

        /**
         * Commit and destroy the proxy, as a single step
         */
		Proxy.prototype.finalize = function() {
			this.commit();
			this.destroy();
		};

		return Proxy;
	}());

	/*--------------------------------------------------------------------------*/

	var rowcol = {
		rotate: rotate,
		proxy: proxyFromIndex,
		array: {
			getIndexes: getIndexes,
			getByIndexes: getByIndexes,
			rotate: arrayRotate
		},
		object: {
			filter: objectFilter,
			filterIndexes: filterIndexes,
			filterMerge: filterMerge,
			rotate: objectRotate,
			objFromIndex: objFromIndex,
			proxy: proxyFromIndex,
			readEach: readEach,
			each: objEach,
			objLength: objectLength
		},
		VERSION: version,
        test: {
            isArray: isArray
        }
	};

	/*--------------------------------------------------------------------------*/

	// some AMD build optimizers like r.js check for condition patterns like the following:
	if (typeof define === 'function' && define.amd && typeof define.amd === 'object') {
	  // Expose to the global object even when an AMD loader is present in
	  // case RowCol is loaded with a RequireJS shim config.
	  // See http://requirejs.org/docs/api.html#config-shim
	  root.rowcol = rowcol;

	  // define as an anonymous module so, through path mapping, it can be
	  // referenced as the "underscore" module
	  define(function() {
		return rowcol;
	  });
	}
	// check for `exports` after `define` in case a build optimizer adds an `exports` object
	else if (freeExports && freeModule) {
	  // in Node.js or RingoJS
	  if (moduleExports) {
		(freeModule.exports = rowcol).rowcol = rowcol;
	  }
	  // in Narwhal or Rhino -require
	  else {
		freeExports.rowcol = rowcol;
	  }
	}
	else {
	  // in a browser or Rhino
	  root.rowcol = rowcol;
	}

}());
<|endoftext|>