<commit_before>require('rootpath')();
var INPUTS_BIN_PATH = "/home/view/current/bin/inputs";
var GESTURE_BIN_PATH = "/home/view/current/bin/gesture";
var EventEmitter = require("events").EventEmitter;
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var Button = require('gpio-button');
var GestureLib = require('apds-gesture');
var db = require("system/db.js");

var inputs = new EventEmitter();

var gesture = GestureLib.use(2); //i2c port 2

gesture.debug = true;

gesture.on('ready', function() {
    console.log("INPUTS: found a gesture sensor");
});

gesture.on('error', function(err) {
    console.log("INPUTS: Gesture Error: ", err);
});

var inputsProcess = null;
var inputsRunning = false;
var gestureProcess = null;
var gestureRunning = false;

var stop = false;
var stopGesture = false;

var HOLD_TIME = 1500;

var powerButton = {
    platformEvent: "1c2ac00.i2c-platform-axp20x-pek",
    116: {
        name: "power",
        pressed: 5,
        held: 6
    }
}
var buttons = {
    platformEvent: "button-knob",
    1: {
        name: "back",
        pressed: 1,
        held: 1+6
    },
    2: {
        name: "enter",
        pressed: 2,
        held: 2+6
    },
    3: {
        name: "menu",
        pressed: 3,
        held: 3+6
    },
    4: {
        name: "knob",
        pressed: 4,
        held: 4+6
    }
};

setupButton(powerButton);
setupButton(buttons);

function setupButton(buttonConfig) {
    buttonConfig._button = new Button(buttonConfig.platformEvent);

    buttonConfig._btnPowerPressedTimer = null;
    buttonConfig._button.on('press', function(code) {
        if(code && buttonConfig[code]) {
            //console.log("button", buttonConfig[code].name, "pressed");
            buttonConfig[code]._pressed = true;
            inputs.emit('B', buttonConfig[code].pressed);
            if(buttonConfig[code]._btnPowerPressedTimer != null) clearTimeout(buttonConfig[code]._btnPowerPressedTimer);
            buttonConfig[code]._btnPowerPressedTimer = setTimeout(function(){
                inputs.emit('B', buttonConfig[code].held);
            }, HOLD_TIME);
        }
    });

    buttonConfig._button.on('release', function(code) {
        if(code && buttonConfig[code]) {
            //console.log("button", buttonConfig[code].name, "released");
            buttonConfig[code]._pressed = false;
            if(buttonConfig[code]._btnPowerPressedTimer != null) clearTimeout(buttonConfig[code]._btnPowerPressedTimer);
        }
    });

    buttonConfig._button.on('error', function(err) {
        console.log("button error: ", buttonConfig.name, err);
    });
}

exec("killall gesture");
exec("killall inputs");
var options = {};
var mcuSetup = false;
inputs.start = function(knobOptions) {
    options = knobOptions;
    if(knobOptions.knob) {
        stop = false;
        if(inputsRunning) return;
        inputsProcess = spawn(INPUTS_BIN_PATH);
        inputsRunning = true;
        console.log("inputs process started");
        inputsProcess.stdout.on('data', function(chunk) {
            //console.log("inputs stdin: " + chunk.toString());
            var matches = chunk.toString().match(/([A-Z])=([A-Z0-9\-]+)/);
            if (matches && matches.length > 1) {
                if(matches[1] == 'D') {
                    var dir = matches[2];
                    if(buttons['4']._pressed) dir += "+";
                    inputs.emit('D', dir);
                }
            }
        });
        inputsProcess.stderr.on('data', function(chunk) {
            console.log("inputs stderr: " + chunk.toString());
            chunk = null;
        });
        inputsProcess.on('close', function(code) {
            console.log("inputs process exited");
            inputsRunning = false;
            if (!stop) {
                setTimeout(function() {
                    if(!stop) inputs.start();
                }, 500);
            }
        });
    } else if(options.mcu) {
        if(mcuSetup) return;
        mcuSetup = true;
        options.mcu.on('knob', function(val) {
            k = 'U';
            if(val < 0) {
                k = 'D';
            }
            if(buttons['4']._pressed) k += "+";
            inputs.emit('D', k);
        });
    }
}

inputs.startGesture = function() {
    inputs.gestureStatus = "enabled";
    db.get('gestureCalibration', function(err, gestureCalibration) {
        gesture.setup(gestureCalibration, function(){
            gesture.start();
        });
    });
}
inputs.calibrateGesture = function(statusCallback) {
    gesture.calibrate(function(err, status, calResults) {
        if(calResults) {
            db.set('gestureCalibration', calResults);
            gesture.start();
        } else if(err) {
            console.log("INPUTS: error calibrating gesture: ", err);
        }
        statusCallback && statusCallback(err, status, (calResults || err) ? true : false);
    });
}

gesture.on('movement', function(dir) {
    inputs.emit('G', dir.substr(0, 1).toUpperCase());
});

inputs.stop = function(callback) {
    process.nextTick(function(){
        stop = true;
        stopGesture = true;
        if (inputsRunning) {
            console.log("inputs process exiting...");
            try {
                inputsProcess.stdin.write('\n\n\n');
                inputsProcess.stdin.end();
            } catch (e) {
                console.log("input close error: ", e);
                setTimeout(function(){
                    inputsProcess.kill();
                }, 1000);
            }
        }
        inputs.stopGesture();
        if(callback) setTimeout(callback, 100); // give time for processes to exit
    });
}

inputs.stopGesture = function() {
    inputs.gestureStatus = "disabled";
    gesture.stop();
    gesture.disable();
}

module.exports = inputs;<commit_msg>add db for cal gesture cal save<commit_after>require('rootpath')();
var INPUTS_BIN_PATH = "/home/view/current/bin/inputs";
var GESTURE_BIN_PATH = "/home/view/current/bin/gesture";
var EventEmitter = require("events").EventEmitter;
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var Button = require('gpio-button');
var GestureLib = require('apds-gesture');
var db = require("system/db.js");

var inputs = new EventEmitter();

var gesture = GestureLib.use(2); //i2c port 2

gesture.debug = true;

gesture.on('ready', function() {
    console.log("INPUTS: found a gesture sensor");
});

gesture.on('error', function(err) {
    console.log("INPUTS: Gesture Error: ", err);
});

var inputsProcess = null;
var inputsRunning = false;
var gestureProcess = null;
var gestureRunning = false;

var stop = false;
var stopGesture = false;

var HOLD_TIME = 1500;

var powerButton = {
    platformEvent: "1c2ac00.i2c-platform-axp20x-pek",
    116: {
        name: "power",
        pressed: 5,
        held: 6
    }
}
var buttons = {
    platformEvent: "button-knob",
    1: {
        name: "back",
        pressed: 1,
        held: 1+6
    },
    2: {
        name: "enter",
        pressed: 2,
        held: 2+6
    },
    3: {
        name: "menu",
        pressed: 3,
        held: 3+6
    },
    4: {
        name: "knob",
        pressed: 4,
        held: 4+6
    }
};

setupButton(powerButton);
setupButton(buttons);

function setupButton(buttonConfig) {
    buttonConfig._button = new Button(buttonConfig.platformEvent);

    buttonConfig._btnPowerPressedTimer = null;
    buttonConfig._button.on('press', function(code) {
        if(code && buttonConfig[code]) {
            //console.log("button", buttonConfig[code].name, "pressed");
            buttonConfig[code]._pressed = true;
            inputs.emit('B', buttonConfig[code].pressed);
            if(buttonConfig[code]._btnPowerPressedTimer != null) clearTimeout(buttonConfig[code]._btnPowerPressedTimer);
            buttonConfig[code]._btnPowerPressedTimer = setTimeout(function(){
                inputs.emit('B', buttonConfig[code].held);
            }, HOLD_TIME);
        }
    });

    buttonConfig._button.on('release', function(code) {
        if(code && buttonConfig[code]) {
            //console.log("button", buttonConfig[code].name, "released");
            buttonConfig[code]._pressed = false;
            if(buttonConfig[code]._btnPowerPressedTimer != null) clearTimeout(buttonConfig[code]._btnPowerPressedTimer);
        }
    });

    buttonConfig._button.on('error', function(err) {
        console.log("button error: ", buttonConfig.name, err);
    });
}

exec("killall gesture");
exec("killall inputs");
var options = {};
var mcuSetup = false;
inputs.start = function(knobOptions) {
    options = knobOptions;
    if(knobOptions.knob) {
        stop = false;
        if(inputsRunning) return;
        inputsProcess = spawn(INPUTS_BIN_PATH);
        inputsRunning = true;
        console.log("inputs process started");
        inputsProcess.stdout.on('data', function(chunk) {
            //console.log("inputs stdin: " + chunk.toString());
            var matches = chunk.toString().match(/([A-Z])=([A-Z0-9\-]+)/);
            if (matches && matches.length > 1) {
                if(matches[1] == 'D') {
                    var dir = matches[2];
                    if(buttons['4']._pressed) dir += "+";
                    inputs.emit('D', dir);
                }
            }
        });
        inputsProcess.stderr.on('data', function(chunk) {
            console.log("inputs stderr: " + chunk.toString());
            chunk = null;
        });
        inputsProcess.on('close', function(code) {
            console.log("inputs process exited");
            inputsRunning = false;
            if (!stop) {
                setTimeout(function() {
                    if(!stop) inputs.start();
                }, 500);
            }
        });
    } else if(options.mcu) {
        if(mcuSetup) return;
        mcuSetup = true;
        options.mcu.on('knob', function(val) {
            k = 'U';
            if(val < 0) {
                k = 'D';
            }
            if(buttons['4']._pressed) k += "+";
            inputs.emit('D', k);
        });
    }
}

inputs.startGesture = function() {
    inputs.gestureStatus = "enabled";
    db.get('gestureCalibration', function(err, gestureCalibration) {
        if(err || !gestureCalibration) gestureCalibration = {};
        gesture.setup(gestureCalibration, function(){
            gesture.start();
        });
    });
}
inputs.calibrateGesture = function(statusCallback) {
    gesture.calibrate(function(err, status, calResults) {
        if(calResults) {
            db.set('gestureCalibration', calResults);
            gesture.start();
        } else if(err) {
            console.log("INPUTS: error calibrating gesture: ", err);
        }
        statusCallback && statusCallback(err, status, (calResults || err) ? true : false);
    });
}

gesture.on('movement', function(dir) {
    inputs.emit('G', dir.substr(0, 1).toUpperCase());
});

inputs.stop = function(callback) {
    process.nextTick(function(){
        stop = true;
        stopGesture = true;
        if (inputsRunning) {
            console.log("inputs process exiting...");
            try {
                inputsProcess.stdin.write('\n\n\n');
                inputsProcess.stdin.end();
            } catch (e) {
                console.log("input close error: ", e);
                setTimeout(function(){
                    inputsProcess.kill();
                }, 1000);
            }
        }
        inputs.stopGesture();
        if(callback) setTimeout(callback, 100); // give time for processes to exit
    });
}

inputs.stopGesture = function() {
    inputs.gestureStatus = "disabled";
    gesture.stop();
    gesture.disable();
}

module.exports = inputs;<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _reactDom = require('react-dom');

var _reactDom2 = _interopRequireDefault(_reactDom);

var _radium = require('radium');

var _radium2 = _interopRequireDefault(_radium);

var _baseStyles = require('./baseStyles');

var _baseStyles2 = _interopRequireDefault(_baseStyles);

var _BurgerIcon = require('./BurgerIcon');

var _BurgerIcon2 = _interopRequireDefault(_BurgerIcon);

var _CrossIcon = require('./CrossIcon');

var _CrossIcon2 = _interopRequireDefault(_CrossIcon);

exports['default'] = function (styles) {

  return (0, _radium2['default'])(_react2['default'].createClass({

    propTypes: {
      customBurgerIcon: _react2['default'].PropTypes.element,
      customCrossIcon: _react2['default'].PropTypes.element,
      id: _react2['default'].PropTypes.string,
      isOpen: _react2['default'].PropTypes.bool,
      noOverlay: _react2['default'].PropTypes.bool,
      onStateChange: _react2['default'].PropTypes.func,
      outerContainerId: _react2['default'].PropTypes.string,
      pageWrapId: _react2['default'].PropTypes.string,
      right: _react2['default'].PropTypes.bool,
      styles: _react2['default'].PropTypes.object,
      width: _react2['default'].PropTypes.number
    },

    toggleMenu: function toggleMenu(isOpenVal) {
      // Order important: handle wrappers before setting sidebar state.
      this.applyWrapperStyles();

      // Disregard isOpenVal if not a boolean.
      var newState = { isOpen: typeof isOpenVal === 'boolean' ? isOpenVal : !this.state.isOpen };
      this.setState(newState, this.props.onStateChange.bind(null, newState));
    },

    // Applies component-specific styles to external wrapper elements.
    applyWrapperStyles: function applyWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, true);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, true);
      }
    },

    // Removes component-specific styles applied to external wrapper elements.
    clearWrapperStyles: function clearWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, false);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, false);
      }
    },

    // Sets or unsets styles on DOM elements outside the menu component.
    // This is necessary for correct page interaction with some of the menus.
    // Throws and returns if the required external elements don't exist,
    // which means any external page animations won't be applied.
    handleExternalWrapper: function handleExternalWrapper(id, wrapperStyles, set) {
      var html = document.querySelector('html');
      var body = document.querySelector('body');
      var wrapper = document.getElementById(id);

      if (!wrapper) {
        console.error("Element with ID '" + id + "' not found");
        return;
      }

      wrapperStyles = wrapperStyles(this.state.isOpen, this.props.width, this.props.right);

      for (var prop in wrapperStyles) {
        if (wrapperStyles.hasOwnProperty(prop)) {
          wrapper.style[prop] = set ? wrapperStyles[prop] : '';
        }
      }

      // Prevent any horizontal scroll.
      [html, body].forEach(function (element) {
        element.style['overflow-x'] = set ? 'hidden' : '';
      });
    },

    // Builds styles incrementally for a given element.
    getStyles: function getStyles(el, index) {
      var propName = 'bm' + el.replace(el.charAt(0), el.charAt(0).toUpperCase());

      // Set base styles.
      var output = _baseStyles2['default'][el] ? [_baseStyles2['default'][el](this.state.isOpen, this.props.width, this.props.right)] : [];

      // Add animation-specific styles.
      if (styles[el]) {
        output.push(styles[el](this.state.isOpen, this.props.width, this.props.right, index + 1));
      }

      // Add custom styles.
      if (this.props.styles[propName]) {
        output.push(this.props.styles[propName]);
      }

      return output;
    },

    listenForClose: function listenForClose(e) {
      e = e || window.event;

      if (this.state.isOpen && (e.key === 'Escape' || e.keyCode === 27)) {
        this.toggleMenu();
      }
    },

    getDefaultProps: function getDefaultProps() {
      return {
        id: '',
        noOverlay: false,
        onStateChange: function onStateChange() {},
        outerContainerId: '',
        pageWrapId: '',
        styles: {},
        width: 300
      };
    },

    getInitialState: function getInitialState() {
      return { isOpen: false };
    },

    componentWillMount: function componentWillMount() {
      if (!styles) {
        throw new Error('No styles supplied');
      }

      // Warn if the selected menu requires external wrapper elements
      // but none were supplied.
      if (styles.pageWrap && !this.props.pageWrapId) {
        console.warn('No pageWrapId supplied');
      }

      if (styles.outerContainer && !this.props.outerContainerId) {
        console.warn('No outerContainerId supplied');
      }

      // Allow initial open state to be set by props.
      if (this.props.isOpen) {
        this.toggleMenu();
      }
    },

    componentDidMount: function componentDidMount() {
      window.onkeydown = this.listenForClose;
    },

    componentWillUnmount: function componentWillUnmount() {
      window.onkeydown = null;

      this.clearWrapperStyles();
    },

    componentDidUpdate: function componentDidUpdate() {
      var _this = this;

      if (styles.svg && this.isMounted()) {
        (function () {
          // Snap.svg workaround for Webpack using imports-loader (https://github.com/webpack/imports-loader).
          var snap = undefined;
          try {
            snap = require('imports?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js');
          } catch (e) {
            snap = require('snapsvg');
          }

          var morphShape = _reactDom2['default'].findDOMNode(_this, 'bm-morph-shape');
          var s = snap(morphShape);
          var path = s.select('path');

          if (_this.state.isOpen) {
            // Animate SVG path.
            styles.svg.animate(path);
          } else {
            // Reset path (timeout ensures animation happens off screen).
            setTimeout(function () {
              path.attr('d', styles.svg.pathInitial);
            }, 300);
          }
        })();
      }
    },

    componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
      // Allow open state to be controlled by props.
      if (typeof nextProps.isOpen === 'boolean') {
        this.toggleMenu(nextProps.isOpen);
      }
    },

    render: function render() {
      var _this2 = this;

      var items = undefined,
          svg = undefined,
          overlay = undefined;

      // Add styles to user-defined menu items.
      if (this.props.children) {
        items = _react2['default'].Children.map(this.props.children, function (item, index) {
          var extraProps = {
            key: index,
            style: _this2.getStyles('item', index)
          };
          return _react2['default'].cloneElement(item, extraProps);
        });
      }

      // Add a morph shape for animations that use SVG.
      if (styles.svg) {
        svg = _react2['default'].createElement(
          'div',
          { className: 'bm-morph-shape', style: this.getStyles('morphShape') },
          _react2['default'].createElement(
            'svg',
            { xmlns: 'http://www.w3.org/2000/svg', width: '100%', height: '100%', viewBox: '0 0 100 800', preserveAspectRatio: 'none' },
            _react2['default'].createElement('path', { d: styles.svg.pathInitial })
          )
        );
      }

      if (!this.props.noOverlay) {
        overlay = _react2['default'].createElement('div', { className: 'bm-overlay', onClick: this.toggleMenu, style: this.getStyles('overlay') });
      }

      return _react2['default'].createElement(
        'div',
        null,
        overlay,
        _react2['default'].createElement(
          'div',
          { id: this.props.id, className: "bm-menu-wrap", style: this.getStyles('menuWrap') },
          svg,
          _react2['default'].createElement(
            'div',
            { className: 'bm-menu', style: this.getStyles('menu') },
            _react2['default'].createElement(
              'nav',
              { className: 'bm-item-list', style: this.getStyles('itemList') },
              items
            )
          ),
          _react2['default'].createElement(
            'div',
            { style: this.getStyles('closeButton') },
            _react2['default'].createElement(_CrossIcon2['default'], { onClick: this.toggleMenu, styles: this.props.styles, customIcon: this.props.customCrossIcon })
          )
        ),
        _react2['default'].createElement(_BurgerIcon2['default'], { onClick: this.toggleMenu, styles: this.props.styles, customIcon: this.props.customBurgerIcon })
      );
    }
  }));
};

module.exports = exports['default'];<commit_msg>fix empty space<commit_after>'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _reactDom = require('react-dom');

var _reactDom2 = _interopRequireDefault(_reactDom);

var _radium = require('radium');

var _radium2 = _interopRequireDefault(_radium);

var _baseStyles = require('./baseStyles');

var _baseStyles2 = _interopRequireDefault(_baseStyles);

var _BurgerIcon = require('./BurgerIcon');

var _BurgerIcon2 = _interopRequireDefault(_BurgerIcon);

var _CrossIcon = require('./CrossIcon');

var _CrossIcon2 = _interopRequireDefault(_CrossIcon);

exports['default'] = function (styles) {

  return (0, _radium2['default'])(_react2['default'].createClass({

    propTypes: {
      customBurgerIcon: _react2['default'].PropTypes.element,
      customCrossIcon: _react2['default'].PropTypes.element,
      id: _react2['default'].PropTypes.string,
      isOpen: _react2['default'].PropTypes.bool,
      noOverlay: _react2['default'].PropTypes.bool,
      onStateChange: _react2['default'].PropTypes.func,
      outerContainerId: _react2['default'].PropTypes.string,
      pageWrapId: _react2['default'].PropTypes.string,
      right: _react2['default'].PropTypes.bool,
      styles: _react2['default'].PropTypes.object,
      width: _react2['default'].PropTypes.number
    },

    toggleMenu: function toggleMenu(isOpenVal) {
      // Order important: handle wrappers before setting sidebar state.
      this.applyWrapperStyles();

      // Disregard isOpenVal if not a boolean.
      var newState = { isOpen: typeof isOpenVal === 'boolean' ? isOpenVal : !this.state.isOpen };
      this.setState(newState, this.props.onStateChange.bind(null, newState));
    },

    // Applies component-specific styles to external wrapper elements.
    applyWrapperStyles: function applyWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, true);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, true);
      }
    },

    // Removes component-specific styles applied to external wrapper elements.
    clearWrapperStyles: function clearWrapperStyles() {
      if (styles.pageWrap && this.props.pageWrapId) {
        this.handleExternalWrapper(this.props.pageWrapId, styles.pageWrap, false);
      }

      if (styles.outerContainer && this.props.outerContainerId) {
        this.handleExternalWrapper(this.props.outerContainerId, styles.outerContainer, false);
      }
    },

    // Sets or unsets styles on DOM elements outside the menu component.
    // This is necessary for correct page interaction with some of the menus.
    // Throws and returns if the required external elements don't exist,
    // which means any external page animations won't be applied.
    handleExternalWrapper: function handleExternalWrapper(id, wrapperStyles, set) {
      var html = document.querySelector('html');
      var body = document.querySelector('body');
      var wrapper = document.getElementById(id);

      if (!wrapper) {
        console.error("Element with ID '" + id + "' not found");
        return;
      }

      wrapperStyles = wrapperStyles(this.state.isOpen, this.props.width, this.props.right);

      for (var prop in wrapperStyles) {
        if (wrapperStyles.hasOwnProperty(prop)) {
          wrapper.style[prop] = set ? wrapperStyles[prop] : '';
        }
      }

      // Prevent any horizontal scroll.
      [html, body].forEach(function (element) {
        element.style['overflow-x'] = set ? 'hidden' : '';
      });
    },

    // Builds styles incrementally for a given element.
    getStyles: function getStyles(el, index) {
      var propName = 'bm' + el.replace(el.charAt(0), el.charAt(0).toUpperCase());

      // Set base styles.
      var output = _baseStyles2['default'][el] ? [_baseStyles2['default'][el](this.state.isOpen, this.props.width, this.props.right)] : [];

      // Add animation-specific styles.
      if (styles[el]) {
        output.push(styles[el](this.state.isOpen, this.props.width, this.props.right, index + 1));
      }

      // Add custom styles.
      if (this.props.styles[propName]) {
        output.push(this.props.styles[propName]);
      }

      return output;
    },

    listenForClose: function listenForClose(e) {
      e = e || window.event;

      if (this.state.isOpen && (e.key === 'Escape' || e.keyCode === 27)) {
        this.toggleMenu();
      }
    },

    getDefaultProps: function getDefaultProps() {
      return {
        id: '',
        noOverlay: false,
        onStateChange: function onStateChange() {},
        outerContainerId: '',
        pageWrapId: '',
        styles: {},
        width: 300
      };
    },

    getInitialState: function getInitialState() {
      return { isOpen: false };
    },

    componentWillMount: function componentWillMount() {
      if (!styles) {
        throw new Error('No styles supplied');
      }

      // Warn if the selected menu requires external wrapper elements
      // but none were supplied.
      if (styles.pageWrap && !this.props.pageWrapId) {
        console.warn('No pageWrapId supplied');
      }

      if (styles.outerContainer && !this.props.outerContainerId) {
        console.warn('No outerContainerId supplied');
      }

      // Allow initial open state to be set by props.
      if (this.props.isOpen) {
        this.toggleMenu();
      }
    },

    componentDidMount: function componentDidMount() {
      window.onkeydown = this.listenForClose;
    },

    componentWillUnmount: function componentWillUnmount() {
      window.onkeydown = null;

      this.clearWrapperStyles();
    },

    componentDidUpdate: function componentDidUpdate() {
      var _this = this;

      if (styles.svg && this.isMounted()) {
        (function () {
          // Snap.svg workaround for Webpack using imports-loader (https://github.com/webpack/imports-loader).
          var snap = undefined;
          try {
            snap = require('imports?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js');
          } catch (e) {
            snap = require('snapsvg');
          }

          var morphShape = _reactDom2['default'].findDOMNode(_this, 'bm-morph-shape');
          var s = snap(morphShape);
          var path = s.select('path');

          if (_this.state.isOpen) {
            // Animate SVG path.
            styles.svg.animate(path);
          } else {
            // Reset path (timeout ensures animation happens off screen).
            setTimeout(function () {
              path.attr('d', styles.svg.pathInitial);
            }, 300);
          }
        })();
      }
    },

    componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
      // Allow open state to be controlled by props.
      if (typeof nextProps.isOpen === 'boolean' && nextProps.isOpen !== this.props.isOpen) {
        this.toggleMenu(nextProps.isOpen);
      }
    },

    render: function render() {
      var _this2 = this;

      var items = undefined,
          svg = undefined,
          overlay = undefined;

      // Add styles to user-defined menu items.
      if (this.props.children) {
        items = _react2['default'].Children.map(this.props.children, function (item, index) {
          var extraProps = {
            key: index,
            style: _this2.getStyles('item', index)
          };
          return _react2['default'].cloneElement(item, extraProps);
        });
      }

      // Add a morph shape for animations that use SVG.
      if (styles.svg) {
        svg = _react2['default'].createElement(
          'div',
          { className: 'bm-morph-shape', style: this.getStyles('morphShape') },
          _react2['default'].createElement(
            'svg',
            { xmlns: 'http://www.w3.org/2000/svg', width: '100%', height: '100%', viewBox: '0 0 100 800', preserveAspectRatio: 'none' },
            _react2['default'].createElement('path', { d: styles.svg.pathInitial })
          )
        );
      }

      if (!this.props.noOverlay) {
        overlay = _react2['default'].createElement('div', { className: 'bm-overlay', onClick: this.toggleMenu, style: this.getStyles('overlay') });
      }

      return _react2['default'].createElement(
        'div',
        null,
        overlay,
        _react2['default'].createElement(
          'div',
          { id: this.props.id, className: "bm-menu-wrap", style: this.getStyles('menuWrap') },
          svg,
          _react2['default'].createElement(
            'div',
            { className: 'bm-menu', style: this.getStyles('menu') },
            _react2['default'].createElement(
              'nav',
              { className: 'bm-item-list', style: this.getStyles('itemList') },
              items
            )
          ),
          _react2['default'].createElement(
            'div',
            { style: this.getStyles('closeButton') },
            _react2['default'].createElement(_CrossIcon2['default'], { onClick: this.toggleMenu, styles: this.props.styles, customIcon: this.props.customCrossIcon })
          )
        ),
        _react2['default'].createElement(_BurgerIcon2['default'], { onClick: this.toggleMenu, styles: this.props.styles, customIcon: this.props.customBurgerIcon })
      );
    }
  }));
};

module.exports = exports['default'];
<|endoftext|>


<commit_before>'use strict';

// We need the yui name to be available in all modules (as a global variable).
// This only happens if we remove the 'var' keyword or add it to the "global"
// variable.
global.YUI = require('yui').YUI;
var path = require('path');
var child_process = require('child_process');
var UglifyJS = require('uglify-js');

YUI().use(['yui'], function(Y) {
  var fs = require('fs'),
      syspath = require('path'),
      compressor = require('node-minify');

  function throw_error(err) {
    if (err) {
      throw err;
    }
  }

  // Combine one or more CSS files.
  function combineCSS(files, outputFile) {
    var unused = new compressor.minify({
      type: 'sqwish',
      fileIn: files,
      fileOut: outputFile,
      callback: throw_error
    });
  }
  exports.combineCSS = combineCSS;

  // Combine one or more JavaScript files.
  function combineJs(files, outputFile) {
    var sourceMapName = syspath.basename(outputFile, '.js') + '-source-map';
    var options = ['--source-map', sourceMapName, '--source-map-root=source',
      '--output', outputFile];
    // We feed the minifier relative path names so the source map will map to
    // relative URLs that can be easily served.
    Y.Array.each(files, function(inputFile) {
      options.push(syspath.relative(process.cwd(), inputFile));
    });
    var result = UglifyJS.minify(files, {
        outSourceMap: sourceMapName,
        sourceRoot: 'source'
    });
    fs.writeFile(outputFile, result.code, throw_error);
    fs.writeFile(sourceMapName, result.map, throw_error);
  }
  exports.combineJs = combineJs;

  // It gets the name of all the files under 'path', recursively. It ignores
  // files and directories included in the "ignore" array. These will
  // typically be set to ignore our assets and our module file.
  function readdir(path, ignore) {
    var result = []; // These are the filenames we will return.
    var dirs = []; // These are the directories into which we will recurse.
    var files = fs.readdirSync(path);
    ignore = ignore || [];

    function shouldNotIgnore(fileName) {
      return ignore.indexOf(fileName) === -1;
    }

    function isJavascriptFile(fileName) {
      return syspath.extname(fileName).toLowerCase() === '.js';
    }

    Y.Array.each(files, function(value) {
      var fileName, file;
      fileName = path + '/' + value;
      file = fs.statSync(fileName);
      if (shouldNotIgnore(fileName)) {
        if (file.isFile() && isJavascriptFile(fileName)) {
          result.push(fileName);
        }
        else if (file.isDirectory()) {
          dirs.push(fileName);
        }
      }
    });
    // We have read all the filenames and all the directory names. Now
    // it is time to recurse into the directories that we have collected.
    Y.Array.each(dirs, function(directory) {
      result.push.apply(result, readdir(directory, ignore));
    });
    return result;
  }
  exports.readdir = readdir;

  // It reads the YUI 'requires' attribute of all our custom js files
  // (as assembled by readdir) and returns the YUI modules on which we
  // directly depend.
  function loadRequires(paths) {
    var originalAdd, modules, yuiReqs;
    modules = {};

    originalAdd = YUI.add;
    // This is a trick to get the 'requires' value from the module
    // definition.
    YUI.add = function(name, fn, version, details) {
      if (details && details.requires) {
        modules[name] = details.requires;
      }
    };

    Y.Array.each(paths, function(path) {
      // It triggers the custom 'add' method above
      require(path);
    });
    YUI.add = originalAdd;

    // Getting all the YUI dependencies that we need
    yuiReqs = [];
    Y.Object.each(modules, function(requires) {
      Y.Array.each(requires, function(value) {
        if (!modules[value]) {
          // This is not one of our modules but a yui one.
          if (yuiReqs.indexOf(value) < 0) {
            // avoid duplicates
            yuiReqs.push(value);
          }
        }
      });
    });
    return yuiReqs;
  }
  exports.loadRequires = loadRequires;

  // Using the example http://yuilibrary.com/yui/docs/yui/loader-resolve.html
  // Given a list of direct YUI requirements, return the filenames of these
  // modules and their dependencies (indirect and direct).
  function getYUIFiles(reqs) {
    var loader, out;
    // The loader automatically handles following our dependencies.
    loader = new Y.Loader({
      // The base tells the loader where to look for the YUI files. We
      // look directly in the npm YUI package, but we could just as well look
      // in the symbolic link app/assets/javascripts/yui.
      base: './node_modules/yui/',
      ignoreRegistered: true,
      filter: 'RAW', // We do not want minified source because we minify it in
        // uglify, when we also produce the source maps.
      require: reqs});
    out = loader.resolve(true);
    return out;
  }
  exports.getYUIFiles = getYUIFiles;
});
<commit_msg>lint fixes<commit_after>'use strict';

// We need the yui name to be available in all modules (as a global variable).
// This only happens if we remove the 'var' keyword or add it to the "global"
// variable.
global.YUI = require('yui').YUI;
var path = require('path');
var child_process = require('child_process');
var UglifyJS = require('uglify-js');

YUI().use(['yui'], function(Y) {
  var fs = require('fs'),
      syspath = require('path'),
      compressor = require('node-minify');

  function throw_error(err) {
    if (err) {
      throw err;
    }
  }

  // Combine one or more CSS files.
  function combineCSS(files, outputFile) {
    var unused = new compressor.minify({
      type: 'sqwish',
      fileIn: files,
      fileOut: outputFile,
      callback: throw_error
    });
  }
  exports.combineCSS = combineCSS;

  // Combine one or more JavaScript files.
  function combineJs(files, outputFile) {
    var sourceMapName = syspath.basename(outputFile, '.js') + '-source-map';
    var options = ['--source-map', sourceMapName, '--source-map-root=source',
      '--output', outputFile];
    // We feed the minifier relative path names so the source map will map to
    // relative URLs that can be easily served.
    Y.Array.each(files, function(inputFile) {
      options.push(syspath.relative(process.cwd(), inputFile));
    });
    var result = UglifyJS.minify(files, {
      outSourceMap: sourceMapName,
      sourceRoot: 'source'
    });
    fs.writeFile(outputFile, result.code, throw_error);
    fs.writeFile(sourceMapName, result.map, throw_error);
  }
  exports.combineJs = combineJs;

  // It gets the name of all the files under 'path', recursively. It ignores
  // files and directories included in the "ignore" array. These will
  // typically be set to ignore our assets and our module file.
  function readdir(path, ignore) {
    var result = []; // These are the filenames we will return.
    var dirs = []; // These are the directories into which we will recurse.
    var files = fs.readdirSync(path);
    ignore = ignore || [];

    function shouldNotIgnore(fileName) {
      return ignore.indexOf(fileName) === -1;
    }

    function isJavascriptFile(fileName) {
      return syspath.extname(fileName).toLowerCase() === '.js';
    }

    Y.Array.each(files, function(value) {
      var fileName, file;
      fileName = path + '/' + value;
      file = fs.statSync(fileName);
      if (shouldNotIgnore(fileName)) {
        if (file.isFile() && isJavascriptFile(fileName)) {
          result.push(fileName);
        }
        else if (file.isDirectory()) {
          dirs.push(fileName);
        }
      }
    });
    // We have read all the filenames and all the directory names. Now
    // it is time to recurse into the directories that we have collected.
    Y.Array.each(dirs, function(directory) {
      result.push.apply(result, readdir(directory, ignore));
    });
    return result;
  }
  exports.readdir = readdir;

  // It reads the YUI 'requires' attribute of all our custom js files
  // (as assembled by readdir) and returns the YUI modules on which we
  // directly depend.
  function loadRequires(paths) {
    var originalAdd, modules, yuiReqs;
    modules = {};

    originalAdd = YUI.add;
    // This is a trick to get the 'requires' value from the module
    // definition.
    YUI.add = function(name, fn, version, details) {
      if (details && details.requires) {
        modules[name] = details.requires;
      }
    };

    Y.Array.each(paths, function(path) {
      // It triggers the custom 'add' method above
      require(path);
    });
    YUI.add = originalAdd;

    // Getting all the YUI dependencies that we need
    yuiReqs = [];
    Y.Object.each(modules, function(requires) {
      Y.Array.each(requires, function(value) {
        if (!modules[value]) {
          // This is not one of our modules but a yui one.
          if (yuiReqs.indexOf(value) < 0) {
            // avoid duplicates
            yuiReqs.push(value);
          }
        }
      });
    });
    return yuiReqs;
  }
  exports.loadRequires = loadRequires;

  // Using the example http://yuilibrary.com/yui/docs/yui/loader-resolve.html
  // Given a list of direct YUI requirements, return the filenames of these
  // modules and their dependencies (indirect and direct).
  function getYUIFiles(reqs) {
    var loader, out;
    // The loader automatically handles following our dependencies.
    loader = new Y.Loader({
      // The base tells the loader where to look for the YUI files. We
      // look directly in the npm YUI package, but we could just as well look
      // in the symbolic link app/assets/javascripts/yui.
      base: './node_modules/yui/',
      ignoreRegistered: true,
      filter: 'RAW', // We do not want minified source because we minify it in
      // uglify, when we also produce the source maps.
      require: reqs});
    out = loader.resolve(true);
    return out;
  }
  exports.getYUIFiles = getYUIFiles;
});
<|endoftext|>


<commit_before>var Element = require('../Element')
var mapValues = require('../utils/mapValues')

var mixin = {
  componentWillMount: function () {
    this.connectedFauxDOM = {}
    this.animateFauxDOMUntil = 0
  },
  connectFauxDOM: function (node, name) {
    this.connectedFauxDOM[name] = typeof node !== 'string' ? node : new Element(node)
    setTimeout(this.drawFauxDOM)
    return this.connectedFauxDOM[name]
  },
  drawFauxDOM: function () {
    var virtualDOM = mapValues(this.connectedFauxDOM, function (n) {
      return n.toReact()
    })
    this.setState(virtualDOM)
  }
}

module.exports = mixin
<commit_msg>Make fauxDOM reusable for updates<commit_after>var Element = require('../Element')
var mapValues = require('../utils/mapValues')

var mixin = {
  componentWillMount: function () {
    this.connectedFauxDOM = {}
    this.animateFauxDOMUntil = 0
  },
  connectFauxDOM: function (node, name) {
    if (!this.connectedFauxDOM[name]) {
      this.connectedFauxDOM[name] = typeof node !== 'string' ? node : new Element(node)
      setTimeout(this.drawFauxDOM)
    }
    return this.connectedFauxDOM[name]
  },
  drawFauxDOM: function () {
    var virtualDOM = mapValues(this.connectedFauxDOM, function (n) {
      return n.toReact()
    })
    this.setState(virtualDOM)
  }
}

module.exports = mixin
<|endoftext|>


<commit_before>var Collection = require('./collection');

var util = require('../util');

function property(obj, name, value) {
  if (value !== null && value !== undefined) {
    util.property.apply(this, arguments);
  }
}

function memoizedProperty(obj, name) {
  if (!obj.constructor.prototype[name]) {
    util.memoizedProperty.apply(this, arguments);
  }
}

function Shape(shape, options, memberName) {
  options = options || {};

  property(this, 'shape', shape.shape);
  property(this, 'api', options.api, false);
  property(this, 'type', shape.type);
  property(this, 'location', shape.location || 'body');
  property(this, 'queryName', shape.queryName);
  property(this, 'queryFlattened', shape.queryFlattened);
  property(this, 'name', this.name || shape.xmlName || shape.locationName ||
                         memberName);
  property(this, 'isStreaming', shape.streaming || false);
  property(this, 'isComposite', shape.isComposite || false);
  property(this, 'isShape', true, false);

  if (options.documentation) {
    property(this, 'documentation', shape.documentation);
    property(this, 'documentationUrl', shape.documentationUrl);
  }

  if (shape.xmlAttribute) {
    property(this, 'isXmlAttribute', shape.xmlAttribute || false);
  }

  // type conversion and parsing
  property(this, 'defaultValue', null);
  this.toString = function(value) {
    if (value === null || value === undefined) return '';
    return value.toString();
  };
  this.toType = function(value) { return value; };
}

Shape.normalizedTypes = {
  character: 'string',
  double: 'float',
  long: 'integer',
  short: 'integer',
  biginteger: 'integer',
  bigdecimal: 'float',
  blob: 'binary'
};

Shape.types = {
  structure: StructureShape,
  list: ListShape,
  map: MapShape,
  boolean: BooleanShape,
  timestamp: TimestampShape,
  float: FloatShape,
  integer: IntegerShape,
  string: StringShape,
  base64: Base64Shape,
  binary: BinaryShape
};

Shape.resolve = function resolve(shape, options) {
  if (shape.shape) {
    var refShape = options.api.shapes[shape.shape];
    if (!refShape) {
      throw new Error('Cannot find shape reference: ' + shape.shape);
    }

    return refShape;
  } else {
    return null;
  }
};

Shape.create = function create(shape, options, memberName) {
  if (shape.isShape) return shape;

  var refShape = Shape.resolve(shape, options);
  if (refShape) {
    var filteredKeys = Object.keys(shape);
    if (!options.documentation) {
      filteredKeys = filteredKeys.filter(function(name) {
        return !name.match(/documentation/);
      });
    }
    if (filteredKeys === ['shape']) { // no inline customizations
      return refShape;
    }

    // create an inline shape with extra members
    function InlineShape() {
      refShape.constructor.call(this, shape, options, memberName);
    }
    InlineShape.prototype = refShape;
    return new InlineShape();
  } else {
    // set type if not set
    if (!shape.type) {
      if (shape.members) shape.type = 'structure';
      else if (shape.member) shape.type = 'list';
      else if (shape.key) shape.type = 'map';
      else shape.type = 'string';
    }

    // normalize types
    var origType = shape.type;
    if (Shape.normalizedTypes[shape.type]) {
      shape.type = Shape.normalizedTypes[shape.type];
    }

    if (Shape.types[shape.type]) {
      return new Shape.types[shape.type](shape, options, memberName);
    } else {
      throw new Error('Unrecognized shape type: ' + origType);
    }
  }
};

function CompositeShape(shape) {
  Shape.apply(this, arguments);
  property(this, 'isComposite', true);

  if (shape.flattened) {
    property(this, 'flattened', shape.flattened || false);
  }
}

function StructureShape(shape, options) {
  var requiredMap = null, firstInit = !this.isShape;

  CompositeShape.apply(this, arguments);

  if (firstInit) {
    property(this, 'defaultValue', function() { return {}; });
    property(this, 'members', {});
    property(this, 'memberNames', []);
    property(this, 'required', []);
    property(this, 'isRequired', function(name) { return false; });
  }

  if (shape.members) {
    property(this, 'members', new Collection(shape.members, options, function(name, member) {
      return Shape.create(member, options, name);
    }));
    memoizedProperty(this, 'memberNames', function() {
      return shape.xmlOrder || Object.keys(shape.members);
    });
  }

  if (shape.required) {
    property(this, 'required', shape.required);
    property(this, 'isRequired', function(name) {
      if (!requiredMap) {
        requiredMap = {};
        for (var i = 0; i < shape.required.length; i++) {
          requiredMap[shape.required[i]] = true;
        }
      }

      return requiredMap[name];
    }, false, true);
  }

  property(this, 'resultWrapper', shape.resultWrapper || null);

  if (shape.payload) {
    property(this, 'payload', shape.payload);
  }

  if (typeof shape.xmlNamespace === 'string') {
    property(this, 'xmlNamespaceUri', shape.xmlNamespace);
  } else if (typeof shape.xmlNamespace === 'object') {
    property(this, 'xmlNamespacePrefix', shape.xmlNamespace.prefix);
    property(this, 'xmlNamespaceUri', shape.xmlNamespace.uri);
  }
}

function ListShape(shape, options) {
  var self = this, firstInit = !this.isShape;
  CompositeShape.apply(this, arguments);

  if (firstInit) {
    property(this, 'defaultValue', function() { return []; });
  }

  if (shape.member) {
    memoizedProperty(this, 'member', function() {
      return Shape.create(shape.member, options);
    });
  }

  if (this.flattened) {
    var oldName = this.name;
    memoizedProperty(this, 'name', function() {
      return self.member.name || oldName;
    });
  }
}

function MapShape(shape, options) {
  var firstInit = !this.isShape;
  CompositeShape.apply(this, arguments);

  if (firstInit) {
    property(this, 'defaultValue', function() { return {}; });
    property(this, 'key', Shape.create({type: 'string'}, options));
    property(this, 'value', Shape.create({type: 'string'}, options));
  }

  if (shape.key) {
    memoizedProperty(this, 'key', function() {
      return Shape.create(shape.key, options);
    });
  }
  if (shape.value) {
    memoizedProperty(this, 'value', function() {
      return Shape.create(shape.value, options);
    });
  }
}

function TimestampShape(shape) {
  var self = this;
  Shape.apply(this, arguments);

  if (shape.timestampFormat) {
    property(this, 'timestampFormat', shape.timestampFormat);
  } else if (this.api) {
    property(this, 'timestampFormat', this.api.timestampFormat);
  }

  this.toType = function(value) {
    if (value === null || value === undefined) return null;
    if (typeof value.toUTCString === 'function') return value;
    return typeof value === 'string' ? util.date.parseTimestamp(value) : null;
  };

  this.toString = function(value) {
    return util.date.format(value, self.timestampFormat);
  };
}

function StringShape() {
  Shape.apply(this, arguments);
}

function FloatShape() {
  Shape.apply(this, arguments);

  this.toType = function(value) {
    if (value === null || value === undefined) return null;
    return parseFloat(value);
  };
}

function IntegerShape() {
  Shape.apply(this, arguments);

  this.toType = function(value) {
    if (value === null || value === undefined) return null;
    return parseInt(value, 10);
  };
}

function BinaryShape() {
  Shape.apply(this, arguments);
}

function Base64Shape() {
  Shape.apply(this, arguments);
  this.toType = util.base64.decode;
  this.toString = util.base64.encode;
}

function BooleanShape() {
  Shape.apply(this, arguments);

  this.toType = function(value) {
    if (value === null || value === undefined) return null;
    return value === 'true';
  };
}

Shape.shapes = {
  StructureShape: StructureShape,
  ListShape: ListShape,
  MapShape: MapShape,
  StringShape: StringShape,
  BooleanShape: BooleanShape,
  Base64Shape: Base64Shape
};

module.exports = Shape;
<commit_msg>Fix ESLint warning<commit_after>var Collection = require('./collection');

var util = require('../util');

function property(obj, name, value) {
  if (value !== null && value !== undefined) {
    util.property.apply(this, arguments);
  }
}

function memoizedProperty(obj, name) {
  if (!obj.constructor.prototype[name]) {
    util.memoizedProperty.apply(this, arguments);
  }
}

function Shape(shape, options, memberName) {
  options = options || {};

  property(this, 'shape', shape.shape);
  property(this, 'api', options.api, false);
  property(this, 'type', shape.type);
  property(this, 'location', shape.location || 'body');
  property(this, 'queryName', shape.queryName);
  property(this, 'queryFlattened', shape.queryFlattened);
  property(this, 'name', this.name || shape.xmlName || shape.locationName ||
                         memberName);
  property(this, 'isStreaming', shape.streaming || false);
  property(this, 'isComposite', shape.isComposite || false);
  property(this, 'isShape', true, false);

  if (options.documentation) {
    property(this, 'documentation', shape.documentation);
    property(this, 'documentationUrl', shape.documentationUrl);
  }

  if (shape.xmlAttribute) {
    property(this, 'isXmlAttribute', shape.xmlAttribute || false);
  }

  // type conversion and parsing
  property(this, 'defaultValue', null);
  this.toString = function(value) {
    if (value === null || value === undefined) return '';
    return value.toString();
  };
  this.toType = function(value) { return value; };
}

Shape.normalizedTypes = {
  character: 'string',
  double: 'float',
  long: 'integer',
  short: 'integer',
  biginteger: 'integer',
  bigdecimal: 'float',
  blob: 'binary'
};

Shape.types = {
  structure: StructureShape,
  list: ListShape,
  map: MapShape,
  boolean: BooleanShape,
  timestamp: TimestampShape,
  float: FloatShape,
  integer: IntegerShape,
  string: StringShape,
  base64: Base64Shape,
  binary: BinaryShape
};

Shape.resolve = function resolve(shape, options) {
  if (shape.shape) {
    var refShape = options.api.shapes[shape.shape];
    if (!refShape) {
      throw new Error('Cannot find shape reference: ' + shape.shape);
    }

    return refShape;
  } else {
    return null;
  }
};

Shape.create = function create(shape, options, memberName) {
  if (shape.isShape) return shape;

  var refShape = Shape.resolve(shape, options);
  if (refShape) {
    var filteredKeys = Object.keys(shape);
    if (!options.documentation) {
      filteredKeys = filteredKeys.filter(function(name) {
        return !name.match(/documentation/);
      });
    }
    if (filteredKeys === ['shape']) { // no inline customizations
      return refShape;
    }

    // create an inline shape with extra members
    var InlineShape = function() {
      refShape.constructor.call(this, shape, options, memberName);
    };
    InlineShape.prototype = refShape;
    return new InlineShape();
  } else {
    // set type if not set
    if (!shape.type) {
      if (shape.members) shape.type = 'structure';
      else if (shape.member) shape.type = 'list';
      else if (shape.key) shape.type = 'map';
      else shape.type = 'string';
    }

    // normalize types
    var origType = shape.type;
    if (Shape.normalizedTypes[shape.type]) {
      shape.type = Shape.normalizedTypes[shape.type];
    }

    if (Shape.types[shape.type]) {
      return new Shape.types[shape.type](shape, options, memberName);
    } else {
      throw new Error('Unrecognized shape type: ' + origType);
    }
  }
};

function CompositeShape(shape) {
  Shape.apply(this, arguments);
  property(this, 'isComposite', true);

  if (shape.flattened) {
    property(this, 'flattened', shape.flattened || false);
  }
}

function StructureShape(shape, options) {
  var requiredMap = null, firstInit = !this.isShape;

  CompositeShape.apply(this, arguments);

  if (firstInit) {
    property(this, 'defaultValue', function() { return {}; });
    property(this, 'members', {});
    property(this, 'memberNames', []);
    property(this, 'required', []);
    property(this, 'isRequired', function(name) { return false; });
  }

  if (shape.members) {
    property(this, 'members', new Collection(shape.members, options, function(name, member) {
      return Shape.create(member, options, name);
    }));
    memoizedProperty(this, 'memberNames', function() {
      return shape.xmlOrder || Object.keys(shape.members);
    });
  }

  if (shape.required) {
    property(this, 'required', shape.required);
    property(this, 'isRequired', function(name) {
      if (!requiredMap) {
        requiredMap = {};
        for (var i = 0; i < shape.required.length; i++) {
          requiredMap[shape.required[i]] = true;
        }
      }

      return requiredMap[name];
    }, false, true);
  }

  property(this, 'resultWrapper', shape.resultWrapper || null);

  if (shape.payload) {
    property(this, 'payload', shape.payload);
  }

  if (typeof shape.xmlNamespace === 'string') {
    property(this, 'xmlNamespaceUri', shape.xmlNamespace);
  } else if (typeof shape.xmlNamespace === 'object') {
    property(this, 'xmlNamespacePrefix', shape.xmlNamespace.prefix);
    property(this, 'xmlNamespaceUri', shape.xmlNamespace.uri);
  }
}

function ListShape(shape, options) {
  var self = this, firstInit = !this.isShape;
  CompositeShape.apply(this, arguments);

  if (firstInit) {
    property(this, 'defaultValue', function() { return []; });
  }

  if (shape.member) {
    memoizedProperty(this, 'member', function() {
      return Shape.create(shape.member, options);
    });
  }

  if (this.flattened) {
    var oldName = this.name;
    memoizedProperty(this, 'name', function() {
      return self.member.name || oldName;
    });
  }
}

function MapShape(shape, options) {
  var firstInit = !this.isShape;
  CompositeShape.apply(this, arguments);

  if (firstInit) {
    property(this, 'defaultValue', function() { return {}; });
    property(this, 'key', Shape.create({type: 'string'}, options));
    property(this, 'value', Shape.create({type: 'string'}, options));
  }

  if (shape.key) {
    memoizedProperty(this, 'key', function() {
      return Shape.create(shape.key, options);
    });
  }
  if (shape.value) {
    memoizedProperty(this, 'value', function() {
      return Shape.create(shape.value, options);
    });
  }
}

function TimestampShape(shape) {
  var self = this;
  Shape.apply(this, arguments);

  if (shape.timestampFormat) {
    property(this, 'timestampFormat', shape.timestampFormat);
  } else if (this.api) {
    property(this, 'timestampFormat', this.api.timestampFormat);
  }

  this.toType = function(value) {
    if (value === null || value === undefined) return null;
    if (typeof value.toUTCString === 'function') return value;
    return typeof value === 'string' ? util.date.parseTimestamp(value) : null;
  };

  this.toString = function(value) {
    return util.date.format(value, self.timestampFormat);
  };
}

function StringShape() {
  Shape.apply(this, arguments);
}

function FloatShape() {
  Shape.apply(this, arguments);

  this.toType = function(value) {
    if (value === null || value === undefined) return null;
    return parseFloat(value);
  };
}

function IntegerShape() {
  Shape.apply(this, arguments);

  this.toType = function(value) {
    if (value === null || value === undefined) return null;
    return parseInt(value, 10);
  };
}

function BinaryShape() {
  Shape.apply(this, arguments);
}

function Base64Shape() {
  Shape.apply(this, arguments);
  this.toType = util.base64.decode;
  this.toString = util.base64.encode;
}

function BooleanShape() {
  Shape.apply(this, arguments);

  this.toType = function(value) {
    if (value === null || value === undefined) return null;
    return value === 'true';
  };
}

Shape.shapes = {
  StructureShape: StructureShape,
  ListShape: ListShape,
  MapShape: MapShape,
  StringShape: StringShape,
  BooleanShape: BooleanShape,
  Base64Shape: Base64Shape
};

module.exports = Shape;
<|endoftext|>


<commit_before>import LinvoDB from 'linvodb3'
import moment from 'moment'
import {join, resolve} from 'path'

LinvoDB.dbPath = join(resolve(__dirname), '../../db')
const dbOpts = {
}

const _dbs = new WeakMap();
export class Base {

  constructor(props) {
    this.props = props;

    this._db = this.constructor.db();
  }

  save(fn) {
    return this._db.insert(this.props, fn);
  }

  static firstBy(where, fn) {
    return this.findBy(where, (err, docs) => {
      if (err) return fn(err);

      if (docs && docs.length > 0) {
        return fn(null, docs[0]);
      } else {
        return fn(null, null);
      }
    })
  }

  static findBy(where, fn) {
    return this.db().find(where, fn);
  }

  static all(fn) {
    return this.db().find({}, fn);
  }

  static liveAll() {
    return this.db()
              .find({})
              .sort({created_at: -1})
              .live();
  }

  static updateBy(where, to, fn) {
    return this.db()
            .update(where, {$set: to}, fn);
  }

  static deleteBy(where, fn) {
    return this.db().remove(where, fn);
  }

  static deleteMulti(where, fn) {
    return this.db().remove(where, {multi: true}, fn);
  }

  static deleteAll(fn) {
    return this.db().remove({}, {multi: true}, fn)
  }

  static dataChannel() {
    const model = this;
    let subscriber;
    return {
      subscribe: (opts, cb) => {
        if (!cb) {
          cb = opts;
        }

        let lately = moment().subtract(1, 'minute').toDate();
        subscriber = this.db()
                      .find({ created_at: { $gt: lately } })
                      .sort({ created_at: -1 })
                      .limit(10)
                      .live();
        this.db()
          .on('liveQueryUpdate', () => {
            cb.apply(subscriber, subscriber.res);
          })
      },
      publish: (json) => {
        model.db().insert(json);
      },
      unsubscribe: () => {
        if (subscriber) {
          subscriber.stop();
        }
      }
    }
  }

  static schema() {
    return {};
  }

  static db() {
    const modelName = this.name;
    if (!_dbs[modelName]) {
      const now = new Date();
      let schema = Object.assign({}, this.schema(), {
        createdAt: {type: Date, default: now},
        updatedAt: {type: Date, default: now},
      });

      _dbs[modelName]
        = new LinvoDB(modelName, schema, dbOpts)
    };

    // return new LinvoDB(modelName, this.schema, dbOpts)
    return _dbs[modelName];
  }
}

export default Base
<commit_msg>Store the last query time<commit_after>import LinvoDB from 'linvodb3'
import moment from 'moment'
import {join, resolve} from 'path'

LinvoDB.dbPath = join(resolve(__dirname), '../../db')
const dbOpts = {
}

const _dbs = new WeakMap();
export class Base {

  constructor(props) {
    this.props = props;

    this._db = this.constructor.db();
  }

  save(fn) {
    return this._db.insert(this.props, fn);
  }

  static firstBy(where, fn) {
    return this.findBy(where, (err, docs) => {
      if (err) return fn(err);

      if (docs && docs.length > 0) {
        return fn(null, docs[0]);
      } else {
        return fn(null, null);
      }
    })
  }

  static findBy(where, fn) {
    return this.db().find(where, fn);
  }

  static all(fn) {
    return this.db().find({}, fn);
  }

  static liveAll() {
    return this.db()
              .find({})
              .sort({created_at: -1})
              .live();
  }

  static updateBy(where, to, fn) {
    return this.db()
            .update(where, {$set: to}, fn);
  }

  static deleteBy(where, fn) {
    return this.db().remove(where, fn);
  }

  static deleteMulti(where, fn) {
    return this.db().remove(where, {multi: true}, fn);
  }

  static deleteAll(fn) {
    return this.db().remove({}, {multi: true}, fn)
  }

  static dataChannel() {
    const model = this;
    let subscriber;
    let lastUpdate = moment().subtract(1, 'minute');
    return {
      subscribe: (opts, cb) => {
        if (!cb) {
          cb = opts;
        }

        subscriber = this.db()
                      .find({ created_at: { $gt: lastUpdate.toDate() } })
                      .sort({ created_at: -1 })
                      .limit(10)
                      .live();
        this.db()
          .on('liveQueryUpdate', () => {
            cb.apply(subscriber, subscriber.res);
            lastUpdate = moment();
          })
      },
      publish: (json) => {
        model.db().insert(json);
      },
      unsubscribe: () => {
        if (subscriber) {
          subscriber.stop();
        }
      }
    }
  }

  static schema() {
    return {};
  }

  static db() {
    const modelName = this.name;
    if (!_dbs[modelName]) {
      const now = new Date();
      let schema = Object.assign({}, this.schema(), {
        createdAt: {type: Date, default: now},
        updatedAt: {type: Date, default: now},
      });

      _dbs[modelName]
        = new LinvoDB(modelName, schema, dbOpts)
    };

    // return new LinvoDB(modelName, this.schema, dbOpts)
    return _dbs[modelName];
  }
}

export default Base
<|endoftext|>


<commit_before>//  ██████╗ ███████╗███████╗████████╗██████╗  ██████╗ ██╗   ██╗     █████╗  ██████╗████████╗██╗ ██████╗ ███╗   ██╗
//  ██╔══██╗██╔════╝██╔════╝╚══██╔══╝██╔══██╗██╔═══██╗╚██╗ ██╔╝    ██╔══██╗██╔════╝╚══██╔══╝██║██╔═══██╗████╗  ██║
//  ██║  ██║█████╗  ███████╗   ██║   ██████╔╝██║   ██║ ╚████╔╝     ███████║██║        ██║   ██║██║   ██║██╔██╗ ██║
//  ██║  ██║██╔══╝  ╚════██║   ██║   ██╔══██╗██║   ██║  ╚██╔╝      ██╔══██║██║        ██║   ██║██║   ██║██║╚██╗██║
//  ██████╔╝███████╗███████║   ██║   ██║  ██║╚██████╔╝   ██║       ██║  ██║╚██████╗   ██║   ██║╚██████╔╝██║ ╚████║
//  ╚═════╝ ╚══════╝╚══════╝   ╚═╝   ╚═╝  ╚═╝ ╚═════╝    ╚═╝       ╚═╝  ╚═╝ ╚═════╝   ╚═╝   ╚═╝ ╚═════╝ ╚═╝  ╚═══╝
//

module.exports = require('machine').build({

  friendlyName: 'Destroy',

  description: 'Destroy record(s) in the database matching a query criteria.',

  inputs: {

    datastore: {
      description: 'The datastore to use for connections.',
      extendedDescription: 'Datastores represent the config and manager required to obtain an active database connection.',
      required: true,
      readOnly: true,
      example: '==='
    },

    models: {
      description: 'An object containing all of the model definitions that have been registered.',
      required: true,
      example: '==='
    },

    query: {
      description: 'A valid stage three Waterline query.',
      required: true,
      example: '==='
    }

  },

  exits: {

    success: {
      description: 'The results of the destroy query.',
      outputVariableName: 'records',
      example: '==='
    },

    invalidDatastore: {
      description: 'The datastore used is invalid. It is missing key pieces.'
    },

    badConnection: {
      friendlyName: 'Bad connection',
      description: 'A connection either could not be obtained or there was an error using the connection.'
    }

  },

  fn: function destroy(inputs, exits) {
    // Dependencies
    var _ = require('@sailshq/lodash');
    var WLUtils = require('waterline-utils');
    var Helpers = require('./private');
    var Converter = WLUtils.query.converter;

    // Store the Query input for easier access
    var query = inputs.query;
    query.meta = query.meta || {};

    // Find the model definition
    var model = inputs.models[query.using];
    if (!model) {
      return exits.invalidDatastore();
    }

    // Set a flag if a leased connection from outside the adapter was used or not.
    var leased = _.has(query.meta, 'leasedConnection');

    // Set a flag to determine if records are being returned
    var fetchRecords = false;

    //  ╔═╗╦ ╦╔═╗╔═╗╦╔═  ┌─┐┌─┐┬─┐  ┌─┐  ┌─┐┌─┐  ┌─┐┌─┐┬ ┬┌─┐┌┬┐┌─┐
    //  ║  ╠═╣║╣ ║  ╠╩╗  ├┤ │ │├┬┘  ├─┤  ├─┘│ ┬  └─┐│  ├─┤├┤ │││├─┤
    //  ╚═╝╩ ╩╚═╝╚═╝╩ ╩  └  └─┘┴└─  ┴ ┴  ┴  └─┘  └─┘└─┘┴ ┴└─┘┴ ┴┴ ┴
    // This is a unique feature of Postgres. It may be passed in on a query
    // by query basis using the meta input or configured on the datastore. Default
    // to use the public schema.
    var schemaName = 'public';
    if (_.has(query.meta, 'schemaName')) {
      schemaName = query.meta.schemaName;
    } else if (inputs.datastore.config && inputs.datastore.config.schemaName) {
      schemaName = inputs.datastore.config.schemaName;
    }

    //  ╔═╗╔═╗╔╗╔╦  ╦╔═╗╦═╗╔╦╗  ┌┬┐┌─┐  ┌─┐┌┬┐┌─┐┌┬┐┌─┐┌┬┐┌─┐┌┐┌┌┬┐
    //  ║  ║ ║║║║╚╗╔╝║╣ ╠╦╝ ║    │ │ │  └─┐ │ ├─┤ │ ├┤ │││├┤ │││ │
    //  ╚═╝╚═╝╝╚╝ ╚╝ ╚═╝╩╚═ ╩    ┴ └─┘  └─┘ ┴ ┴ ┴ ┴ └─┘┴ ┴└─┘┘└┘ ┴
    // Convert the Waterline criteria into a Waterline Query Statement. This
    // turns it into something that is declarative and can be easily used to
    // build a SQL query.
    // See: https://github.com/treelinehq/waterline-query-docs for more info
    // on Waterline Query Statements.
    var statement;
    try {
      statement = Converter({
        model: query.using,
        method: 'destroy',
        criteria: query.criteria,
        opts: {
          schema: schemaName
        }
      });
    } catch (e) {
      return exits.error(e);
    }

    //  ╔╦╗╔═╗╔╦╗╔═╗╦═╗╔╦╗╦╔╗╔╔═╗  ┬ ┬┬ ┬┬┌─┐┬ ┬  ┬  ┬┌─┐┬  ┬ ┬┌─┐┌─┐
    //   ║║║╣  ║ ║╣ ╠╦╝║║║║║║║║╣   │││├─┤││  ├─┤  └┐┌┘├─┤│  │ │├┤ └─┐
    //  ═╩╝╚═╝ ╩ ╚═╝╩╚═╩ ╩╩╝╚╝╚═╝  └┴┘┴ ┴┴└─┘┴ ┴   └┘ ┴ ┴┴─┘└─┘└─┘└─┘
    //  ┌┬┐┌─┐  ┬─┐┌─┐┌┬┐┬ ┬┬─┐┌┐┌
    //   │ │ │  ├┬┘├┤  │ │ │├┬┘│││
    //   ┴ └─┘  ┴└─└─┘ ┴ └─┘┴└─┘└┘
    if (_.has(query.meta, 'fetch') && query.meta.fetch) {
      fetchRecords = true;

      // Add the postgres RETURNING * piece to the statement to prevent the
      // overhead of running two additional queries.
      statement.returning = '*';
    }

    // Compile the original Waterline Query
    var compiledQuery;
    try {
      compiledQuery = Helpers.query.compileStatement(statement);
    } catch (e) {
      return exits.error(e);
    }

    //  ╔═╗╔═╗╔═╗╦ ╦╔╗╔  ┌─┐┌─┐┌┐┌┌┐┌┌─┐┌─┐┌┬┐┬┌─┐┌┐┌
    //  ╚═╗╠═╝╠═╣║║║║║║  │  │ │││││││├┤ │   │ ││ ││││
    //  ╚═╝╩  ╩ ╩╚╩╝╝╚╝  └─┘└─┘┘└┘┘└┘└─┘└─┘ ┴ ┴└─┘┘└┘
    //  ┌─┐┬─┐  ┬ ┬┌─┐┌─┐  ┬  ┌─┐┌─┐┌─┐┌─┐┌┬┐  ┌─┐┌─┐┌┐┌┌┐┌┌─┐┌─┐┌┬┐┬┌─┐┌┐┌
    //  │ │├┬┘  │ │└─┐├┤   │  ├┤ ├─┤└─┐├┤  ││  │  │ │││││││├┤ │   │ ││ ││││
    //  └─┘┴└─  └─┘└─┘└─┘  ┴─┘└─┘┴ ┴└─┘└─┘─┴┘  └─┘└─┘┘└┘┘└┘└─┘└─┘ ┴ ┴└─┘┘└┘
    // Spawn a new connection for running queries on.
    Helpers.connection.spawnOrLeaseConnection(inputs.datastore, query.meta, function spawnConnectionCb(err, connection) {
      if (err) {
        return exits.badConnection(err);
      }

      //  ╦═╗╦ ╦╔╗╔  ┌┬┐┌─┐┌─┐┌┬┐┬─┐┌─┐┬ ┬  ┌─┐ ┬ ┬┌─┐┬─┐┬ ┬
      //  ╠╦╝║ ║║║║   ││├┤ └─┐ │ ├┬┘│ │└┬┘  │─┼┐│ │├┤ ├┬┘└┬┘
      //  ╩╚═╚═╝╝╚╝  ─┴┘└─┘└─┘ ┴ ┴└─└─┘ ┴   └─┘└└─┘└─┘┴└─ ┴
      Helpers.query.runQuery({
        connection: connection,
        nativeQuery: compiledQuery,
        disconnectOnError: leased ? false : true
      },

      function runQueryCb(err, report) {
        // The connection will have been disconnected on error already if needed.
        if (err) {
          return exits.error(err);
        }

        // Always release the connection unless a leased connection from outside
        // the adapter was used.
        Helpers.connection.releaseConnection(connection, leased, function cb() {
          if (fetchRecords) {
            var selectRecords = report.result;
            var orm = {
              collections: inputs.models
            };

            // Process each record to normalize output
            try {
              Helpers.query.processEachRecord({
                records: selectRecords,
                identity: model.identity,
                orm: orm
              });
            } catch (e) {
              return exits.error(e);
            }

            return exits.success({ records: selectRecords });
          }

          return exits.success();
        }); // </ releaseConnection >
      }); // </ runQuery >
    }); // </ spawnConnection >
  }
});
<commit_msg>Parse the response from a `destroy` query as if it's a `select`<commit_after>//  ██████╗ ███████╗███████╗████████╗██████╗  ██████╗ ██╗   ██╗     █████╗  ██████╗████████╗██╗ ██████╗ ███╗   ██╗
//  ██╔══██╗██╔════╝██╔════╝╚══██╔══╝██╔══██╗██╔═══██╗╚██╗ ██╔╝    ██╔══██╗██╔════╝╚══██╔══╝██║██╔═══██╗████╗  ██║
//  ██║  ██║█████╗  ███████╗   ██║   ██████╔╝██║   ██║ ╚████╔╝     ███████║██║        ██║   ██║██║   ██║██╔██╗ ██║
//  ██║  ██║██╔══╝  ╚════██║   ██║   ██╔══██╗██║   ██║  ╚██╔╝      ██╔══██║██║        ██║   ██║██║   ██║██║╚██╗██║
//  ██████╔╝███████╗███████║   ██║   ██║  ██║╚██████╔╝   ██║       ██║  ██║╚██████╗   ██║   ██║╚██████╔╝██║ ╚████║
//  ╚═════╝ ╚══════╝╚══════╝   ╚═╝   ╚═╝  ╚═╝ ╚═════╝    ╚═╝       ╚═╝  ╚═╝ ╚═════╝   ╚═╝   ╚═╝ ╚═════╝ ╚═╝  ╚═══╝
//

module.exports = require('machine').build({

  friendlyName: 'Destroy',

  description: 'Destroy record(s) in the database matching a query criteria.',

  inputs: {

    datastore: {
      description: 'The datastore to use for connections.',
      extendedDescription: 'Datastores represent the config and manager required to obtain an active database connection.',
      required: true,
      readOnly: true,
      example: '==='
    },

    models: {
      description: 'An object containing all of the model definitions that have been registered.',
      required: true,
      example: '==='
    },

    query: {
      description: 'A valid stage three Waterline query.',
      required: true,
      example: '==='
    }

  },

  exits: {

    success: {
      description: 'The results of the destroy query.',
      outputVariableName: 'records',
      example: '==='
    },

    invalidDatastore: {
      description: 'The datastore used is invalid. It is missing key pieces.'
    },

    badConnection: {
      friendlyName: 'Bad connection',
      description: 'A connection either could not be obtained or there was an error using the connection.'
    }

  },

  fn: function destroy(inputs, exits) {
    // Dependencies
    var _ = require('@sailshq/lodash');
    var WLUtils = require('waterline-utils');
    var Helpers = require('./private');
    var Converter = WLUtils.query.converter;

    // Store the Query input for easier access
    var query = inputs.query;
    query.meta = query.meta || {};

    // Find the model definition
    var model = inputs.models[query.using];
    if (!model) {
      return exits.invalidDatastore();
    }

    // Set a flag if a leased connection from outside the adapter was used or not.
    var leased = _.has(query.meta, 'leasedConnection');

    // Set a flag to determine if records are being returned
    var fetchRecords = false;

    //  ╔═╗╦ ╦╔═╗╔═╗╦╔═  ┌─┐┌─┐┬─┐  ┌─┐  ┌─┐┌─┐  ┌─┐┌─┐┬ ┬┌─┐┌┬┐┌─┐
    //  ║  ╠═╣║╣ ║  ╠╩╗  ├┤ │ │├┬┘  ├─┤  ├─┘│ ┬  └─┐│  ├─┤├┤ │││├─┤
    //  ╚═╝╩ ╩╚═╝╚═╝╩ ╩  └  └─┘┴└─  ┴ ┴  ┴  └─┘  └─┘└─┘┴ ┴└─┘┴ ┴┴ ┴
    // This is a unique feature of Postgres. It may be passed in on a query
    // by query basis using the meta input or configured on the datastore. Default
    // to use the public schema.
    var schemaName = 'public';
    if (_.has(query.meta, 'schemaName')) {
      schemaName = query.meta.schemaName;
    } else if (inputs.datastore.config && inputs.datastore.config.schemaName) {
      schemaName = inputs.datastore.config.schemaName;
    }

    //  ╔═╗╔═╗╔╗╔╦  ╦╔═╗╦═╗╔╦╗  ┌┬┐┌─┐  ┌─┐┌┬┐┌─┐┌┬┐┌─┐┌┬┐┌─┐┌┐┌┌┬┐
    //  ║  ║ ║║║║╚╗╔╝║╣ ╠╦╝ ║    │ │ │  └─┐ │ ├─┤ │ ├┤ │││├┤ │││ │
    //  ╚═╝╚═╝╝╚╝ ╚╝ ╚═╝╩╚═ ╩    ┴ └─┘  └─┘ ┴ ┴ ┴ ┴ └─┘┴ ┴└─┘┘└┘ ┴
    // Convert the Waterline criteria into a Waterline Query Statement. This
    // turns it into something that is declarative and can be easily used to
    // build a SQL query.
    // See: https://github.com/treelinehq/waterline-query-docs for more info
    // on Waterline Query Statements.
    var statement;
    try {
      statement = Converter({
        model: query.using,
        method: 'destroy',
        criteria: query.criteria,
        opts: {
          schema: schemaName
        }
      });
    } catch (e) {
      return exits.error(e);
    }

    //  ╔╦╗╔═╗╔╦╗╔═╗╦═╗╔╦╗╦╔╗╔╔═╗  ┬ ┬┬ ┬┬┌─┐┬ ┬  ┬  ┬┌─┐┬  ┬ ┬┌─┐┌─┐
    //   ║║║╣  ║ ║╣ ╠╦╝║║║║║║║║╣   │││├─┤││  ├─┤  └┐┌┘├─┤│  │ │├┤ └─┐
    //  ═╩╝╚═╝ ╩ ╚═╝╩╚═╩ ╩╩╝╚╝╚═╝  └┴┘┴ ┴┴└─┘┴ ┴   └┘ ┴ ┴┴─┘└─┘└─┘└─┘
    //  ┌┬┐┌─┐  ┬─┐┌─┐┌┬┐┬ ┬┬─┐┌┐┌
    //   │ │ │  ├┬┘├┤  │ │ │├┬┘│││
    //   ┴ └─┘  ┴└─└─┘ ┴ └─┘┴└─┘└┘
    if (_.has(query.meta, 'fetch') && query.meta.fetch) {
      fetchRecords = true;

      // Add the postgres RETURNING * piece to the statement to prevent the
      // overhead of running two additional queries.
      statement.returning = '*';
    }

    // Compile the original Waterline Query
    var compiledQuery;
    try {
      compiledQuery = Helpers.query.compileStatement(statement);
    } catch (e) {
      return exits.error(e);
    }

    //  ╔═╗╔═╗╔═╗╦ ╦╔╗╔  ┌─┐┌─┐┌┐┌┌┐┌┌─┐┌─┐┌┬┐┬┌─┐┌┐┌
    //  ╚═╗╠═╝╠═╣║║║║║║  │  │ │││││││├┤ │   │ ││ ││││
    //  ╚═╝╩  ╩ ╩╚╩╝╝╚╝  └─┘└─┘┘└┘┘└┘└─┘└─┘ ┴ ┴└─┘┘└┘
    //  ┌─┐┬─┐  ┬ ┬┌─┐┌─┐  ┬  ┌─┐┌─┐┌─┐┌─┐┌┬┐  ┌─┐┌─┐┌┐┌┌┐┌┌─┐┌─┐┌┬┐┬┌─┐┌┐┌
    //  │ │├┬┘  │ │└─┐├┤   │  ├┤ ├─┤└─┐├┤  ││  │  │ │││││││├┤ │   │ ││ ││││
    //  └─┘┴└─  └─┘└─┘└─┘  ┴─┘└─┘┴ ┴└─┘└─┘─┴┘  └─┘└─┘┘└┘┘└┘└─┘└─┘ ┴ ┴└─┘┘└┘
    // Spawn a new connection for running queries on.
    Helpers.connection.spawnOrLeaseConnection(inputs.datastore, query.meta, function spawnConnectionCb(err, connection) {
      if (err) {
        return exits.badConnection(err);
      }

      //  ╦═╗╦ ╦╔╗╔  ┌┬┐┌─┐┌─┐┌┬┐┬─┐┌─┐┬ ┬  ┌─┐ ┬ ┬┌─┐┬─┐┬ ┬
      //  ╠╦╝║ ║║║║   ││├┤ └─┐ │ ├┬┘│ │└┬┘  │─┼┐│ │├┤ ├┬┘└┬┘
      //  ╩╚═╚═╝╝╚╝  ─┴┘└─┘└─┘ ┴ ┴└─└─┘ ┴   └─┘└└─┘└─┘┴└─ ┴
      Helpers.query.runQuery({
        queryType: 'select',
        connection: connection,
        nativeQuery: compiledQuery,
        disconnectOnError: leased ? false : true
      },

      function runQueryCb(err, report) {
        // The connection will have been disconnected on error already if needed.
        if (err) {
          return exits.error(err);
        }

        // Always release the connection unless a leased connection from outside
        // the adapter was used.
        Helpers.connection.releaseConnection(connection, leased, function cb() {
          if (fetchRecords) {
            var selectRecords = report.result;
            var orm = {
              collections: inputs.models
            };

            // Process each record to normalize output
            try {
              Helpers.query.processEachRecord({
                records: selectRecords,
                identity: model.identity,
                orm: orm
              });
            } catch (e) {
              return exits.error(e);
            }

            return exits.success({ records: selectRecords });
          }

          return exits.success();
        }); // </ releaseConnection >
      }); // </ runQuery >
    }); // </ spawnConnection >
  }
});
<|endoftext|>


<commit_before>/**
 * Created by JuanCarlos on 8/30/2015.
 */

angular.module('app').service('EventService', ['$http', 'HostFactory', function($http, HostFactory){

    var baseUrl = HostFactory.serverName ;
    var eventService = {};

    eventService.createEvent = function(event){
        return $http.post(baseUrl + '/api/event', event);
    };

    eventService.getAllEvents = function(){
        return $http.get(baseUrl + '/api/event');
    };

    eventService.getEvent = function(id){
        return $http.get(baseUrl + '/api/event/' + id);
    };
    eventService.updateEvent = function(event){
        return $htpp.put(baseUrl +'/api/event',event);
    }
    eventService.deleteEvent = function(id){
        return $htpp.delete(baseUrl +'/api/event',id)
    }
    return eventService;
}]);
<commit_msg>Update Event Working<commit_after>/**
 * Created by JuanCarlos on 8/30/2015.
 */

angular.module('app').service('EventService', ['$http', 'HostFactory', function($http, HostFactory){

    var baseUrl = HostFactory.serverName ;
    var eventService = {};

    eventService.createEvent = function(event){
        return $http.post(baseUrl + '/api/event', event);
    };

    eventService.getAllEvents = function(){
        return $http.get(baseUrl + '/api/event');
    };

    eventService.getEvent = function(id){
        return $http.get(baseUrl + '/api/event/' + id);
    };
    eventService.updateEvent = function(event){
        return $http.put(baseUrl +'/api/event',event);
    }
    eventService.deleteEvent = function(id){
        return $htpp.delete(baseUrl +'/api/event',id)
    }
    return eventService;
}]);
<|endoftext|>


<commit_before>import {$, HTML} from 'minified'
import Modal from 'bootstrap-native/lib/modal-native.js'

import {i18n} from '../util.js'
import Eventable from '../Eventable.js'

let paneHtml = () => `

Workspace

  <button type="button" class="btn btn-primary create-dataset-button">Load Data</button>

Click on "Add to Workspace" in the search tab to add datasets.

`

let bodyHtml = `

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

Select a format

        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

      <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

Input your data

        Give your new dataset a name:
        <input class="form-control dataset-title" type="text" id="formDatasetTitle" placeholder="My new dataset">

      <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

`
$('body').add(HTML(bodyHtml))

const TEMPLATES = {
  // Important: No whitespace at beginning as this introduces text nodes and we just get the first node!
  'workspace-dataset':
  `

        <button type="button" class="close" aria-label="Close">×</button>

Loading...

`,

  'workspace-dataset-distribution':
  `

Title:

Type:

Content:

`,

  'workspace-dataset-distribution-action':
  `
    <button type="button" class="btn btn-primary"></button>
  `,

  'workspace-dataset-distribution-error':
  `

Type:

Error:

Details:

`,

  'format-button-item':
  `<span><button type="button" class="btn btn-primary format-button" data-dismiss="modal"></button></span> `,

  'url-input-panel':
  `

By URL

        <input type="text" class="form-control data-url" placeholder="http://..." />

          <button class="btn btn-primary load-url-button" type="button" data-dismiss="modal">Load</button>

`,

  'file-input-panel':
  `

By Local File

        <input type="file" class="form-control data-file" />

          <button class="btn btn-primary load-file-button" type="button" data-dismiss="modal">Load</button>

`,

  'text-input-panel':
  `

By Direct Input

      <textarea class="form-control data-textarea" rows="10"></textarea>
      <button class="btn btn-primary load-text-button" type="button" data-dismiss="modal">Load</button>

`
}

let css = `

`
$('head').add(HTML(css))

export default class WorkspacePane extends Eventable {
  constructor (sidebar, paneId) {
    super()
    this.sidebar = sidebar
    this.id = paneId

    $('#' + paneId).fill(HTML(paneHtml()))

    this.workspace = sidebar.workspace
    this.app = sidebar.app

    this._registerUIListeners()
    this._registerModelListeners()
  }

  _registerUIListeners() {
    $('.create-dataset-button', '#' + this.id).on('click', () => this._createDatasetWorkflow())
  }

  _createDatasetWorkflow () {
    // Step 1: show first modal and let user select the format
    // Step 2: show second modal and display URL field, text area (if media type json or xml), and local file field
    // Step 3: create virtual dataset

    let formatModal = () => {
      let modalEl = $('#formatSelectModal')

      // iterate over all formats and skip the ones without a proper mimetype (not in the form */*)
      // (these are not real file formats and exist only internally for derived object-only data (e.g. "CoverageData"))

      $('.format-list', modalEl).fill()
      for (let format of this.app.formats) {
        if (format.mediaTypes.some(mt => mt.indexOf('/') !== -1)) {
          let el = $(HTML(TEMPLATES['format-button-item']))
          $('.format-button', el).fill(format.label).on('|click', () => {
            setTimeout(() => dataModal(format), 100)
          })

          $('.format-list', modalEl).add(el)
        }
      }

      new Modal(modalEl[0]).open()
    }

    let dataModal = format => {
      let modalEl = $('#dataCreateLoadModal')

      let methods = $('.data-input-methods', modalEl)
      methods.fill()
      methods.add(HTML(TEMPLATES['url-input-panel']))
      methods.add(HTML(TEMPLATES['file-input-panel']))

      $('.load-url-button', modalEl).on('|click', () => {
        let datasetTitle = $('.dataset-title', modalEl).get('value') || '(No title)'
        let url = $('.data-url', modalEl).get('value')
        let virtualDataset = {
          title: new Map([['en', datasetTitle]]),
          virtual: true,
          distributions: [{
            title: new Map([['en', 'Data']]),
            mediaType: format.mediaTypes[0],
            url
          }]
        }

        this.workspace.addDataset(virtualDataset)
        this.workspace.requestFocus(virtualDataset)
      })

      $('.load-file-button', modalEl).on('|click', () => {

      })

      // check if the format has a text media type, if yes: show text area
      if (format.mediaTypes.some(mt => mt.indexOf('json') !== -1 || mt.indexOf('xml') !== -1)) {
        methods.add(HTML(TEMPLATES['text-input-panel']))

        $('.load-text-button', modalEl).on('|click', () => {

        })
      }

      new Modal(modalEl[0]).open()
    }

    formatModal()
  }

  _registerModelListeners () {
    this.workspace.on('add', ({dataset}) => {
      let tab = $('a.sidebar-tab', '#' + this.sidebar.id).filter(t => $(t).get('@href') === '#' + this.id)
      tab.set('-highlight-anim')
      setTimeout(() => { // doesn't work without small delay
        tab.set('+highlight-anim')
      }, 100)

      this._addDataset(dataset)

      $('.user-hint', '#' + this.id).remove()
    })

    this.workspace.on('remove', ({dataset}) => {
      $(dataset.domEl).remove()
    })

    this.workspace.on('distributionsLoading', ({dataset}) => {
      $('.panel-body', dataset.domEl).show()
    })

    this.workspace.on('distributionsLoad', ({dataset}) => {
      $('.panel-body', dataset.domEl).hide()
    })

    this.workspace.on('distributionLoad', ({dataset, distribution}) => {
      this._addDistribution(dataset, distribution)
    })

    this.workspace.on('distributionLoadError', ({dataset, distribution, error}) => {
      this._addDistributionLoadError(dataset, distribution, error)
    })

    this.workspace.on('requestFocus', ({dataset}) => {
      // not added to dom yet, defer
      if (!dataset.domEl) {
        var fn = data => {
          if (data.dataset === dataset) {
            dataset.domEl.scrollIntoView()
            this.off('add', fn)
          }
        }
        this.on('add', fn)
      } else {
        dataset.domEl.scrollIntoView()
      }
    })
  }

  _addDataset (dataset) {
    let el = HTML(TEMPLATES['workspace-dataset'])[0] // the outer div
    $('.workspace-dataset-list', '#' + this.id).add(el)
    dataset.domEl = el

    if (dataset.virtual) {
      $(el).set('+panel-info')
    } else {
      $(el).set('+panel-default')
    }
    $('.dataset-title', el).fill(i18n(dataset.title))

    $('.close', el).on('click', () => {
      this.workspace.removeDataset(dataset)
    })
    this.fire('add', {dataset})
  }

  _addDistribution (dataset, distribution) {
    let el = HTML(TEMPLATES['workspace-dataset-distribution'])
    $('.workspace-dataset-distribution-list', dataset.domEl).add(el)
    distribution.domEl = el
    let meta = distribution.metadata

    $('.distribution-title', el).fill(i18n(distribution.title))
    $('.distribution-format', el).fill(meta.format)
    $('.distribution-metadata', el).fill(meta.type)

    if (distribution.actions) {
      for (let action of distribution.actions) {
        let actionEl = HTML(TEMPLATES['workspace-dataset-distribution-action'])
        $('button', actionEl).fill(action.label).on('click', () => {
          action.run()
        })
        $('.distribution-actions', el).add(actionEl)
      }
    }
  }

  _addDistributionLoadError (dataset, distribution, error) {
    let el = HTML(TEMPLATES['workspace-dataset-distribution-error'])
    $('.workspace-dataset-distribution-list', dataset.domEl).add(el)
    distribution.domEl = el

    $('.distribution-format', el).fill(distribution.formatImpl.label)
    $('.error-message', el).fill(error.message)
    if (Object.keys(error).length > 0) {
      $('.error-details', el).fill(JSON.stringify(error, null, 1))
    } else {
      $('.error-details-section', el).remove()
    }
  }

}
<commit_msg>support loading data by file upload and text input<commit_after>import {$, HTML} from 'minified'
import Modal from 'bootstrap-native/lib/modal-native.js'

import {i18n} from '../util.js'
import Eventable from '../Eventable.js'

let paneHtml = () => `

Workspace

  <button type="button" class="btn btn-primary create-dataset-button">Load Data</button>

Click on "Add to Workspace" in the search tab to add datasets.

`

let bodyHtml = `

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

Select a format

          The data you add here is not uploaded to a server. It stays within your browser and is gone when you reload the page.

        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

      <button type="button" class="close" data-dismiss="modal" aria-label="Close">×</button>

Input your data

        Give your new dataset a name:
        <input class="form-control dataset-title" type="text" id="formDatasetTitle" placeholder="My new dataset">

      <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

`
$('body').add(HTML(bodyHtml))

const TEMPLATES = {
  // Important: No whitespace at beginning as this introduces text nodes and we just get the first node!
  'workspace-dataset':
  `

        <button type="button" class="close" aria-label="Close">×</button>

Loading...

`,

  'workspace-dataset-distribution':
  `

Title:

Type:

Content:

`,

  'workspace-dataset-distribution-action':
  `
    <button type="button" class="btn btn-primary"></button>
  `,

  'workspace-dataset-distribution-error':
  `

Type:

Error:

Details:

`,

  'format-button-item':
  `<span><button type="button" class="btn btn-primary format-button" data-dismiss="modal"></button></span> `,

  'url-input-panel':
  `

By URL

        <input type="text" class="form-control data-url" placeholder="http://..." />

          <button class="btn btn-primary load-url-button" type="button" data-dismiss="modal">Load</button>

`,

  'file-input-panel':
  `

By Local File

        <input type="file" class="form-control data-file" />

          <button class="btn btn-primary load-file-button" type="button" data-dismiss="modal">Load</button>

`,

  'text-input-panel':
  `

By Direct Input

      <textarea class="form-control data-textarea" rows="10"></textarea>
      <button class="btn btn-primary load-text-button" type="button" data-dismiss="modal">Load</button>

`
}

let css = `

`
$('head').add(HTML(css))

export default class WorkspacePane extends Eventable {
  constructor (sidebar, paneId) {
    super()
    this.sidebar = sidebar
    this.id = paneId

    $('#' + paneId).fill(HTML(paneHtml()))

    this.workspace = sidebar.workspace
    this.app = sidebar.app

    this._registerUIListeners()
    this._registerModelListeners()
  }

  _registerUIListeners() {
    $('.create-dataset-button', '#' + this.id).on('click', () => this._createDatasetWorkflow())
  }

  _createDatasetWorkflow () {
    // Step 1: show first modal and let user select the format
    // Step 2: show second modal and display URL field, text area (if media type json or xml), and local file field
    // Step 3: create virtual dataset

    let formatModal = () => {
      let modalEl = $('#formatSelectModal')

      // iterate over all formats and skip the ones without a proper mimetype (not in the form */*)
      // (these are not real file formats and exist only internally for derived object-only data (e.g. "CoverageData"))

      $('.format-list', modalEl).fill()
      for (let format of this.app.formats) {
        if (format.mediaTypes.some(mt => mt.indexOf('/') !== -1)) {
          let el = $(HTML(TEMPLATES['format-button-item']))
          $('.format-button', el).fill(format.label).on('|click', () => {
            setTimeout(() => dataModal(format), 100)
          })

          $('.format-list', modalEl).add(el)
        }
      }

      new Modal(modalEl[0]).open()
    }

    let dataModal = format => {
      let modalEl = $('#dataCreateLoadModal')

      let methods = $('.data-input-methods', modalEl)
      methods.fill()
      methods.add(HTML(TEMPLATES['url-input-panel']))
      methods.add(HTML(TEMPLATES['file-input-panel']))

      // FIXME when a format has multiple media types we currently use the first one which doesn't work for CovJSON
      // -> this is more a problem of CovJSON where CovCBOR should be an own format
      // a format which has multiple media types should still have exactly the same content

      let createVirtualDataset = (url, data) => {
        let datasetTitle = $('.dataset-title', modalEl).get('value') || '(No title)'
        let virtualDataset = {
          title: new Map([['en', datasetTitle]]),
          virtual: true,
          distributions: [{
            title: new Map([['en', 'Data']]),
            mediaType: format.mediaTypes[0],
            url, data
          }]
        }
        return virtualDataset
      }
      let addVirtualDataset = virtualDataset => {
        this.workspace.addDataset(virtualDataset)
        this.workspace.requestFocus(virtualDataset)
      }
      let createAndAddVirtualDataset = (url, data) => {
        addVirtualDataset(createVirtualDataset(url, data))
      }

      $('.load-url-button', modalEl).on('|click', () => {
        let url = $('.data-url', modalEl).get('value')
        createAndAddVirtualDataset(url)
      })

      $('.load-file-button', modalEl).on('|click', () => {
        let file = $('.data-file', modalEl)[0].files[0]
        let blob = new Blob([file], {type: format.mediaTypes[0]})
        let url = URL.createObjectURL(blob)
        let virtualDataset = createVirtualDataset(url)

        var fn = ({dataset}) => {
          if (dataset === virtualDataset) {
            URL.revokeObjectURL(url)
            this.workspace.off('distributionsLoad', fn)
          }
        }
        this.workspace.on('distributionsLoad', fn)

        addVirtualDataset(virtualDataset)
      })

      // check if the format has a JSON media type, if yes: show text area
      if (format.mediaTypes.some(mt => mt.indexOf('json') !== -1)) {
        methods.add(HTML(TEMPLATES['text-input-panel']))

        $('.load-text-button', modalEl).on('|click', event => {
          let text = $('.data-textarea', modalEl).get('value')
          let obj
          try {
            obj = JSON.parse(text)
          } catch (e) {
            $('.json-parse-error', modalEl).show().fill(e.message)
            event.stopPropagation() // prevent closing of modal
            return
          }
          createAndAddVirtualDataset(null, obj)
        })
      }

      new Modal(modalEl[0]).open()
    }

    formatModal()
  }

  _registerModelListeners () {
    this.workspace.on('add', ({dataset}) => {
      let tab = $('a.sidebar-tab', '#' + this.sidebar.id).filter(t => $(t).get('@href') === '#' + this.id)
      tab.set('-highlight-anim')
      setTimeout(() => { // doesn't work without small delay
        tab.set('+highlight-anim')
      }, 100)

      this._addDataset(dataset)

      $('.user-hint', '#' + this.id).remove()
    })

    this.workspace.on('remove', ({dataset}) => {
      $(dataset.domEl).remove()
    })

    this.workspace.on('distributionsLoading', ({dataset}) => {
      $('.panel-body', dataset.domEl).show()
    })

    this.workspace.on('distributionsLoad', ({dataset}) => {
      $('.panel-body', dataset.domEl).hide()
    })

    this.workspace.on('distributionLoad', ({dataset, distribution}) => {
      this._addDistribution(dataset, distribution)
    })

    this.workspace.on('distributionLoadError', ({dataset, distribution, error}) => {
      this._addDistributionLoadError(dataset, distribution, error)
    })

    this.workspace.on('requestFocus', ({dataset}) => {
      // not added to dom yet, defer
      if (!dataset.domEl) {
        var fn = data => {
          if (data.dataset === dataset) {
            dataset.domEl.scrollIntoView()
            this.off('add', fn)
          }
        }
        this.on('add', fn)
      } else {
        dataset.domEl.scrollIntoView()
      }
    })
  }

  _addDataset (dataset) {
    let el = HTML(TEMPLATES['workspace-dataset'])[0] // the outer div
    $('.workspace-dataset-list', '#' + this.id).add(el)
    dataset.domEl = el

    if (dataset.virtual) {
      $(el).set('+panel-info')
    } else {
      $(el).set('+panel-default')
    }
    $('.dataset-title', el).fill(i18n(dataset.title))

    $('.close', el).on('click', () => {
      this.workspace.removeDataset(dataset)
    })
    this.fire('add', {dataset})
  }

  _addDistribution (dataset, distribution) {
    let el = HTML(TEMPLATES['workspace-dataset-distribution'])
    $('.workspace-dataset-distribution-list', dataset.domEl).add(el)
    distribution.domEl = el
    let meta = distribution.metadata

    $('.distribution-title', el).fill(i18n(distribution.title))
    $('.distribution-format', el).fill(meta.format)
    $('.distribution-metadata', el).fill(meta.type)

    if (distribution.actions) {
      for (let action of distribution.actions) {
        let actionEl = HTML(TEMPLATES['workspace-dataset-distribution-action'])
        $('button', actionEl).fill(action.label).on('click', () => {
          action.run()
        })
        $('.distribution-actions', el).add(actionEl)
      }
    }
  }

  _addDistributionLoadError (dataset, distribution, error) {
    let el = HTML(TEMPLATES['workspace-dataset-distribution-error'])
    $('.workspace-dataset-distribution-list', dataset.domEl).add(el)
    distribution.domEl = el

    $('.distribution-format', el).fill(distribution.formatImpl.label)
    $('.error-message', el).fill(error.message)
    if (Object.keys(error).length > 0) {
      $('.error-details', el).fill(JSON.stringify(error, null, 1))
    } else {
      $('.error-details-section', el).remove()
    }
  }

}
<|endoftext|>